重构核心服务SSH模块,修正以下问题:

1. 某些情况下会卡在登录流程(通道中创建shell操作与收到服务端数据操作造成死锁);
2. 某些情况下连接断开了,但web界面仍然显示使用中(没有正确处理断开事件,没有更新数据库);
3. cat一个大文件会很慢,有时会导致连接断开(每个数据包都完整解析导致处理时间过长);
4. 连接/认证过程出错(密码错误、协议不支持、远程连接超时等等),均会提示用户重新输入密码(改为断开连接,避免造成误解);
dev
Apex Liu 2020-11-02 02:50:49 +08:00
parent b7d9f6f0d8
commit f26c71d52d
34 changed files with 1692 additions and 2112 deletions

View File

@ -4,67 +4,65 @@
#include "ex_types.h"
#include "ex_thread.h"
#define EX_LOG_LEVEL_DEBUG 0
#define EX_LOG_LEVEL_VERBOSE 1
#define EX_LOG_LEVEL_INFO 2
#define EX_LOG_LEVEL_WARN 3
#define EX_LOG_LEVEL_ERROR 4
#define EX_LOG_LEVEL_DEBUG 0
#define EX_LOG_LEVEL_VERBOSE 1
#define EX_LOG_LEVEL_INFO 2
#define EX_LOG_LEVEL_WARN 3
#define EX_LOG_LEVEL_ERROR 4
#define EX_LOG_FILE_MAX_SIZE 1024*1024*10
#define EX_LOG_FILE_MAX_COUNT 10
#define EX_LOG_FILE_MAX_SIZE 1024*1024*10
#define EX_LOG_FILE_MAX_COUNT 10
class ExLogger
{
public:
ExLogger();
~ExLogger();
ExLogger();
~ExLogger();
bool set_log_file(const ex_wstr& log_path, const ex_wstr& log_name, ex_u32 max_filesize, ex_u8 max_count);
void log_a(int level, const char* fmt, va_list valist);
void log_w(int level, const wchar_t* fmt, va_list valist);
bool write_a(const char* buf);
bool write_w(const wchar_t* buf);
bool set_log_file(const ex_wstr &log_path, const ex_wstr &log_name, ex_u32 max_filesize, ex_u8 max_count);
void log_a(int level, const char *fmt, va_list valist);
void log_w(int level, const wchar_t *fmt, va_list valist);
bool write_a(const char *buf);
bool write_w(const wchar_t *buf);
protected:
bool _open_file();
bool _rotate_file(void); // 将现有日志文件改名备份,然后新开一个日志文件
bool _open_file();
// 将现有日志文件改名备份,然后新开一个日志文件
bool _rotate_file();
public:
ExThreadLock lock;
int min_level;
bool debug_mode;
bool to_console;
ExThreadLock lock;
int min_level;
bool debug_mode;
bool to_console;
#ifdef EX_OS_WIN32
HANDLE console_handle;
HANDLE console_handle;
#endif
protected:
ex_u32 m_filesize;
ex_u32 m_max_filesize;
ex_u8 m_max_count;
ex_wstr m_path;
ex_wstr m_filename;
ex_wstr m_fullname;
ex_u32 m_filesize;
ex_u32 m_max_filesize;
ex_u8 m_max_count;
ex_wstr m_path;
ex_wstr m_filename;
ex_wstr m_fullname;
#ifdef EX_OS_WIN32
HANDLE m_file;
HANDLE m_file;
#else
FILE* m_file;
FILE *m_file;
#endif
};
//extern ExLogger g_ex_logger;
// extern void* ex_logger;
void EXLOG_USE_LOGGER(ExLogger* logger);
void EXLOG_USE_LOGGER(ExLogger *logger);
void EXLOG_LEVEL(int min_level);
void EXLOG_DEBUG(bool debug_mode);
// 设定日志文件名及路径如未指定路径则为可执行程序所在目录下的log目录。
void EXLOG_FILE(const wchar_t* log_file, const wchar_t* log_path = NULL, ex_u32 max_filesize = EX_LOG_FILE_MAX_SIZE, ex_u8 max_filecount = EX_LOG_FILE_MAX_COUNT);
void EXLOG_FILE(const wchar_t *log_file, const wchar_t *log_path = nullptr, ex_u32 max_filesize = EX_LOG_FILE_MAX_SIZE, ex_u8 max_filecount = EX_LOG_FILE_MAX_COUNT);
void EXLOG_CONSOLE(bool output_to_console);
@ -82,20 +80,20 @@ void ex_printf_e_lasterror(const wchar_t* fmt, ...);
#endif
void ex_printf_d(const char* fmt, ...);
void ex_printf_v(const char* fmt, ...);
void ex_printf_i(const char* fmt, ...);
void ex_printf_w(const char* fmt, ...);
void ex_printf_e(const char* fmt, ...);
void ex_printf_d(const char *fmt, ...);
void ex_printf_v(const char *fmt, ...);
void ex_printf_i(const char *fmt, ...);
void ex_printf_w(const char *fmt, ...);
void ex_printf_e(const char *fmt, ...);
void ex_printf_d(const wchar_t* fmt, ...);
void ex_printf_v(const wchar_t* fmt, ...);
void ex_printf_i(const wchar_t* fmt, ...);
void ex_printf_w(const wchar_t* fmt, ...);
void ex_printf_e(const wchar_t* fmt, ...);
void ex_printf_d(const wchar_t *fmt, ...);
void ex_printf_v(const wchar_t *fmt, ...);
void ex_printf_i(const wchar_t *fmt, ...);
void ex_printf_w(const wchar_t *fmt, ...);
void ex_printf_e(const wchar_t *fmt, ...);
void ex_printf_bin(const ex_u8* bin_data, size_t bin_size, const char* fmt, ...);
void ex_printf_bin(const ex_u8* bin_data, size_t bin_size, const wchar_t* fmt, ...);
void ex_printf_bin(const ex_u8 *bin_data, size_t bin_size, const char *fmt, ...);
void ex_printf_bin(const ex_u8 *bin_data, size_t bin_size, const wchar_t *fmt, ...);
#endif // __EX_LOG_H__

View File

@ -81,7 +81,6 @@
# endif
#endif
/*
* On Windows PATH_MAX does not exist but MAX_PATH does.
* WinAPI MAX_PATH limit is only 256. MSVCR fuctions does not have this limit.

View File

@ -206,6 +206,6 @@ int ex_atomic_inc(volatile int* pt);
int ex_atomic_dec(volatile int* pt);
// 线程相关操作
ex_u64 ex_get_thread_id();
uint64_t ex_get_thread_id();
#endif // __EX_THREAD_H__

View File

@ -2,6 +2,7 @@
#define __LIB_EX_TYPE_H__
#include "ex_platform.h"
#include <cstdint>
#include <vector>
@ -31,7 +32,7 @@ typedef int EX_BOOL;
typedef std::vector<ex_u8> ex_bin;
typedef std::vector<char> ex_chars;
typedef ex_u32 ex_rv;
typedef uint32_t ex_rv;
#if defined(EX_OS_WIN32)

View File

@ -32,7 +32,6 @@ void ex_sleep_ms(int ms);
EX_BOOL ex_localtime_now(int* t, struct tm* dt);
FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode);
FILE* ex_fopen(const ex_astr& filename, const char* mode);

View File

@ -1,5 +1,6 @@
#include <ex/ex_log.h>
#include <ex/ex_path.h>
#include <ex/ex_thread.h>
//#include <ex/ex_thread.h>
//#include <vector>
//#include <deque>
@ -16,119 +17,125 @@
#define EX_LOG_CONTENT_MAX_LEN 2048
//typedef std::deque<unsigned long long> log_file_deque;
static ExLogger* g_exlog = nullptr;
static ExLogger* g_exlog = NULL;
void EXLOG_USE_LOGGER(ExLogger* logger)
{
void EXLOG_USE_LOGGER(ExLogger* logger) {
g_exlog = logger;
}
void EXLOG_LEVEL(int min_level)
{
if(NULL != g_exlog)
g_exlog->min_level = min_level;
void EXLOG_LEVEL(int min_level) {
if (nullptr != g_exlog)
g_exlog->min_level = min_level;
}
void EXLOG_DEBUG(bool debug_mode)
{
if (NULL != g_exlog)
g_exlog->debug_mode = debug_mode;
void EXLOG_DEBUG(bool debug_mode) {
if (nullptr != g_exlog)
g_exlog->debug_mode = debug_mode;
}
void EXLOG_CONSOLE(bool output_to_console)
{
if(NULL != g_exlog)
g_exlog->to_console = output_to_console;
void EXLOG_CONSOLE(bool output_to_console) {
if (nullptr != g_exlog)
g_exlog->to_console = output_to_console;
}
void EXLOG_FILE(const wchar_t* log_file, const wchar_t* log_path /*= NULL*/, ex_u32 max_filesize /*= EX_LOG_FILE_MAX_SIZE*/, ex_u8 max_filecount /*= EX_LOG_FILE_MAX_COUNT*/)
{
if(NULL == g_exlog)
void EXLOG_FILE(const wchar_t* log_file, const wchar_t* log_path /*= nullptr*/, ex_u32 max_filesize /*= EX_LOG_FILE_MAX_SIZE*/, ex_u8 max_filecount /*= EX_LOG_FILE_MAX_COUNT*/) {
if (nullptr == g_exlog)
return;
ex_wstr _path;
if (NULL == log_path)
{
ex_exec_file(_path);
ex_dirname(_path);
ex_path_join(_path, false, L"log", NULL);
}
else
{
_path = log_path;
}
ex_wstr _path;
if (nullptr == log_path) {
ex_exec_file(_path);
ex_dirname(_path);
ex_path_join(_path, false, L"log", nullptr);
}
else {
_path = log_path;
}
g_exlog->set_log_file(_path, log_file, max_filesize, max_filecount);
g_exlog->set_log_file(_path, log_file, max_filesize, max_filecount);
}
ExLogger::ExLogger()
{
ExLogger::ExLogger() {
#ifdef EX_OS_WIN32
console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
min_level = EX_LOG_LEVEL_INFO;
debug_mode = false;
to_console = true;
min_level = EX_LOG_LEVEL_INFO;
debug_mode = false;
to_console = true;
m_file = NULL;
m_filesize = 0;
m_file = nullptr;
m_filesize = 0;
}
ExLogger::~ExLogger()
{
if (NULL != m_file)
{
ExLogger::~ExLogger() {
if (nullptr != m_file) {
#ifdef EX_OS_WIN32
CloseHandle(m_file);
CloseHandle(m_file);
#else
fclose(m_file);
fclose(m_file);
#endif
m_file = NULL;
}
m_file = nullptr;
}
}
void ExLogger::log_a(int level, const char* fmt, va_list valist)
{
if (NULL == fmt)
return;
void ExLogger::log_a(int level, const char* fmt, va_list valist) {
if (nullptr == fmt)
return;
if (0 == strlen(fmt))
return;
if (0 == strlen(fmt))
return;
char szTmp[4096] = { 0 };
size_t offset = 0;
const char* _level = "";
if (level == EX_LOG_LEVEL_ERROR)
_level = " [E]";
else if (level == EX_LOG_LEVEL_WARN)
_level = " [W]";
else if (level == EX_LOG_LEVEL_INFO)
_level = " [I]";
if (level == EX_LOG_LEVEL_ERROR)
{
szTmp[0] = '[';
szTmp[1] = 'E';
szTmp[2] = ']';
szTmp[3] = ' ';
offset = 4;
}
char prefix[100] = {0};
#ifdef EX_OS_WIN32
SYSTEMTIME st;
GetLocalTime(&st);
// sprintf_s(prefix, 100, "[%04d-%02d-%02d %02d:%02d:%02d %llu%s] ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, ex_get_thread_id(), _level);
// sprintf_s(prefix, 100, "[%02d-%02d %02d:%02d:%02d %llu%s] ", st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, ex_get_thread_id(), _level);
sprintf_s(prefix, 100, "[%04d%02d%02d %02d:%02d:%02d %llu%s] ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, ex_get_thread_id(), _level);
#else
time_t timep;
struct tm* p;
time(&timep);
p = localtime(&timep);
if (p == nullptr)
return;
// sprintf(prefix, "[%04d-%02d-%02d %02d:%02d:%02d %llu%s] ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, ex_get_thread_id(), _level);
// sprintf(prefix, "[%02d-%02d %02d:%02d:%02d %llu%s] ", p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, ex_get_thread_id(), _level);
sprintf(prefix, "[%04d%02d%02d %02d:%02d:%02d %llu]%s ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, ex_get_thread_id(), _level);
#endif
size_t offset = strlen(prefix);
char szTmp[4096] = {0};
memcpy(szTmp, prefix, offset);
#ifdef EX_OS_WIN32
vsnprintf_s(szTmp+offset, 4096-offset, 4095-offset, fmt, valist);
if(to_console)
{
if (NULL != console_handle)
{
printf_s("%s", szTmp);
fflush(stdout);
}
else
{
if(debug_mode)
OutputDebugStringA(szTmp);
}
}
vsnprintf_s(szTmp+offset, 4096-offset, 4095-offset, fmt, valist);
if(to_console)
{
if (nullptr != console_handle)
{
printf_s("%s", szTmp);
fflush(stdout);
}
else
{
if(debug_mode)
OutputDebugStringA(szTmp);
}
}
#else
vsnprintf(szTmp+offset, 4095-offset, fmt, valist);
if(to_console)
{
vsnprintf(szTmp + offset, 4095 - offset, fmt, valist);
if (to_console) {
// On linux, the stdout only output the first time output format (char or wchar_t).
// e.g.: first time you use printf(), then after that, every wprintf() not work, and vice versa.
// so we always use wprintf() to fix that.
@ -138,164 +145,186 @@ void ExLogger::log_a(int level, const char* fmt, va_list valist)
ex_astr2wstr(tmp, _tmp);
wprintf(L"%ls", _tmp.c_str());
fflush(stdout);
// printf("%s", szTmp);
// fflush(stdout);
}
}
#endif
write_a(szTmp);
write_a(szTmp);
}
void ExLogger::log_w(int level, const wchar_t* fmt, va_list valist)
{
if (NULL == fmt || 0 == wcslen(fmt))
return;
void ExLogger::log_w(int level, const wchar_t* fmt, va_list valist) {
if (nullptr == fmt || 0 == wcslen(fmt))
return;
wchar_t szTmp[4096] = { 0 };
size_t offset = 0;
if (level == EX_LOG_LEVEL_ERROR)
{
szTmp[0] = L'[';
szTmp[1] = L'E';
szTmp[2] = L']';
szTmp[3] = L' ';
offset = 4;
}
const char* _level = "";
if (level == EX_LOG_LEVEL_ERROR)
_level = " [E]";
else if (level == EX_LOG_LEVEL_WARN)
_level = " [W]";
else if (level == EX_LOG_LEVEL_INFO)
_level = " [I]";
char prefix[100] = {0};
#ifdef EX_OS_WIN32
_vsnwprintf_s(szTmp+offset, 4096-offset, 4095-offset, fmt, valist);
if(to_console)
{
if (NULL != console_handle)
{
wprintf_s(_T("%s"), szTmp);
fflush(stdout);
}
else
{
if(debug_mode)
OutputDebugStringW(szTmp);
}
}
SYSTEMTIME st;
GetLocalTime(&st);
// sprintf_s(prefix, 100, "[%04d-%02d-%02d %02d:%02d:%02d %llu%s] ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, ex_get_thread_id(), _level);
// sprintf_s(prefix, 100, "[%02d-%02d %02d:%02d:%02d %llu%s] ", st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, ex_get_thread_id(), _level);
sprintf_s(prefix, 100, "[%04d%02d-%02d %02d:%02d:%02d %llu]%s ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, ex_get_thread_id(), _level);
#else
vswprintf(szTmp+offset, 4095-offset, fmt, valist);
if(to_console)
{
wprintf(L"%ls", szTmp);
fflush(stdout);
}
time_t timep;
struct tm* p;
time(&timep);
p = localtime(&timep);
if (p == nullptr)
return;
// sprintf(prefix, "[%04d-%02d-%02d %02d:%02d:%02d %llu%s] ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, ex_get_thread_id(), _level);
// sprintf(prefix, "[%02d-%02d %02d:%02d:%02d %llu%s] ", p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, ex_get_thread_id(), _level);
sprintf(prefix, "[%04d%02d%02d %02d:%02d:%02d %llu]%s ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, ex_get_thread_id(), _level);
#endif
write_w(szTmp);
ex_wstr w_prefix;
ex_astr2wstr(prefix, w_prefix);
size_t offset = wcslen(w_prefix.c_str());
wchar_t szTmp[4096] = {0};
memcpy(szTmp, w_prefix.c_str(), offset * sizeof(wchar_t));
#ifdef EX_OS_WIN32
_vsnwprintf_s(szTmp+offset, 4096-offset, 4095-offset, fmt, valist);
if(to_console)
{
if (nullptr != console_handle)
{
wprintf_s(_T("%s"), szTmp);
fflush(stdout);
}
else
{
if(debug_mode)
OutputDebugStringW(szTmp);
}
}
#else
vswprintf(szTmp + offset, 4095 - offset, fmt, valist);
if (to_console) {
wprintf(L"%ls", szTmp);
fflush(stdout);
}
#endif
write_w(szTmp);
}
#define EX_PRINTF_XA(fn, level) \
void fn(const char* fmt, ...) \
{ \
if(NULL == g_exlog) \
if(nullptr == g_exlog) \
return; \
if (g_exlog->min_level > level) \
return; \
ExThreadSmartLock locker(g_exlog->lock); \
va_list valist; \
va_start(valist, fmt); \
g_exlog->log_a(level, fmt, valist); \
va_end(valist); \
if (g_exlog->min_level > level) \
return; \
ExThreadSmartLock locker(g_exlog->lock); \
va_list valist; \
va_start(valist, fmt); \
g_exlog->log_a(level, fmt, valist); \
va_end(valist); \
}
#define EX_PRINTF_XW(fn, level) \
void fn(const wchar_t* fmt, ...) \
{ \
if(NULL == g_exlog) \
if(nullptr == g_exlog) \
return; \
if (g_exlog->min_level > level) \
return; \
ExThreadSmartLock locker(g_exlog->lock); \
va_list valist; \
va_start(valist, fmt); \
g_exlog->log_w(level, fmt, valist); \
va_end(valist); \
if (g_exlog->min_level > level) \
return; \
ExThreadSmartLock locker(g_exlog->lock); \
va_list valist; \
va_start(valist, fmt); \
g_exlog->log_w(level, fmt, valist); \
va_end(valist); \
}
EX_PRINTF_XA(ex_printf_d, EX_LOG_LEVEL_DEBUG)
EX_PRINTF_XA(ex_printf_v, EX_LOG_LEVEL_VERBOSE)
EX_PRINTF_XA(ex_printf_i, EX_LOG_LEVEL_INFO)
EX_PRINTF_XA(ex_printf_w, EX_LOG_LEVEL_WARN)
EX_PRINTF_XA(ex_printf_e, EX_LOG_LEVEL_ERROR)
EX_PRINTF_XW(ex_printf_d, EX_LOG_LEVEL_DEBUG)
EX_PRINTF_XW(ex_printf_v, EX_LOG_LEVEL_VERBOSE)
EX_PRINTF_XW(ex_printf_i, EX_LOG_LEVEL_INFO)
EX_PRINTF_XW(ex_printf_w, EX_LOG_LEVEL_WARN)
EX_PRINTF_XW(ex_printf_e, EX_LOG_LEVEL_ERROR)
#ifdef EX_OS_WIN32
void ex_printf_e_lasterror(const char* fmt, ...)
{
ExThreadSmartLock locker(g_exlog->lock);
ExThreadSmartLock locker(g_exlog->lock);
va_list valist;
va_start(valist, fmt);
g_exlog->log_a(EX_LOG_LEVEL_ERROR, fmt, valist);
va_end(valist);
va_list valist;
va_start(valist, fmt);
g_exlog->log_a(EX_LOG_LEVEL_ERROR, fmt, valist);
va_end(valist);
//=========================================
//=========================================
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf, 0, NULL);
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf, 0, nullptr);
ex_printf_e(" - WinErr(%d): %s\n", dw, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
ex_printf_e(" - WinErr(%d): %s\n", dw, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
void ex_printf_e_lasterror(const wchar_t* fmt, ...)
{
ExThreadSmartLock locker(g_exlog->lock);
ExThreadSmartLock locker(g_exlog->lock);
va_list valist;
va_start(valist, fmt);
g_exlog->log_w(EX_LOG_LEVEL_ERROR, fmt, valist);
va_end(valist);
va_list valist;
va_start(valist, fmt);
g_exlog->log_w(EX_LOG_LEVEL_ERROR, fmt, valist);
va_end(valist);
//=========================================
//=========================================
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf, 0, NULL);
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf, 0, nullptr);
ex_printf_e(" - WinErr(%d): %s\n", dw, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
ex_printf_e(" - WinErr(%d): %s\n", dw, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
#endif
void ex_printf_bin(const ex_u8* bin_data, size_t bin_size, const char* fmt, ...)
{
if(NULL == g_exlog)
void ex_printf_bin(const ex_u8* bin_data, size_t bin_size, const char* fmt, ...) {
if (nullptr == g_exlog)
return;
if (!g_exlog->debug_mode)
return;
if (!g_exlog->debug_mode)
return;
ExThreadSmartLock locker(g_exlog->lock);
ExThreadSmartLock locker(g_exlog->lock);
if (NULL == fmt)
if (nullptr == fmt)
return;
if (0 == strlen(fmt))
return;
char szTmp[128] = { 0 };
// size_t offset = 0;
char szTmp[128] = {0};
va_list valist;
va_start(valist, fmt);
@ -307,235 +336,186 @@ void ex_printf_bin(const ex_u8* bin_data, size_t bin_size, const char* fmt, ...)
#endif
va_end(valist);
//
//
//
//
// va_list valist;
// va_start(valist, fmt);
// g_exlog->log_a(EX_LOG_LEVEL_DEBUG, fmt, valist);
// va_end(valist);
//
ex_printf_d("%s (%d/0x%02x Bytes)\n", szTmp, bin_size, bin_size);
ex_printf_d("%s (%d/0x%02x Bytes)\n", szTmp, bin_size, bin_size);
const ex_u8* line = bin_data;
size_t thisline = 0;
size_t offset = 0;
unsigned int i = 0;
const ex_u8* line = bin_data;
size_t offset = 0;
while (offset < bin_size) {
size_t _offset = 0;
memset(szTmp, 0, 128);
// char szTmp[128] = { 0 };
size_t _offset = 0;
snprintf(szTmp + _offset, 128 - _offset, "%06x ", (int) offset);
_offset += 8;
while (offset < bin_size)
{
memset(szTmp, 0, 128);
_offset = 0;
size_t this_line = bin_size - offset;
if (this_line > 16)
this_line = 16;
snprintf(szTmp + _offset, 128 - _offset, "%06x ", (int)offset);
_offset += 8;
size_t i = 0;
for (; i < this_line; i++) {
snprintf(szTmp + _offset, 128 - _offset, "%02x ", line[i]);
_offset += 3;
}
thisline = bin_size - offset;
if (thisline > 16)
thisline = 16;
snprintf(szTmp + _offset, 128 - _offset, " ");
_offset += 2;
for (i = 0; i < thisline; i++)
{
snprintf(szTmp + _offset, 128 - _offset, "%02x ", line[i]);
_offset += 3;
}
for (; i < 16; i++) {
snprintf(szTmp + _offset, 128 - _offset, " ");
_offset += 3;
}
snprintf(szTmp + _offset, 128 - _offset, " ");
_offset += 2;
for (i = 0; i < this_line; i++) {
snprintf(szTmp + _offset, 128 - _offset, "%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
_offset += 1;
}
for (; i < 16; i++)
{
snprintf(szTmp + _offset, 128 - _offset, " ");
_offset += 3;
}
snprintf(szTmp + _offset, 128 - _offset, "\n");
for (i = 0; i < thisline; i++)
{
snprintf(szTmp + _offset, 128 - _offset, "%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
_offset += 1;
}
ex_printf_d("%s", szTmp);
snprintf(szTmp + _offset, 128 - _offset, "\n");
_offset += 1;
offset += this_line;
line += this_line;
}
ex_printf_d("%s", szTmp);
offset += thisline;
line += thisline;
}
fflush(stdout);
fflush(stdout);
}
bool ExLogger::set_log_file(const ex_wstr& log_path, const ex_wstr& log_name, ex_u32 max_filesize, ex_u8 max_count)
{
m_max_filesize = max_filesize;
m_max_count = max_count;
bool ExLogger::set_log_file(const ex_wstr& log_path, const ex_wstr& log_name, ex_u32 max_filesize, ex_u8 max_count) {
m_max_filesize = max_filesize;
m_max_count = max_count;
m_filename = log_name;
m_filename = log_name;
m_path = log_path;
ex_abspath(m_path);
m_path = log_path;
ex_abspath(m_path);
ex_mkdirs(m_path);
ex_mkdirs(m_path);
m_fullname = m_path;
ex_path_join(m_fullname, false, log_name.c_str(), NULL);
m_fullname = m_path;
ex_path_join(m_fullname, false, log_name.c_str(), nullptr);
return _open_file();
return _open_file();
}
bool ExLogger::_open_file()
{
if (m_file)
{
bool ExLogger::_open_file() {
if (m_file) {
#ifdef EX_OS_WIN32
CloseHandle(m_file);
CloseHandle(m_file);
#else
fclose(m_file);
fclose(m_file);
#endif
m_file = NULL;
}
m_file = nullptr;
}
#ifdef EX_OS_WIN32
// 注意:这里必须使用 CreateFile() 来打开日志文件使用FILE指针无法传递给动态库进行操作。
m_file = CreateFileW(m_fullname.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == m_file)
{
m_file = NULL;
return false;
}
// 注意:这里必须使用 CreateFile() 来打开日志文件使用FILE指针无法传递给动态库进行操作。
m_file = CreateFileW(m_fullname.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (INVALID_HANDLE_VALUE == m_file)
{
m_file = nullptr;
return false;
}
SetFilePointer(m_file, 0, NULL, FILE_END);
m_filesize = GetFileSize(m_file, NULL);
SetFilePointer(m_file, 0, nullptr, FILE_END);
m_filesize = GetFileSize(m_file, nullptr);
#else
ex_astr _fullname;
ex_wstr2astr(m_fullname, _fullname);
m_file = fopen(_fullname.c_str(), "a");
ex_astr _fullname;
ex_wstr2astr(m_fullname, _fullname);
m_file = fopen(_fullname.c_str(), "a");
if (NULL == m_file)
{
return false;
}
if (nullptr == m_file) {
return false;
}
fseek(m_file, 0, SEEK_END);
m_filesize = (ex_u32)ftell(m_file);
fseek(m_file, 0, SEEK_END);
m_filesize = (ex_u32) ftell(m_file);
#endif
return _rotate_file();
return _rotate_file();
}
bool ExLogger::_rotate_file(void)
{
if (m_filesize < m_max_filesize)
return true;
bool ExLogger::_rotate_file() {
if (m_filesize < m_max_filesize)
return true;
if (m_file)
{
if (m_file) {
#ifdef EX_OS_WIN32
CloseHandle(m_file);
CloseHandle(m_file);
#else
fclose(m_file);
fclose(m_file);
#endif
m_file = NULL;
}
m_file = nullptr;
}
// make a name for backup file.
wchar_t _tmpname[64] = { 0 };
// make a name for backup file.
wchar_t _tmpname[64] = {0};
#ifdef EX_OS_WIN32
SYSTEMTIME st;
GetLocalTime(&st);
swprintf_s(_tmpname, 64, L"%s.%04d%02d%02d%02d%02d%02d.bak", m_filename.c_str(), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
SYSTEMTIME st;
GetLocalTime(&st);
swprintf_s(_tmpname, 64, L"%s.%04d%02d%02d%02d%02d%02d.bak", m_filename.c_str(), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
#else
time_t timep;
time(&timep);
struct tm *p = localtime(&timep);
if (p == NULL)
return false;
time_t timep;
time(&timep);
struct tm* p = localtime(&timep);
if (p == nullptr)
return false;
ex_wcsformat(_tmpname, 64, L"%ls.%04d%02d%02d%02d%02d%02d.bak", m_filename.c_str(), p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
ex_wcsformat(_tmpname, 64, L"%ls.%04d%02d%02d%02d%02d%02d.bak", m_filename.c_str(), p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
#endif
ex_wstr _new_fullname(m_path);
ex_path_join(_new_fullname, false, _tmpname, NULL);
ex_wstr _new_fullname(m_path);
ex_path_join(_new_fullname, false, _tmpname, nullptr);
#ifdef EX_OS_WIN32
if (!MoveFileW(m_fullname.c_str(), _new_fullname.c_str()))
{
EXLOGE_WIN("can not rename log file, remove old one and try again.");
DeleteFileW(_new_fullname.c_str());
if (!MoveFileW(m_fullname.c_str(), _new_fullname.c_str()))
return false;
}
if (!MoveFileW(m_fullname.c_str(), _new_fullname.c_str()))
{
EXLOGE_WIN("can not rename log file, remove old one and try again.");
DeleteFileW(_new_fullname.c_str());
if (!MoveFileW(m_fullname.c_str(), _new_fullname.c_str()))
return false;
}
#else
ex_astr _a_fullname;
ex_astr _a_new_fullname;
ex_wstr2astr(m_fullname, _a_fullname);
ex_wstr2astr(_new_fullname, _a_new_fullname);
ex_astr _a_fullname;
ex_astr _a_new_fullname;
ex_wstr2astr(m_fullname, _a_fullname);
ex_wstr2astr(_new_fullname, _a_new_fullname);
if (rename(_a_fullname.c_str(), _a_new_fullname.c_str()) != 0)
{
remove(_a_new_fullname.c_str());
if (0 != (rename(_a_fullname.c_str(), _a_new_fullname.c_str())))
return false;
}
if (rename(_a_fullname.c_str(), _a_new_fullname.c_str()) != 0) {
remove(_a_new_fullname.c_str());
if (0 != (rename(_a_fullname.c_str(), _a_new_fullname.c_str())))
return false;
}
#endif
return _open_file();
return _open_file();
}
bool ExLogger::write_a(const char* buf)
{
if (NULL == m_file)
return false;
bool ExLogger::write_a(const char* buf) {
if (nullptr == m_file)
return false;
size_t len = strlen(buf);
size_t len = strlen(buf);
if (len > EX_LOG_CONTENT_MAX_LEN)
return false;
if (len > EX_LOG_CONTENT_MAX_LEN)
return false;
char szTime[100] = { 0 };
#ifdef EX_OS_WIN32
SYSTEMTIME st;
GetLocalTime(&st);
sprintf_s(szTime, 100, "[%04d-%02d-%02d %02d:%02d:%02d] ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
int lenTime = strlen(szTime);
DWORD dwWritten = 0;
WriteFile(m_file, szTime, lenTime, &dwWritten, NULL);
m_filesize += lenTime;
WriteFile(m_file, buf, len, &dwWritten, NULL);
m_filesize += len;
FlushFileBuffers(m_file);
WriteFile(m_file, buf, len, &dwWritten, nullptr);
m_filesize += len;
FlushFileBuffers(m_file);
#else
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
if (p == NULL)
return false;
sprintf(szTime, "[%04d-%02d-%02d %02d:%02d:%02d] ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
size_t lenTime = strlen(szTime);
fwrite(szTime, lenTime, 1, m_file);
m_filesize += lenTime;
fwrite(buf, len, 1, m_file);
m_filesize += len;
fwrite(buf, len, 1, m_file);
m_filesize += len;
fflush(m_file);
#endif
return _rotate_file();
return _rotate_file();
}
bool ExLogger::write_w(const wchar_t* buf)
{
ex_astr _buf;
ex_wstr2astr(buf, _buf, EX_CODEPAGE_UTF8);
return write_a(_buf.c_str());
bool ExLogger::write_w(const wchar_t* buf) {
ex_astr _buf;
ex_wstr2astr(buf, _buf, EX_CODEPAGE_UTF8);
return write_a(_buf.c_str());
}

View File

@ -214,11 +214,17 @@ int ex_atomic_dec(volatile int *pt) {
#endif
}
ex_u64 ex_get_thread_id() {
#ifdef EX_OS_WIN32
return GetCurrentThreadId();
uint64_t ex_get_thread_id()
{
#if defined(EX_OS_WIN32)
return (uint64_t)GetCurrentThreadId();
#elif defined(EX_OS_LINUX)
return pthread_self();
#elif defined(EX_OS_MACOS)
uint64_t tid = 0;
pthread_threadid_np(nullptr, &tid);
return tid;
#else
return (ex_u64) pthread_self();
# error "unsupport platform."
#endif
}

View File

@ -3,19 +3,20 @@
#include <ex/ex_str.h>
#include <ex/ex_log.h>
EX_BOOL ex_initialize(const char *lc_ctype) {
EX_BOOL ex_initialize(const char *lc_ctype)
{
#ifdef EX_OS_UNIX
const char *_lc_default = "en_US.UTF-8";
const char *_lc_ctype = NULL;
char *_loc = NULL;
if (NULL == lc_ctype)
const char *_lc_ctype = nullptr;
char *_loc = nullptr;
if (nullptr == lc_ctype)
_lc_ctype = _lc_default;
else
_lc_ctype = lc_ctype;
_loc = setlocale(LC_CTYPE, _lc_ctype);
if (NULL == _loc)
if (nullptr == _loc)
return EX_FALSE;
// if(0 != strcmp(_loc, _lc_ctype))
// return EX_FALSE;
@ -27,50 +28,61 @@ EX_BOOL ex_initialize(const char *lc_ctype) {
}
void ex_free(void *buffer) {
if (NULL == buffer)
void ex_free(void *buffer)
{
if (nullptr == buffer)
return;
free(buffer);
}
const ex_u8 *ex_memmem(const ex_u8 *haystack, size_t haystacklen, const ex_u8 *needle, size_t needlelen) {
const ex_u8 *cursor = NULL;
const ex_u8 *ex_memmem(const ex_u8 *haystack, size_t haystacklen, const ex_u8 *needle, size_t needlelen)
{
const ex_u8 *cursor = nullptr;
const ex_u8 *last_possible_needle_location = haystack + haystacklen - needlelen;
/** Easy answers */
if (needlelen > haystacklen) return (NULL);
if (needle == NULL) return (NULL);
if (haystack == NULL) return (NULL);
if (needlelen == 0) return (NULL);
if (haystacklen == 0) return (NULL);
if (needlelen > haystacklen)
return (nullptr);
if (needle == nullptr)
return (nullptr);
if (haystack == nullptr)
return (nullptr);
if (needlelen == 0)
return (nullptr);
if (haystacklen == 0)
return (nullptr);
for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) {
for (cursor = haystack; cursor <= last_possible_needle_location; cursor++)
{
if (memcmp(needle, cursor, needlelen) == 0)
return cursor;
}
return (NULL);
return (nullptr);
}
void ex_mem_reverse(ex_u8 *p, size_t l) {
ex_u8 temp = 0;
size_t i = 0, j = 0;
void ex_mem_reverse(ex_u8 *p, size_t l)
{
ex_u8 temp = 0;
size_t i = 0, j = 0;
for (i = 0, j = l - 1; i < j; i++, j--) {
for (i = 0, j = l - 1; i < j; i++, j--)
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
void ex_printf(const char *fmt, ...) {
if (NULL == fmt || 0 == strlen(fmt))
void ex_printf(const char *fmt, ...)
{
if (nullptr == fmt || 0 == strlen(fmt))
return;
va_list valist;
va_start(valist, fmt);
//_ts_printf_a(TS_COLOR_GRAY, TS_COLOR_BLACK, fmt, valist);
char _tmp[4096] = {0};
char _tmp[4096] = { 0 };
#ifdef EX_OS_WIN32
vsnprintf_s(_tmp, 4096, 4095, fmt, valist);
printf_s("%s", _tmp);
@ -84,14 +96,15 @@ void ex_printf(const char *fmt, ...) {
va_end(valist);
}
void ex_wprintf(const wchar_t *fmt, ...) {
if (NULL == fmt || 0 == wcslen(fmt))
void ex_wprintf(const wchar_t *fmt, ...)
{
if (nullptr == fmt || 0 == wcslen(fmt))
return;
va_list valist;
va_start(valist, fmt);
wchar_t _tmp[4096] = {0};
wchar_t _tmp[4096] = { 0 };
#ifdef EX_OS_WIN32
_vsnwprintf_s(_tmp, 4096, 4095, fmt, valist);
wprintf_s(L"%s", _tmp);
@ -109,7 +122,8 @@ void ex_wprintf(const wchar_t *fmt, ...) {
va_end(valist);
}
ex_u64 ex_get_tick_count(void) {
ex_u64 ex_get_tick_count(void)
{
#ifdef EX_OS_WIN32
# if (_WIN32_WINNT >= 0x0600)
return GetTickCount64();
@ -132,7 +146,8 @@ ex_u64 ex_get_tick_count(void) {
#endif
}
void ex_sleep_ms(int ms) {
void ex_sleep_ms(int ms)
{
#ifdef EX_OS_WIN32
Sleep(ms);
#else
@ -140,8 +155,9 @@ void ex_sleep_ms(int ms) {
#endif
}
EX_BOOL ex_localtime_now(int *t, struct tm *dt) {
// if (NULL == dt)
EX_BOOL ex_localtime_now(int *t, struct tm *dt)
{
// if (nullptr == dt)
// return EX_FALSE;
//struct tm *_tmp;
@ -152,34 +168,35 @@ EX_BOOL ex_localtime_now(int *t, struct tm *dt) {
_time32(&timep);
if (0 != _localtime32_s(&_tmp, &timep))
return EX_FALSE;
if(NULL != dt)
if(nullptr != dt)
memcpy(dt, &_tmp, sizeof(struct tm));
#else
struct tm *_tmp;
time_t timep;
time_t timep;
time(&timep);
_tmp = localtime(&timep); //get server's time
if (_tmp == NULL)
if (_tmp == nullptr)
return EX_FALSE;
if (NULL != dt)
if (nullptr != dt)
memcpy(dt, _tmp, sizeof(struct tm));
#endif
if (NULL != t)
if (nullptr != t)
*t = (int) timep;
return EX_TRUE;
}
FILE *ex_fopen(const ex_wstr &filename, const wchar_t *mode) {
FILE *f = NULL;
FILE *ex_fopen(const ex_wstr &filename, const wchar_t *mode)
{
FILE *f = nullptr;
#ifdef EX_OS_WIN32
errno_t err = 0;
err = _wfopen_s(&f, filename.c_str(), mode);
if (0 == err)
return f;
else
return NULL;
return nullptr;
#else
ex_astr _fname;
ex_wstr2astr(filename, _fname);
@ -190,32 +207,35 @@ FILE *ex_fopen(const ex_wstr &filename, const wchar_t *mode) {
#endif
}
FILE* ex_fopen(const ex_astr& filename, const char* mode) {
FILE *f = NULL;
FILE *ex_fopen(const ex_astr &filename, const char *mode)
{
FILE *f = nullptr;
#ifdef EX_OS_WIN32
errno_t err = 0;
err = fopen_s(&f, filename.c_str(), mode);
if (0 == err)
return f;
else
return NULL;
errno_t err = 0;
err = fopen_s(&f, filename.c_str(), mode);
if (0 == err)
return f;
else
return nullptr;
#else
f = fopen(filename.c_str(), mode);
return f;
f = fopen(filename.c_str(), mode);
return f;
#endif
}
bool ex_read_text_file(const ex_wstr &strFileName, ex_astr& file_content) {
bool ex_read_text_file(const ex_wstr &strFileName, ex_astr &file_content)
{
std::vector<char> tmp;
FILE *f = ex_fopen(strFileName, L"rb");
if (f == NULL)
if (f == nullptr)
return false;
fseek(f, 0L, SEEK_END);
unsigned long ulFileSize = (unsigned long) ftell(f);
if (-1 == ulFileSize) {
if (-1 == ulFileSize)
{
fclose(f);
return false;
}
@ -230,22 +250,27 @@ bool ex_read_text_file(const ex_wstr &strFileName, ex_astr& file_content) {
fclose(f);
if(ulRead != ulFileSize) {
if (ulRead != ulFileSize)
{
return false;
}
if ((ulFileSize > 3) && (0 == memcmp(&tmp[0], "\xEF\xBB\xBF", 3))) {
if ((ulFileSize > 3) && (0 == memcmp(&tmp[0], "\xEF\xBB\xBF", 3)))
{
file_content = &tmp[3];
} else {
}
else
{
file_content = &tmp[0];
}
return true;
}
bool ex_write_text_file(const ex_wstr &strFileName, const ex_astr& file_content) {
bool ex_write_text_file(const ex_wstr &strFileName, const ex_astr &file_content)
{
FILE *f = ex_fopen(strFileName, L"wb");
if (f == NULL)
if (f == nullptr)
return false;
unsigned long ulWrite = fwrite(file_content.c_str(), 1, file_content.length(), f);
@ -254,35 +279,39 @@ bool ex_write_text_file(const ex_wstr &strFileName, const ex_astr& file_content)
return ulWrite == file_content.length();
}
EX_DYLIB_HANDLE ex_dlopen(const wchar_t *dylib_path) {
EX_DYLIB_HANDLE handle = NULL;
EX_DYLIB_HANDLE ex_dlopen(const wchar_t *dylib_path)
{
EX_DYLIB_HANDLE handle = nullptr;
#ifdef EX_OS_WIN32
handle = LoadLibraryExW(dylib_path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (NULL == handle)
handle = LoadLibraryExW(dylib_path, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
if (nullptr == handle)
{
EXLOGE_WIN(L"LoadLibraryEx('%ls') failed.\n", dylib_path);
return NULL;
return nullptr;
}
#else
ex_astr path;
if (!ex_wstr2astr(dylib_path, path, EX_CODEPAGE_UTF8)) {
if (!ex_wstr2astr(dylib_path, path, EX_CODEPAGE_UTF8))
{
EXLOGE("convert dylib_path failed.\n");
return NULL;
return nullptr;
}
handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (NULL == handle) {
if (nullptr == handle)
{
EXLOGE("dlopen() failed: %s.\n", dlerror());
return NULL;
return nullptr;
}
#endif
return handle;
}
void ex_dlclose(EX_DYLIB_HANDLE dylib) {
void ex_dlclose(EX_DYLIB_HANDLE dylib)
{
#ifdef EX_OS_WIN32
FreeLibrary(dylib);
#else
@ -294,7 +323,7 @@ void ex_dlclose(EX_DYLIB_HANDLE dylib) {
// static const char fmt[] = "%u.%u.%u.%u";
// char tmp[32];
// int l;
//
//
// l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
// if (l <= 0 || (size_t) l >= size) {
// return -1;
@ -303,178 +332,193 @@ void ex_dlclose(EX_DYLIB_HANDLE dylib) {
// dst[size - 1] = '\0';
// return 0;
// }
//
//
// int ex_ip4_name(const struct sockaddr_in *src, char *dst, size_t size) {
// return _inet_ntop4((const unsigned char *) &(src->sin_addr), dst, size);
// }
//
static const char * _inet_ntop_v4(const void *src, char *dst, size_t size)
//
static const char *_inet_ntop_v4(const void *src, char *dst, size_t size)
{
const char digits[] = "0123456789";
int i;
struct in_addr *addr = (struct in_addr *)src;
u_long a = ntohl(addr->s_addr);
const char *orig_dst = dst;
const char digits[] = "0123456789";
int i;
struct in_addr *addr = (struct in_addr *) src;
u_long a = ntohl(addr->s_addr);
const char *orig_dst = dst;
if (size < EX_IPV4_NAME_LEN) {
//errno = ENOSPC;
return NULL;
}
for (i = 0; i < 4; ++i) {
int n = (a >> (24 - i * 8)) & 0xFF;
int non_zerop = 0;
if (size < EX_IPV4_NAME_LEN)
{
//errno = ENOSPC;
return nullptr;
}
for (i = 0; i < 4; ++i)
{
int n = (a >> (24 - i * 8)) & 0xFF;
int non_zerop = 0;
if (non_zerop || n / 100 > 0) {
*dst++ = digits[n / 100];
n %= 100;
non_zerop = 1;
}
if (non_zerop || n / 10 > 0) {
*dst++ = digits[n / 10];
n %= 10;
non_zerop = 1;
}
*dst++ = digits[n];
if (i != 3)
*dst++ = '.';
}
*dst++ = '\0';
return orig_dst;
if (non_zerop || n / 100 > 0)
{
*dst++ = digits[n / 100];
n %= 100;
non_zerop = 1;
}
if (non_zerop || n / 10 > 0)
{
*dst++ = digits[n / 10];
n %= 10;
non_zerop = 1;
}
*dst++ = digits[n];
if (i != 3)
*dst++ = '.';
}
*dst++ = '\0';
return orig_dst;
}
#define IN6ADDRSZ 16
#define IN6ADDRSZ 16
#define INT16SZ 2
static const char * _inet_ntop_v6(const ex_u8 *src, char *dst, size_t size)
static const char *_inet_ntop_v6(const ex_u8 *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[EX_IPV6_NAME_LEN];
char *tp;
struct {
long base;
long len;
} best, cur;
u_long words[IN6ADDRSZ / INT16SZ];
int i;
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[EX_IPV6_NAME_LEN];
char *tp;
struct
{
long base;
long len;
} best, cur;
u_long words[IN6ADDRSZ / INT16SZ];
int i;
/* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, 0, sizeof(words));
for (i = 0; i < IN6ADDRSZ; i++)
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
/* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, 0, sizeof(words));
for (i = 0; i < IN6ADDRSZ; i++)
{
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
}
best.base = -1;
cur.base = -1;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
if (words[i] == 0)
{
if (cur.base == -1) {
best.base = -1;
cur.base = -1;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
if (words[i] == 0)
{
if (cur.base == -1)
{
cur.base = i;
cur.len = 1;
cur.len = 1;
}
else{
else
{
cur.len++;
}
}
else if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
best = cur;
if (best.base != -1 && best.len < 2)
best.base = -1;
}
else if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
best = cur;
if (best.base != -1 && best.len < 2)
best.base = -1;
/* Format the result.
*/
tp = tmp;
size_t tmp_size = 0;
size_t offset = 0;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
/* Are we inside the best run of 0x00's?
*/
if (best.base != -1 && i >= best.base && i < (best.base + best.len))
{
if (i == best.base) {
*tp++ = ':';
offset += 1;
}
continue;
}
/* Format the result.
*/
tp = tmp;
size_t tmp_size = 0;
size_t offset = 0;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
/* Are we inside the best run of 0x00's?
*/
if (best.base != -1 && i >= best.base && i < (best.base + best.len))
{
if (i == best.base)
{
*tp++ = ':';
offset += 1;
}
continue;
}
/* Are we following an initial run of 0x00s or any real hex?
*/
if (i != 0) {
*tp++ = ':';
offset += 1;
}
/* Are we following an initial run of 0x00s or any real hex?
*/
if (i != 0)
{
*tp++ = ':';
offset += 1;
}
/* Is this address an encapsulated IPv4?
*/
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
if (!_inet_ntop_v4(src + 12, tp, sizeof(tmp) - (tp - tmp)))
{
//errno = ENOSPC;
return (NULL);
}
tmp_size = strlen(tp);
tp += tmp_size;
offset += tmp_size;
break;
}
//tp += ex_strformat(tp, "%lX", words[i]);
tmp_size = ex_strformat(tp, EX_IPV6_NAME_LEN-offset, "%lX", words[i]);
tp += tmp_size;
offset += tmp_size;
}
/* Is this address an encapsulated IPv4?
*/
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
if (!_inet_ntop_v4(src + 12, tp, sizeof(tmp) - (tp - tmp)))
{
//errno = ENOSPC;
return (nullptr);
}
tmp_size = strlen(tp);
tp += tmp_size;
offset += tmp_size;
break;
}
//tp += ex_strformat(tp, "%lX", words[i]);
tmp_size = ex_strformat(tp, EX_IPV6_NAME_LEN - offset, "%lX", words[i]);
tp += tmp_size;
offset += tmp_size;
}
/* Was it a trailing run of 0x00's?
*/
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/* Was it a trailing run of 0x00's?
*/
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size)
{
//errno = ENOSPC;
return (NULL);
}
//return strcpy(dst, tmp);
return ex_strcpy(dst, size, tmp);
//return (NULL);
/* Check for overflow, copy, and we're done.
*/
if ((size_t) (tp - tmp) > size)
{
//errno = ENOSPC;
return (nullptr);
}
//return strcpy(dst, tmp);
return ex_strcpy(dst, size, tmp);
//return (nullptr);
}
const char* ex_inet_ntop(int af, const void *src, char *dst, size_t size) {
switch (af) {
case AF_INET:
return _inet_ntop_v4(src, dst, size);
case AF_INET6:
return _inet_ntop_v6((const ex_u8*)src, dst, size);
default:
errno = EAFNOSUPPORT;
return NULL;
}
const char *ex_inet_ntop(int af, const void *src, char *dst, size_t size)
{
switch (af)
{
case AF_INET:
return _inet_ntop_v4(src, dst, size);
case AF_INET6:
return _inet_ntop_v6((const ex_u8 *) src, dst, size);
default:
errno = EAFNOSUPPORT;
return nullptr;
}
}
int ex_ip4_name(const struct sockaddr_in *src, char *dst, size_t size) {
if (NULL == _inet_ntop_v4((const unsigned char *)&(src->sin_addr), dst, size))
return -1;
return 0;
int ex_ip4_name(const struct sockaddr_in *src, char *dst, size_t size)
{
if (nullptr == _inet_ntop_v4((const unsigned char *) &(src->sin_addr), dst, size))
return -1;
return 0;
}

View File

@ -11,142 +11,143 @@
//=======================================================
// Urlprotocol相关
//=======================================================
#define TP_URLPROTO_APP_NAME "teleport"
#define TP_URLPROTO_APP_NAME "teleport"
//=======================================================
// 远程连接认证方式
//=======================================================
#define TP_AUTH_TYPE_NONE 0
#define TP_AUTH_TYPE_PASSWORD 1
#define TP_AUTH_TYPE_PRIVATE_KEY 2
#define TP_AUTH_TYPE_NONE 0
#define TP_AUTH_TYPE_PASSWORD 1
#define TP_AUTH_TYPE_PRIVATE_KEY 2
//=======================================================
// 远程连接协议
//=======================================================
#define TP_PROTOCOL_TYPE_RDP 1
#define TP_PROTOCOL_TYPE_SSH 2
#define TP_PROTOCOL_TYPE_TELNET 3
#define TP_PROTOCOL_TYPE_RDP 1
#define TP_PROTOCOL_TYPE_SSH 2
#define TP_PROTOCOL_TYPE_TELNET 3
//=======================================================
// 远程连接子协议
//=======================================================
#define TP_PROTOCOL_TYPE_RDP_DESKTOP 100
#define TP_PROTOCOL_TYPE_SSH_SHELL 200
#define TP_PROTOCOL_TYPE_SSH_SFTP 201
#define TP_PROTOCOL_TYPE_TELNET_SHELL 300
#define TP_PROTOCOL_TYPE_RDP_DESKTOP 100
#define TP_PROTOCOL_TYPE_SSH_SHELL 200
#define TP_PROTOCOL_TYPE_SSH_SFTP 201
#define TP_PROTOCOL_TYPE_TELNET_SHELL 300
//=======================================================
// 远程主机操作系统
//=======================================================
#define TP_OS_TYPE_WINDOWS 1
#define TP_OS_TYPE_LINUX 2
#define TP_OS_TYPE_WINDOWS 1
#define TP_OS_TYPE_LINUX 2
//=======================================================
// 远程连接会话状态
//=======================================================
#define TP_SESS_STAT_RUNNING 0 // 会话开始了,正在连接
#define TP_SESS_STAT_END 9999 // 会话成功结束
#define TP_SESS_STAT_ERR_AUTH_DENIED 1 // 会话结束,因为认证失败
#define TP_SESS_STAT_ERR_CONNECT 2 // 会话结束,因为无法连接到远程主机
#define TP_SESS_STAT_ERR_BAD_SSH_KEY 3 // 会话结束因为无法识别SSH私钥
#define TP_SESS_STAT_ERR_INTERNAL 4 // 会话结束,因为内部错误
#define TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL 5 // 会话结束,因为协议不支持(RDP)
#define TP_SESS_STAT_ERR_BAD_PKG 6 // 会话结束,因为收到错误的报文
#define TP_SESS_STAT_ERR_RESET 7 // 会话结束因为teleport核心服务重置了
#define TP_SESS_STAT_ERR_IO 8 // 会话结束,因为网络中断
#define TP_SESS_STAT_ERR_SESSION 9 // 会话结束因为无效的会话ID
#define TP_SESS_STAT_ERR_AUTH_TYPE 10 // 会话结束,因为不被允许的认证方式
#define TP_SESS_STAT_RUNNING 0 // 会话开始了,正在连接
#define TP_SESS_STAT_ERR_AUTH_DENIED 1 // 会话结束,因为认证失败
#define TP_SESS_STAT_ERR_CONNECT 2 // 会话结束,因为无法连接到远程主机
#define TP_SESS_STAT_ERR_BAD_SSH_KEY 3 // 会话结束因为无法识别SSH私钥
#define TP_SESS_STAT_ERR_INTERNAL 4 // 会话结束,因为内部错误
#define TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL 5 // 会话结束,因为协议不支持(RDP)
#define TP_SESS_STAT_ERR_BAD_PKG 6 // 会话结束,因为收到错误的报文
#define TP_SESS_STAT_ERR_RESET 7 // 会话结束因为teleport核心服务重置了
#define TP_SESS_STAT_ERR_IO 8 // 会话结束,因为网络中断
#define TP_SESS_STAT_ERR_SESSION 9 // 会话结束因为无效的会话ID
#define TP_SESS_STAT_ERR_AUTH_TYPE 10 // 会话结束,因为不被允许的认证方式
#define TP_SESS_STAT_ERR_CREATE_CHANNEL 11 // 会话结束,因为创建通道失败
#define TP_SESS_STAT_STARTED 100 // 已经连接成功了,开始记录录像了
#define TP_SESS_STAT_ERR_START_INTERNAL 104 // 会话结束,因为内部错误
#define TP_SESS_STAT_ERR_START_BAD_PKG 106 // 会话结束,因为收到错误的报文
#define TP_SESS_STAT_ERR_START_RESET 107 // 会话结束因为teleport核心服务重置了
#define TP_SESS_STAT_ERR_START_IO 108 // 会话结束,因为网络中断
#define TP_SESS_STAT_END 9999 // 会话成功结束
//=======================================================
// 授权标记
//=======================================================
#define TP_FLAG_ALL 0xFFFFFFFF
#define TP_FLAG_ALL 0xFFFFFFFF
// 会话记录相关
#define TP_FLAG_RECORD_REPLAY 0x00000001 // 允许记录历史(录像回放)
#define TP_FLAG_RECORD_REAL_TIME 0x00000002 // 允许实时监控
#define TP_FLAG_RECORD_REPLAY 0x00000001 // 允许记录历史(录像回放)
#define TP_FLAG_RECORD_REAL_TIME 0x00000002 // 允许实时监控
// RDP相关
#define TP_FLAG_RDP_DESKTOP 0x00000001 // 允许远程桌面
#define TP_FLAG_RDP_CLIPBOARD 0x00000002 // 允许剪贴板
#define TP_FLAG_RDP_DISK 0x00000004 // 允许磁盘映射
#define TP_FLAG_RDP_APP 0x00000008 // 允许远程APP尚未实现
#define TP_FLAG_RDP_CONSOLE 0x00001000 //允许连接到管理员会话RDP的console选项
#define TP_FLAG_RDP_DESKTOP 0x00000001 // 允许远程桌面
#define TP_FLAG_RDP_CLIPBOARD 0x00000002 // 允许剪贴板
#define TP_FLAG_RDP_DISK 0x00000004 // 允许磁盘映射
#define TP_FLAG_RDP_APP 0x00000008 // 允许远程APP尚未实现
#define TP_FLAG_RDP_CONSOLE 0x00001000 // 允许连接到管理员会话RDP的console选项
// SSH相关
#define TP_FLAG_SSH_SHELL 0x00000001 // 允许SHELL
#define TP_FLAG_SSH_SFTP 0x00000002 // 允许SFTP
#define TP_FLAG_SSH_X11 0x00000004 // 允许X11转发尚未实现
#define TP_FLAG_SSH_EXEC 0x00000008 // 允许exec执行远程命令尚未实现
#define TP_FLAG_SSH_TUNNEL 0x00000010 // allow ssh tunnel. (not impl.)
#define TP_FLAG_SSH_SHELL 0x00000001 // 允许SHELL
#define TP_FLAG_SSH_SFTP 0x00000002 // 允许SFTP
#define TP_FLAG_SSH_X11 0x00000004 // 允许X11转发尚未实现
#define TP_FLAG_SSH_EXEC 0x00000008 // 允许exec执行远程命令尚未实现
#define TP_FLAG_SSH_TUNNEL 0x00000010 // allow ssh tunnel. (not impl.)
//=======================================================
// 错误值
//=======================================================
#define TPE_OK 0 // 成功
#define TPE_OK 0 // 成功
//-------------------------------------------------------
// 通用错误值
//-------------------------------------------------------
#define TPE_NEED_MORE_DATA 1 // 需要更多数据(不一定是错误)
#define TPE_NEED_LOGIN 2 // 需要登录
#define TPE_PRIVILEGE 3 // 没有操作权限
#define TPE_NOT_IMPLEMENT 7 // 功能尚未实现
#define TPE_EXISTS 8 // 目标已经存在
#define TPE_NOT_EXISTS 9 // 目标不存在
#define TPE_NEED_MORE_DATA 1 // 需要更多数据(不一定是错误)
#define TPE_NEED_LOGIN 2 // 需要登录
#define TPE_PRIVILEGE 3 // 没有操作权限
#define TPE_NOT_IMPLEMENT 7 // 功能尚未实现
#define TPE_EXISTS 8 // 目标已经存在
#define TPE_NOT_EXISTS 9 // 目标不存在
// 100~299是通用错误值
#define TPE_FAILED 100 // 内部错误
#define TPE_NETWORK 101 // 网络错误
#define TPE_DATABASE 102 // 数据库操作失败
#define TPE_FAILED 100 // 内部错误
#define TPE_NETWORK 101 // 网络错误
#define TPE_DATABASE 102 // 数据库操作失败
// HTTP请求相关错误
#define TPE_HTTP_METHOD 120 // 无效的请求方法不是GET/POST等或者错误的请求方法例如需要POST却使用GET方式请求
#define TPE_HTTP_URL_ENCODE 121 // URL编码错误无法解码
//#define TPE_HTTP_URI 122 // 无效的URI
#define TPE_HTTP_METHOD 120 // 无效的请求方法不是GET/POST等或者错误的请求方法例如需要POST却使用GET方式请求
#define TPE_HTTP_URL_ENCODE 121 // URL编码错误无法解码
//#define TPE_HTTP_URI 122 // 无效的URI
#define TPE_UNKNOWN_CMD 124 // 未知的命令
#define TPE_JSON_FORMAT 125 // 错误的JSON格式需要JSON格式数据但是却无法按JSON格式解码
#define TPE_PARAM 126 // 参数错误
#define TPE_INVALID_DATA 127 // 数据错误
#define TPE_UNEXPECTED_DATA 128 // 不是期望的数据
#define TPE_UNKNOWN_CMD 124 // 未知的命令
#define TPE_JSON_FORMAT 125 // 错误的JSON格式需要JSON格式数据但是却无法按JSON格式解码
#define TPE_PARAM 126 // 参数错误
#define TPE_INVALID_DATA 127 // 数据错误
#define TPE_UNEXPECTED_DATA 128 // 不是期望的数据
// #define TPE_OPENFILE_ERROR 0x1007 // 无法打开文件
// #define TPE_GETTEMPPATH_ERROR 0x1007
#define TPE_OPENFILE 300
// #define TPE_OPENFILE_ERROR 0x1007 // 无法打开文件
// #define TPE_GETTEMPPATH_ERROR 0x1007
#define TPE_OPENFILE 300
//-------------------------------------------------------
// WEB服务专用错误值
//-------------------------------------------------------
#define TPE_CAPTCHA_EXPIRED 10000 // 验证码已过期
#define TPE_CAPTCHA_MISMATCH 10001 // 验证码错误
#define TPE_OATH_MISMATCH 10002 // 身份验证器动态验证码错误
#define TPE_SYS_MAINTENANCE 10003 // 系统维护中
#define TPE_CAPTCHA_EXPIRED 10000 // 验证码已过期
#define TPE_CAPTCHA_MISMATCH 10001 // 验证码错误
#define TPE_OATH_MISMATCH 10002 // 身份验证器动态验证码错误
#define TPE_SYS_MAINTENANCE 10003 // 系统维护中
#define TPE_USER_LOCKED 10100 // 用户已经被锁定(连续多次错误密码)
#define TPE_USER_DISABLED 10101 // 用户已经被禁用
#define TPE_USER_AUTH 10102 // 身份验证失败
#define TPE_USER_LOCKED 10100 // 用户已经被锁定(连续多次错误密码)
#define TPE_USER_DISABLED 10101 // 用户已经被禁用
#define TPE_USER_AUTH 10102 // 身份验证失败
//-------------------------------------------------------
// 助手程序专用错误值
//-------------------------------------------------------
#define TPE_NO_ASSIST 100000 // 未能检测到助手程序
#define TPE_OLD_ASSIST 100001 // 助手程序版本太低
#define TPE_START_CLIENT 100002 // 无法启动客户端程序(无法创建进程)
#define TPE_NO_ASSIST 100000 // 未能检测到助手程序
#define TPE_OLD_ASSIST 100001 // 助手程序版本太低
#define TPE_START_CLIENT 100002 // 无法启动客户端程序(无法创建进程)
//-------------------------------------------------------
// 核心服务专用错误值
//-------------------------------------------------------
#define TPE_NO_CORE_SERVER 200000 // 未能检测到核心服务
#define TPE_NO_CORE_SERVER 200000 // 未能检测到核心服务
#endif // __TELEPORT_CONST_H__

View File

@ -1,48 +1,46 @@
#include "base_env.h"
TppEnvBase::TppEnvBase()
{}
TppEnvBase::TppEnvBase() :
get_connect_info(nullptr),
free_connect_info(nullptr),
session_begin(nullptr),
session_update(nullptr),
session_end(nullptr) {}
TppEnvBase::~TppEnvBase()
{}
TppEnvBase::~TppEnvBase() = default;
bool TppEnvBase::init(TPP_INIT_ARGS* args)
{
if (NULL == args)
{
EXLOGE("invalid init args(1).\n");
return false;
}
bool TppEnvBase::init(TPP_INIT_ARGS* args) {
if (nullptr == args) {
EXLOGE("invalid init args(1).\n");
return false;
}
EXLOG_USE_LOGGER(args->logger);
EXLOG_USE_LOGGER(args->logger);
exec_path = args->exec_path;
etc_path = args->etc_path;
replay_path = args->replay_path;
exec_path = args->exec_path;
etc_path = args->etc_path;
replay_path = args->replay_path;
get_connect_info = args->func_get_connect_info;
free_connect_info = args->func_free_connect_info;
session_begin = args->func_session_begin;
session_update = args->func_session_update;
session_end = args->func_session_end;
get_connect_info = args->func_get_connect_info;
free_connect_info = args->func_free_connect_info;
session_begin = args->func_session_begin;
session_update = args->func_session_update;
session_end = args->func_session_end;
if (NULL == get_connect_info || NULL == free_connect_info || NULL == session_begin || NULL == session_update || NULL == session_end)
{
EXLOGE("invalid init args(2).\n");
return false;
}
if (!get_connect_info || !free_connect_info || !session_begin || !session_update || !session_end) {
EXLOGE("invalid init args(2).\n");
return false;
}
if (NULL == args->cfg)
{
EXLOGE("invalid init args(3).\n");
return false;
}
if (nullptr == args->cfg) {
EXLOGE("invalid init args(3).\n");
return false;
}
if (!_on_init(args))
{
EXLOGE("invalid init args(4).\n");
return false;
}
if (!_on_init(args)) {
EXLOGE("invalid init args(4).\n");
return false;
}
return true;
return true;
}

View File

@ -3,27 +3,27 @@
#include "protocol_interface.h"
class TppEnvBase
{
class TppEnvBase {
public:
TppEnvBase();
virtual ~TppEnvBase();
TppEnvBase();
bool init(TPP_INIT_ARGS* args);
virtual ~TppEnvBase();
bool init(TPP_INIT_ARGS* args);
public:
ex_wstr exec_path;
ex_wstr etc_path; // 配置文件、SSH服务器的私钥文件的存放路径
ex_wstr replay_path;
ex_wstr exec_path;
ex_wstr etc_path; // 配置文件、SSH服务器的私钥文件的存放路径
ex_wstr replay_path;
TPP_GET_CONNNECT_INFO_FUNC get_connect_info;
TPP_FREE_CONNECT_INFO_FUNC free_connect_info;
TPP_SESSION_BEGIN_FUNC session_begin;
TPP_SESSION_UPDATE_FUNC session_update;
TPP_SESSION_END_FUNC session_end;
TPP_GET_CONNECT_INFO_FUNC get_connect_info;
TPP_FREE_CONNECT_INFO_FUNC free_connect_info;
TPP_SESSION_BEGIN_FUNC session_begin;
TPP_SESSION_UPDATE_FUNC session_update;
TPP_SESSION_END_FUNC session_end;
protected:
virtual bool _on_init(TPP_INIT_ARGS* args) = 0;
virtual bool _on_init(TPP_INIT_ARGS* args) = 0;
};
#endif // __TS_BASE_ENV_H__

View File

@ -14,87 +14,87 @@
# define TPP_API
#endif
#define TPP_CMD_INIT 0x00000000
#define TPP_CMD_SET_RUNTIME_CFG 0x00000005
#define TPP_CMD_KILL_SESSIONS 0x00000006
#define TPP_CMD_INIT 0x00000000
#define TPP_CMD_SET_RUNTIME_CFG 0x00000005
#define TPP_CMD_KILL_SESSIONS 0x00000006
typedef struct TPP_CONNECT_INFO
{
char* sid;
typedef struct TPP_CONNECT_INFO {
char* sid;
// 与此连接信息相关的三个要素的ID
int user_id;
int host_id;
int acc_id;
// 与此连接信息相关的三个要素的ID
int user_id;
int host_id;
int acc_id;
char* user_username; // 申请本次连接的用户名
char* user_username; // 申请本次连接的用户名
char* host_ip; // 真正的远程主机IP如果是直接连接模式则与remote_host_ip相同
char* conn_ip; // 要连接的远程主机的IP如果是端口映射模式则为路由主机的IP
int conn_port; // 要连接的远程主机的端口(如果是端口映射模式,则为路由主机的端口)
char* client_ip;
char* host_ip; // 真正的远程主机IP如果是直接连接模式则与remote_host_ip相同
char* conn_ip; // 要连接的远程主机的IP如果是端口映射模式则为路由主机的IP
int conn_port; // 要连接的远程主机的端口(如果是端口映射模式,则为路由主机的端口)
char* client_ip;
char* acc_username; // 远程主机的账号
char* acc_secret; // 远程主机账号的密码(或者私钥)
char* username_prompt; // for telnet
char* password_prompt; // for telnet
char* acc_username; // 远程主机的账号
char* acc_secret; // 远程主机账号的密码(或者私钥)
char* username_prompt; // for telnet
char* password_prompt; // for telnet
int protocol_type;
int protocol_sub_type;
int protocol_flag;
int record_flag;
int auth_type;
}TPP_CONNECT_INFO;
int protocol_type;
int protocol_sub_type;
int protocol_flag;
int record_flag;
int auth_type;
} TPP_CONNECT_INFO;
typedef TPP_CONNECT_INFO* (*TPP_GET_CONNNECT_INFO_FUNC)(const char* sid);
typedef void(*TPP_FREE_CONNECT_INFO_FUNC)(TPP_CONNECT_INFO* info);
typedef bool(*TPP_SESSION_BEGIN_FUNC)(const TPP_CONNECT_INFO* info, int* db_id);
typedef bool(*TPP_SESSION_UPDATE_FUNC)(int db_id, int protocol_sub_type, int state);
typedef bool(*TPP_SESSION_END_FUNC)(const char* sid, int db_id, int ret);
typedef TPP_CONNECT_INFO* (* TPP_GET_CONNECT_INFO_FUNC)(const char* sid);
typedef void(* TPP_FREE_CONNECT_INFO_FUNC)(TPP_CONNECT_INFO* info);
typedef bool(* TPP_SESSION_BEGIN_FUNC)(const TPP_CONNECT_INFO* info, int* db_id);
typedef bool(* TPP_SESSION_UPDATE_FUNC)(int db_id, int protocol_sub_type, int state);
typedef bool(* TPP_SESSION_END_FUNC)(const char* sid, int db_id, int ret);
typedef struct TPP_INIT_ARGS
{
ExLogger* logger;
ex_wstr exec_path;
ex_wstr etc_path;
ex_wstr replay_path;
ExIniFile* cfg;
typedef struct TPP_INIT_ARGS {
ExLogger* logger;
ex_wstr exec_path;
ex_wstr etc_path;
ex_wstr replay_path;
ExIniFile* cfg;
TPP_GET_CONNNECT_INFO_FUNC func_get_connect_info;
TPP_FREE_CONNECT_INFO_FUNC func_free_connect_info;
TPP_SESSION_BEGIN_FUNC func_session_begin;
TPP_SESSION_UPDATE_FUNC func_session_update;
TPP_SESSION_END_FUNC func_session_end;
}TPP_INIT_ARGS;
// typedef struct TPP_SET_CFG_ARGS {
// ex_u32 noop_timeout; // as second.
// }TPP_SET_CFG_ARGS;
TPP_GET_CONNECT_INFO_FUNC func_get_connect_info;
TPP_FREE_CONNECT_INFO_FUNC func_free_connect_info;
TPP_SESSION_BEGIN_FUNC func_session_begin;
TPP_SESSION_UPDATE_FUNC func_session_update;
TPP_SESSION_END_FUNC func_session_end;
} TPP_INIT_ARGS;
#ifdef __cplusplus
extern "C"
{
#endif
TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args);
TPP_API ex_rv tpp_start(void);
TPP_API ex_rv tpp_stop(void);
TPP_API void tpp_timer(void);
// TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args);
TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args);
TPP_API ex_rv tpp_start(void);
TPP_API ex_rv tpp_stop(void);
TPP_API void tpp_timer(void);
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param);
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param);
#ifdef __cplusplus
}
#endif
typedef ex_rv (*TPP_INIT_FUNC)(TPP_INIT_ARGS* init_args);
typedef ex_rv (*TPP_START_FUNC)(void);
typedef ex_rv(*TPP_STOP_FUNC)(void);
typedef void(*TPP_TIMER_FUNC)(void);
// typedef void(*TPP_SET_CFG_FUNC)(TPP_SET_CFG_ARGS* cfg_args);
typedef ex_rv (* TPP_INIT_FUNC)(TPP_INIT_ARGS* init_args);
typedef ex_rv(*TPP_COMMAND_FUNC)(ex_u32 cmd, const char* param); // param is a JSON formatted string.
typedef ex_rv (* TPP_START_FUNC)(void);
typedef ex_rv(* TPP_STOP_FUNC)(void);
typedef void(* TPP_TIMER_FUNC)(void);
// param: a JSON formatted string.
typedef ex_rv(* TPP_COMMAND_FUNC)(ex_u32 cmd, const char* param);
#endif // __TP_PROTOCOL_INTERFACE_H__

View File

@ -28,7 +28,7 @@ static ex_u8 g_run_type = RUN_UNKNOWN;
#define EOM_CORE_SERVICE_NAME L"Teleport Core Service"
static bool _run_daemon(void);
static bool _run_daemon();
#ifdef EX_OS_WIN32
static int service_install()
@ -113,7 +113,7 @@ static bool _process_cmd_line(int argc, wchar_t** argv)
}
static int _main_loop(void)
static int _main_loop()
{
if (g_run_type == RUN_CORE)
return ts_main();
@ -163,7 +163,7 @@ int _app_main(int argc, wchar_t** argv)
if (g_run_type == RUN_STOP) {
char url[1024] = {0};
ex_strformat(url, 1023, "http://%s:%d/rpc?{\"method\":\"exit\"}", g_env.rpc_bind_ip.c_str(), g_env.rpc_bind_port);
ex_strformat(url, 1023, R"(http://%s:%d/rpc?{"method":"exit"})", g_env.rpc_bind_ip.c_str(), g_env.rpc_bind_port);
ex_astr body;
ts_http_get(url, body);
ex_printf("%s\n", body.c_str());
@ -195,8 +195,8 @@ int _app_main(int argc, wchar_t** argv)
#endif
static SERVICE_STATUS g_ServiceStatus = { 0 };
static SERVICE_STATUS_HANDLE g_hServiceStatusHandle = NULL;
HANDLE g_hWorkerThread = NULL;
static SERVICE_STATUS_HANDLE g_hServiceStatusHandle = nullptr;
HANDLE g_hWorkerThread = nullptr;
VOID WINAPI service_main(DWORD argc, wchar_t** argv);
void WINAPI service_handler(DWORD fdwControl);
@ -212,9 +212,9 @@ int main()
wchar_t** _argv = ::CommandLineToArgvW(szCmdLine, &_argc); //拆分命令行参数字符串;
ret = _app_main(_argc, _argv);
LocalFree(_argv);
_argv = NULL;
_argv = nullptr;
return ret;
}
@ -224,8 +224,8 @@ static bool _run_daemon(void)
SERVICE_TABLE_ENTRY DispatchTable[2];
DispatchTable[0].lpServiceName = EOM_CORE_SERVICE_NAME;
DispatchTable[0].lpServiceProc = service_main;
DispatchTable[1].lpServiceName = NULL;
DispatchTable[1].lpServiceProc = NULL;
DispatchTable[1].lpServiceName = nullptr;
DispatchTable[1].lpServiceProc = nullptr;
if (!StartServiceCtrlDispatcher(DispatchTable))
{
@ -262,7 +262,7 @@ static void WINAPI service_handler(DWORD fdwControl)
if (g_hWorkerThread)
{
// TerminateThread(g_hWorkerThread, 1);
// g_hWorkerThread = NULL;
// g_hWorkerThread = nullptr;
g_exit_flag = true;
g_ServiceStatus.dwWin32ExitCode = 0;
@ -307,8 +307,8 @@ VOID WINAPI service_main(DWORD argc, wchar_t** argv)
}
DWORD tid = 0;
g_hWorkerThread = CreateThread(NULL, 0, service_thread_func, NULL, 0, &tid);
if (NULL == g_hWorkerThread)
g_hWorkerThread = CreateThread(nullptr, 0, service_thread_func, nullptr, 0, &tid);
if (nullptr == g_hWorkerThread)
{
EXLOGE_WIN("CreateThread()");
@ -345,7 +345,7 @@ int main(int argc, char** argv)
memset(&act, 0, sizeof(act));
act.sa_sigaction = _sig_handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &act, NULL);
sigaction(SIGINT, &act, nullptr);
wchar_t** wargv = ex_make_wargv(argc, argv);
int ret = _app_main(argc, wargv);
@ -359,12 +359,12 @@ void _sig_handler(int signum, siginfo_t* info, void* ptr)
{
if (signum == SIGINT || signum == SIGTERM)
{
EXLOGW("\n[core] received signal SIGINT, exit now.\n");
EXLOGW("[core] received signal SIGINT, exit now.\n");
g_exit_flag = true;
}
}
static bool _run_daemon(void)
static bool _run_daemon()
{
pid_t pid = fork();
if (pid < 0)
@ -382,7 +382,7 @@ static bool _run_daemon(void)
{
EXLOGE("[core] setsid() failed.\n");
assert(0);
exit(EXIT_FAILURE);
// exit(EXIT_FAILURE);
}
umask(0);
@ -399,14 +399,14 @@ static bool _run_daemon(void)
}
// now I'm second children.
int ret = chdir("/");
chdir("/");
close(STDIN_FILENO);
int stdfd = open("/dev/null", O_RDWR);
int std_fd = open("/dev/null", O_RDWR);
close(STDOUT_FILENO);
close(STDERR_FILENO);
dup2(stdfd, STDOUT_FILENO);
dup2(stdfd, STDERR_FILENO);
dup2(std_fd, STDOUT_FILENO);
dup2(std_fd, STDERR_FILENO);
return true;
}

View File

@ -1,126 +1,108 @@
#include "tp_tpp_mgr.h"
#include "ts_main.h"
// #include "ts_session.h"
// #include "ts_http_rpc.h"
// #include "ts_web_rpc.h"
#include "ts_env.h"
// #include <mbedtls/platform.h>
// #include <mbedtls/debug.h>
TppManager g_tpp_mgr;
extern ExLogger g_ex_logger;
bool TppManager::load_tpp(const ex_wstr& libname)
{
ex_wstr filename;
bool TppManager::load_tpp(const ex_wstr& libname) {
ex_wstr filename;
#ifdef EX_OS_WIN32
filename = libname + L".dll";
filename = libname + L".dll";
#elif defined (EX_OS_LINUX)
filename = L"lib";
filename += libname;
filename += L".so";
filename += L".so";
#elif defined (EX_OS_MACOS)
filename = L"lib";
filename = L"lib";
filename += libname;
filename += L".dylib";
filename += L".dylib";
#endif
ex_wstr libfile = g_env.m_exec_path;
ex_path_join(libfile, false, filename.c_str(), NULL);
EXLOGV(L"[core] load protocol lib: %ls\n", libfile.c_str());
ex_wstr lib_file = g_env.m_exec_path;
ex_path_join(lib_file, false, filename.c_str(), nullptr);
EXLOGI(L"[core] load protocol lib: %ls\n", lib_file.c_str());
TPP_LIB* lib = new TPP_LIB;
auto lib = new TPP_LIB;
lib->dylib = ex_dlopen(libfile.c_str());
if (NULL == lib->dylib)
{
EXLOGE(L"[core] load dylib `%ls` failed.\n", libfile.c_str());
delete lib;
return false;
}
lib->dylib = ex_dlopen(lib_file.c_str());
if (nullptr == lib->dylib) {
EXLOGE(L"[core] load dylib `%ls` failed.\n", lib_file.c_str());
delete lib;
return false;
}
#ifdef EX_OS_WIN32
lib->init = (TPP_INIT_FUNC)GetProcAddress(lib->dylib, "tpp_init");
lib->start = (TPP_START_FUNC)GetProcAddress(lib->dylib, "tpp_start");
lib->stop = (TPP_STOP_FUNC)GetProcAddress(lib->dylib, "tpp_stop");
lib->timer = (TPP_TIMER_FUNC)GetProcAddress(lib->dylib, "tpp_timer");
// lib->set_cfg = (TPP_SET_CFG_FUNC)GetProcAddress(lib->dylib, "tpp_set_cfg");
lib->command = (TPP_COMMAND_FUNC)GetProcAddress(lib->dylib, "tpp_command");
lib->init = (TPP_INIT_FUNC)GetProcAddress(lib->dylib, "tpp_init");
lib->start = (TPP_START_FUNC)GetProcAddress(lib->dylib, "tpp_start");
lib->stop = (TPP_STOP_FUNC)GetProcAddress(lib->dylib, "tpp_stop");
lib->timer = (TPP_TIMER_FUNC)GetProcAddress(lib->dylib, "tpp_timer");
lib->command = (TPP_COMMAND_FUNC)GetProcAddress(lib->dylib, "tpp_command");
#else
lib->init = (TPP_INIT_FUNC)dlsym(lib->dylib, "tpp_init");
lib->start = (TPP_START_FUNC)dlsym(lib->dylib, "tpp_start");
lib->stop = (TPP_STOP_FUNC)dlsym(lib->dylib, "tpp_stop");
lib->timer = (TPP_TIMER_FUNC)dlsym(lib->dylib, "tpp_timer");
// lib->set_cfg = (TPP_SET_CFG_FUNC)dlsym(lib->dylib, "tpp_set_cfg");
lib->command = (TPP_COMMAND_FUNC)dlsym(lib->dylib, "tpp_command");
lib->init = (TPP_INIT_FUNC) dlsym(lib->dylib, "tpp_init");
lib->start = (TPP_START_FUNC) dlsym(lib->dylib, "tpp_start");
lib->stop = (TPP_STOP_FUNC) dlsym(lib->dylib, "tpp_stop");
lib->timer = (TPP_TIMER_FUNC) dlsym(lib->dylib, "tpp_timer");
lib->command = (TPP_COMMAND_FUNC) dlsym(lib->dylib, "tpp_command");
#endif
if (
lib->init == NULL
|| lib->start == NULL
|| lib->stop == NULL
|| lib->timer == NULL
//|| lib->set_cfg == NULL
|| lib->command == NULL
)
{
EXLOGE(L"[core] load dylib `%ls` failed, can not locate all functions.\n", libfile.c_str());
delete lib;
return false;
}
if (
lib->init == nullptr
|| lib->start == nullptr
|| lib->stop == nullptr
|| lib->timer == nullptr
|| lib->command == nullptr
) {
EXLOGE(L"[core] load dylib `%ls` failed, can not locate all functions.\n", lib_file.c_str());
delete lib;
return false;
}
TPP_INIT_ARGS init_args;
init_args.logger = &g_ex_logger;
init_args.exec_path = g_env.m_exec_path;
init_args.etc_path = g_env.m_etc_path;
init_args.replay_path = g_env.m_replay_path;
init_args.cfg = &g_env.get_ini();
init_args.func_get_connect_info = tpp_get_connect_info;
init_args.func_free_connect_info = tpp_free_connect_info;
init_args.func_session_begin = tpp_session_begin;
init_args.func_session_update = tpp_session_update;
init_args.func_session_end = tpp_session_end;
TPP_INIT_ARGS init_args;
init_args.logger = &g_ex_logger;
init_args.exec_path = g_env.m_exec_path;
init_args.etc_path = g_env.m_etc_path;
init_args.replay_path = g_env.m_replay_path;
init_args.cfg = &g_env.get_ini();
init_args.func_get_connect_info = tpp_get_connect_info;
init_args.func_free_connect_info = tpp_free_connect_info;
init_args.func_session_begin = tpp_session_begin;
init_args.func_session_update = tpp_session_update;
init_args.func_session_end = tpp_session_end;
if (EXRV_OK != lib->init(&init_args))
{
EXLOGE(L"[core] failed to init protocol `%ls`.\n", libname.c_str());
delete lib;
return false;
}
if (EXRV_OK != lib->start())
{
EXLOGE(L"[core] failed to start protocol `%ls`.\n", libname.c_str());
delete lib;
return false;
}
if (EXRV_OK != lib->init(&init_args)) {
EXLOGE(L"[core] failed to init protocol `%ls`.\n", libname.c_str());
delete lib;
return false;
}
if (EXRV_OK != lib->start()) {
EXLOGE(L"[core] failed to start protocol `%ls`.\n", libname.c_str());
delete lib;
return false;
}
m_libs.push_back(lib);
return true;
m_libs.push_back(lib);
return true;
}
void TppManager::stop_all(void) {
tpp_libs::iterator it = m_libs.begin();
for (; it != m_libs.end(); ++it)
{
(*it)->stop();
}
void TppManager::stop_all() {
for (auto& lib : m_libs) {
lib->stop();
}
}
void TppManager::timer(void) {
tpp_libs::iterator it = m_libs.begin();
for (; it != m_libs.end(); ++it)
{
(*it)->timer();
}
void TppManager::timer() {
for (auto& lib : m_libs) {
lib->timer();
}
}
// void TppManager::set_config(int noop_timeout) {
//
//
// TPP_SET_CFG_ARGS args;
// args.noop_timeout = noop_timeout;
//
//
// tpp_libs::iterator it = m_libs.begin();
// for (; it != m_libs.end(); ++it)
// {
@ -129,16 +111,13 @@ void TppManager::timer(void) {
// }
void TppManager::set_runtime_config(const ex_astr& sp) {
tpp_libs::iterator it = m_libs.begin();
for (; it != m_libs.end(); ++it) {
(*it)->command(TPP_CMD_SET_RUNTIME_CFG, sp.c_str());
}
for (auto& lib : m_libs) {
lib->command(TPP_CMD_SET_RUNTIME_CFG, sp.c_str());
}
}
void TppManager::kill_sessions(const ex_astr& sp) {
tpp_libs::iterator it = m_libs.begin();
for (; it != m_libs.end(); ++it) {
(*it)->command(TPP_CMD_KILL_SESSIONS, sp.c_str());
}
for (auto& lib : m_libs) {
lib->command(TPP_CMD_KILL_SESSIONS, sp.c_str());
}
}

View File

@ -1,65 +1,65 @@
#ifndef __TP_TPP_MGR_H__
#define __TP_TPP_MGR_H__
#include "../common/protocol_interface.h"
#include <ex.h>
typedef struct TPP_LIB
{
TPP_LIB()
{
dylib = NULL;
init = NULL;
}
~TPP_LIB()
{
if (NULL != dylib)
ex_dlclose(dylib);
dylib = NULL;
}
#ifndef __TP_TPP_MGR_H__
#define __TP_TPP_MGR_H__
EX_DYLIB_HANDLE dylib;
TPP_INIT_FUNC init;
TPP_START_FUNC start;
TPP_STOP_FUNC stop;
TPP_TIMER_FUNC timer;
// TPP_SET_CFG_FUNC set_cfg;
#include "../common/protocol_interface.h"
TPP_COMMAND_FUNC command;
}TPP_LIB;
#include <ex.h>
typedef struct TPP_LIB {
TPP_LIB() :
dylib(nullptr),
init(nullptr),
start(nullptr),
stop(nullptr),
timer(nullptr),
command(nullptr) {
}
~TPP_LIB() {
if (nullptr != dylib)
ex_dlclose(dylib);
dylib = nullptr;
}
EX_DYLIB_HANDLE dylib;
TPP_INIT_FUNC init;
TPP_START_FUNC start;
TPP_STOP_FUNC stop;
TPP_TIMER_FUNC timer;
TPP_COMMAND_FUNC command;
} TPP_LIB;
typedef std::list<TPP_LIB*> tpp_libs;
class TppManager
{
class TppManager {
public:
TppManager()
{
}
~TppManager()
{
tpp_libs::iterator it = m_libs.begin();
for (; it != m_libs.end(); ++it)
{
delete (*it);
}
m_libs.clear();
}
TppManager() = default;
bool load_tpp(const ex_wstr& libfile);
void stop_all(void);
void timer(void); // ´óÔ¼1Ãëµ÷ÓÃÒ»´Î
int count(void) { return m_libs.size(); }
~TppManager() {
for (auto lib : m_libs) {
delete lib;
}
m_libs.clear();
}
void set_config(int noop_timeout);
void set_runtime_config(const ex_astr& sp);
void kill_sessions(const ex_astr& sp);
bool load_tpp(const ex_wstr& lib_file);
void stop_all();
void timer(); // ´óÔ¼1Ãëµ÷ÓÃÒ»´Î
int count() {
return m_libs.size();
}
void set_runtime_config(const ex_astr& sp);
void kill_sessions(const ex_astr& sp);
private:
tpp_libs m_libs;
tpp_libs m_libs;
};
extern TppManager g_tpp_mgr;
#endif // __TP_TPP_MGR_H__
#endif // __TP_TPP_MGR_H__

View File

@ -6,52 +6,53 @@
#include "tp_tpp_mgr.h"
#include <mbedtls/platform.h>
#include <mbedtls/debug.h>
// #include <mbedtls/debug.h>
bool g_exit_flag = false;
TPP_CONNECT_INFO *tpp_get_connect_info(const char *sid) {
TS_CONNECT_INFO sinfo;
bool ret = g_session_mgr.get_connect_info(sid, sinfo);
TPP_CONNECT_INFO* tpp_get_connect_info(const char* sid) {
TS_CONNECT_INFO connect_info;
bool ret = g_session_mgr.get_connect_info(sid, connect_info);
if (!ret)
return NULL;
return nullptr;
TPP_CONNECT_INFO *info = (TPP_CONNECT_INFO *) calloc(1, sizeof(TPP_CONNECT_INFO));
auto info = (TPP_CONNECT_INFO*) calloc(1, sizeof(TPP_CONNECT_INFO));
info->sid = (char *) calloc(1, sinfo.sid.length() + 1);
ex_strcpy(info->sid, sinfo.sid.length() + 1, sinfo.sid.c_str());
info->user_username = (char *) calloc(1, sinfo.user_username.length() + 1);
ex_strcpy(info->user_username, sinfo.user_username.length() + 1, sinfo.user_username.c_str());
info->host_ip = (char *) calloc(1, sinfo.host_ip.length() + 1);
ex_strcpy(info->host_ip, sinfo.host_ip.length() + 1, sinfo.host_ip.c_str());
info->conn_ip = (char *) calloc(1, sinfo.conn_ip.length() + 1);
ex_strcpy(info->conn_ip, sinfo.conn_ip.length() + 1, sinfo.conn_ip.c_str());
info->client_ip = (char *) calloc(1, sinfo.client_ip.length() + 1);
ex_strcpy(info->client_ip, sinfo.client_ip.length() + 1, sinfo.client_ip.c_str());
info->acc_username = (char *) calloc(1, sinfo.acc_username.length() + 1);
ex_strcpy(info->acc_username, sinfo.acc_username.length() + 1, sinfo.acc_username.c_str());
info->acc_secret = (char *) calloc(1, sinfo.acc_secret.length() + 1);
ex_strcpy(info->acc_secret, sinfo.acc_secret.length() + 1, sinfo.acc_secret.c_str());
info->username_prompt = (char *) calloc(1, sinfo.username_prompt.length() + 1);
ex_strcpy(info->username_prompt, sinfo.username_prompt.length() + 1, sinfo.username_prompt.c_str());
info->password_prompt = (char *) calloc(1, sinfo.password_prompt.length() + 1);
ex_strcpy(info->password_prompt, sinfo.password_prompt.length() + 1, sinfo.password_prompt.c_str());
info->sid = (char*) calloc(1, connect_info.sid.length() + 1);
ex_strcpy(info->sid, connect_info.sid.length() + 1, connect_info.sid.c_str());
info->user_username = (char*) calloc(1, connect_info.user_username.length() + 1);
ex_strcpy(info->user_username, connect_info.user_username.length() + 1, connect_info.user_username.c_str());
info->host_ip = (char*) calloc(1, connect_info.host_ip.length() + 1);
ex_strcpy(info->host_ip, connect_info.host_ip.length() + 1, connect_info.host_ip.c_str());
info->conn_ip = (char*) calloc(1, connect_info.conn_ip.length() + 1);
ex_strcpy(info->conn_ip, connect_info.conn_ip.length() + 1, connect_info.conn_ip.c_str());
info->client_ip = (char*) calloc(1, connect_info.client_ip.length() + 1);
ex_strcpy(info->client_ip, connect_info.client_ip.length() + 1, connect_info.client_ip.c_str());
info->acc_username = (char*) calloc(1, connect_info.acc_username.length() + 1);
ex_strcpy(info->acc_username, connect_info.acc_username.length() + 1, connect_info.acc_username.c_str());
info->acc_secret = (char*) calloc(1, connect_info.acc_secret.length() + 1);
ex_strcpy(info->acc_secret, connect_info.acc_secret.length() + 1, connect_info.acc_secret.c_str());
info->username_prompt = (char*) calloc(1, connect_info.username_prompt.length() + 1);
ex_strcpy(info->username_prompt, connect_info.username_prompt.length() + 1, connect_info.username_prompt.c_str());
info->password_prompt = (char*) calloc(1, connect_info.password_prompt.length() + 1);
ex_strcpy(info->password_prompt, connect_info.password_prompt.length() + 1, connect_info.password_prompt.c_str());
info->user_id = sinfo.user_id;
info->host_id = sinfo.host_id;
info->acc_id = sinfo.acc_id;
info->conn_port = sinfo.conn_port;
info->protocol_type = sinfo.protocol_type;
info->protocol_sub_type = sinfo.protocol_sub_type;
info->protocol_flag = sinfo.protocol_flag;
info->record_flag = sinfo.record_flag;
info->auth_type = sinfo.auth_type;
info->user_id = connect_info.user_id;
info->host_id = connect_info.host_id;
info->acc_id = connect_info.acc_id;
info->conn_port = connect_info.conn_port;
info->protocol_type = connect_info.protocol_type;
info->protocol_sub_type = connect_info.protocol_sub_type;
info->protocol_flag = connect_info.protocol_flag;
info->record_flag = connect_info.record_flag;
info->auth_type = connect_info.auth_type;
return info;
}
void tpp_free_connect_info(TPP_CONNECT_INFO *info) {
if (NULL == info)
void tpp_free_connect_info(TPP_CONNECT_INFO* info) {
if (nullptr == info)
return;
g_session_mgr.free_connect_info(info->sid);
@ -68,190 +69,46 @@ void tpp_free_connect_info(TPP_CONNECT_INFO *info) {
free(info);
}
bool tpp_session_begin(const TPP_CONNECT_INFO *info, int *db_id) {
if (NULL == info || NULL == db_id)
bool tpp_session_begin(const TPP_CONNECT_INFO* info, int* db_id) {
if (nullptr == info || nullptr == db_id)
return false;
TS_CONNECT_INFO sinfo;
sinfo.sid = info->sid;
sinfo.user_id = info->user_id;
sinfo.host_id = info->host_id;
sinfo.acc_id = info->acc_id;
sinfo.user_username = info->user_username;
sinfo.host_ip = info->host_ip;
sinfo.conn_ip = info->conn_ip;
sinfo.client_ip = info->client_ip;
sinfo.acc_username = info->acc_username;
TS_CONNECT_INFO connect_info;
connect_info.sid = info->sid;
connect_info.user_id = info->user_id;
connect_info.host_id = info->host_id;
connect_info.acc_id = info->acc_id;
connect_info.user_username = info->user_username;
connect_info.host_ip = info->host_ip;
connect_info.conn_ip = info->conn_ip;
connect_info.client_ip = info->client_ip;
connect_info.acc_username = info->acc_username;
sinfo.conn_port = info->conn_port;
sinfo.protocol_type = info->protocol_type;
sinfo.protocol_sub_type = info->protocol_sub_type;
sinfo.auth_type = info->auth_type;
connect_info.conn_port = info->conn_port;
connect_info.protocol_type = info->protocol_type;
connect_info.protocol_sub_type = info->protocol_sub_type;
connect_info.auth_type = info->auth_type;
return ts_web_rpc_session_begin(sinfo, *db_id);
return ts_web_rpc_session_begin(connect_info, *db_id);
}
bool tpp_session_update(int db_id, int protocol_sub_type, int state) {
return ts_web_rpc_session_update(db_id, protocol_sub_type, state);
}
bool tpp_session_end(const char *sid, int db_id, int ret) {
bool tpp_session_end(const char* sid, int db_id, int ret) {
return ts_web_rpc_session_end(sid, db_id, ret);
}
// typedef struct TPP_LIB
// {
// TPP_LIB()
// {
// dylib = NULL;
// init = NULL;
// }
// ~TPP_LIB()
// {
// if (NULL != dylib)
// ex_dlclose(dylib);
// dylib = NULL;
// }
//
// EX_DYLIB_HANDLE dylib;
// TPP_INIT_FUNC init;
// TPP_START_FUNC start;
// TPP_STOP_FUNC stop;
// TPP_TIMER_FUNC timer;
// }TPP_LIB;
//
// typedef std::list<TPP_LIB*> tpp_libs;
//
// class TppManager
// {
// public:
// TppManager()
// {
// }
// ~TppManager()
// {
// tpp_libs::iterator it = m_libs.begin();
// for (; it != m_libs.end(); ++it)
// {
// delete (*it);
// }
// m_libs.clear();
// }
//
// bool load_tpp(const ex_wstr& libfile);
// void stop_all(void);
// void timer(void); // ´óÔ¼1Ãëµ÷ÓÃÒ»´Î
// int count(void) { return m_libs.size(); }
//
// private:
// tpp_libs m_libs;
// };
//
// static TppManager g_tpp_mgr;
// extern ExLogger g_ex_logger;
//
// bool TppManager::load_tpp(const ex_wstr& libname)
// {
// ex_wstr filename;
// #ifdef EX_OS_WIN32
// filename = libname + L".dll";
// #elif defined (EX_OS_LINUX)
// filename = L"lib";
// filename += libname;
// filename += L".so";
// #elif defined (EX_OS_MACOS)
// filename = L"lib";
// filename += libname;
// filename += L".dylib";
// #endif
//
// ex_wstr libfile = g_env.m_exec_path;
// ex_path_join(libfile, false, filename.c_str(), NULL);
// EXLOGV(L"[core] load protocol lib: %ls\n", libfile.c_str());
//
// TPP_LIB* lib = new TPP_LIB;
//
// lib->dylib = ex_dlopen(libfile.c_str());
// if (NULL == lib->dylib)
// {
// EXLOGE(L"[core] load dylib `%ls` failed.\n", libfile.c_str());
// delete lib;
// return false;
// }
//
// #ifdef EX_OS_WIN32
// lib->init = (TPP_INIT_FUNC)GetProcAddress(lib->dylib, "tpp_init");
// lib->start = (TPP_START_FUNC)GetProcAddress(lib->dylib, "tpp_start");
// lib->stop = (TPP_STOP_FUNC)GetProcAddress(lib->dylib, "tpp_stop");
// lib->timer = (TPP_TIMER_FUNC)GetProcAddress(lib->dylib, "tpp_timer");
// #else
// lib->init = (TPP_INIT_FUNC)dlsym(lib->dylib, "tpp_init");
// lib->start = (TPP_START_FUNC)dlsym(lib->dylib, "tpp_start");
// lib->stop = (TPP_STOP_FUNC)dlsym(lib->dylib, "tpp_stop");
// lib->timer = (TPP_TIMER_FUNC)dlsym(lib->dylib, "tpp_timer");
// #endif
//
// if (lib->init == NULL || lib->start == NULL || lib->stop == NULL || lib->timer == NULL)
// {
// EXLOGE(L"[core] load dylib `%ls` failed, can not locate all functions.\n", libfile.c_str());
// delete lib;
// return false;
// }
//
// TPP_INIT_ARGS init_args;
// init_args.logger = &g_ex_logger;
// init_args.exec_path = g_env.m_exec_path;
// init_args.etc_path = g_env.m_etc_path;
// init_args.replay_path = g_env.m_replay_path;
// init_args.cfg = &g_env.get_ini();
// init_args.func_get_connect_info = tpp_get_connect_info;
// init_args.func_free_connect_info = tpp_free_connect_info;
// init_args.func_session_begin = tpp_session_begin;
// init_args.func_session_update = tpp_session_update;
// init_args.func_session_end = tpp_session_end;
//
// if (EXRV_OK != lib->init(&init_args))
// {
// EXLOGE(L"[core] failed to init protocol `%ls`.\n", libname.c_str());
// delete lib;
// return false;
// }
// if (EXRV_OK != lib->start())
// {
// EXLOGE(L"[core] failed to start protocol `%ls`.\n", libname.c_str());
// delete lib;
// return false;
// }
//
// m_libs.push_back(lib);
// return true;
// }
//
// void TppManager::stop_all(void) {
// tpp_libs::iterator it = m_libs.begin();
// for (; it != m_libs.end(); ++it)
// {
// (*it)->stop();
// }
// }
//
// void TppManager::timer(void) {
// tpp_libs::iterator it = m_libs.begin();
// for (; it != m_libs.end(); ++it)
// {
// (*it)->timer();
// }
// }
int ts_main() {
ExIniFile& ini = g_env.get_ini();
int ts_main(void) {
ExIniFile &ini = g_env.get_ini();
EXLOGI(L"\n");
EXLOGI(L"###############################################################\n");
EXLOGI("\n");
EXLOGI("###############################################################\n");
EXLOGI(L"Load config file: %ls.\n", ini.get_filename().c_str());
EXLOGI(L"Teleport Core Server starting ...\n");
EXLOGI("Teleport Core Server starting ...\n");
ex_ini_sections &secs = ini.GetAllSections();
ex_ini_sections& secs = ini.GetAllSections();
TsHttpRpc rpc;
// 枚举配置文件中的[protocol-xxx]小节,加载对应的协议动态库
@ -259,18 +116,18 @@ int ts_main(void) {
do {
if (!g_session_mgr.start()) {
EXLOGE(L"[core] failed to start session-id manager.\n");
EXLOGE("[core] failed to start session-id manager.\n");
all_ok = false;
break;
}
if (!rpc.init() || !rpc.start()) {
EXLOGE(L"[core] rpc init/start failed.\n");
EXLOGE("[core] rpc init/start failed.\n");
all_ok = false;
break;
}
ex_ini_sections::iterator it = secs.begin();
auto it = secs.begin();
for (; it != secs.end(); ++it) {
if (it->first.length() > 9 && 0 == wcsncmp(it->first.c_str(), L"protocol-", 9)) {
ex_wstr libname;
@ -280,7 +137,7 @@ int ts_main(void) {
bool enabled = false;
it->second->GetBool(L"enabled", enabled, false);
if (!enabled) {
EXLOGV(L"[core] `%ls` not enabled.\n", libname.c_str());
EXLOGW(L"[core] `%ls` not enabled.\n", libname.c_str());
continue;
}
@ -291,7 +148,7 @@ int ts_main(void) {
}
}
} while (0);
} while (false);
if (0 == g_tpp_mgr.count()) {
all_ok = false;
@ -304,17 +161,19 @@ int ts_main(void) {
if (!g_exit_flag) {
ts_web_rpc_register_core();
EXLOGV("[core] ---- initialized, ready for service ----\n");
EXLOGI("[core] ---- initialized, ready for service ----\n");
while (!g_exit_flag) {
ex_sleep_ms(1000);
g_tpp_mgr.timer();
}
}
EXLOGW("[core] try to stop all thread and exit.\n");
EXLOGI("[core] try to stop all thread and exit.\n");
g_tpp_mgr.stop_all();
rpc.stop();
g_session_mgr.stop();
EXLOGI("[core] done.\n");
return 0;
}

View File

@ -3,13 +3,13 @@
#include "../common/protocol_interface.h"
int ts_main(void);
int ts_main();
TPP_CONNECT_INFO* tpp_get_connect_info(const char* sid);
void tpp_free_connect_info(TPP_CONNECT_INFO* info);
bool tpp_session_begin(const TPP_CONNECT_INFO* info, int* db_id);
bool tpp_session_update(int db_id, int protocol_sub_type, int state);
bool tpp_session_end(const char* sid, int db_id, int ret);
TPP_CONNECT_INFO* tpp_get_connect_info(const char* sid);
void tpp_free_connect_info(TPP_CONNECT_INFO* info);
bool tpp_session_begin(const TPP_CONNECT_INFO* info, int* db_id);
bool tpp_session_update(int db_id, int protocol_sub_type, int state);
bool tpp_session_end(const char* sid, int db_id, int ret);
#endif // __TS_MAIN_H__

View File

@ -11,7 +11,7 @@ TsSessionManager::TsSessionManager() :
}
TsSessionManager::~TsSessionManager() {
ts_connections::iterator it_conn = m_connections.begin();
auto it_conn = m_connections.begin();
for (; it_conn != m_connections.end(); ++it_conn) {
EXLOGD("[core] m_connections not clean: %s, %s\n", it_conn->first.c_str(), it_conn->second->acc_username.c_str());
delete it_conn->second;
@ -19,7 +19,7 @@ TsSessionManager::~TsSessionManager() {
m_connections.clear();
}
void TsSessionManager::_thread_loop(void) {
void TsSessionManager::_thread_loop() {
for (;;) {
ex_sleep_ms(1000);
if (m_need_stop)
@ -28,13 +28,13 @@ void TsSessionManager::_thread_loop(void) {
}
}
void TsSessionManager::_remove_expired_connect_info(void) {
void TsSessionManager::_remove_expired_connect_info() {
// 超过15秒未进行连接的connect-info会被移除
ExThreadSmartLock locker(m_lock);
ex_u64 _now = ex_get_tick_count();
ts_connections::iterator it = m_connections.begin();
auto it = m_connections.begin();
for (; it != m_connections.end();) {
//EXLOGD("[core] check expired connect info: [%s] %d, %d %d %d\n", it->first.c_str(), it->second->ref_count, int(_now), int(it->second->ticket_start), int(_now - it->second->ticket_start));
if (it->second->ref_count == 0 && _now - 15000 > it->second->ticket_start) {
@ -42,16 +42,17 @@ void TsSessionManager::_remove_expired_connect_info(void) {
delete it->second;
m_connections.erase(it++);
EXLOGD("[core] there are %d connection info exists.\n", m_connections.size());
} else {
}
else {
++it;
}
}
}
bool TsSessionManager::get_connect_info(const ex_astr &sid, TS_CONNECT_INFO &info) {
bool TsSessionManager::get_connect_info(const ex_astr& sid, TS_CONNECT_INFO& info) {
ExThreadSmartLock locker(m_lock);
ts_connections::iterator it = m_connections.find(sid);
auto it = m_connections.find(sid);
if (it == m_connections.end())
return false;
@ -79,10 +80,10 @@ bool TsSessionManager::get_connect_info(const ex_astr &sid, TS_CONNECT_INFO &inf
return true;
}
bool TsSessionManager::free_connect_info(const ex_astr &sid) {
bool TsSessionManager::free_connect_info(const ex_astr& sid) {
ExThreadSmartLock locker(m_lock);
ts_connections::iterator it = m_connections.find(sid);
auto it = m_connections.find(sid);
if (it == m_connections.end())
return false;
@ -97,7 +98,8 @@ bool TsSessionManager::free_connect_info(const ex_astr &sid) {
m_connections.erase(it);
EXLOGD("[core] there are %d connection info exists.\n", m_connections.size());
}
} else {
}
else {
if (it->second->ref_count == 1)
it->second->ref_count = 0;
it->second->ticket_start = ex_get_tick_count() + 45000; // 我们将时间向后移动45秒这样如果没有发生RDP的第二次连接这个连接信息就会在一分钟后被清除。
@ -107,11 +109,14 @@ bool TsSessionManager::free_connect_info(const ex_astr &sid) {
return true;
}
bool TsSessionManager::request_session(ex_astr &sid, TS_CONNECT_INFO *info) {
bool TsSessionManager::request_session(ex_astr& sid, TS_CONNECT_INFO* info) {
ExThreadSmartLock locker(m_lock);
EXLOGD("[core] request session: account: [%s], protocol: [%d], auth-mode: [%d]\n", info->acc_username.c_str(),
info->protocol_type, info->auth_type);
EXLOGD(
"[core] request session: account: [%s], protocol: [%d], auth-mode: [%d]\n",
info->acc_username.c_str(),
info->protocol_type, info->auth_type
);
ex_astr _sid;
int retried = 0;
@ -143,7 +148,7 @@ bool TsSessionManager::request_session(ex_astr &sid, TS_CONNECT_INFO *info) {
return true;
}
void TsSessionManager::_gen_session_id(ex_astr &sid, const TS_CONNECT_INFO *info, int len) {
void TsSessionManager::_gen_session_id(ex_astr& sid, const TS_CONNECT_INFO* info, int len) {
mbedtls_sha1_context sha;
ex_u8 sha_digist[20] = {0};
@ -152,11 +157,11 @@ void TsSessionManager::_gen_session_id(ex_astr &sid, const TS_CONNECT_INFO *info
mbedtls_sha1_init(&sha);
mbedtls_sha1_starts(&sha);
mbedtls_sha1_update(&sha, (const unsigned char *) &_tick, sizeof(ex_u64));
mbedtls_sha1_update(&sha, (const unsigned char *) &_tid, sizeof(ex_u64));
mbedtls_sha1_update(&sha, (const unsigned char *) info->conn_ip.c_str(), info->conn_ip.length());
mbedtls_sha1_update(&sha, (const unsigned char *) info->client_ip.c_str(), info->client_ip.length());
mbedtls_sha1_update(&sha, (const unsigned char *) info->acc_username.c_str(), info->acc_username.length());
mbedtls_sha1_update(&sha, (const unsigned char*) &_tick, sizeof(ex_u64));
mbedtls_sha1_update(&sha, (const unsigned char*) &_tid, sizeof(ex_u64));
mbedtls_sha1_update(&sha, (const unsigned char*) info->conn_ip.c_str(), info->conn_ip.length());
mbedtls_sha1_update(&sha, (const unsigned char*) info->client_ip.c_str(), info->client_ip.length());
mbedtls_sha1_update(&sha, (const unsigned char*) info->acc_username.c_str(), info->acc_username.length());
mbedtls_sha1_finish(&sha, sha_digist);
mbedtls_sha1_free(&sha);

View File

@ -6,68 +6,65 @@
#include <ex.h>
typedef struct TS_CONNECT_INFO
{
// TODO:
//TPP_CONNECT_INFO conn;
typedef struct TS_CONNECT_INFO {
ex_astr sid;
ex_astr sid;
// 与此连接信息相关的三个要素的ID
int user_id;
int host_id;
int acc_id;
// 与此连接信息相关的三个要素的ID
int user_id;
int host_id;
int acc_id;
ex_astr user_username;// 申请本次连接的用户名
ex_astr user_username;// 申请本次连接的用户名
ex_astr host_ip;// 真正的远程主机IP如果是直接连接模式则与remote_host_ip相同
ex_astr conn_ip;// 要连接的远程主机的IP如果是端口映射模式则为路由主机的IP
int conn_port;// 要连接的远程主机的端口(如果是端口映射模式,则为路由主机的端口)
ex_astr client_ip;
ex_astr host_ip;// 真正的远程主机IP如果是直接连接模式则与remote_host_ip相同
ex_astr conn_ip;// 要连接的远程主机的IP如果是端口映射模式则为路由主机的IP
int conn_port;// 要连接的远程主机的端口(如果是端口映射模式,则为路由主机的端口)
ex_astr client_ip;
ex_astr acc_username; // 远程主机的账号
ex_astr acc_secret; // 远程主机账号的密码(或者私钥
ex_astr username_prompt;// for telnet
ex_astr password_prompt;// for telnet
ex_astr acc_username; // 远程主机的账号
ex_astr acc_secret; // 远程主机账号的密码(或者私钥)
ex_astr username_prompt;// for telnet
ex_astr password_prompt;// for telnet
int protocol_type;
int protocol_sub_type;
int protocol_flag;
int record_flag;
int auth_type;
int protocol_type;
int protocol_sub_type;
int protocol_flag;
int record_flag;
int auth_type;
int ref_count;// 这个连接信息的引用计数如果创建的连接信息从来未被使用则超过30秒后自动销毁
ex_u64 ticket_start;// 此连接信息的创建时间(用于超时未使用就销毁的功能)
}TS_CONNECT_INFO;
int ref_count;// 这个连接信息的引用计数如果创建的连接信息从来未被使用则超过30秒后自动销毁
ex_u64 ticket_start;// 此连接信息的创建时间(用于超时未使用就销毁的功能)
} TS_CONNECT_INFO;
typedef std::map<ex_astr, TS_CONNECT_INFO*> ts_connections; // sid -> TS_CONNECT_INFO
class TsSessionManager : public ExThreadBase
{
class TsSessionManager : public ExThreadBase {
public:
TsSessionManager();
~TsSessionManager();
TsSessionManager();
// generate a sid for connection info.
bool request_session(ex_astr& sid, TS_CONNECT_INFO* info);
~TsSessionManager() override;
// 根据sid得到连接信息并增加引用计数
bool get_connect_info(const ex_astr& sid, TS_CONNECT_INFO& info);
// 减少引用计数当引用计数为0时删除之
bool free_connect_info(const ex_astr& sid);
// generate a sid for connection info.
bool request_session(ex_astr& sid, TS_CONNECT_INFO* info);
// 根据sid得到连接信息并增加引用计数
bool get_connect_info(const ex_astr& sid, TS_CONNECT_INFO& info);
// 减少引用计数当引用计数为0时删除之
bool free_connect_info(const ex_astr& sid);
protected:
void _thread_loop(void);
void _thread_loop() override;
private:
void _gen_session_id(ex_astr& sid, const TS_CONNECT_INFO* info, int len);
void _gen_session_id(ex_astr& sid, const TS_CONNECT_INFO* info, int len);
// 定时检查超过30秒未进行连接的connect-info会被移除
void _remove_expired_connect_info(void);
// 定时检查超过30秒未进行连接的connect-info会被移除
void _remove_expired_connect_info();
private:
ExThreadLock m_lock;
ts_connections m_connections;
ExThreadLock m_lock;
ts_connections m_connections;
};
extern TsSessionManager g_session_mgr;

View File

@ -148,7 +148,7 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
EXLOGE("got connection info from web-server, but not all info valid.\n");
return TPE_PARAM;
}
int user_id;
int host_id;
int acc_id;
@ -253,7 +253,6 @@ bool ts_web_rpc_session_begin(TS_CONNECT_INFO& info, int& record_id)
jreq["param"]["protocol_sub_type"] = info.protocol_sub_type;
ex_astr json_param;
//json_param = json_writer.write(jreq);
Json::StreamWriterBuilder jwb;
std::unique_ptr<Json::StreamWriter> jwriter(jwb.newStreamWriter());
ex_aoss os;
@ -276,16 +275,13 @@ bool ts_web_rpc_session_begin(TS_CONNECT_INFO& info, int& record_id)
return false;
}
//Json::Reader jreader;
Json::Value jret;
//if (!jreader.parse(body.c_str(), jret))
Json::CharReaderBuilder jcrb;
std::unique_ptr<Json::CharReader> const jreader(jcrb.newCharReader());
const char *str_json_begin = body.c_str();
ex_astr err;
//if (!jreader.parse(func_args.c_str(), jsRoot)) {
if (!jreader->parse(str_json_begin, str_json_begin + body.length(), &jret, &err))
return false;
if (!jret.isObject())
@ -346,7 +342,7 @@ bool ts_web_rpc_session_end(const char* sid, int record_id, int ret_code)
ex_aoss os;
jwriter->write(jreq, &os);
json_param = os.str();
ex_astr param;
ts_url_encode(json_param.c_str(), param);

View File

@ -4,78 +4,66 @@
#include <teleport_const.h>
SshChannelPair::SshChannelPair(SshSession *_owner, ssh_channel _rsc_tp2cli, ssh_channel _rsc_tp2srv) :
m_owner(_owner),
rsc_tp2cli(_rsc_tp2cli),
rsc_tp2srv(_rsc_tp2srv)
{
SshChannelPair::SshChannelPair(SshSession* _owner, uint32_t dbg_id, ssh_channel _rsc_tp2cli, ssh_channel _rsc_tp2srv) :
m_owner(_owner),
m_dbg_id(dbg_id),
type(TS_SSH_CHANNEL_TYPE_UNKNOWN),
win_width(0),
rsc_tp2cli(_rsc_tp2cli),
rsc_tp2srv(_rsc_tp2srv) {
last_access_timestamp = (ex_u32) time(nullptr);
ex_strformat(m_dbg_name, 128, "%s-%d", m_owner->dbg_name().c_str(), dbg_id);
state = TP_SESS_STAT_RUNNING;
db_id = 0;
channel_id = 0;
state = TP_SESS_STAT_RUNNING;
db_id = 0;
win_width = 0;
is_first_server_data = true;
need_close = false;
m_is_cmd_mode = false;
m_recv_prompt = false;
m_client_last_char = 0;
need_close = false;
m_pty_stat = PTY_STAT_NORMAL_WAIT_PROMPT;
}
SshChannelPair::~SshChannelPair()
{
}
SshChannelPair::~SshChannelPair() = default;
void SshChannelPair::process_pty_data_from_client(const uint8_t *data, uint32_t len)
{
void SshChannelPair::process_pty_data_from_client(const uint8_t* data, uint32_t len) {
if (data == nullptr || len == 0)
return;
if (len == 1)
{
if (data[0] == 0x0d)
{
if (len == 1) {
if (data[0] == 0x0d) {
// 0x0d 回车键
if (!m_cmd.empty())
EXLOGD("[%s] CMD=[%s]\n", m_owner->dbg_name().c_str(), m_cmd.str().c_str());
if (!m_cmd.empty()) {
// EXLOGD("[%s] CMD=[%s]\n", m_owner->dbg_name().c_str(), m_cmd.str().c_str());
rec.record_command(0, m_cmd.str());
}
m_cmd.reset();
m_pty_stat = PTY_STAT_NORMAL_WAIT_PROMPT;
// EXLOGD("------ turn to PTY_STAT_NORMAL_WAIT_PROMPT, input single RETURN.\n");
return;
}
else if (data[0] == 0x03)
{
else if (data[0] == 0x03) {
// 0x03 Ctrl-C
m_pty_stat = PTY_STAT_NORMAL_WAIT_PROMPT;
// EXLOGD("------ turn to PTY_STAT_NORMAL_WAIT_PROMPT, input Ctrl-C.\n");
return;
}
else if (data[0] == 0x09)
{
else if (data[0] == 0x09) {
// 0x09 TAB键
if (m_pty_stat == PTY_STAT_WAIT_CLIENT_INPUT || m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT || m_pty_stat == PTY_STAT_TAB_PRESSED)
{
if (m_pty_stat == PTY_STAT_WAIT_CLIENT_INPUT || m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT || m_pty_stat == PTY_STAT_TAB_PRESSED) {
m_pty_stat = PTY_STAT_TAB_PRESSED;
// EXLOGD("------ turn to PTY_STAT_TAB_PRESSED, input TAB.\n");
return;
}
}
else if (data[0] == 0x7f)
{
else if (data[0] == 0x7f) {
// 7f backspace 回删键
m_pty_stat = PTY_STAT_WAIT_SERVER_ECHO;
// EXLOGD("------ turn to PTY_STAT_WAIT_SERVER_ECHO, input BACKSPACE.\n");
return;
}
}
else if (len == 3)
{
if (data[0] == 0x1b && data[1] == 0x5b && (data[2] == 0x41 || data[2] == 0x42 || data[2] == 0x43 || data[2] == 0x44))
{
else if (len == 3) {
if (data[0] == 0x1b && data[1] == 0x5b && (data[2] == 0x41 || data[2] == 0x42 || data[2] == 0x43 || data[2] == 0x44)) {
// 1b 5b 41 (上箭头)
// 1b 5b 42 (下箭头)
// 1b 5b 43 (右箭头)
@ -85,10 +73,8 @@ void SshChannelPair::process_pty_data_from_client(const uint8_t *data, uint32_t
return;
}
}
else if (len == 4)
{
if (data[0] == 0x1b && data[1] == 0x5b && data[2] == 0x33 && data[3] == 0x7e)
{
else if (len == 4) {
if (data[0] == 0x1b && data[1] == 0x5b && data[2] == 0x33 && data[3] == 0x7e) {
// 1b 5b 33 7e (删除一个字符)
m_pty_stat = PTY_STAT_WAIT_SERVER_ECHO;
// EXLOGD("------ turn to PTY_STAT_WAIT_SERVER_ECHO, input DEL.\n");
@ -96,44 +82,36 @@ void SshChannelPair::process_pty_data_from_client(const uint8_t *data, uint32_t
}
}
if (len >= 512)
{
if (m_pty_stat != PTY_STAT_EXEC_MULTI_LINE_CMD)
{
if (len >= 512) {
if (m_pty_stat != PTY_STAT_EXEC_MULTI_LINE_CMD) {
m_pty_stat = PTY_STAT_NORMAL_WAIT_PROMPT;
// EXLOGD("------ turn to PTY_STAT_NORMAL_WAIT_PROMPT, input too large.\n");
}
return;
}
int return_count = 0;
bool valid_input = true;
int return_count = 0;
bool valid_input = true;
int offset = 0;
int offset = 0;
int last_return_pos = 0;
for (; offset < len;)
{
for (; offset < len;) {
uint8_t ch = data[offset];
switch (ch)
{
switch (ch) {
case 0x1b:
if (offset + 1 < len)
{
if (data[offset + 1] == 0x5b)
{
if (offset + 1 < len) {
if (data[offset + 1] == 0x5b) {
valid_input = false;
break;
}
}
break;
case 0x0d:
return_count++;
case 0x0d:return_count++;
last_return_pos = offset;
break;
default:
break;
default:break;
}
if (!valid_input)
@ -142,33 +120,29 @@ void SshChannelPair::process_pty_data_from_client(const uint8_t *data, uint32_t
offset++;
}
if (!valid_input)
{
if (m_pty_stat != PTY_STAT_EXEC_MULTI_LINE_CMD)
{
if (!valid_input) {
if (m_pty_stat != PTY_STAT_EXEC_MULTI_LINE_CMD) {
m_pty_stat = PTY_STAT_NORMAL_WAIT_PROMPT;
// EXLOGD("------ turn to PTY_STAT_NORMAL_WAIT_PROMPT, input invalid.\n");
}
return;
}
if (return_count > 0)
{
std::string tmp_cmd((const char *) data, last_return_pos + 1);
if (return_count > 0) {
std::string tmp_cmd((const char*) data, last_return_pos + 1);
EXLOGD("[%s] Paste CMD=[%s]\n", m_owner->dbg_name().c_str(), tmp_cmd.c_str());
rec.record_command(1, tmp_cmd);
m_pty_stat = PTY_STAT_EXEC_MULTI_LINE_CMD;
// EXLOGD("------ turn to PTY_STAT_EXEC_MULTI_LINE_CMD, maybe paste.\n");
}
else
{
else {
m_pty_stat = PTY_STAT_WAIT_SERVER_ECHO;
// EXLOGD("------ turn to PTY_STAT_WAIT_SERVER_ECHO, input something.\n");
}
}
void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t len)
{
void SshChannelPair::process_pty_data_from_server(const uint8_t* data, uint32_t len) {
if (data == nullptr || len == 0)
return;
@ -176,32 +150,26 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
if (m_pty_stat == PTY_STAT_NORMAL_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO)
{
if (_contains_cmd_prompt(data, len))
{
|| m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO) {
if (_contains_cmd_prompt(data, len)) {
contains_prompt = true;
if (m_pty_stat == PTY_STAT_NORMAL_WAIT_PROMPT)
{
if (m_pty_stat == PTY_STAT_NORMAL_WAIT_PROMPT) {
// EXLOGD("------ turn to PTY_STAT_WAIT_CLIENT_INPUT, recv prompt after exec.\n");
m_pty_stat = PTY_STAT_WAIT_CLIENT_INPUT;
return;
}
else if (m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT)
{
else if (m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT) {
// EXLOGD("------ turn to PTY_STAT_WAIT_CLIENT_INPUT, recv prompt after TAB.\n");
m_pty_stat = PTY_STAT_WAIT_CLIENT_INPUT;
return;
}
else if (m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT)
{
else if (m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT) {
// EXLOGD("------ turn to PTY_STAT_MULTI_CMD_WAIT_PROMPT, recv prompt while multi-exec.\n");
m_pty_stat = PTY_STAT_EXEC_MULTI_LINE_CMD;
return;
}
else if (m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO)
{
else if (m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO) {
// EXLOGD("------ turn to PTY_STAT_WAIT_CLIENT_INPUT, recv prompt while wait echo.\n");
m_pty_stat = PTY_STAT_WAIT_CLIENT_INPUT;
m_cmd.reset();
@ -210,46 +178,39 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
}
}
if (!contains_prompt)
{
if (!contains_prompt) {
if (m_pty_stat == PTY_STAT_NORMAL_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT)
{
|| m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT) {
return;
}
}
if (!(
m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO
|| m_pty_stat == PTY_STAT_EXEC_MULTI_LINE_CMD
|| m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_TAB_PRESSED
))
{
m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO
|| m_pty_stat == PTY_STAT_EXEC_MULTI_LINE_CMD
|| m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_TAB_WAIT_PROMPT
|| m_pty_stat == PTY_STAT_TAB_PRESSED
)) {
// EXLOGD("------ keep PTY_STAT, recv but not in ECHO or multi-cmd mode.\n");
return;
}
if (len > 512)
{
if (len > 512) {
// EXLOGD("------ keep PTY_STAT, recv too large.\n");
return;
}
// 处理输入回显,合成最终的命令行字符串
int offset = 0;
int offset = 0;
bool esc_mode = false;
int esc_arg = 0;
for (; offset < len;)
{
int esc_arg = 0;
for (; offset < len;) {
uint8_t ch = data[offset];
if (esc_mode)
{
switch (ch)
{
if (esc_mode) {
switch (ch) {
case '0':
case '1':
case '2':
@ -259,30 +220,24 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
case '6':
case '7':
case '8':
case '9':
esc_arg = esc_arg * 10 + (ch - '0');
case '9':esc_arg = esc_arg * 10 + (ch - '0');
break;
case 0x3f:
case ';':
case '>':
m_cmd.reset();
case '>':m_cmd.reset();
return;
case 0x4b:
{ // 'K'
if (0 == esc_arg)
{
case 0x4b: { // 'K'
if (0 == esc_arg) {
// 删除光标到行尾的字符串
m_cmd.erase_to_end();
}
else if (1 == esc_arg)
{
else if (1 == esc_arg) {
// 删除从开始到光标处的字符串
m_cmd.erase_to_begin();
}
else if (2 == esc_arg)
{
else if (2 == esc_arg) {
// 删除整行
m_cmd.reset();
}
@ -290,8 +245,7 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
esc_mode = false;
break;
}
case 0x43:
{// ^[C
case 0x43: {// ^[C
// 光标右移
if (esc_arg == 0)
esc_arg = 1;
@ -299,8 +253,7 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
esc_mode = false;
break;
}
case 0x44:
{ // ^[D
case 0x44: { // ^[D
// 光标左移
if (esc_arg == 0)
esc_arg = 1;
@ -309,8 +262,7 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
break;
}
case 0x50:
{
case 0x50: {
// 'P' 删除指定数量的字符
if (esc_arg == 0)
esc_arg = 1;
@ -319,8 +271,7 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
break;
}
case 0x40:
{ // '@' 插入指定数量的空白字符
case 0x40: { // '@' 插入指定数量的空白字符
if (esc_arg == 0)
esc_arg = 1;
m_cmd.insert_white_space(esc_arg);
@ -328,8 +279,7 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
break;
}
default:
esc_mode = false;
default:esc_mode = false;
break;
}
@ -337,25 +287,20 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
continue;
}
switch (ch)
{
switch (ch) {
case 0x07:
// 响铃
break;
case 0x08:
{
case 0x08: {
// 光标左移
m_cmd.cursor_move_left(1);
break;
}
case 0x1b:
{
if (offset + 1 < len)
{
if (data[offset + 1] == 0x5b)
{
case 0x1b: {
if (offset + 1 < len) {
if (data[offset + 1] == 0x5b) {
esc_mode = true;
esc_arg = 0;
esc_arg = 0;
offset += 1;
}
@ -363,12 +308,9 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
break;
}
case 0x0d:
{
if (offset + 1 < len && data[offset + 1] == 0x0a)
{
if (m_pty_stat == PTY_STAT_EXEC_MULTI_LINE_CMD)
{
case 0x0d: {
if (offset + 1 < len && data[offset + 1] == 0x0a) {
if (m_pty_stat == PTY_STAT_EXEC_MULTI_LINE_CMD) {
if (!m_cmd.empty())
EXLOGD("[%s] one of multi-cmd, CMD=[%s]\n", m_owner->dbg_name().c_str(), m_cmd.str().c_str());
m_cmd.reset();
@ -376,14 +318,12 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
m_pty_stat = PTY_STAT_MULTI_CMD_WAIT_PROMPT;
// EXLOGD("------ turn to PTY_STAT_MULTI_CMD_WAIT_PROMPT, recv 0x0d0a after multi-exec.\n");
if (_contains_cmd_prompt(data, len))
{
if (_contains_cmd_prompt(data, len)) {
m_pty_stat = PTY_STAT_EXEC_MULTI_LINE_CMD;
// EXLOGD("------ turn to PTY_STAT_EXEC_MULTI_LINE_CMD, recv prompt after multi-exec.\n");
}
}
else if (m_pty_stat == PTY_STAT_TAB_PRESSED)
{
else if (m_pty_stat == PTY_STAT_TAB_PRESSED) {
m_pty_stat = PTY_STAT_TAB_WAIT_PROMPT;
// EXLOGD("------ turn to PTY_STAT_TAB_WAIT_PROMPT, recv 0d0a after TAB pressed.\n");
}
@ -392,10 +332,8 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
break;
}
default:
m_cmd.replace(ch);
if (m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO)
{
default:m_cmd.replace(ch);
if (m_pty_stat == PTY_STAT_WAIT_SERVER_ECHO) {
m_pty_stat = PTY_STAT_WAIT_CLIENT_INPUT;
// EXLOGD("------ turn to PTY_STAT_WAIT_CLIENT_INPUT, recv something.\n");
}
@ -405,15 +343,13 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t *data, uint32_t
offset++;
}
if (m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT && contains_prompt)
{
if (m_pty_stat == PTY_STAT_MULTI_CMD_WAIT_PROMPT && contains_prompt) {
m_pty_stat = PTY_STAT_EXEC_MULTI_LINE_CMD;
// EXLOGD("------ turn to PTY_STAT_EXEC_MULTI_LINE_CMD, recv prompt.\n");
}
}
bool SshChannelPair::_contains_cmd_prompt(const uint8_t *data, uint32_t len)
{
bool SshChannelPair::_contains_cmd_prompt(const uint8_t* data, uint32_t len) {
// 正常情况下收到的服务端数据一包数据不会太大可以考虑限定在512字节范围内从后向前查找 0x07它的位置
// 应该位于倒数256字节范围内这之后的数据可能是命令行提示符的内容了不会太长的。继续向前找应该能够找到正
// 序为 1b 5d 30/31/32/33 3b ... 直到刚才的 07。满足这样格式的99%可能处于命令行模式了还有1%可能是Mac
@ -434,21 +370,19 @@ bool SshChannelPair::_contains_cmd_prompt(const uint8_t *data, uint32_t len)
bool found_0x07 = false;
bool found_0x3b = false;
bool found_Ps = false;
bool found_Ps = false;
bool found_0x5d = false;
int offset = static_cast<int>(len) - 1;
for (int i = 0; offset >= 0; i++)
{
for (int i = 0; offset >= 0; i++) {
if (i > 256)
return false;
if (found_0x5d)
return (data[offset] == 0x1b);
if (found_Ps)
{
if (found_Ps) {
found_0x5d = (data[offset] == 0x5d);
if (!found_0x5d)
return false;
@ -456,8 +390,7 @@ bool SshChannelPair::_contains_cmd_prompt(const uint8_t *data, uint32_t len)
continue;
}
if (found_0x3b)
{
if (found_0x3b) {
found_Ps = (data[offset] == 0x30 || data[offset] == 0x31 || data[offset] == 0x32);
if (!found_Ps)
return false;
@ -465,8 +398,7 @@ bool SshChannelPair::_contains_cmd_prompt(const uint8_t *data, uint32_t len)
continue;
}
if (!found_0x07)
{
if (!found_0x07) {
found_0x07 = (data[offset] == 0x07);
offset--;
continue;
@ -479,8 +411,7 @@ bool SshChannelPair::_contains_cmd_prompt(const uint8_t *data, uint32_t len)
return false;
}
void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t *data, uint32_t len)
{
void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t* data, uint32_t len) {
// SFTP protocol: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13
// EXLOG_BIN(data, len, "[sftp] client channel data");
@ -502,8 +433,7 @@ void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t *data, u
ex_u8 sftp_cmd = data[4];
if (sftp_cmd == 0x01)
{
if (sftp_cmd == 0x01) {
// 0x01 = 1 = SSH_FXP_INIT
rec.record_command(0, "SFTP INITIALIZE\r\n");
EXLOGD("[sftp-%s] SFTP INITIALIZE\n", m_owner->dbg_name().c_str());
@ -516,16 +446,15 @@ void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t *data, u
if (len < 14)
return;
ex_u8 *str1_ptr = (ex_u8 *) data + 9;
int str1_len = (int) ((str1_ptr[0] << 24) | (str1_ptr[1] << 16) | (str1_ptr[2] << 8) | str1_ptr[3]);
ex_u8* str1_ptr = (ex_u8*) data + 9;
int str1_len = (int) ((str1_ptr[0] << 24) | (str1_ptr[1] << 16) | (str1_ptr[2] << 8) | str1_ptr[3]);
// if (str1_len + 9 != pkg_len)
// return;
ex_u8 *str2_ptr = nullptr;// (ex_u8*)data + 13;
int str2_len = 0;// (int)((data[9] << 24) | (data[10] << 16) | (data[11] << 8) | data[12]);
ex_u8* str2_ptr = nullptr;// (ex_u8*)data + 13;
int str2_len = 0;// (int)((data[9] << 24) | (data[10] << 16) | (data[11] << 8) | data[12]);
switch (sftp_cmd)
{
switch (sftp_cmd) {
case 0x03:
// 0x03 = 3 = SSH_FXP_OPEN
EXLOGD("[sftp-%s] SSH_FXP_OPEN\n", m_owner->dbg_name().c_str());
@ -560,8 +489,7 @@ void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t *data, u
str2_len = (int) ((str2_ptr[0] << 24) | (str2_ptr[1] << 16) | (str2_ptr[2] << 8) | str2_ptr[3]);
EXLOGD("[sftp-%s] SSH_FXP_LINK\n", m_owner->dbg_name().c_str());
break;
default:
return;
default:return;
}
int total_len = 5 + str1_len + 4;
@ -570,16 +498,14 @@ void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t *data, u
if (total_len > pkg_len)
return;
char msg[2048] = { 0 };
if (str2_len == 0)
{
ex_astr str1((char *) ((ex_u8 *) data + 13), str1_len);
char msg[2048] = {0};
if (str2_len == 0) {
ex_astr str1((char*) ((ex_u8*) data + 13), str1_len);
ex_strformat(msg, 2048, "%d,%d,%s", sftp_cmd, 0, str1.c_str());
}
else
{
ex_astr str1((char *) (str1_ptr + 4), str1_len);
ex_astr str2((char *) (str2_ptr + 4), str2_len);
else {
ex_astr str1((char*) (str1_ptr + 4), str1_len);
ex_astr str2((char*) (str2_ptr + 4), str2_len);
ex_strformat(msg, 2048, "%d,%d,%s:%s", sftp_cmd, 0, str1.c_str(), str2.c_str());
}
@ -587,21 +513,20 @@ void SshChannelPair::process_sftp_command(ssh_channel ch, const uint8_t *data, u
rec.record_command(0, msg);
}
bool SshChannelPair::record_begin(const TPP_CONNECT_INFO *conn_info)
{
bool SshChannelPair::record_begin(const TPP_CONNECT_INFO* conn_info) {
#ifndef TEST_SSH_SESSION_000000
if (!g_ssh_env.session_begin(conn_info, &db_id)) {
EXLOGE("[ssh] can not save to database, channel begin failed.\n");
EXLOGE("[%s] can not save to database, channel begin failed.\n", m_dbg_name.c_str());
return false;
}
else {
channel_id = db_id;
// EXLOGD("[ssh] [channel:%d] channel begin\n", cp->channel_id);
}
// else {
// channel_id = db_id;
// // EXLOGD("[ssh] [channel:%d] channel begin\n", cp->channel_id);
// }
if (!g_ssh_env.session_update(db_id, conn_info->protocol_sub_type, TP_SESS_STAT_STARTED)) {
EXLOGE("[ssh] [channel:%d] can not update state, cannel begin failed.\n", channel_id);
EXLOGE("[%s] can not update state, cannel begin failed.\n", m_dbg_name.c_str());
return false;
}
@ -611,11 +536,10 @@ bool SshChannelPair::record_begin(const TPP_CONNECT_INFO *conn_info)
return true;
}
void SshChannelPair::record_end()
{
void SshChannelPair::record_end() {
#ifndef TEST_SSH_SESSION_000000
if (db_id > 0) {
// EXLOGD("[ssh] [channel:%d] channel end with code: %d\n", cp->channel_id, cp->state);
EXLOGD("[%s] channel end with code: %d\n", m_dbg_name.c_str(), state);
// 如果会话过程中没有发生错误,则将其状态改为结束,否则记录下错误值
if (state == TP_SESS_STAT_RUNNING || state == TP_SESS_STAT_STARTED)
@ -626,7 +550,7 @@ void SshChannelPair::record_end()
db_id = 0;
}
else {
// EXLOGD("[ssh] [channel:%d] when channel end, no db-id.\n", cp->channel_id);
EXLOGD("[%s] when channel end, no db-id.\n", m_dbg_name.c_str());
}
#endif
}
@ -636,17 +560,13 @@ void SshChannelPair::record_end()
// SshCommand
// ==================================================
SshCommand::SshCommand()
{
SshCommand::SshCommand() {
m_cmd.clear();
m_pos = m_cmd.begin();
}
SshCommand::~SshCommand()
{
}
SshCommand::~SshCommand() = default;
void SshCommand::_dump(const char *msg)
{
void SshCommand::_dump(const char* msg) {
// EXLOGD("CMD-BUFFER: %s [%s]\n", msg, str().c_str());
}

View File

@ -8,53 +8,46 @@
class SshSession;
class SshCommand
{
class SshCommand {
public:
SshCommand();
virtual ~SshCommand();
void reset()
{
void reset() {
m_cmd.clear();
m_pos = m_cmd.end();
_dump("reset");
}
std::string str()
{
std::string str() {
if (empty())
return "";
else
return std::string(m_cmd.begin(), m_cmd.end());
}
bool empty() const
{
bool empty() const {
return m_cmd.empty();
}
void erase_to_end()
{
void erase_to_end() {
// 删除光标到行尾的字符串
m_cmd.erase(m_pos, m_cmd.end());
m_pos = m_cmd.end();
_dump("erase to end");
}
void erase_to_begin()
{
void erase_to_begin() {
// 删除从开始到光标处的字符串
m_cmd.erase(m_cmd.begin(), m_pos);
m_pos = m_cmd.begin();
_dump("erase to begin");
}
void cursor_move_right(int count)
{
void cursor_move_right(int count) {
// 光标右移
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < count; ++i) {
if (m_pos != m_cmd.end())
m_pos++;
else
@ -63,11 +56,9 @@ public:
_dump("cursor move right");
}
void cursor_move_left(int count)
{
void cursor_move_left(int count) {
// 光标左移
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < count; ++i) {
if (m_pos != m_cmd.begin())
m_pos--;
else
@ -76,11 +67,9 @@ public:
_dump("cursor move left");
}
void erase_chars(int count)
{
void erase_chars(int count) {
// 删除指定数量的字符
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < count; ++i) {
if (m_pos != m_cmd.end())
m_pos = m_cmd.erase(m_pos);
else
@ -89,26 +78,21 @@ public:
_dump("erase char");
}
void insert_white_space(int count)
{
void insert_white_space(int count) {
// 插入指定数量的空白字符
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < count; ++i) {
m_pos = m_cmd.insert(m_pos, ' ');
}
_dump("insert white space");
}
void replace(uint8_t ch)
{
if (m_pos != m_cmd.end())
{
void replace(uint8_t ch) {
if (m_pos != m_cmd.end()) {
m_pos = m_cmd.erase(m_pos);
m_pos = m_cmd.insert(m_pos, ch);
m_pos++;
}
else
{
else {
m_cmd.push_back(ch);
//cmd_char_pos = cmd_char_list.end();
m_pos = m_cmd.end();
@ -116,17 +100,13 @@ public:
_dump("replace char");
}
void insert(const uint8_t *data, int len)
{
for (int i = 0; i < len; ++i)
{
if (m_pos == m_cmd.end())
{
void insert(const uint8_t* data, int len) {
for (int i = 0; i < len; ++i) {
if (m_pos == m_cmd.end()) {
m_cmd.push_back(data[i]);
m_pos = m_cmd.end();
}
else
{
else {
m_pos = m_cmd.insert(m_pos, data[i]);
m_pos++;
}
@ -134,15 +114,12 @@ public:
_dump("insert chars");
}
void insert(uint8_t ch)
{
if (m_pos == m_cmd.end())
{
void insert(uint8_t ch) {
if (m_pos == m_cmd.end()) {
m_cmd.push_back(ch);
m_pos = m_cmd.end();
}
else
{
else {
m_pos = m_cmd.insert(m_pos, ch);
m_pos++;
}
@ -150,16 +127,15 @@ public:
}
protected:
void _dump(const char *msg);
void _dump(const char* msg);
private:
std::list<char> m_cmd;
std::list<char> m_cmd;
std::list<char>::iterator m_pos;
};
// SSH命令解析有限状态机状态值
enum PTY_STAT
{
enum PTY_STAT {
PTY_STAT_NORMAL_WAIT_PROMPT = 0,
PTY_STAT_MULTI_CMD_WAIT_PROMPT,
PTY_STAT_TAB_PRESSED,
@ -170,35 +146,37 @@ enum PTY_STAT
};
class SshChannelPair
{
class SshChannelPair {
friend class SshSession;
public:
SshChannelPair(SshSession *owner, ssh_channel rsc_tp2cli, ssh_channel rsc_tp2srv);
SshChannelPair(SshSession* owner, uint32_t dbg_id, ssh_channel rsc_tp2cli, ssh_channel rsc_tp2srv);
virtual ~SshChannelPair();
void process_pty_data_from_client(const uint8_t *data, uint32_t len);
void process_pty_data_from_server(const uint8_t *data, uint32_t len);
void process_pty_data_from_client(const uint8_t* data, uint32_t len);
void process_pty_data_from_server(const uint8_t* data, uint32_t len);
void process_sftp_command(ssh_channel ch, const uint8_t *data, uint32_t len);
void process_sftp_command(ssh_channel ch, const uint8_t* data, uint32_t len);
// when client<->server channel created, start to record.
bool record_begin(const TPP_CONNECT_INFO *conn_info);
bool record_begin(const TPP_CONNECT_INFO* conn_info);
// stop record because channel closed.
void record_end();
protected:
bool _contains_cmd_prompt(const uint8_t *data, uint32_t len);
bool _contains_cmd_prompt(const uint8_t* data, uint32_t len);
protected:
SshSession *m_owner;
SshSession* m_owner;
uint32_t m_dbg_id;
std::string m_dbg_name;
int win_width; // window width, in char count.
int type; // TS_SSH_CHANNEL_TYPE_SHELL or TS_SSH_CHANNEL_TYPE_SFTP
int win_width; // window width, in char count.
ssh_channel rsc_tp2cli;
ssh_channel rsc_tp2srv;
@ -206,28 +184,18 @@ protected:
uint32_t last_access_timestamp;
TppSshRec rec;
int db_id;
int db_id;
int state;
int channel_id; // for debug only.
bool is_first_server_data;
bool need_close;
// 是否处于命令行输入模式
bool m_is_cmd_mode;
bool m_recv_prompt;
uint8_t m_client_last_char;
SshCommand m_cmd;
// uint32_t m_input_flag;
// std::vector<uint8_t> m_last_input;
PTY_STAT m_pty_stat;
};
typedef std::list<SshChannelPair *> TPChannelPairs;
typedef std::map<ssh_channel, SshChannelPair *> channel_map;
typedef std::list<SshChannelPair*> TPChannelPairs;
typedef std::map<ssh_channel, SshChannelPair*> channel_map;
#endif //__SSH_CHANNEL_PAIR_H__

View File

@ -4,46 +4,39 @@
SshProxy g_ssh_proxy;
SshProxy::SshProxy() noexcept:
ExThreadBase("ssh-proxy-thread"),
m_bind(nullptr),
m_host_port(0)
{
ExThreadBase("ssh-proxy-thread"),
m_bind(nullptr),
m_host_port(0) {
m_timer_counter_check_noop = 0;
m_timer_counter_keep_alive = 0;
m_noop_timeout_sec = 0;//900; // default to 15 minutes.
m_listener_running = false;
m_dbg_id = 0;
m_noop_timeout_sec = 0;//900; // default to 15 minutes.
m_listener_running = false;
m_dbg_id = 0;
}
SshProxy::~SshProxy()
{
if (m_bind)
{
SshProxy::~SshProxy() {
if (m_bind) {
ssh_bind_free(m_bind);
m_bind = nullptr;
}
}
bool SshProxy::init()
{
m_host_ip = g_ssh_env.bind_ip;
bool SshProxy::init() {
m_host_ip = g_ssh_env.bind_ip;
m_host_port = g_ssh_env.bind_port;
m_bind = ssh_bind_new();
if (!m_bind)
{
if (!m_bind) {
EXLOGE("[ssh] can not create bind.\n");
return false;
}
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDADDR, m_host_ip.c_str()))
{
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDADDR, m_host_ip.c_str())) {
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDADDR.\n");
return false;
}
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDPORT, &m_host_port))
{
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDPORT, &m_host_port)) {
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDPORT.\n");
return false;
}
@ -53,15 +46,13 @@ bool SshProxy::init()
ex_astr key_file;
ex_wstr2astr(_key_file, key_file);
EXLOGV("[ssh] try to load ssh-server-key: %s\n", key_file.c_str());
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_RSAKEY, key_file.c_str()))
{
EXLOGI("[ssh] loading ssh-server-key: %s\n", key_file.c_str());
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_RSAKEY, key_file.c_str())) {
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_RSAKEY.\n");
return false;
}
if (ssh_bind_listen(m_bind) < 0)
{
if (ssh_bind_listen(m_bind) < 0) {
EXLOGE("[ssh] can not listen on port %d: %s\n", m_host_port, ssh_get_error(m_bind));
return false;
}
@ -69,8 +60,7 @@ bool SshProxy::init()
return true;
}
void SshProxy::timer()
{
void SshProxy::timer() {
// timer() will be called per one second by tp_core main thread.
m_timer_counter_check_noop++;
@ -78,18 +68,15 @@ void SshProxy::timer()
{
ExThreadSmartLock locker(m_lock);
for (auto it = m_sessions.begin(); it != m_sessions.end();)
{
for (auto it = m_sessions.begin(); it != m_sessions.end();) {
// 检查通道是否已经关闭
it->first->check_channels();
// 检查会话是否已经关闭,如果会话已经完全关闭,则销毁之
if (it->first->closed())
{
if (it->first->closed()) {
delete it->first;
m_sessions.erase(it++);
}
else
{
else {
++it;
}
}
@ -99,15 +86,13 @@ void SshProxy::timer()
}
// check no-op per 5 seconds.
if (m_timer_counter_check_noop >= 5)
{
if (m_timer_counter_check_noop >= 5) {
auto t_now = (ex_u32) time(nullptr);
m_timer_counter_check_noop = 0;
ExThreadSmartLock locker(m_lock);
for (auto &session : m_sessions)
{
for (auto& session : m_sessions) {
session.first->save_record();
if (0 != m_noop_timeout_sec)
session.first->check_noop_timeout(t_now, m_noop_timeout_sec);
@ -115,21 +100,16 @@ void SshProxy::timer()
}
}
void SshProxy::set_cfg(ex_u32 noop_timeout)
{
void SshProxy::set_cfg(ex_u32 noop_timeout) {
m_noop_timeout_sec = noop_timeout;
}
void SshProxy::kill_sessions(const ex_astrs &sessions)
{
void SshProxy::kill_sessions(const ex_astrs& sessions) {
ExThreadSmartLock locker(m_lock);
for (auto &session : m_sessions)
{
for (const auto &sid : sessions)
{
if (session.first->sid() == sid)
{
for (auto& session : m_sessions) {
for (const auto& sid : sessions) {
if (session.first->sid() == sid) {
EXLOGW("[ssh] kill session %s\n", sid.c_str());
session.first->check_noop_timeout(0, 0); // 立即结束
break;
@ -138,14 +118,12 @@ void SshProxy::kill_sessions(const ex_astrs &sessions)
}
}
void SshProxy::_thread_loop()
{
void SshProxy::_thread_loop() {
EXLOGI("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
m_listener_running = true;
for (;;)
{
for (;;) {
ssh_session rs_tp2cli = ssh_new();
// #ifdef EX_DEBUG
@ -153,39 +131,36 @@ void SshProxy::_thread_loop()
// ssh_options_set(rs_tp2cli, SSH_OPTIONS_LOG_VERBOSITY, &flag);
// #endif
if (ssh_bind_accept(m_bind, rs_tp2cli) != SSH_OK)
{
if (ssh_bind_accept(m_bind, rs_tp2cli) != SSH_OK) {
EXLOGE("[ssh] accepting a connection failed: %s.\n", ssh_get_error(m_bind));
continue;
}
EXLOGD("[ssh] ssh_bind_accept() returned...\n");
if (m_need_stop)
{
if (m_need_stop) {
ssh_free(rs_tp2cli);
break;
}
struct sockaddr_storage sock_client{};
char ip[32] = { 0 };
int len = sizeof(ip);
char ip[32] = {0};
int len = sizeof(ip);
#ifdef EX_OS_WIN32
getpeername(ssh_get_fd(rs_tp2cli), (struct sockaddr *) &sock_client, &len);
#else
getpeername(ssh_get_fd(rs_tp2cli), (struct sockaddr *) &sock_client, (unsigned int *) &len);
getpeername(ssh_get_fd(rs_tp2cli), (struct sockaddr*) &sock_client, (unsigned int*) &len);
#endif
auto addr = (sockaddr_in *) &sock_client;
auto addr = (sockaddr_in*) &sock_client;
if (0 != ex_ip4_name(addr, ip, sizeof(ip)))
{
if (0 != ex_ip4_name(addr, ip, sizeof(ip))) {
EXLOGW("[ssh] can not parse client address into IP and port.\n");
}
uint32_t dbg_id = m_dbg_id++;
auto session = new SshSession(this, rs_tp2cli, dbg_id, ip, addr->sin_port);
uint32_t dbg_id = m_dbg_id++;
auto session = new SshSession(this, rs_tp2cli, dbg_id, ip, addr->sin_port);
EXLOGW("[ssh] ------ NEW SSH SESSION [%s from %s:%d] ------\n", session->dbg_name().c_str(), ip, addr->sin_port);
{
@ -201,15 +176,13 @@ void SshProxy::_thread_loop()
ExThreadSmartLock locker(m_lock);
for (auto &session : m_sessions)
{
for (auto& session : m_sessions) {
session.first->check_noop_timeout(0, 0);
}
}
// 等待所有session完成关闭清理操作工作线程退出
for (;;)
{
for (;;) {
// tp_core退出时会先停止timer线程所以这里需要自己调用timer()来进行session状态检查
timer();
@ -225,12 +198,10 @@ void SshProxy::_thread_loop()
EXLOGV("[ssh] main-loop end.\n");
}
void SshProxy::_on_stop()
{
void SshProxy::_on_stop() {
ExThreadBase::_on_stop();
if (m_is_running)
{
if (m_is_running) {
// 用一个变通的方式来结束阻塞中的监听,就是连接一下它。
ex_astr host_ip = m_host_ip;
if (host_ip == "0.0.0.0")
@ -250,8 +221,7 @@ void SshProxy::_on_stop()
ex_sleep_ms(500);
}
while (m_listener_running)
{
while (m_listener_running) {
ex_sleep_ms(1000);
}
}

View File

@ -7,15 +7,15 @@ TppSshRec::TppSshRec() {
m_cmd_cache.reserve(MAX_SIZE_PER_FILE);
memset(&m_head, 0, sizeof(TS_RECORD_HEADER));
memcpy((ex_u8 *) (&m_head.info.magic), TPP_RECORD_MAGIC, sizeof(ex_u32));
memcpy((ex_u8*) (&m_head.info.magic), TPP_RECORD_MAGIC, sizeof(ex_u32));
m_head.info.ver = 0x04;
m_head.info.type = TS_TPPR_TYPE_SSH;
m_header_changed = false;
m_save_full_header = false;
m_file_info = NULL;
m_file_data = NULL;
m_file_cmd = NULL;
m_file_info = nullptr;
m_file_data = nullptr;
m_file_cmd = nullptr;
}
@ -23,10 +23,10 @@ TppSshRec::~TppSshRec() {
end();
}
bool TppSshRec::_on_begin(const TPP_CONNECT_INFO *info) {
if (NULL == info)
bool TppSshRec::_on_begin(const TPP_CONNECT_INFO* info) {
if (nullptr == info)
return false;
m_head.basic.timestamp = (ex_u64) time(NULL);
m_head.basic.timestamp = (ex_u64) time(nullptr);
m_head.basic.protocol_type = (ex_u16) info->protocol_type;
m_head.basic.protocol_sub_type = (ex_u16) info->protocol_sub_type;
m_head.basic.conn_port = (ex_u16) info->conn_port;
@ -44,11 +44,11 @@ bool TppSshRec::_on_end() {
// 如果还有剩下未写入的数据,写入文件中。
save_record();
if (m_file_info != NULL)
if (m_file_info != nullptr)
fclose(m_file_info);
if (m_file_data != NULL)
if (m_file_data != nullptr)
fclose(m_file_data);
if (m_file_cmd != NULL)
if (m_file_cmd != nullptr)
fclose(m_file_cmd);
return true;
@ -59,8 +59,8 @@ void TppSshRec::save_record() {
_save_to_cmd_file();
}
void TppSshRec::record(ex_u8 type, const ex_u8 *data, size_t size) {
if (data == NULL || 0 == size)
void TppSshRec::record(ex_u8 type, const ex_u8* data, size_t size) {
if (data == nullptr || 0 == size)
return;
if (sizeof(TS_RECORD_PKG) + size + m_cache.size() > MAX_SIZE_PER_FILE)
@ -77,7 +77,7 @@ void TppSshRec::record(ex_u8 type, const ex_u8 *data, size_t size) {
m_header_changed = true;
}
m_cache.append((ex_u8 *) &pkg, sizeof(TS_RECORD_PKG));
m_cache.append((ex_u8*) &pkg, sizeof(TS_RECORD_PKG));
m_cache.append(data, size);
//m_head.info.packages++;
@ -94,11 +94,11 @@ void TppSshRec::record_win_size_change(int width, int height) {
TS_RECORD_WIN_SIZE pkg = {0};
pkg.width = (ex_u16) width;
pkg.height = (ex_u16) height;
record(TS_RECORD_TYPE_SSH_TERM_SIZE, (ex_u8 *) &pkg, sizeof(TS_RECORD_WIN_SIZE));
record(TS_RECORD_TYPE_SSH_TERM_SIZE, (ex_u8*) &pkg, sizeof(TS_RECORD_WIN_SIZE));
}
// 为了录像回放和命令历史能够对应(比如点击命令直接跳到录像的对应时点),仿照录像数据包的方式记录相对时间偏移,而不是绝对时间。
void TppSshRec::record_command(int flag, const ex_astr &cmd) {
void TppSshRec::record_command(int flag, const ex_astr& cmd) {
char szTime[100] = {0};
#ifdef EX_OS_WIN32
// SYSTEMTIME st;
@ -109,7 +109,7 @@ void TppSshRec::record_command(int flag, const ex_astr &cmd) {
// struct tm *p;
// time(&timep);
// p = localtime(&timep);
// if (p == NULL)
// if (p == nullptr)
// return;
// sprintf(szTime, "[%04d-%02d-%02d %02d:%02d:%02d %d] ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, flag);
#endif
@ -120,23 +120,23 @@ void TppSshRec::record_command(int flag, const ex_astr &cmd) {
if (m_cmd_cache.size() + cmd.length() + lenTime > MAX_SIZE_PER_FILE)
_save_to_cmd_file();
m_cmd_cache.append((ex_u8 *) szTime, lenTime);
m_cmd_cache.append((ex_u8 *) cmd.c_str(), cmd.length());
m_cmd_cache.append((ex_u8 *) "\r\n", 2);
m_cmd_cache.append((ex_u8*) szTime, lenTime);
m_cmd_cache.append((ex_u8*) cmd.c_str(), cmd.length());
m_cmd_cache.append((ex_u8*) "\r\n", 2);
}
bool TppSshRec::_save_to_info_file() {
if (!m_header_changed)
return true;
if (m_file_info == NULL) {
if (m_file_info == nullptr) {
ex_wstr fname = m_base_path;
if(!ex_path_join(fname, false, m_base_fname.c_str(), NULL))
if (!ex_path_join(fname, false, m_base_fname.c_str(), nullptr))
return false;
fname += L".tpr";
m_file_info = ex_fopen(fname, L"wb");
if (NULL == m_file_info) {
if (nullptr == m_file_info) {
EXLOGE("[ssh] can not open record info-file for write.\n");
return false;
}
@ -150,7 +150,8 @@ bool TppSshRec::_save_to_info_file() {
fwrite(&m_head, ts_record_header_size, 1, m_file_info);
fflush(m_file_info);
m_save_full_header = false;
} else {
}
else {
fwrite(&m_head.info, ts_record_header_info_size, 1, m_file_info);
fflush(m_file_info);
}
@ -162,14 +163,14 @@ bool TppSshRec::_save_to_data_file() {
if (m_cache.size() == 0)
return true;
if (m_file_data == NULL) {
if (m_file_data == nullptr) {
ex_wstr fname = m_base_path;
if(!ex_path_join(fname, false, m_base_fname.c_str(), NULL))
if (!ex_path_join(fname, false, m_base_fname.c_str(), nullptr))
return false;
fname += L".dat";
m_file_data = ex_fopen(fname, L"wb");
if (NULL == m_file_data) {
if (nullptr == m_file_data) {
EXLOGE("[ssh] can not open record data-file for write.\n");
return false;
}
@ -188,14 +189,14 @@ bool TppSshRec::_save_to_cmd_file() {
if (m_cmd_cache.size() == 0)
return true;
if (NULL == m_file_cmd) {
if (nullptr == m_file_cmd) {
ex_wstr fname = m_base_path;
if (!ex_path_join(fname, false, m_base_fname.c_str(), NULL))
if (!ex_path_join(fname, false, m_base_fname.c_str(), nullptr))
return false;
fname += L"-cmd.txt";
m_file_cmd = ex_fopen(fname, L"wb");
if (NULL == m_file_cmd) {
if (nullptr == m_file_cmd) {
EXLOGE("[ssh] can not open record cmd-file for write.\n");
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -14,14 +14,13 @@
#include "ssh_channel_pair.h"
#define TEST_SSH_SESSION_000000
// #define TEST_SSH_SESSION_000000
#define TS_SSH_CHANNEL_TYPE_UNKNOWN 0
#define TS_SSH_CHANNEL_TYPE_SHELL 1
#define TS_SSH_CHANNEL_TYPE_SFTP 2
enum SSH_SESSION_STATUS
{
enum SSH_SESSION_STATUS {
SSH_SESSION_STATE_CLOSED = 0,
SSH_SESSION_STATE_STARTING,
SSH_SESSION_STATE_AUTHING,
@ -35,35 +34,25 @@ class SshProxy;
class SshSession;
class SshSession :
public ExThreadBase
{
public ExThreadBase {
public:
SshSession(SshProxy *proxy, ssh_session rs_tp2cli, uint32_t dbg_id, const char *client_ip, uint16_t client_port);
SshSession(SshProxy* proxy, ssh_session rs_tp2cli, uint32_t dbg_id, const char* client_ip, uint16_t client_port);
virtual ~SshSession();
// uint32_t dbg_id() const
// {
// return m_dbg_id;
// }
const std::string &dbg_name() const
{
const std::string& dbg_name() const {
return m_dbg_name;
}
const std::string &dbg_client() const
{
const std::string& dbg_client() const {
return m_dbg_client;
}
const std::string &dbg_server() const
{
const std::string& dbg_server() const {
return m_dbg_server;
}
const std::string &sid()
{
const std::string& sid() {
return m_sid;
}
@ -76,13 +65,11 @@ public:
void keep_alive();
bool closed() const
{
bool closed() const {
return m_state == SSH_SESSION_STATE_CLOSED;
}
ssh_session get_peer_raw_session(ssh_session session)
{
ssh_session get_peer_raw_session(ssh_session session) {
if (session == m_rs_tp2cli)
return m_rs_tp2srv;
else if (session == m_rs_tp2srv)
@ -95,9 +82,11 @@ public:
// 通道管理
// --------------------------
void set_channel_tp2srv_callbacks(ssh_channel ch_tp2srv);
bool make_channel_pair(ssh_channel ch_tp2cli, ssh_channel ch_tp2srv);
SshChannelPair *get_channel_pair(ssh_channel ch);
SshChannelPair* get_channel_pair(ssh_channel ch);
void check_channels();
protected:
@ -113,57 +102,57 @@ protected:
private:
void _close_channels();
int _do_auth(const char *user, const char *secret);
int _do_auth(const char* user, const char* secret);
void _set_last_error(int err_code);
bool _send(ssh_channel channel_to, int is_stderr, void *data, uint32_t len);
bool _send(ssh_channel channel_to, int is_stderr, void* data, uint32_t len);
static int _on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata);
static int _on_auth_password_request(ssh_session session, const char* user, const char* password, void* userdata);
static ssh_channel _on_new_channel_request(ssh_session session, void *userdata);
static ssh_channel _on_new_channel_request(ssh_session session, void* userdata);
static int _on_client_pty_request(ssh_session session, ssh_channel channel, const char *term, int x, int y, int px, int py, void *userdata);
static int _on_client_pty_request(ssh_session session, ssh_channel channel, const char* term, int x, int y, int px, int py, void* userdata);
static int _on_client_shell_request(ssh_session session, ssh_channel channel, void *userdata);
static int _on_client_shell_request(ssh_session session, ssh_channel channel, void* userdata);
static void _on_client_channel_close(ssh_session session, ssh_channel channel, void *userdata);
static void _on_client_channel_close(ssh_session session, ssh_channel channel, void* userdata);
static int _on_client_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
static int _on_client_channel_data(ssh_session session, ssh_channel channel, void* data, unsigned int len, int is_stderr, void* userdata);
static int _on_client_pty_win_change(ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata);
static int _on_client_pty_win_change(ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void* userdata);
static int _on_client_channel_subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata);
static int _on_client_channel_subsystem_request(ssh_session session, ssh_channel channel, const char* subsystem, void* userdata);
static int _on_client_channel_exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata);
static int _on_client_channel_exec_request(ssh_session session, ssh_channel channel, const char* command, void* userdata);
static int _on_server_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
static int _on_server_channel_data(ssh_session session, ssh_channel channel, void* data, unsigned int len, int is_stderr, void* userdata);
static void _on_server_channel_close(ssh_session session, ssh_channel channel, void *userdata);
static void _on_server_channel_close(ssh_session session, ssh_channel channel, void* userdata);
private:
SshProxy *m_proxy;
SshProxy* m_proxy;
SSH_SESSION_STATUS m_state;
ssh_session m_rs_tp2cli;
ssh_session m_rs_tp2srv;
ssh_session m_rs_tp2cli;
ssh_session m_rs_tp2srv;
ExThreadLock m_lock;
uint32_t m_dbg_id;
uint32_t m_dbg_id;
std::string m_dbg_name;
std::string m_dbg_client;
std::string m_dbg_server;
TPP_CONNECT_INFO *m_conn_info;
TPP_CONNECT_INFO* m_conn_info;
std::string m_sid;
std::string m_conn_ip;
uint16_t m_conn_port;
uint16_t m_conn_port;
std::string m_acc_name;
std::string m_acc_secret;
uint32_t m_flags;
int m_auth_type;
bool m_allow_user_input_password;
uint32_t m_flags;
int m_auth_type;
bool m_allow_user_input_password;
bool m_first_auth;
// 远程主机认证是否通过
@ -171,25 +160,17 @@ private:
// 发生了不可逆的错误,需要关闭整个会话(包括所有的通道)
bool m_fault;
// int m_ssh_ver;
// 一个ssh_session中可以打开多个ssh_channel
// tp_channels m_channels;
// 管理两端的通道对
TPChannelPairs m_pairs;
uint32_t m_pair_id; // for debug.
TPChannelPairs m_pairs;
// 用于快速查找
channel_map m_channel_map;
channel_map m_channel_map;
// 本会话中的所有通道(无论哪一端的)
std::list<ssh_channel> m_channels;
bool m_need_send_keepalive;
bool m_recving_from_srv; // 是否正在从服务器接收数据?
bool m_recving_from_cli; // 是否正在从客户端接收数据?
struct ssh_server_callbacks_struct m_srv_cb;
struct ssh_server_callbacks_struct m_srv_cb;
struct ssh_channel_callbacks_struct m_cli_channel_cb;
struct ssh_channel_callbacks_struct m_srv_channel_cb;
};

View File

@ -2,37 +2,30 @@
TppSshEnv g_ssh_env;
TppSshEnv::TppSshEnv()
{
TppSshEnv::TppSshEnv() noexcept:
bind_port(0) {
}
TppSshEnv::~TppSshEnv()
{
}
TppSshEnv::~TppSshEnv() = default;
bool TppSshEnv::_on_init(TPP_INIT_ARGS *args)
{
bool TppSshEnv::_on_init(TPP_INIT_ARGS* args) {
ex_path_join(replay_path, false, L"ssh", NULL);
auto ps = args->cfg->GetSection(L"protocol-ssh");
if (!ps)
{
if (!ps) {
EXLOGE("[ssh] invalid config(2).\n");
return false;
}
ex_wstr tmp;
if (!ps->GetStr(L"bind-ip", tmp))
{
if (!ps->GetStr(L"bind-ip", tmp)) {
bind_ip = TS_SSH_PROXY_HOST;
}
else
{
else {
ex_wstr2astr(tmp, bind_ip);
}
if (!ps->GetInt(L"bind-port", bind_port))
{
if (!ps->GetInt(L"bind-port", bind_port)) {
bind_port = TS_SSH_PROXY_PORT;
}

View File

@ -3,18 +3,18 @@
#include "../../common/base_env.h"
class TppSshEnv : public TppEnvBase
{
class TppSshEnv : public TppEnvBase {
public:
TppSshEnv();
~TppSshEnv();
TppSshEnv() noexcept;
~TppSshEnv() override;
public:
ex_astr bind_ip;
int bind_port;
int bind_port;
private:
bool _on_init(TPP_INIT_ARGS *args);
bool _on_init(TPP_INIT_ARGS* args) override;
};
extern TppSshEnv g_ssh_env;

View File

@ -4,8 +4,7 @@
#include <teleport_const.h>
#include <json/json.h>
TPP_API ex_rv tpp_init(TPP_INIT_ARGS *init_args)
{
TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args) {
#ifdef EX_OS_UNIX
ssh_threads_set_callbacks(ssh_threads_get_pthread());
ssh_init();
@ -19,8 +18,7 @@ TPP_API ex_rv tpp_init(TPP_INIT_ARGS *init_args)
return 0;
}
TPP_API ex_rv tpp_start(void)
{
TPP_API ex_rv tpp_start(void) {
if (!g_ssh_proxy.init())
return TPE_FAILED;
if (!g_ssh_proxy.start())
@ -29,26 +27,23 @@ TPP_API ex_rv tpp_start(void)
return 0;
}
TPP_API ex_rv tpp_stop(void)
{
TPP_API ex_rv tpp_stop(void) {
g_ssh_proxy.stop();
ssh_finalize();
return 0;
}
TPP_API void tpp_timer(void)
{
TPP_API void tpp_timer(void) {
// be called per one second.
g_ssh_proxy.timer();
}
static ex_rv tpp_cmd_set_runtime_config(const char *param)
{
Json::Value jp;
Json::CharReaderBuilder jcrb;
static ex_rv tpp_cmd_set_runtime_config(const char* param) {
Json::Value jp;
Json::CharReaderBuilder jcrb;
std::unique_ptr<Json::CharReader> const jreader(jcrb.newCharReader());
const char *str_json_begin = param;
ex_astr err;
const char* str_json_begin = param;
ex_astr err;
if (!jreader->parse(str_json_begin, param + strlen(param), &jp, &err))
return TPE_JSON_FORMAT;
@ -68,12 +63,11 @@ static ex_rv tpp_cmd_set_runtime_config(const char *param)
return TPE_PARAM;
}
static ex_rv tpp_cmd_kill_sessions(const char *param)
{
Json::Value jp;
static ex_rv tpp_cmd_kill_sessions(const char* param) {
Json::Value jp;
Json::CharReaderBuilder reader_builder;
const char *str_json_begin = param;
ex_astr err;
const char* str_json_begin = param;
ex_astr err;
std::unique_ptr<Json::CharReader> const json_reader(reader_builder.newCharReader());
if (!json_reader->parse(str_json_begin, param + strlen(param), &jp, &err))
@ -84,10 +78,8 @@ static ex_rv tpp_cmd_kill_sessions(const char *param)
ex_astrs ss;
for (const auto &item : jp)
{
if (!item.isString())
{
for (const auto& item : jp) {
if (!item.isString()) {
return TPE_PARAM;
}
@ -99,18 +91,13 @@ static ex_rv tpp_cmd_kill_sessions(const char *param)
return TPE_PARAM;
}
TPP_API ex_rv tpp_command(ex_u32 cmd, const char *param)
{
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param) {
if (!param || strlen(param) == 0)
return TPE_PARAM;
switch (cmd)
{
case TPP_CMD_SET_RUNTIME_CFG:
return tpp_cmd_set_runtime_config(param);
case TPP_CMD_KILL_SESSIONS:
return tpp_cmd_kill_sessions(param);
default:
return TPE_UNKNOWN_CMD;
switch (cmd) {
case TPP_CMD_SET_RUNTIME_CFG:return tpp_cmd_set_runtime_config(param);
case TPP_CMD_KILL_SESSIONS:return tpp_cmd_kill_sessions(param);
default:return TPE_UNKNOWN_CMD;
}
}

View File

@ -313,6 +313,9 @@ $app.on_table_host_render_created = function (render) {
case TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL:
msg = '协议不支持';
break;
case TP_SESS_STAT_ERR_CREATE_CHANNEL:
msg = '无法创建数据通道';
break;
case TP_SESS_STAT_ERR_BAD_PKG:
case TP_SESS_STAT_ERR_START_BAD_PKG:
msg = '数据格式错误';

View File

@ -324,6 +324,9 @@ $app.on_table_session_render_created = function (render) {
case TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL:
msg = '协议不支持';
break;
case TP_SESS_STAT_ERR_CREATE_CHANNEL:
msg = '无法创建数据通道';
break;
case TP_SESS_STAT_ERR_BAD_PKG:
case TP_SESS_STAT_ERR_START_BAD_PKG:
msg = '数据格式错误';

View File

@ -38,23 +38,26 @@ var TP_OS_TYPE_LINUX = 2;
// =======================================================
// 远程连接会话状态
// =======================================================
var TP_SESS_STAT_RUNNING = 0; // 会话开始了,尚未结束,还在连接过程中
var TP_SESS_STAT_END = 9999; // 会话成功结束
var TP_SESS_STAT_ERR_AUTH_DENIED = 1; // 会话结束,因为认证失败
var TP_SESS_STAT_ERR_CONNECT = 2; // 会话结束,因为无法连接到远程主机
var TP_SESS_STAT_ERR_BAD_SSH_KEY = 3; // 会话结束因为无法识别SSH私钥
var TP_SESS_STAT_ERR_INTERNAL = 4; // 会话结束,因为内部错误
var TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL = 5; // 会话结束,因为协议不支持(RDP)
var TP_SESS_STAT_ERR_BAD_PKG = 6; // 会话结束,因为收到错误的报文
var TP_SESS_STAT_ERR_RESET = 7; // 会话结束因为teleport核心服务重置了
var TP_SESS_STAT_ERR_IO = 8; // 会话结束,因为网络中断
var TP_SESS_STAT_ERR_SESSION = 9; // 会话结束因为无效的会话ID
var TP_SESS_STAT_ERR_AUTH_TYPE = 10; // // 会话结束,因为服务端不支持此认证方式
var TP_SESS_STAT_STARTED = 100; // 已经连接成功了,开始记录录像了
var TP_SESS_STAT_ERR_START_INTERNAL = 104; // 会话结束,因为内部错误
var TP_SESS_STAT_ERR_START_BAD_PKG = 106; // 会话结束,因为收到错误的报文
var TP_SESS_STAT_ERR_START_RESET = 107; // 会话结束因为teleport核心服务重置了
var TP_SESS_STAT_ERR_START_IO = 108; // 会话结束,因为网络中断
var TP_SESS_STAT_RUNNING = 0; // 会话开始了,尚未结束,还在连接过程中
var TP_SESS_STAT_ERR_AUTH_DENIED = 1; // 会话结束,因为认证失败
var TP_SESS_STAT_ERR_CONNECT = 2; // 会话结束,因为无法连接到远程主机
var TP_SESS_STAT_ERR_BAD_SSH_KEY = 3; // 会话结束因为无法识别SSH私钥
var TP_SESS_STAT_ERR_INTERNAL = 4; // 会话结束,因为内部错误
var TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL = 5; // 会话结束,因为协议不支持(RDP)
var TP_SESS_STAT_ERR_BAD_PKG = 6; // 会话结束,因为收到错误的报文
var TP_SESS_STAT_ERR_RESET = 7; // 会话结束因为teleport核心服务重置了
var TP_SESS_STAT_ERR_IO = 8; // 会话结束,因为网络中断
var TP_SESS_STAT_ERR_SESSION = 9; // 会话结束因为无效的会话ID
var TP_SESS_STAT_ERR_AUTH_TYPE = 10; // 会话结束,因为服务端不支持此认证方式
var TP_SESS_STAT_ERR_CREATE_CHANNEL = 11; // 会话结束,因为创建通道失败
var TP_SESS_STAT_STARTED = 100; // 已经连接成功了,开始记录录像了
var TP_SESS_STAT_ERR_START_INTERNAL = 104; // 会话结束,因为内部错误
var TP_SESS_STAT_ERR_START_BAD_PKG = 106; // 会话结束,因为收到错误的报文
var TP_SESS_STAT_ERR_START_RESET = 107; // 会话结束因为teleport核心服务重置了
var TP_SESS_STAT_ERR_START_IO = 108; // 会话结束,因为网络中断
var TP_SESS_STAT_END = 9999; // 会话成功结束
// ==========================================================================
// 对象类型
@ -332,7 +335,7 @@ function tp_error_msg(error_code, message) {
case TPE_SYS_MAINTENANCE:
msg = '系统维护中';
break;
case TPE_OATH_ALREADY_BIND:
msg = '该账号已经绑定了身份验证器,如无法使用,请联系管理员重置密码或更换登录方式';
break;

View File

@ -7,6 +7,7 @@ import sys
import threading
import time
import traceback
import builtins
__all__ = ['log']
@ -14,6 +15,7 @@ USE_TPWEB_LOG = False
try:
import tpweb
USE_TPWEB_LOG = True
except ImportError:
pass
@ -627,6 +629,4 @@ del Logger
# log._test()
# print('test built-in `print` function.')
import builtins
builtins.__dict__['print'] = log.log_print

View File

@ -2,11 +2,11 @@
from enum import IntEnum, unique
TP_LOGIN_AUTH_SYS_DEFAULT = 0 # 系统默认(根据系统配置进行)
TP_LOGIN_AUTH_USERNAME_PASSWORD = 0x0001 # 用户名+密码
TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA = 0x0002 # 用户名+密码+验证码
TP_LOGIN_AUTH_USERNAME_OATH = 0x0004 # 用户名+OATH
TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH = 0x0008 # 用户名+密码+OATH
TP_LOGIN_AUTH_SYS_DEFAULT = 0 # 系统默认(根据系统配置进行)
TP_LOGIN_AUTH_USERNAME_PASSWORD = 0x0001 # 用户名+密码
TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA = 0x0002 # 用户名+密码+验证码
TP_LOGIN_AUTH_USERNAME_OATH = 0x0004 # 用户名+OATH
TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH = 0x0008 # 用户名+密码+OATH
APP_MODE_NORMAL = 1
APP_MODE_MAINTENANCE = 2
@ -67,7 +67,7 @@ TP_OS_TYPE_LINUX = 2
# 远程连接会话状态
# =======================================================
TP_SESS_STAT_RUNNING = 0 # 会话开始了,尚未结束
TP_SESS_STAT_END = 9999 # 会话成功结束
TP_SESS_STAT_ERR_AUTH_DENIED = 1 # 会话结束,因为认证失败
TP_SESS_STAT_ERR_CONNECT = 2 # 会话结束,因为无法连接到远程主机
TP_SESS_STAT_ERR_BAD_SSH_KEY = 3 # 会话结束因为无法识别SSH私钥
@ -77,12 +77,18 @@ TP_SESS_STAT_ERR_BAD_PKG = 6 # 会话结束,因为收到错误的报文
TP_SESS_STAT_ERR_RESET = 7 # 会话结束因为teleport核心服务重置了
TP_SESS_STAT_ERR_IO = 8 # 会话结束,因为网络中断
TP_SESS_STAT_ERR_SESSION = 9 # 会话结束因为无效的会话ID
TP_SESS_STAT_ERR_AUTH_TYPE = 10 # 会话结束,因为服务端不支持此认证方式
TP_SESS_STAT_ERR_CREATE_CHANNEL = 11 # 会话结束,因为创建通道失败
TP_SESS_STAT_STARTED = 100 # 已经连接成功了,开始记录录像了
TP_SESS_STAT_ERR_START_INTERNAL = 104 # 会话结束,因为内部错误
TP_SESS_STAT_ERR_START_BAD_PKG = 106 # 会话结束,因为收到错误的报文
TP_SESS_STAT_ERR_START_RESET = 107 # 会话结束因为teleport核心服务重置了
TP_SESS_STAT_ERR_START_IO = 108 # 会话结束,因为网络中断
TP_SESS_STAT_END = 9999 # 会话成功结束
# ==========================================================================
# 分组类型
# ==========================================================================
@ -228,7 +234,7 @@ TPE_CAPTCHA_EXPIRED = 10000
TPE_CAPTCHA_MISMATCH = 10001
TPE_OATH_MISMATCH = 10002
TPE_SYS_MAINTENANCE = 10003
TPE_OATH_ALREADY_BIND = 10004
TPE_OATH_ALREADY_BIND = 10004
TPE_USER_LOCKED = 10100
TPE_USER_DISABLED = 10101