diff --git a/.gitignore b/.gitignore index bb2164f..919bcb9 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ profile *.moved-aside /server/share/tmp +/server/tp_core/testssh/Debug +/server/tp_core/testssh/Release diff --git a/common/libex/include/ex.h b/common/libex/include/ex.h index 68166fb..2c668d3 100644 --- a/common/libex/include/ex.h +++ b/common/libex/include/ex.h @@ -1,4 +1,4 @@ -#ifndef __LIB_EX_H__ +#ifndef __LIB_EX_H__ #define __LIB_EX_H__ #ifdef EX_HAVE_CONFIG diff --git a/common/libex/include/ex/ex_const.h b/common/libex/include/ex/ex_const.h index 30604a7..699bf10 100644 --- a/common/libex/include/ex/ex_const.h +++ b/common/libex/include/ex/ex_const.h @@ -1,4 +1,4 @@ -#ifndef __LIB_EX_CONST_H__ +#ifndef __LIB_EX_CONST_H__ #define __LIB_EX_CONST_H__ #include "ex_platform.h" @@ -43,8 +43,8 @@ // error code. //==================================================== #define EXRV_OK 0 -#define EXRV_SYS_ERR 1 // ϵͳ󣬿ʹGetLastErrorerrnoȡֵ -#define EXRV_FAILED 2 // ʧ +#define EXRV_SYS_ERR 1 // 系统错误,可以使用GetLastError或者errno来获取具体错误值 +#define EXRV_FAILED 2 // 操作失败 //#define EXRV_CANNOT_FOUND 9 #define EXRV_CANNOT_CREATE 10 diff --git a/common/libex/include/ex/ex_ini.h b/common/libex/include/ex/ex_ini.h index 38749f5..681f05f 100644 --- a/common/libex/include/ex/ex_ini.h +++ b/common/libex/include/ex/ex_ini.h @@ -1,4 +1,4 @@ -#ifndef __EX_INI_H__ +#ifndef __EX_INI_H__ #define __EX_INI_H__ /* diff --git a/common/libex/include/ex/ex_log.h b/common/libex/include/ex/ex_log.h index 29a1b41..1cd89ab 100644 --- a/common/libex/include/ex/ex_log.h +++ b/common/libex/include/ex/ex_log.h @@ -1,4 +1,4 @@ -#ifndef __EX_LOG_H__ +#ifndef __EX_LOG_H__ #define __EX_LOG_H__ #include "ex_types.h" @@ -27,7 +27,7 @@ public: protected: bool _open_file(); - bool _rotate_file(void); // ־ļݣȻ¿һ־ļ + bool _rotate_file(void); // 将现有日志文件改名备份,然后新开一个日志文件 public: ExThreadLock lock; @@ -63,7 +63,7 @@ void EXLOG_USE_LOGGER(ExLogger* logger); void EXLOG_LEVEL(int min_level); void EXLOG_DEBUG(bool debug_mode); -// 趨־ļ·δָ·ΪִгĿ¼µlogĿ¼ +// 设定日志文件名及路径,如未指定路径,则为可执行程序所在目录下的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_CONSOLE(bool output_to_console); diff --git a/common/libex/include/ex/ex_path.h b/common/libex/include/ex/ex_path.h index 2f1fa19..20ac79e 100644 --- a/common/libex/include/ex/ex_path.h +++ b/common/libex/include/ex/ex_path.h @@ -1,4 +1,4 @@ -#ifndef __LIB_EX_PATH_H__ +#ifndef __LIB_EX_PATH_H__ #define __LIB_EX_PATH_H__ #include "ex_platform.h" @@ -39,7 +39,7 @@ bool ex_path_join(ex_wstr& inout_path, EX_BOOL auto_abspath, ...); bool ex_abspath_to(const ex_wstr& base_abs_path, const ex_wstr& relate_path, ex_wstr& out_path); bool ex_mkdirs(const ex_wstr& in_path); -// ȡļеչ֣.abc.py py +// 获取文件名中的扩展名部分(不包括.,例如abc.py,返回 py) bool ex_path_ext_name(const ex_wstr& in_filename, ex_wstr& out_ext); #endif diff --git a/common/libex/include/ex/ex_platform.h b/common/libex/include/ex/ex_platform.h index 3000efe..6a23715 100644 --- a/common/libex/include/ex/ex_platform.h +++ b/common/libex/include/ex/ex_platform.h @@ -1,4 +1,4 @@ -#ifndef __LIB_EX_PLATFORM_H__ +#ifndef __LIB_EX_PLATFORM_H__ #define __LIB_EX_PLATFORM_H__ #if defined(_WIN32) || defined(WIN32) diff --git a/common/libex/include/ex/ex_str.h b/common/libex/include/ex/ex_str.h index b5c4a43..070b999 100644 --- a/common/libex/include/ex/ex_str.h +++ b/common/libex/include/ex/ex_str.h @@ -1,86 +1,86 @@ -#ifndef __LIB_EX_STR_H__ -#define __LIB_EX_STR_H__ - -#include "ex_types.h" - -#define EX_CODEPAGE_ACP 0 -#define EX_CODEPAGE_UTF8 1 -#ifdef EX_OS_WIN32 -# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_ACP -#else -# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_UTF8 -#endif - -#define EX_RSC_BEGIN 0x01 -#define EX_RSC_END 0x02 -#define EX_RSC_ALL EX_RSC_BEGIN | EX_RSC_END - -//================================================= -// C Interface -//================================================= - -// copy a string from `source` to `target`. -// `size` is size of target buffer. -// if buffer is to small, NULL will return, but `size-1` characters have been copied. -char* ex_strcpy(char* target, size_t size, const char* source); -wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source); - - -// dupilicate a string. -// must use ex_free() to release the returned value. -char* ex_strdup(const char* src); -wchar_t* ex_wcsdup(const wchar_t* src); - -// convert between mutli-bytes and wide char string. -// must use ex_free() to release the returned value. -wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page); -char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page); - -// convert char** argv to wchar_t** argv. -// must use ex_free_argv() to release the returned value. -wchar_t** ex_make_wargv(int argc, char** argv); -void ex_free_wargv(int argc, wchar_t** argv); - -EX_BOOL ex_str_only_white_space(const wchar_t* src); -EX_BOOL ex_wcs_only_white_space(const char* src); - - -int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...); -int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...); - -//================================================= -// C++ Interface -//================================================= -#ifdef __cplusplus - -#include -#include - -typedef std::string ex_astr; -typedef std::wstring ex_wstr; - -typedef std::vector ex_astrs; -typedef std::vector ex_wstrs; -typedef std::vector ex_str_utf16le; - -bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); -bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); -bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); -bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); - -bool ex_only_white_space(const ex_astr& str_check); -bool ex_only_white_space(const ex_wstr& str_check); - -void ex_remove_white_space(ex_astr& str_fix, int ulFlag = EX_RSC_ALL); -void ex_remove_white_space(ex_wstr& str_fix, int ulFlag = EX_RSC_ALL); - -ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value); -ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value); - -// UTF8ַתΪUTF16-LEַ\0 -bool ex_utf8_to_utf16le(const std::string& from, ex_str_utf16le& to); - -#endif - - -#endif // __LIB_EX_STR_H__ +#ifndef __LIB_EX_STR_H__ +#define __LIB_EX_STR_H__ + +#include "ex_types.h" + +#define EX_CODEPAGE_ACP 0 +#define EX_CODEPAGE_UTF8 1 +#ifdef EX_OS_WIN32 +# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_ACP +#else +# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_UTF8 +#endif + +#define EX_RSC_BEGIN 0x01 +#define EX_RSC_END 0x02 +#define EX_RSC_ALL EX_RSC_BEGIN | EX_RSC_END + +//================================================= +// C Interface +//================================================= + +// copy a string from `source` to `target`. +// `size` is size of target buffer. +// if buffer is to small, NULL will return, but `size-1` characters have been copied. +char* ex_strcpy(char* target, size_t size, const char* source); +wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source); + + +// dupilicate a string. +// must use ex_free() to release the returned value. +char* ex_strdup(const char* src); +wchar_t* ex_wcsdup(const wchar_t* src); + +// convert between mutli-bytes and wide char string. +// must use ex_free() to release the returned value. +wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page); +char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page); + +// convert char** argv to wchar_t** argv. +// must use ex_free_argv() to release the returned value. +wchar_t** ex_make_wargv(int argc, char** argv); +void ex_free_wargv(int argc, wchar_t** argv); + +EX_BOOL ex_str_only_white_space(const wchar_t* src); +EX_BOOL ex_wcs_only_white_space(const char* src); + + +int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...); +int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...); + +//================================================= +// C++ Interface +//================================================= +#ifdef __cplusplus + +#include +#include + +typedef std::string ex_astr; +typedef std::wstring ex_wstr; + +typedef std::vector ex_astrs; +typedef std::vector ex_wstrs; +typedef std::vector ex_str_utf16le; + +bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); +bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); +bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); +bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); + +bool ex_only_white_space(const ex_astr& str_check); +bool ex_only_white_space(const ex_wstr& str_check); + +void ex_remove_white_space(ex_astr& str_fix, int ulFlag = EX_RSC_ALL); +void ex_remove_white_space(ex_wstr& str_fix, int ulFlag = EX_RSC_ALL); + +ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value); +ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value); + +// 将UTF8字符串转换为UTF16-LE字符串(输出结果包含\0结束符) +bool ex_utf8_to_utf16le(const std::string& from, ex_str_utf16le& to); + +#endif + + +#endif // __LIB_EX_STR_H__ diff --git a/common/libex/include/ex/ex_thread.h b/common/libex/include/ex/ex_thread.h index f3d4170..3948749 100644 --- a/common/libex/include/ex/ex_thread.h +++ b/common/libex/include/ex/ex_thread.h @@ -1,4 +1,4 @@ -#ifndef __EX_THREAD_H__ +#ifndef __EX_THREAD_H__ #define __EX_THREAD_H__ #include "ex_str.h" @@ -23,11 +23,11 @@ public: bool is_running(void) { return m_is_running; } - // ִ̣߳б˵run() + // 创建并启动线程(执行被重载了的run()函数) bool start(void); - // ̣߳ȴwait_timeout_ms룬wait_timeout_msΪ0޵ȴ + // 结束线程(等待wait_timeout_ms毫秒,如果wait_timeout_ms为0,则无限等待) bool stop(void); - // ֱӽ̣߳ǿɱʹã + // 直接结束线程(强杀,不建议使用) bool terminate(void); protected: @@ -52,7 +52,7 @@ protected: }; -// ߳ʹã +// 线程锁(进程内使用) class ExThreadLock { public: @@ -70,7 +70,7 @@ private: #endif }; -// ߳ +// 线程锁辅助类 class ExThreadSmartLock { public: @@ -109,12 +109,12 @@ private: }; -// ԭӲ +// 原子操作 int ex_atomic_add(volatile int* pt, int t); int ex_atomic_inc(volatile int* pt); int ex_atomic_dec(volatile int* pt); -// ߳ز +// 线程相关操作 ex_u64 ex_get_thread_id(void); #endif // __EX_THREAD_H__ diff --git a/common/libex/include/ex/ex_types.h b/common/libex/include/ex/ex_types.h index 0187b0a..3ad1a01 100644 --- a/common/libex/include/ex/ex_types.h +++ b/common/libex/include/ex/ex_types.h @@ -1,44 +1,44 @@ -#ifndef __LIB_EX_TYPE_H__ -#define __LIB_EX_TYPE_H__ - -#include "ex_platform.h" - -#include - -typedef signed char ex_i8; -typedef signed short ex_i16; - -typedef unsigned char ex_u8; -typedef unsigned short ex_u16; -typedef unsigned int ex_u32; -typedef unsigned long ex_ulong; - -#if defined(EX_OS_WIN32) -typedef unsigned __int64 ex_u64; -typedef signed __int64 ex_i64; -typedef wchar_t ex_utf16; -#else -typedef unsigned long long ex_u64; -typedef signed long long ex_i64; -typedef ex_i16 ex_utf16; -#endif - -typedef int EX_BOOL; -#define EX_TRUE 1 -#define EX_FALSE 0 - - -typedef std::vector ex_bin; -typedef std::vector ex_chars; - -typedef ex_u32 ex_rv; - - -#if defined(EX_OS_WIN32) -# define EX_DYLIB_HANDLE HINSTANCE -#else -# define EX_DYLIB_HANDLE void* -#endif - - -#endif // __LIB_EX_TYPE_H__ +#ifndef __LIB_EX_TYPE_H__ +#define __LIB_EX_TYPE_H__ + +#include "ex_platform.h" + +#include + +typedef signed char ex_i8; +typedef signed short ex_i16; + +typedef unsigned char ex_u8; +typedef unsigned short ex_u16; +typedef unsigned int ex_u32; +typedef unsigned long ex_ulong; + +#if defined(EX_OS_WIN32) +typedef unsigned __int64 ex_u64; +typedef signed __int64 ex_i64; +typedef wchar_t ex_utf16; +#else +typedef unsigned long long ex_u64; +typedef signed long long ex_i64; +typedef ex_i16 ex_utf16; +#endif + +typedef int EX_BOOL; +#define EX_TRUE 1 +#define EX_FALSE 0 + + +typedef std::vector ex_bin; +typedef std::vector ex_chars; + +typedef ex_u32 ex_rv; + + +#if defined(EX_OS_WIN32) +# define EX_DYLIB_HANDLE HINSTANCE +#else +# define EX_DYLIB_HANDLE void* +#endif + + +#endif // __LIB_EX_TYPE_H__ diff --git a/common/libex/include/ex/ex_util.h b/common/libex/include/ex/ex_util.h index 06b78ec..17b2556 100644 --- a/common/libex/include/ex/ex_util.h +++ b/common/libex/include/ex/ex_util.h @@ -1,55 +1,55 @@ -#ifndef __LIB_EX_UTIL_H__ -#define __LIB_EX_UTIL_H__ - -#include "ex_types.h" -#include "ex_str.h" - -#ifdef EX_OS_WIN32 -# include -//# include -//# include -// #include -#pragma comment(lib, "ws2_32.lib") -#else -// #include -# include -# include -#endif - -EX_BOOL ex_initialize(const char* lc_ctype); - -void ex_free(void* buffer); - -// haystackΪhaystacklenֽڣвneedleΪneedlelenʼַNULLʾûҵ -const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen); -void ex_mem_reverse(ex_u8* p, size_t l); - -void ex_printf(const char* fmt, ...); -void ex_wprintf(const wchar_t* fmt, ...); - -ex_u64 ex_get_tick_count(void); -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); - -// open a text file and read all content. -bool ex_read_text_file(const ex_wstr& file_name, ex_astr& file_content); -// open a file and write content. -bool ex_write_text_file(const ex_wstr& file_name, const ex_astr& file_content); - -EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path); -void ex_dlclose(EX_DYLIB_HANDLE dylib); - - -// inet... -int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); - -#define EX_IPV4_NAME_LEN 16 -#define EX_IPV6_NAME_LEN 46 -const char* ex_inet_ntop(int af, const void *src, char *dst, size_t size); - -#endif // __LIB_EX_UTIL_H__ +#ifndef __LIB_EX_UTIL_H__ +#define __LIB_EX_UTIL_H__ + +#include "ex_types.h" +#include "ex_str.h" + +#ifdef EX_OS_WIN32 +# include +//# include +//# include +// #include +#pragma comment(lib, "ws2_32.lib") +#else +// #include +# include +# include +#endif + +EX_BOOL ex_initialize(const char* lc_ctype); + +void ex_free(void* buffer); + +// 在haystack(长度为haystacklen字节)中查找needle(长度为needlelen)的起始地址,返回NULL表示没有找到 +const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen); +void ex_mem_reverse(ex_u8* p, size_t l); + +void ex_printf(const char* fmt, ...); +void ex_wprintf(const wchar_t* fmt, ...); + +ex_u64 ex_get_tick_count(void); +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); + +// open a text file and read all content. +bool ex_read_text_file(const ex_wstr& file_name, ex_astr& file_content); +// open a file and write content. +bool ex_write_text_file(const ex_wstr& file_name, const ex_astr& file_content); + +EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path); +void ex_dlclose(EX_DYLIB_HANDLE dylib); + + +// inet... +int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); + +#define EX_IPV4_NAME_LEN 16 +#define EX_IPV6_NAME_LEN 46 +const char* ex_inet_ntop(int af, const void *src, char *dst, size_t size); + +#endif // __LIB_EX_UTIL_H__ diff --git a/common/libex/include/ex/ex_winsrv.h b/common/libex/include/ex/ex_winsrv.h index 91938ec..15ac6ee 100644 --- a/common/libex/include/ex/ex_winsrv.h +++ b/common/libex/include/ex/ex_winsrv.h @@ -1,4 +1,4 @@ -#ifndef __EX_WINSRV_H__ +#ifndef __EX_WINSRV_H__ #define __EX_WINSRV_H__ #include "ex_str.h" diff --git a/common/libex/src/ex_ini.cpp b/common/libex/src/ex_ini.cpp index 669b890..e471752 100644 --- a/common/libex/src/ex_ini.cpp +++ b/common/libex/src/ex_ini.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -241,7 +241,7 @@ bool ExIniFile::LoadFromFile(const ex_wstr& strFileName, bool bClearOld) { pOffset += 3; } - // ļʹUTF8 + // 配置文件均使用UTF8编码 ex_wstr fileData; if (!ex_astr2wstr(pOffset, fileData, EX_CODEPAGE_UTF8)) return false; @@ -357,7 +357,7 @@ void ExIniFile::Save(int codepage/* = EX_CODEPAGE_UTF8*/) return; } - // вκСڵֵԣȱ֮ + // 如果有不属于任何小节的值对,先保存之 if (m_dumy_sec.Count() > 0) m_dumy_sec.Save(file, codepage); @@ -415,16 +415,16 @@ ExIniSection* ExIniFile::GetSection(const ex_wstr& strName, bool bCreateIfNotExi } // static function. -// һУֵΪ [/ֵ/ע/ʲôҲ/] -// => strKey = [section_name] -// ֵ => strKey = strValue +// 解析一行,返回值为 [节名/值对/注释/什么也不是/出错了] +// 节名 => strKey = [section_name] +// 值对 => strKey = strValue ExIniFile::PARSE_RV ExIniFile::_ParseLine(const ex_wstr& strOrigLine, ex_wstr& strKey, ex_wstr& strValue) { - // ȥ׵Ŀո TAB + // 首先去掉行首的空格或者 TAB 控制 ex_wstr strLine(strOrigLine); ex_remove_white_space(strLine, EX_RSC_BEGIN); - // жǷΪע͡ .ini ļ ֺ';'/'#' Ϊעеĵһַ + // 判断是否为注释。 .ini 文件以 分号';'/'#' 作为注释行的第一个字符 if (';' == strLine[0] || '#' == strLine[0]) { return PARSE_COMMENT; @@ -432,7 +432,7 @@ ExIniFile::PARSE_RV ExIniFile::_ParseLine(const ex_wstr& strOrigLine, ex_wstr& s if ('[' == strLine[0]) { - // һ(section) + // 这是一个节(section) ex_wstr::size_type startPos = strLine.find('['); ex_wstr::size_type endPos = strLine.rfind(']'); strLine.erase(endPos); @@ -443,23 +443,23 @@ ExIniFile::PARSE_RV ExIniFile::_ParseLine(const ex_wstr& strOrigLine, ex_wstr& s } else { - // ܷҵȺ(=) key=value б𷽷 + // 看看能否找到等号(=),这是 key=value 的判别方法 ex_wstr::size_type pos = strLine.find('='); if (ex_wstr::npos == pos) { - //return PARSE_OTHER; // ûеȺ + //return PARSE_OTHER; // 没有等号 ex_remove_white_space(strLine); strKey = strLine; strValue.clear(); return PARSE_KEYVALUE; } - // ȺǰȺźķָ + // 将等号前面的与等号后面的分割 strKey.assign(strLine, 0, pos); strValue.assign(strLine, pos + 1, strLine.length() - pos); ex_remove_white_space(strKey); - // ȺźӦԭⲻӦƳհַ + // 等号后面的应该原封不动,不应该移除空白字符 ex_remove_white_space(strValue, EX_RSC_BEGIN); return PARSE_KEYVALUE; @@ -489,7 +489,7 @@ bool ExIniFile::_ProcessLine(const ex_wstr strLine, ExIniSection** pCurSection) break; case PARSE_SECTION: { - // һ + // 创建一个节 ExIniSection* pSection = GetSection(strKey, true); if (NULL == pSection) { @@ -508,7 +508,7 @@ bool ExIniFile::_ProcessLine(const ex_wstr strLine, ExIniSection** pCurSection) *pCurSection = &m_dumy_sec; } - // һֵ + // 创建一个值对 if (!(*pCurSection)->SetValue(strKey, strValue, true)) { bError = true; diff --git a/common/libex/src/ex_log.cpp b/common/libex/src/ex_log.cpp index 7a2f9fa..4810a37 100644 --- a/common/libex/src/ex_log.cpp +++ b/common/libex/src/ex_log.cpp @@ -1,517 +1,517 @@ -#include -#include -//#include -//#include -//#include -//#include - -#ifdef EX_OS_WIN32 -# include -# include -# include -#else -//# include -//# include -#endif - -#define EX_LOG_CONTENT_MAX_LEN 2048 - -//typedef std::deque log_file_deque; - -static ExLogger* g_exlog = NULL; - -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_DEBUG(bool debug_mode) -{ - if (NULL != 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_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) - 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; - } - - g_exlog->set_log_file(_path, log_file, max_filesize, max_filecount); -} - -ExLogger::ExLogger() -{ -#ifdef EX_OS_WIN32 - console_handle = GetStdHandle(STD_OUTPUT_HANDLE); -#endif - - min_level = EX_LOG_LEVEL_INFO; - debug_mode = false; - to_console = true; - - m_file = NULL; - m_filesize = 0; -} - -ExLogger::~ExLogger() -{ - if (NULL != m_file) - { -#ifdef EX_OS_WIN32 - CloseHandle(m_file); -#else - fclose(m_file); -#endif - m_file = NULL; - } -} - -void ExLogger::log_a(int level, const char* fmt, va_list valist) -{ - if (NULL == fmt) - return; - - if (0 == strlen(fmt)) - return; - - char szTmp[4096] = { 0 }; - size_t offset = 0; - - if (level == EX_LOG_LEVEL_ERROR) - { - szTmp[0] = '['; - szTmp[1] = 'E'; - szTmp[2] = ']'; - szTmp[3] = ' '; - offset = 4; - } - -#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); - } - } -#else - 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. - - ex_astr tmp(szTmp); - ex_wstr _tmp; - ex_astr2wstr(tmp, _tmp); - wprintf(L"%ls", _tmp.c_str()); - fflush(stdout); - -// printf("%s", szTmp); -// fflush(stdout); - } -#endif - - write_a(szTmp); -} - -void ExLogger::log_w(int level, const wchar_t* fmt, va_list valist) -{ - if (NULL == 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; - } - -#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); - } - } -#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) \ - 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); \ -} - -#define EX_PRINTF_XW(fn, level) \ -void fn(const wchar_t* fmt, ...) \ -{ \ - if(NULL == 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); \ -} - -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); - - 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(); - - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&lpMsgBuf, 0, NULL); - - 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); - - 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(); - - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&lpMsgBuf, 0, NULL); - - 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) - return; - if (!g_exlog->debug_mode) - return; - - ExThreadSmartLock locker(g_exlog->lock); - - va_list valist; - va_start(valist, fmt); - g_exlog->log_a(EX_LOG_LEVEL_DEBUG, fmt, valist); - va_end(valist); - - ex_printf_d(" (%d/0x%02x Bytes)\n", bin_size, bin_size); - - const ex_u8* line = bin_data; - size_t thisline = 0; - size_t offset = 0; - unsigned int i = 0; - - char szTmp[128] = { 0 }; - size_t _offset = 0; - - while (offset < bin_size) - { - memset(szTmp, 0, 128); - _offset = 0; - - snprintf(szTmp + _offset, 128 - _offset, "%06x ", (int)offset); - _offset += 8; - - thisline = bin_size - offset; - if (thisline > 16) - thisline = 16; - - for (i = 0; i < thisline; i++) - { - snprintf(szTmp + _offset, 128 - _offset, "%02x ", line[i]); - _offset += 3; - } - - snprintf(szTmp + _offset, 128 - _offset, " "); - _offset += 2; - - for (; i < 16; i++) - { - snprintf(szTmp + _offset, 128 - _offset, " "); - _offset += 3; - } - - for (i = 0; i < thisline; i++) - { - snprintf(szTmp + _offset, 128 - _offset, "%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); - _offset += 1; - } - - snprintf(szTmp + _offset, 128 - _offset, "\n"); - _offset += 1; - - ex_printf_d("%s", szTmp); - - offset += thisline; - line += thisline; - } - - 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; - - m_filename = log_name; - - m_path = log_path; - ex_abspath(m_path); - - ex_mkdirs(m_path); - - m_fullname = m_path; - ex_path_join(m_fullname, false, log_name.c_str(), NULL); - - return _open_file(); -} - - -bool ExLogger::_open_file() -{ - if (m_file) - { -#ifdef EX_OS_WIN32 - CloseHandle(m_file); -#else - fclose(m_file); -#endif - m_file = NULL; - } - -#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; - } - - SetFilePointer(m_file, 0, NULL, FILE_END); - m_filesize = GetFileSize(m_file, NULL); -#else - ex_astr _fullname; - ex_wstr2astr(m_fullname, _fullname); - m_file = fopen(_fullname.c_str(), "a"); - - if (NULL == m_file) - { - return false; - } - - fseek(m_file, 0, SEEK_END); - m_filesize = (ex_u32)ftell(m_file); -#endif - - return _rotate_file(); -} - -bool ExLogger::_rotate_file(void) -{ - if (m_filesize < m_max_filesize) - return true; - - if (m_file) - { -#ifdef EX_OS_WIN32 - CloseHandle(m_file); -#else - fclose(m_file); -#endif - m_file = NULL; - } - - // 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); -#else - time_t timep; - time(&timep); - struct tm *p = localtime(&timep); - if (p == NULL) - 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); -#endif - - ex_wstr _new_fullname(m_path); - ex_path_join(_new_fullname, false, _tmpname, NULL); - -#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; - } -#else - 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; - } -#endif - - return _open_file(); -} - -bool ExLogger::write_a(const char* buf) -{ - if (NULL == m_file) - return false; - - size_t len = strlen(buf); - - 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); -#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; - fflush(m_file); -#endif - - - 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()); -} +#include +#include +//#include +//#include +//#include +//#include + +#ifdef EX_OS_WIN32 +# include +# include +# include +#else +//# include +//# include +#endif + +#define EX_LOG_CONTENT_MAX_LEN 2048 + +//typedef std::deque log_file_deque; + +static ExLogger* g_exlog = NULL; + +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_DEBUG(bool debug_mode) +{ + if (NULL != 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_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) + 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; + } + + g_exlog->set_log_file(_path, log_file, max_filesize, max_filecount); +} + +ExLogger::ExLogger() +{ +#ifdef EX_OS_WIN32 + console_handle = GetStdHandle(STD_OUTPUT_HANDLE); +#endif + + min_level = EX_LOG_LEVEL_INFO; + debug_mode = false; + to_console = true; + + m_file = NULL; + m_filesize = 0; +} + +ExLogger::~ExLogger() +{ + if (NULL != m_file) + { +#ifdef EX_OS_WIN32 + CloseHandle(m_file); +#else + fclose(m_file); +#endif + m_file = NULL; + } +} + +void ExLogger::log_a(int level, const char* fmt, va_list valist) +{ + if (NULL == fmt) + return; + + if (0 == strlen(fmt)) + return; + + char szTmp[4096] = { 0 }; + size_t offset = 0; + + if (level == EX_LOG_LEVEL_ERROR) + { + szTmp[0] = '['; + szTmp[1] = 'E'; + szTmp[2] = ']'; + szTmp[3] = ' '; + offset = 4; + } + +#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); + } + } +#else + 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. + + ex_astr tmp(szTmp); + ex_wstr _tmp; + ex_astr2wstr(tmp, _tmp); + wprintf(L"%ls", _tmp.c_str()); + fflush(stdout); + +// printf("%s", szTmp); +// fflush(stdout); + } +#endif + + write_a(szTmp); +} + +void ExLogger::log_w(int level, const wchar_t* fmt, va_list valist) +{ + if (NULL == 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; + } + +#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); + } + } +#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) \ + 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); \ +} + +#define EX_PRINTF_XW(fn, level) \ +void fn(const wchar_t* fmt, ...) \ +{ \ + if(NULL == 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); \ +} + +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); + + 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(); + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&lpMsgBuf, 0, NULL); + + 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); + + 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(); + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&lpMsgBuf, 0, NULL); + + 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) + return; + if (!g_exlog->debug_mode) + return; + + ExThreadSmartLock locker(g_exlog->lock); + + va_list valist; + va_start(valist, fmt); + g_exlog->log_a(EX_LOG_LEVEL_DEBUG, fmt, valist); + va_end(valist); + + ex_printf_d(" (%d/0x%02x Bytes)\n", bin_size, bin_size); + + const ex_u8* line = bin_data; + size_t thisline = 0; + size_t offset = 0; + unsigned int i = 0; + + char szTmp[128] = { 0 }; + size_t _offset = 0; + + while (offset < bin_size) + { + memset(szTmp, 0, 128); + _offset = 0; + + snprintf(szTmp + _offset, 128 - _offset, "%06x ", (int)offset); + _offset += 8; + + thisline = bin_size - offset; + if (thisline > 16) + thisline = 16; + + for (i = 0; i < thisline; i++) + { + snprintf(szTmp + _offset, 128 - _offset, "%02x ", line[i]); + _offset += 3; + } + + snprintf(szTmp + _offset, 128 - _offset, " "); + _offset += 2; + + for (; i < 16; i++) + { + snprintf(szTmp + _offset, 128 - _offset, " "); + _offset += 3; + } + + for (i = 0; i < thisline; i++) + { + snprintf(szTmp + _offset, 128 - _offset, "%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + _offset += 1; + } + + snprintf(szTmp + _offset, 128 - _offset, "\n"); + _offset += 1; + + ex_printf_d("%s", szTmp); + + offset += thisline; + line += thisline; + } + + 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; + + m_filename = log_name; + + m_path = log_path; + ex_abspath(m_path); + + ex_mkdirs(m_path); + + m_fullname = m_path; + ex_path_join(m_fullname, false, log_name.c_str(), NULL); + + return _open_file(); +} + + +bool ExLogger::_open_file() +{ + if (m_file) + { +#ifdef EX_OS_WIN32 + CloseHandle(m_file); +#else + fclose(m_file); +#endif + m_file = NULL; + } + +#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; + } + + SetFilePointer(m_file, 0, NULL, FILE_END); + m_filesize = GetFileSize(m_file, NULL); +#else + ex_astr _fullname; + ex_wstr2astr(m_fullname, _fullname); + m_file = fopen(_fullname.c_str(), "a"); + + if (NULL == m_file) + { + return false; + } + + fseek(m_file, 0, SEEK_END); + m_filesize = (ex_u32)ftell(m_file); +#endif + + return _rotate_file(); +} + +bool ExLogger::_rotate_file(void) +{ + if (m_filesize < m_max_filesize) + return true; + + if (m_file) + { +#ifdef EX_OS_WIN32 + CloseHandle(m_file); +#else + fclose(m_file); +#endif + m_file = NULL; + } + + // 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); +#else + time_t timep; + time(&timep); + struct tm *p = localtime(&timep); + if (p == NULL) + 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); +#endif + + ex_wstr _new_fullname(m_path); + ex_path_join(_new_fullname, false, _tmpname, NULL); + +#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; + } +#else + 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; + } +#endif + + return _open_file(); +} + +bool ExLogger::write_a(const char* buf) +{ + if (NULL == m_file) + return false; + + size_t len = strlen(buf); + + 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); +#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; + fflush(m_file); +#endif + + + 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()); +} diff --git a/common/libex/src/ex_path.cpp b/common/libex/src/ex_path.cpp index fd3e7f4..4ac23d5 100644 --- a/common/libex/src/ex_path.cpp +++ b/common/libex/src/ex_path.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/common/libex/src/ex_str.cpp b/common/libex/src/ex_str.cpp index a3fac76..1aa6046 100644 --- a/common/libex/src/ex_str.cpp +++ b/common/libex/src/ex_str.cpp @@ -1,855 +1,855 @@ -#include -#include -#include - -char* ex_strcpy(char* target, size_t size, const char* source) -{ - if (target == source) - return target; - -#ifdef EX_OS_WIN32 - if (SUCCEEDED(StringCchCopyA(target, size, source))) - return target; - else - return NULL; -#else - size_t len = strlen(source); - if (size > len) - { - return strcpy(target, source); - } - else - { - memmove(target, source, size - 1); - return NULL; - } -#endif -} - -wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source) -{ - if (target == source) - return target; - -#ifdef EX_OS_WIN32 - if (SUCCEEDED(StringCchCopyW(target, size, source))) - return target; - else - return NULL; -#else - size_t len = wcslen(source); - if (size > len) - { - return wcscpy(target, source); - } - else - { - memmove(target, source, (size - 1)*sizeof(wchar_t)); - return NULL; - } -#endif -} - -char* ex_strdup(const char* src) -{ - if (NULL == src) - return NULL; - size_t len = strlen(src) + 1; - char* ret = (char*)calloc(1, len); - memcpy(ret, src, len); - return ret; -} - -wchar_t* ex_wcsdup(const wchar_t* src) -{ - if (NULL == src) - return NULL; - size_t len = wcslen(src) + 1; - wchar_t* ret = (wchar_t*)calloc(sizeof(wchar_t), len); - memcpy(ret, src, sizeof(wchar_t)*len); - return ret; -} - -wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page) -{ - wchar_t* out_buffer = NULL; -#ifdef EX_OS_WIN32 - int wlen = 0; - UINT _cp = 0; - if (code_page == EX_CODEPAGE_ACP) - _cp = CP_ACP; - else if (code_page == EX_CODEPAGE_UTF8) - _cp = CP_UTF8; - - wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, NULL, 0); - if (0 == wlen) - return NULL; - - out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); - if (NULL == out_buffer) - return NULL; - - wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, out_buffer, wlen); - if (0 == wlen) - { - free(out_buffer); - return NULL; - } - -#else - size_t wlen = 0; - wlen = mbstowcs(NULL, in_buffer, 0); - if (wlen <= 0) - return NULL; - - out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); - if (NULL == out_buffer) - return NULL; - - wlen = mbstowcs(out_buffer, in_buffer, wlen); - if (wlen <= 0) - { - free(out_buffer); - return NULL; - } - -#endif - - return out_buffer; -} - - -char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page) -{ - char* out_buffer = NULL; - - if(NULL == in_buffer) - return NULL; - -#ifdef EX_OS_WIN32 - int len = 0; - UINT _cp = 0; - if (code_page == EX_CODEPAGE_ACP) - _cp = CP_ACP; - else if (code_page == EX_CODEPAGE_UTF8) - _cp = CP_UTF8; - - len = WideCharToMultiByte(_cp, 0, in_buffer, -1, NULL, 0, NULL, NULL); - if (0 == len) - return NULL; - - out_buffer = (char*)calloc(len + 1, sizeof(char)); - if (NULL == out_buffer) - return NULL; - - len = WideCharToMultiByte(_cp, 0, in_buffer, -1, out_buffer, len, NULL, NULL); - if (0 == len) - { - free(out_buffer); - return NULL; - } - -#else - size_t len = 0; - len = wcstombs(NULL, in_buffer, 0); - if (len <= 0) - return NULL; - - out_buffer = (char*)calloc(len + 1, sizeof(char)); - if (NULL == out_buffer) - return NULL; - - len = wcstombs(out_buffer, in_buffer, len); - if (len <= 0) - { - free(out_buffer); - return NULL; - } - -#endif - - return out_buffer; -} - -wchar_t** ex_make_wargv(int argc, char** argv) -{ - int i = 0; - wchar_t** ret = NULL; - - ret = (wchar_t**)calloc(argc + 1, sizeof(wchar_t*)); - if (!ret) - { - return NULL; - } - - for (i = 0; i < argc; ++i) - { - ret[i] = ex_str2wcs_alloc(argv[i], EX_CODEPAGE_DEFAULT); - if (NULL == ret[i]) - goto err; - } - - return ret; - -err: - ex_free_wargv(argc, ret); - return NULL; -} - -void ex_free_wargv(int argc, wchar_t** argv) -{ - int i = 0; - for (i = 0; i < argc; ++i) - free(argv[i]); - - free(argv); -} - -EX_BOOL ex_str_only_white_space(const wchar_t* src) -{ - if (ex_only_white_space(src)) - return EX_TRUE; - else - return EX_FALSE; -} - -EX_BOOL ex_wcs_only_white_space(const char* src) -{ - if (ex_only_white_space(src)) - return EX_TRUE; - else - return EX_FALSE; -} - -int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...) -{ - int ret = 0; - va_list valist; - va_start(valist, fmt); - //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); -#ifdef EX_OS_WIN32 - ret = vsnprintf(out_buf, buf_size, fmt, valist); -#else - ret = vsprintf(out_buf, fmt, valist); -#endif - va_end(valist); - return ret; -} - -int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...) -{ - int ret = 0; - va_list valist; - va_start(valist, fmt); - //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); -#ifdef EX_OS_WIN32 - //ret = vsnprintf(out_buf, buf_size, fmt, valist); - ret = _vsnwprintf_s(out_buf, buf_size, buf_size, fmt, valist); -#else - //ret = vsprintf(out_buf, fmt, valist); - ret = vswprintf(out_buf, buf_size, fmt, valist); -#endif - va_end(valist); - return ret; -} - - -#ifdef __cplusplus -bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - return ex_wstr2astr(in_str.c_str(), out_str, code_page); -} - -bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - char* astr = ex_wcs2str_alloc(in_str, code_page); - if (NULL == astr) - return false; - - out_str = astr; - ex_free(astr); - return true; -} - -bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - return ex_astr2wstr(in_str.c_str(), out_str, code_page); -} - -bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - wchar_t* wstr = ex_str2wcs_alloc(in_str, code_page); - if (NULL == wstr) - return false; - - out_str = wstr; - ex_free(wstr); - return true; -} - -bool ex_only_white_space(const ex_astr& str_check) -{ - ex_astr::size_type pos = 0; - ex_astr strFilter(" \t\r\n"); - pos = str_check.find_first_not_of(strFilter); - if (ex_astr::npos == pos) - return true; - else - return false; -} - -bool ex_only_white_space(const ex_wstr& str_check) -{ - ex_wstr::size_type pos = 0; - ex_wstr strFilter(L" \t\r\n"); - pos = str_check.find_first_not_of(strFilter); - if (ex_wstr::npos == pos) - return true; - else - return false; -} - -void ex_remove_white_space(ex_astr& str_fix, int ulFlag /*= EX_RSC_ALL*/) -{ - ex_astr::size_type pos = 0; - ex_astr strFilter(" \t\r\n"); - - if (ulFlag & EX_RSC_BEGIN) - { - pos = str_fix.find_first_not_of(strFilter); - if (ex_astr::npos != pos) - str_fix.erase(0, pos); - // FIXME - } - if (ulFlag & EX_RSC_END) - { - pos = str_fix.find_last_not_of(strFilter); - if (ex_astr::npos != pos) - str_fix.erase(pos + 1); - // FIXME - } -} - -void ex_remove_white_space(ex_wstr& str_fix, int ulFlag /*= EX_RSC_ALL*/) -{ - ex_wstr::size_type pos = 0; - ex_wstr strFilter(L" \t\r\n"); - - if (ulFlag & EX_RSC_BEGIN) - { - pos = str_fix.find_first_not_of(strFilter); - if (ex_wstr::npos != pos) - str_fix.erase(0, pos); - // FIXME - } - if (ulFlag & EX_RSC_END) - { - pos = str_fix.find_last_not_of(strFilter); - if (ex_wstr::npos != pos) - str_fix.erase(pos + 1); - // FIXME - } -} - -ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value) -{ - for (ex_astr::size_type pos(0); pos != ex_astr::npos; pos += new_value.length()) - { - if ((pos = str.find(old_value, pos)) != ex_astr::npos) - str.replace(pos, old_value.length(), new_value); - else - break; - } - - return str; -} - -ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value) -{ - for (ex_wstr::size_type pos(0); pos != ex_wstr::npos; pos += new_value.length()) - { - if ((pos = str.find(old_value, pos)) != ex_wstr::npos) - str.replace(pos, old_value.length(), new_value); - else - break; - } - - return str; -} - - - -#ifndef EX_OS_WIN32 - -#define BYTE ex_u8 -#define DWORD ex_u32 -#define WCHAR ex_i16 -#define LPWSTR WCHAR* -#define BOOL int -#define TRUE 1 -#define FALSE 0 -#define UINT unsigned int -#define LPCSTR const char* -#define CP_UTF8 1 - -typedef enum -{ - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum -{ - strictConversion = 0, - lenientConversion -} ConversionFlags; - -static const char trailingBytesForUTF8[256] = -{ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -static const DWORD offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL -}; - -static const BYTE firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const DWORD halfBase = 0x0010000UL; -static const DWORD halfMask = 0x3FFUL; - -#define UNI_SUR_HIGH_START (DWORD)0xD800 -#define UNI_SUR_HIGH_END (DWORD)0xDBFF -#define UNI_SUR_LOW_START (DWORD)0xDC00 -#define UNI_SUR_LOW_END (DWORD)0xDFFF - -#define UNI_REPLACEMENT_CHAR (DWORD)0x0000FFFD -#define UNI_MAX_BMP (DWORD)0x0000FFFF -#define UNI_MAX_UTF16 (DWORD)0x0010FFFF -#define UNI_MAX_UTF32 (DWORD)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (DWORD)0x0010FFFF - - -static ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sourceEnd, BYTE** targetStart, BYTE* targetEnd, ConversionFlags flags) -{ - BYTE* target; - const WCHAR* source; - BOOL computeLength; - ConversionResult result; - computeLength = (!targetEnd) ? TRUE : FALSE; - source = *sourceStart; - target = *targetStart; - result = conversionOK; - - while (source < sourceEnd) - { - DWORD ch; - unsigned short bytesToWrite = 0; - const DWORD byteMask = 0xBF; - const DWORD byteMark = 0x80; - const WCHAR* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) - { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) - { - DWORD ch2 = *source; - - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) - { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } - else if (flags == strictConversion) - { - /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - else - { - /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } - else if (flags == strictConversion) - { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) - { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - - /* Figure out how many bytes the result will require */ - if (ch < (DWORD)0x80) - { - bytesToWrite = 1; - } - else if (ch < (DWORD)0x800) - { - bytesToWrite = 2; - } - else if (ch < (DWORD)0x10000) - { - bytesToWrite = 3; - } - else if (ch < (DWORD)0x110000) - { - bytesToWrite = 4; - } - else - { - bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - - if ((target > targetEnd) && (!computeLength)) - { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; - result = targetExhausted; - break; - } - - if (!computeLength) - { - switch (bytesToWrite) - { - /* note: everything falls through. */ - case 4: - *--target = (BYTE)((ch | byteMark) & byteMask); - ch >>= 6; - - case 3: - *--target = (BYTE)((ch | byteMark) & byteMask); - ch >>= 6; - - case 2: - *--target = (BYTE)((ch | byteMark) & byteMask); - ch >>= 6; - - case 1: - *--target = (BYTE)(ch | firstByteMark[bytesToWrite]); - } - } - else - { - switch (bytesToWrite) - { - /* note: everything falls through. */ - case 4: - --target; - ch >>= 6; - - case 3: - --target; - ch >>= 6; - - case 2: - --target; - ch >>= 6; - - case 1: - --target; - } - } - - target += bytesToWrite; - } - - *sourceStart = source; - *targetStart = target; - return result; -} - - -static BOOL isLegalUTF8(const BYTE* source, int length) -{ - BYTE a; - const BYTE* srcptr = source + length; - - switch (length) - { - default: - return FALSE; - - /* Everything else falls through when "TRUE"... */ - case 4: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return FALSE; - - case 3: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return FALSE; - - case 2: - if ((a = (*--srcptr)) > 0xBF) return FALSE; - - switch (*source) - { - /* no fall-through in this inner switch */ - case 0xE0: - if (a < 0xA0) return FALSE; - - break; - - case 0xED: - if (a > 0x9F) return FALSE; - - break; - - case 0xF0: - if (a < 0x90) return FALSE; - - break; - - case 0xF4: - if (a > 0x8F) return FALSE; - - break; - - default: - if (a < 0x80) return FALSE; - } - - case 1: - if (*source >= 0x80 && *source < 0xC2) return FALSE; - } - - if (*source > 0xF4) - return FALSE; - - return TRUE; -} - -static ConversionResult _ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* sourceEnd, WCHAR** targetStart, WCHAR* targetEnd, ConversionFlags flags) -{ - WCHAR* target; - const BYTE* source; - BOOL computeLength; - ConversionResult result; - computeLength = (!targetEnd) ? TRUE : FALSE; - result = conversionOK; - source = *sourceStart; - target = *targetStart; - - while (source < sourceEnd) - { - DWORD ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - - if ((source + extraBytesToRead) >= sourceEnd) - { - result = sourceExhausted; - break; - } - - /* Do this check whether lenient or strict */ - if (!isLegalUTF8(source, extraBytesToRead + 1)) - { - result = sourceIllegal; - break; - } - - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) - { - case 5: - ch += *source++; - ch <<= 6; /* remember, illegal UTF-8 */ - - case 4: - ch += *source++; - ch <<= 6; /* remember, illegal UTF-8 */ - - case 3: - ch += *source++; - ch <<= 6; - - case 2: - ch += *source++; - ch <<= 6; - - case 1: - ch += *source++; - ch <<= 6; - - case 0: - ch += *source++; - } - - ch -= offsetsFromUTF8[extraBytesToRead]; - - if ((target >= targetEnd) && (!computeLength)) - { - source -= (extraBytesToRead + 1); /* Back up source pointer! */ - result = targetExhausted; - break; - } - - if (ch <= UNI_MAX_BMP) - { - /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) - { - if (flags == strictConversion) - { - source -= (extraBytesToRead + 1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - else - { - if (!computeLength) - *target++ = UNI_REPLACEMENT_CHAR; - else - target++; - } - } - else - { - if (!computeLength) - *target++ = (WCHAR)ch; /* normal case */ - else - target++; - } - } - else if (ch > UNI_MAX_UTF16) - { - if (flags == strictConversion) - { - result = sourceIllegal; - source -= (extraBytesToRead + 1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } - else - { - if (!computeLength) - *target++ = UNI_REPLACEMENT_CHAR; - else - target++; - } - } - else - { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if ((target + 1 >= targetEnd) && (!computeLength)) - { - source -= (extraBytesToRead + 1); /* Back up source pointer! */ - result = targetExhausted; - break; - } - - ch -= halfBase; - - if (!computeLength) - { - *target++ = (WCHAR)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (WCHAR)((ch & halfMask) + UNI_SUR_LOW_START); - } - else - { - target++; - target++; - } - } - } - - *sourceStart = source; - *targetStart = target; - return result; -} - -static int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) -{ - int length; - LPWSTR targetStart; - const BYTE* sourceStart; - ConversionResult result; - - /* If cbMultiByte is 0, the function fails */ - - if (cbMultiByte == 0) - return 0; - - /* If cbMultiByte is -1, the string is null-terminated */ - - if (cbMultiByte == -1) - cbMultiByte = (int)strlen((char*)lpMultiByteStr) + 1; - - /* - * if cchWideChar is 0, the function returns the required buffer size - * in characters for lpWideCharStr and makes no use of the output parameter itself. - */ - - if (cchWideChar == 0) - { - sourceStart = (const BYTE*)lpMultiByteStr; - targetStart = (WCHAR*)NULL; - - result = _ConvertUTF8toUTF16(&sourceStart, &sourceStart[cbMultiByte], - &targetStart, NULL, strictConversion); - - length = (int)(targetStart - ((WCHAR*)NULL)); - cchWideChar = length; - } - else - { - sourceStart = (const BYTE*)lpMultiByteStr; - targetStart = lpWideCharStr; - - result = _ConvertUTF8toUTF16(&sourceStart, &sourceStart[cbMultiByte], - &targetStart, &targetStart[cchWideChar], strictConversion); - - length = (int)(targetStart - ((WCHAR*)lpWideCharStr)); - cchWideChar = length; - } - - return cchWideChar; -} - -#endif - - - -bool ex_utf8_to_utf16le(const std::string& from, ex_str_utf16le& to) -{ - int iSize = MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, NULL, 0); - if (iSize <= 0) - return false; - - //++iSize; - to.resize(iSize); - memset(&to[0], 0, sizeof(ex_utf16)); - - MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, &to[0], iSize); - - return true; -} - -#endif +#include +#include +#include + +char* ex_strcpy(char* target, size_t size, const char* source) +{ + if (target == source) + return target; + +#ifdef EX_OS_WIN32 + if (SUCCEEDED(StringCchCopyA(target, size, source))) + return target; + else + return NULL; +#else + size_t len = strlen(source); + if (size > len) + { + return strcpy(target, source); + } + else + { + memmove(target, source, size - 1); + return NULL; + } +#endif +} + +wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source) +{ + if (target == source) + return target; + +#ifdef EX_OS_WIN32 + if (SUCCEEDED(StringCchCopyW(target, size, source))) + return target; + else + return NULL; +#else + size_t len = wcslen(source); + if (size > len) + { + return wcscpy(target, source); + } + else + { + memmove(target, source, (size - 1)*sizeof(wchar_t)); + return NULL; + } +#endif +} + +char* ex_strdup(const char* src) +{ + if (NULL == src) + return NULL; + size_t len = strlen(src) + 1; + char* ret = (char*)calloc(1, len); + memcpy(ret, src, len); + return ret; +} + +wchar_t* ex_wcsdup(const wchar_t* src) +{ + if (NULL == src) + return NULL; + size_t len = wcslen(src) + 1; + wchar_t* ret = (wchar_t*)calloc(sizeof(wchar_t), len); + memcpy(ret, src, sizeof(wchar_t)*len); + return ret; +} + +wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page) +{ + wchar_t* out_buffer = NULL; +#ifdef EX_OS_WIN32 + int wlen = 0; + UINT _cp = 0; + if (code_page == EX_CODEPAGE_ACP) + _cp = CP_ACP; + else if (code_page == EX_CODEPAGE_UTF8) + _cp = CP_UTF8; + + wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, NULL, 0); + if (0 == wlen) + return NULL; + + out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); + if (NULL == out_buffer) + return NULL; + + wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, out_buffer, wlen); + if (0 == wlen) + { + free(out_buffer); + return NULL; + } + +#else + size_t wlen = 0; + wlen = mbstowcs(NULL, in_buffer, 0); + if (wlen <= 0) + return NULL; + + out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); + if (NULL == out_buffer) + return NULL; + + wlen = mbstowcs(out_buffer, in_buffer, wlen); + if (wlen <= 0) + { + free(out_buffer); + return NULL; + } + +#endif + + return out_buffer; +} + + +char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page) +{ + char* out_buffer = NULL; + + if(NULL == in_buffer) + return NULL; + +#ifdef EX_OS_WIN32 + int len = 0; + UINT _cp = 0; + if (code_page == EX_CODEPAGE_ACP) + _cp = CP_ACP; + else if (code_page == EX_CODEPAGE_UTF8) + _cp = CP_UTF8; + + len = WideCharToMultiByte(_cp, 0, in_buffer, -1, NULL, 0, NULL, NULL); + if (0 == len) + return NULL; + + out_buffer = (char*)calloc(len + 1, sizeof(char)); + if (NULL == out_buffer) + return NULL; + + len = WideCharToMultiByte(_cp, 0, in_buffer, -1, out_buffer, len, NULL, NULL); + if (0 == len) + { + free(out_buffer); + return NULL; + } + +#else + size_t len = 0; + len = wcstombs(NULL, in_buffer, 0); + if (len <= 0) + return NULL; + + out_buffer = (char*)calloc(len + 1, sizeof(char)); + if (NULL == out_buffer) + return NULL; + + len = wcstombs(out_buffer, in_buffer, len); + if (len <= 0) + { + free(out_buffer); + return NULL; + } + +#endif + + return out_buffer; +} + +wchar_t** ex_make_wargv(int argc, char** argv) +{ + int i = 0; + wchar_t** ret = NULL; + + ret = (wchar_t**)calloc(argc + 1, sizeof(wchar_t*)); + if (!ret) + { + return NULL; + } + + for (i = 0; i < argc; ++i) + { + ret[i] = ex_str2wcs_alloc(argv[i], EX_CODEPAGE_DEFAULT); + if (NULL == ret[i]) + goto err; + } + + return ret; + +err: + ex_free_wargv(argc, ret); + return NULL; +} + +void ex_free_wargv(int argc, wchar_t** argv) +{ + int i = 0; + for (i = 0; i < argc; ++i) + free(argv[i]); + + free(argv); +} + +EX_BOOL ex_str_only_white_space(const wchar_t* src) +{ + if (ex_only_white_space(src)) + return EX_TRUE; + else + return EX_FALSE; +} + +EX_BOOL ex_wcs_only_white_space(const char* src) +{ + if (ex_only_white_space(src)) + return EX_TRUE; + else + return EX_FALSE; +} + +int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...) +{ + int ret = 0; + va_list valist; + va_start(valist, fmt); + //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); +#ifdef EX_OS_WIN32 + ret = vsnprintf(out_buf, buf_size, fmt, valist); +#else + ret = vsprintf(out_buf, fmt, valist); +#endif + va_end(valist); + return ret; +} + +int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...) +{ + int ret = 0; + va_list valist; + va_start(valist, fmt); + //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); +#ifdef EX_OS_WIN32 + //ret = vsnprintf(out_buf, buf_size, fmt, valist); + ret = _vsnwprintf_s(out_buf, buf_size, buf_size, fmt, valist); +#else + //ret = vsprintf(out_buf, fmt, valist); + ret = vswprintf(out_buf, buf_size, fmt, valist); +#endif + va_end(valist); + return ret; +} + + +#ifdef __cplusplus +bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + return ex_wstr2astr(in_str.c_str(), out_str, code_page); +} + +bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + char* astr = ex_wcs2str_alloc(in_str, code_page); + if (NULL == astr) + return false; + + out_str = astr; + ex_free(astr); + return true; +} + +bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + return ex_astr2wstr(in_str.c_str(), out_str, code_page); +} + +bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + wchar_t* wstr = ex_str2wcs_alloc(in_str, code_page); + if (NULL == wstr) + return false; + + out_str = wstr; + ex_free(wstr); + return true; +} + +bool ex_only_white_space(const ex_astr& str_check) +{ + ex_astr::size_type pos = 0; + ex_astr strFilter(" \t\r\n"); + pos = str_check.find_first_not_of(strFilter); + if (ex_astr::npos == pos) + return true; + else + return false; +} + +bool ex_only_white_space(const ex_wstr& str_check) +{ + ex_wstr::size_type pos = 0; + ex_wstr strFilter(L" \t\r\n"); + pos = str_check.find_first_not_of(strFilter); + if (ex_wstr::npos == pos) + return true; + else + return false; +} + +void ex_remove_white_space(ex_astr& str_fix, int ulFlag /*= EX_RSC_ALL*/) +{ + ex_astr::size_type pos = 0; + ex_astr strFilter(" \t\r\n"); + + if (ulFlag & EX_RSC_BEGIN) + { + pos = str_fix.find_first_not_of(strFilter); + if (ex_astr::npos != pos) + str_fix.erase(0, pos); + // FIXME + } + if (ulFlag & EX_RSC_END) + { + pos = str_fix.find_last_not_of(strFilter); + if (ex_astr::npos != pos) + str_fix.erase(pos + 1); + // FIXME + } +} + +void ex_remove_white_space(ex_wstr& str_fix, int ulFlag /*= EX_RSC_ALL*/) +{ + ex_wstr::size_type pos = 0; + ex_wstr strFilter(L" \t\r\n"); + + if (ulFlag & EX_RSC_BEGIN) + { + pos = str_fix.find_first_not_of(strFilter); + if (ex_wstr::npos != pos) + str_fix.erase(0, pos); + // FIXME + } + if (ulFlag & EX_RSC_END) + { + pos = str_fix.find_last_not_of(strFilter); + if (ex_wstr::npos != pos) + str_fix.erase(pos + 1); + // FIXME + } +} + +ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value) +{ + for (ex_astr::size_type pos(0); pos != ex_astr::npos; pos += new_value.length()) + { + if ((pos = str.find(old_value, pos)) != ex_astr::npos) + str.replace(pos, old_value.length(), new_value); + else + break; + } + + return str; +} + +ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value) +{ + for (ex_wstr::size_type pos(0); pos != ex_wstr::npos; pos += new_value.length()) + { + if ((pos = str.find(old_value, pos)) != ex_wstr::npos) + str.replace(pos, old_value.length(), new_value); + else + break; + } + + return str; +} + + + +#ifndef EX_OS_WIN32 + +#define BYTE ex_u8 +#define DWORD ex_u32 +#define WCHAR ex_i16 +#define LPWSTR WCHAR* +#define BOOL int +#define TRUE 1 +#define FALSE 0 +#define UINT unsigned int +#define LPCSTR const char* +#define CP_UTF8 1 + +typedef enum +{ + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum +{ + strictConversion = 0, + lenientConversion +} ConversionFlags; + +static const char trailingBytesForUTF8[256] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static const DWORD offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL +}; + +static const BYTE firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const DWORD halfBase = 0x0010000UL; +static const DWORD halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (DWORD)0xD800 +#define UNI_SUR_HIGH_END (DWORD)0xDBFF +#define UNI_SUR_LOW_START (DWORD)0xDC00 +#define UNI_SUR_LOW_END (DWORD)0xDFFF + +#define UNI_REPLACEMENT_CHAR (DWORD)0x0000FFFD +#define UNI_MAX_BMP (DWORD)0x0000FFFF +#define UNI_MAX_UTF16 (DWORD)0x0010FFFF +#define UNI_MAX_UTF32 (DWORD)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (DWORD)0x0010FFFF + + +static ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sourceEnd, BYTE** targetStart, BYTE* targetEnd, ConversionFlags flags) +{ + BYTE* target; + const WCHAR* source; + BOOL computeLength; + ConversionResult result; + computeLength = (!targetEnd) ? TRUE : FALSE; + source = *sourceStart; + target = *targetStart; + result = conversionOK; + + while (source < sourceEnd) + { + DWORD ch; + unsigned short bytesToWrite = 0; + const DWORD byteMask = 0xBF; + const DWORD byteMark = 0x80; + const WCHAR* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) + { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) + { + DWORD ch2 = *source; + + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) + { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } + else if (flags == strictConversion) + { + /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + else + { + /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } + else if (flags == strictConversion) + { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) + { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + + /* Figure out how many bytes the result will require */ + if (ch < (DWORD)0x80) + { + bytesToWrite = 1; + } + else if (ch < (DWORD)0x800) + { + bytesToWrite = 2; + } + else if (ch < (DWORD)0x10000) + { + bytesToWrite = 3; + } + else if (ch < (DWORD)0x110000) + { + bytesToWrite = 4; + } + else + { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + + if ((target > targetEnd) && (!computeLength)) + { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + + if (!computeLength) + { + switch (bytesToWrite) + { + /* note: everything falls through. */ + case 4: + *--target = (BYTE)((ch | byteMark) & byteMask); + ch >>= 6; + + case 3: + *--target = (BYTE)((ch | byteMark) & byteMask); + ch >>= 6; + + case 2: + *--target = (BYTE)((ch | byteMark) & byteMask); + ch >>= 6; + + case 1: + *--target = (BYTE)(ch | firstByteMark[bytesToWrite]); + } + } + else + { + switch (bytesToWrite) + { + /* note: everything falls through. */ + case 4: + --target; + ch >>= 6; + + case 3: + --target; + ch >>= 6; + + case 2: + --target; + ch >>= 6; + + case 1: + --target; + } + } + + target += bytesToWrite; + } + + *sourceStart = source; + *targetStart = target; + return result; +} + + +static BOOL isLegalUTF8(const BYTE* source, int length) +{ + BYTE a; + const BYTE* srcptr = source + length; + + switch (length) + { + default: + return FALSE; + + /* Everything else falls through when "TRUE"... */ + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return FALSE; + + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return FALSE; + + case 2: + if ((a = (*--srcptr)) > 0xBF) return FALSE; + + switch (*source) + { + /* no fall-through in this inner switch */ + case 0xE0: + if (a < 0xA0) return FALSE; + + break; + + case 0xED: + if (a > 0x9F) return FALSE; + + break; + + case 0xF0: + if (a < 0x90) return FALSE; + + break; + + case 0xF4: + if (a > 0x8F) return FALSE; + + break; + + default: + if (a < 0x80) return FALSE; + } + + case 1: + if (*source >= 0x80 && *source < 0xC2) return FALSE; + } + + if (*source > 0xF4) + return FALSE; + + return TRUE; +} + +static ConversionResult _ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* sourceEnd, WCHAR** targetStart, WCHAR* targetEnd, ConversionFlags flags) +{ + WCHAR* target; + const BYTE* source; + BOOL computeLength; + ConversionResult result; + computeLength = (!targetEnd) ? TRUE : FALSE; + result = conversionOK; + source = *sourceStart; + target = *targetStart; + + while (source < sourceEnd) + { + DWORD ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + + if ((source + extraBytesToRead) >= sourceEnd) + { + result = sourceExhausted; + break; + } + + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead + 1)) + { + result = sourceIllegal; + break; + } + + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) + { + case 5: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + + case 4: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + + case 3: + ch += *source++; + ch <<= 6; + + case 2: + ch += *source++; + ch <<= 6; + + case 1: + ch += *source++; + ch <<= 6; + + case 0: + ch += *source++; + } + + ch -= offsetsFromUTF8[extraBytesToRead]; + + if ((target >= targetEnd) && (!computeLength)) + { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + + if (ch <= UNI_MAX_BMP) + { + /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) + { + if (flags == strictConversion) + { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + else + { + if (!computeLength) + *target++ = UNI_REPLACEMENT_CHAR; + else + target++; + } + } + else + { + if (!computeLength) + *target++ = (WCHAR)ch; /* normal case */ + else + target++; + } + } + else if (ch > UNI_MAX_UTF16) + { + if (flags == strictConversion) + { + result = sourceIllegal; + source -= (extraBytesToRead + 1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } + else + { + if (!computeLength) + *target++ = UNI_REPLACEMENT_CHAR; + else + target++; + } + } + else + { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if ((target + 1 >= targetEnd) && (!computeLength)) + { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + + ch -= halfBase; + + if (!computeLength) + { + *target++ = (WCHAR)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (WCHAR)((ch & halfMask) + UNI_SUR_LOW_START); + } + else + { + target++; + target++; + } + } + } + + *sourceStart = source; + *targetStart = target; + return result; +} + +static int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) +{ + int length; + LPWSTR targetStart; + const BYTE* sourceStart; + ConversionResult result; + + /* If cbMultiByte is 0, the function fails */ + + if (cbMultiByte == 0) + return 0; + + /* If cbMultiByte is -1, the string is null-terminated */ + + if (cbMultiByte == -1) + cbMultiByte = (int)strlen((char*)lpMultiByteStr) + 1; + + /* + * if cchWideChar is 0, the function returns the required buffer size + * in characters for lpWideCharStr and makes no use of the output parameter itself. + */ + + if (cchWideChar == 0) + { + sourceStart = (const BYTE*)lpMultiByteStr; + targetStart = (WCHAR*)NULL; + + result = _ConvertUTF8toUTF16(&sourceStart, &sourceStart[cbMultiByte], + &targetStart, NULL, strictConversion); + + length = (int)(targetStart - ((WCHAR*)NULL)); + cchWideChar = length; + } + else + { + sourceStart = (const BYTE*)lpMultiByteStr; + targetStart = lpWideCharStr; + + result = _ConvertUTF8toUTF16(&sourceStart, &sourceStart[cbMultiByte], + &targetStart, &targetStart[cchWideChar], strictConversion); + + length = (int)(targetStart - ((WCHAR*)lpWideCharStr)); + cchWideChar = length; + } + + return cchWideChar; +} + +#endif + + + +bool ex_utf8_to_utf16le(const std::string& from, ex_str_utf16le& to) +{ + int iSize = MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, NULL, 0); + if (iSize <= 0) + return false; + + //++iSize; + to.resize(iSize); + memset(&to[0], 0, sizeof(ex_utf16)); + + MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, &to[0], iSize); + + return true; +} + +#endif diff --git a/common/libex/src/ex_thread.cpp b/common/libex/src/ex_thread.cpp index acdcdf8..9358a77 100644 --- a/common/libex/src/ex_thread.cpp +++ b/common/libex/src/ex_thread.cpp @@ -1,224 +1,224 @@ -#include -#include - -//========================================================= -// -//========================================================= - - -#ifdef EX_OS_WIN32 -unsigned int WINAPI ExThreadBase::_thread_func(LPVOID pParam) -#else - -void *ExThreadBase::_thread_func(void *pParam) -#endif -{ - ExThreadBase *_this = (ExThreadBase *) pParam; - - _this->m_is_running = true; - _this->_thread_loop(); - _this->m_is_running = false; - _this->m_handle = 0; - - EXLOGV(" # thread [%s] exit.\n", _this->m_thread_name.c_str()); - _this->_on_stopped(); - return 0; -} - -ExThreadBase::ExThreadBase(const char *thread_name) : - m_handle(0), - m_is_running(false), - m_need_stop(false) { - m_thread_name = thread_name; -} - -ExThreadBase::~ExThreadBase() { - if(m_is_running) { - EXLOGE(" # thread [%s] not stop before destroy.\n", m_thread_name.c_str()); - } -} - -bool ExThreadBase::start(void) { - m_need_stop = false; - EXLOGV(" . thread [%s] starting.\n", m_thread_name.c_str()); -#ifdef WIN32 - HANDLE h = (HANDLE)_beginthreadex(NULL, 0, _thread_func, (void*)this, 0, NULL); - - if (NULL == h) - { - return false; - } - m_handle = h; -#else - pthread_t ptid = 0; - int ret = pthread_create(&ptid, NULL, _thread_func, (void *) this); - if (ret != 0) { - return false; - } - m_handle = ptid; - -#endif - - return true; -} - -bool ExThreadBase::stop(void) { - if (m_handle == 0) { - EXLOGW("[thread] thread [%s] already stopped.\n", m_thread_name.c_str()); - return true; - } - - EXLOGV("[thread] try to stop thread [%s].\n", m_thread_name.c_str()); - m_need_stop = true; - _on_stop(); - - EXLOGV("[thread] wait thread [%s] exit.\n", m_thread_name.c_str()); - -#ifdef EX_OS_WIN32 - if (WaitForSingleObject(m_handle, INFINITE) != WAIT_OBJECT_0) - { - return false; - } -#else - if (pthread_join(m_handle, NULL) != 0) { - return false; - } -#endif - - return true; -} - -bool ExThreadBase::terminate(void) { -#ifdef EX_OS_WIN32 - return (TerminateThread(m_handle, 1) == TRUE); -#else - return (pthread_cancel(m_handle) == 0); -#endif -} - -//========================================================= -// -//========================================================= - -ExThreadManager::ExThreadManager() {} - -ExThreadManager::~ExThreadManager() { - if (!m_threads.empty()) { - EXLOGE("when destroy thread manager, there are %d thread not exit.\n", m_threads.size()); - stop_all(); - } -} - -void ExThreadManager::stop_all(void) { - ExThreadSmartLock locker(m_lock); - - ex_threads::iterator it = m_threads.begin(); - for (; it != m_threads.end(); ++it) { - (*it)->stop(); - } - m_threads.clear(); -} - -void ExThreadManager::add(ExThreadBase *tb) { - ExThreadSmartLock locker(m_lock); - - ex_threads::iterator it = m_threads.begin(); - for (; it != m_threads.end(); ++it) { - if ((*it) == tb) { - EXLOGE("when add thread to manager, it already exist.\n"); - return; - } - } - - m_threads.push_back(tb); -} - -void ExThreadManager::remove(ExThreadBase *tb) { - ExThreadSmartLock locker(m_lock); - - ex_threads::iterator it = m_threads.begin(); - for (; it != m_threads.end(); ++it) { - if ((*it) == tb) { - m_threads.erase(it); - return; - } - } - EXLOGE("thread not hold by thread-manager while remove it.\n"); -} - -//========================================================= -// -//========================================================= - -ExThreadLock::ExThreadLock() { -#ifdef EX_OS_WIN32 - InitializeCriticalSection(&m_locker); -#else - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m_locker, &attr); - pthread_mutexattr_destroy(&attr); -#endif -} - -ExThreadLock::~ExThreadLock() { -#ifdef EX_OS_WIN32 - DeleteCriticalSection(&m_locker); -#else - pthread_mutex_destroy(&m_locker); -#endif -} - -void ExThreadLock::lock(void) { -#ifdef EX_OS_WIN32 - EnterCriticalSection(&m_locker); -#else - pthread_mutex_lock(&m_locker); -#endif -} - -void ExThreadLock::unlock(void) { -#ifdef EX_OS_WIN32 - LeaveCriticalSection(&m_locker); -#else - pthread_mutex_unlock(&m_locker); -#endif -} - -//========================================================= -// -//========================================================= - -int ex_atomic_add(volatile int *pt, int t) { -#ifdef EX_OS_WIN32 - return (int)InterlockedExchangeAdd((long*)pt, (long)t); -#else - return __sync_add_and_fetch(pt, t); -#endif -} - -int ex_atomic_inc(volatile int *pt) { -#ifdef EX_OS_WIN32 - return (int)InterlockedIncrement((long*)pt); -#else - return __sync_add_and_fetch(pt, 1); -#endif -} - -int ex_atomic_dec(volatile int *pt) { -#ifdef EX_OS_WIN32 - return (int)InterlockedDecrement((long*)pt); -#else - return __sync_add_and_fetch(pt, -1); -#endif -} - - -ex_u64 ex_get_thread_id(void) { -#ifdef EX_OS_WIN32 - return GetCurrentThreadId(); -#else - return (ex_u64) pthread_self(); -#endif -} +#include +#include + +//========================================================= +// +//========================================================= + + +#ifdef EX_OS_WIN32 +unsigned int WINAPI ExThreadBase::_thread_func(LPVOID pParam) +#else + +void *ExThreadBase::_thread_func(void *pParam) +#endif +{ + ExThreadBase *_this = (ExThreadBase *) pParam; + + _this->m_is_running = true; + _this->_thread_loop(); + _this->m_is_running = false; + _this->m_handle = 0; + + EXLOGV(" # thread [%s] exit.\n", _this->m_thread_name.c_str()); + _this->_on_stopped(); + return 0; +} + +ExThreadBase::ExThreadBase(const char *thread_name) : + m_handle(0), + m_is_running(false), + m_need_stop(false) { + m_thread_name = thread_name; +} + +ExThreadBase::~ExThreadBase() { + if(m_is_running) { + EXLOGE(" # thread [%s] not stop before destroy.\n", m_thread_name.c_str()); + } +} + +bool ExThreadBase::start(void) { + m_need_stop = false; + EXLOGV(" . thread [%s] starting.\n", m_thread_name.c_str()); +#ifdef WIN32 + HANDLE h = (HANDLE)_beginthreadex(NULL, 0, _thread_func, (void*)this, 0, NULL); + + if (NULL == h) + { + return false; + } + m_handle = h; +#else + pthread_t ptid = 0; + int ret = pthread_create(&ptid, NULL, _thread_func, (void *) this); + if (ret != 0) { + return false; + } + m_handle = ptid; + +#endif + + return true; +} + +bool ExThreadBase::stop(void) { + if (m_handle == 0) { + EXLOGW("[thread] thread [%s] already stopped.\n", m_thread_name.c_str()); + return true; + } + + EXLOGV("[thread] try to stop thread [%s].\n", m_thread_name.c_str()); + m_need_stop = true; + _on_stop(); + + EXLOGV("[thread] wait thread [%s] exit.\n", m_thread_name.c_str()); + +#ifdef EX_OS_WIN32 + if (WaitForSingleObject(m_handle, INFINITE) != WAIT_OBJECT_0) + { + return false; + } +#else + if (pthread_join(m_handle, NULL) != 0) { + return false; + } +#endif + + return true; +} + +bool ExThreadBase::terminate(void) { +#ifdef EX_OS_WIN32 + return (TerminateThread(m_handle, 1) == TRUE); +#else + return (pthread_cancel(m_handle) == 0); +#endif +} + +//========================================================= +// +//========================================================= + +ExThreadManager::ExThreadManager() {} + +ExThreadManager::~ExThreadManager() { + if (!m_threads.empty()) { + EXLOGE("when destroy thread manager, there are %d thread not exit.\n", m_threads.size()); + stop_all(); + } +} + +void ExThreadManager::stop_all(void) { + ExThreadSmartLock locker(m_lock); + + ex_threads::iterator it = m_threads.begin(); + for (; it != m_threads.end(); ++it) { + (*it)->stop(); + } + m_threads.clear(); +} + +void ExThreadManager::add(ExThreadBase *tb) { + ExThreadSmartLock locker(m_lock); + + ex_threads::iterator it = m_threads.begin(); + for (; it != m_threads.end(); ++it) { + if ((*it) == tb) { + EXLOGE("when add thread to manager, it already exist.\n"); + return; + } + } + + m_threads.push_back(tb); +} + +void ExThreadManager::remove(ExThreadBase *tb) { + ExThreadSmartLock locker(m_lock); + + ex_threads::iterator it = m_threads.begin(); + for (; it != m_threads.end(); ++it) { + if ((*it) == tb) { + m_threads.erase(it); + return; + } + } + EXLOGE("thread not hold by thread-manager while remove it.\n"); +} + +//========================================================= +// +//========================================================= + +ExThreadLock::ExThreadLock() { +#ifdef EX_OS_WIN32 + InitializeCriticalSection(&m_locker); +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_locker, &attr); + pthread_mutexattr_destroy(&attr); +#endif +} + +ExThreadLock::~ExThreadLock() { +#ifdef EX_OS_WIN32 + DeleteCriticalSection(&m_locker); +#else + pthread_mutex_destroy(&m_locker); +#endif +} + +void ExThreadLock::lock(void) { +#ifdef EX_OS_WIN32 + EnterCriticalSection(&m_locker); +#else + pthread_mutex_lock(&m_locker); +#endif +} + +void ExThreadLock::unlock(void) { +#ifdef EX_OS_WIN32 + LeaveCriticalSection(&m_locker); +#else + pthread_mutex_unlock(&m_locker); +#endif +} + +//========================================================= +// +//========================================================= + +int ex_atomic_add(volatile int *pt, int t) { +#ifdef EX_OS_WIN32 + return (int)InterlockedExchangeAdd((long*)pt, (long)t); +#else + return __sync_add_and_fetch(pt, t); +#endif +} + +int ex_atomic_inc(volatile int *pt) { +#ifdef EX_OS_WIN32 + return (int)InterlockedIncrement((long*)pt); +#else + return __sync_add_and_fetch(pt, 1); +#endif +} + +int ex_atomic_dec(volatile int *pt) { +#ifdef EX_OS_WIN32 + return (int)InterlockedDecrement((long*)pt); +#else + return __sync_add_and_fetch(pt, -1); +#endif +} + + +ex_u64 ex_get_thread_id(void) { +#ifdef EX_OS_WIN32 + return GetCurrentThreadId(); +#else + return (ex_u64) pthread_self(); +#endif +} diff --git a/common/libex/src/ex_util.cpp b/common/libex/src/ex_util.cpp index a84a001..c4daeba 100644 --- a/common/libex/src/ex_util.cpp +++ b/common/libex/src/ex_util.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/common/libex/src/ex_winsrv.cpp b/common/libex/src/ex_winsrv.cpp index 4c909f4..0b5087c 100644 --- a/common/libex/src/ex_winsrv.cpp +++ b/common/libex/src/ex_winsrv.cpp @@ -1,4 +1,4 @@ -#include +#include #ifdef EX_OS_WIN32 @@ -44,14 +44,14 @@ ex_rv ex_winsrv_install(const ex_wstr& srv_name, const ex_wstr& disp_name, const } SERVICE_FAILURE_ACTIONS failure_action; - failure_action.dwResetPeriod = 0; // reset failure count to zero ʱ䣬λΪ + failure_action.dwResetPeriod = 0; // reset failure count to zero 的时间,单位为秒 failure_action.lpRebootMsg = NULL; // Message to broadcast to server users before rebooting failure_action.lpCommand = NULL; // Command line of the process for the CreateProcess function to execute in response - failure_action.cActions = 3; // actionĸ + failure_action.cActions = 3; // action数组的个数 SC_ACTION actionarray[3]; - actionarray[0].Type = SC_ACTION_RESTART; // - actionarray[0].Delay = 60000; // λΪ + actionarray[0].Type = SC_ACTION_RESTART; // 重新启动服务 + actionarray[0].Delay = 60000; // 单位为毫秒 actionarray[1].Type = SC_ACTION_RESTART; actionarray[1].Delay = 60000; actionarray[2].Type = SC_ACTION_RESTART; diff --git a/common/teleport/teleport_const.h b/common/teleport/teleport_const.h index 8660e18..1f33d72 100644 --- a/common/teleport/teleport_const.h +++ b/common/teleport/teleport_const.h @@ -1,151 +1,151 @@ -#ifndef __TELEPORT_CONST_H__ -#define __TELEPORT_CONST_H__ - -// עͬͬԵconstļ - -// ļ趨teleportģ֮ͨѶʱĴֵJSONݣ -// - WEB -// - WEBWEB̨ -// - WEB̨COREķ - -//======================================================= -// Urlprotocol -//======================================================= -#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_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_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_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_FLAG_ALL 0xFFFFFFFF -// Ự¼ -#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 //ӵԱỰRDPconsoleѡ -// 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 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 // Ŀ겻 - -// 100~299ͨôֵ - -#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_UNKNOWN_CMD 124 // δ֪ -#define TPE_JSON_FORMAT 125 // JSONʽҪJSONʽݣȴ޷JSONʽ룩 -#define TPE_PARAM 126 // -#define TPE_DATA 127 // ݴ - -// #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_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_CORE_SERVER 200000 // δܼ⵽ķ - - - -#endif // __TELEPORT_CONST_H__ +#ifndef __TELEPORT_CONST_H__ +#define __TELEPORT_CONST_H__ + +// 注意同步更新三个不同语言的const文件 + +// 本文件设定teleport各个模块之间通讯时的错误值(JSON数据),包括: +// - WEB界面与助手 +// - WEB界面与WEB后台 +// - WEB后台与CORE核心服务 + +//======================================================= +// Urlprotocol相关 +//======================================================= +#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_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_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_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_FLAG_ALL 0xFFFFFFFF +// 会话记录相关 +#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选项) +// 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 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 // 目标不存在 + +// 100~299是通用错误值 + +#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_UNKNOWN_CMD 124 // 未知的命令 +#define TPE_JSON_FORMAT 125 // 错误的JSON格式(需要JSON格式数据,但是却无法按JSON格式解码) +#define TPE_PARAM 126 // 参数错误 +#define TPE_DATA 127 // 数据错误 + +// #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_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_CORE_SERVER 200000 // 未能检测到核心服务 + + + +#endif // __TELEPORT_CONST_H__ diff --git a/server/tp_core/common/base_env.cpp b/server/tp_core/common/base_env.cpp index 0975cfd..34f8c07 100644 --- a/server/tp_core/common/base_env.cpp +++ b/server/tp_core/common/base_env.cpp @@ -1,48 +1,48 @@ -#include "base_env.h" - -TppEnvBase::TppEnvBase() -{} - -TppEnvBase::~TppEnvBase() -{} - -bool TppEnvBase::init(TPP_INIT_ARGS* args) -{ - if (NULL == args) - { - EXLOGE("invalid init args(1).\n"); - return false; - } - - EXLOG_USE_LOGGER(args->logger); - - 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; - - 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 (NULL == args->cfg) - { - EXLOGE("invalid init args(3).\n"); - return false; - } - - if (!_on_init(args)) - { - EXLOGE("invalid init args(4).\n"); - return false; - } - - return true; -} +#include "base_env.h" + +TppEnvBase::TppEnvBase() +{} + +TppEnvBase::~TppEnvBase() +{} + +bool TppEnvBase::init(TPP_INIT_ARGS* args) +{ + if (NULL == args) + { + EXLOGE("invalid init args(1).\n"); + return false; + } + + EXLOG_USE_LOGGER(args->logger); + + 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; + + 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 (NULL == args->cfg) + { + EXLOGE("invalid init args(3).\n"); + return false; + } + + if (!_on_init(args)) + { + EXLOGE("invalid init args(4).\n"); + return false; + } + + return true; +} diff --git a/server/tp_core/common/base_env.h b/server/tp_core/common/base_env.h index c57fd41..316216d 100644 --- a/server/tp_core/common/base_env.h +++ b/server/tp_core/common/base_env.h @@ -1,29 +1,29 @@ -#ifndef __TS_BASE_ENV_H__ -#define __TS_BASE_ENV_H__ - -#include "protocol_interface.h" - -class TppEnvBase -{ -public: - TppEnvBase(); - virtual ~TppEnvBase(); - - bool init(TPP_INIT_ARGS* args); - -public: - 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; - -protected: - virtual bool _on_init(TPP_INIT_ARGS* args) = 0; -}; - -#endif // __TS_BASE_ENV_H__ +#ifndef __TS_BASE_ENV_H__ +#define __TS_BASE_ENV_H__ + +#include "protocol_interface.h" + +class TppEnvBase +{ +public: + TppEnvBase(); + virtual ~TppEnvBase(); + + bool init(TPP_INIT_ARGS* args); + +public: + 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; + +protected: + virtual bool _on_init(TPP_INIT_ARGS* args) = 0; +}; + +#endif // __TS_BASE_ENV_H__ diff --git a/server/tp_core/common/base_record.cpp b/server/tp_core/common/base_record.cpp index 10849db..ae0d19f 100644 --- a/server/tp_core/common/base_record.cpp +++ b/server/tp_core/common/base_record.cpp @@ -1,4 +1,4 @@ -#include +#include #include "base_record.h" diff --git a/server/tp_core/common/base_record.h b/server/tp_core/common/base_record.h index cdcabb3..a78d1b0 100644 --- a/server/tp_core/common/base_record.h +++ b/server/tp_core/common/base_record.h @@ -1,101 +1,101 @@ -#ifndef __TS_BASE_RECORD_H__ -#define __TS_BASE_RECORD_H__ - -#include "base_env.h" -#include "ts_membuf.h" -#include "protocol_interface.h" - -#include - -#define MAX_SIZE_PER_FILE 4194304 // 4M = 1024*1024*4 - -#pragma pack(push,1) - -/* - * ¼ - * - * һ¼ΪļһϢļһļ - * ڲ4M5룬ͽдļУͬʱϢļ - * - */ - - -// ¼ļͷ(¼д룬ıIJ) -typedef struct TS_RECORD_HEADER_INFO -{ - ex_u32 magic; // "TPPR" ־ TelePort Protocol Record - ex_u16 ver; // ¼ļ汾ĿǰΪ3 - ex_u32 packages; // ܰ - ex_u32 time_ms; // ܺʱ룩 - //ex_u32 file_size; // ļС -}TS_RECORD_HEADER_INFO; -#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO) - -// ¼ļͷ(̶䲿) -typedef struct TS_RECORD_HEADER_BASIC -{ - ex_u16 protocol_type; // Э飺1=RDP, 2=SSH, 3=Telnet - ex_u16 protocol_sub_type; // Э飺100=RDP-DESKTOP, 200=SSH-SHELL, 201=SSH-SFTP, 300=Telnet - ex_u64 timestamp; // ¼ʼʱ䣨UTCʱ - ex_u16 width; // ʼĻߴ磺 - ex_u16 height; // ʼĻߴ磺 - char user_username[64]; // teleport˺ - char acc_username[64]; // Զû - - char host_ip[40]; // ԶIP - char conn_ip[40]; // ԶIP - ex_u16 conn_port; // Զ˿ - - char client_ip[40]; // ͻIP - - // RDPר - ex_u8 rdp_security; // 0 = RDP, 1 = TLS - - ex_u8 _reserve[512 - 2 - 2 - 8 - 2 - 2 - 64 - 64 - 40 - 40 - 2 - 40 - 1 - ts_record_header_info_size]; -}TS_RECORD_HEADER_BASIC; -#define ts_record_header_basic_size sizeof(TS_RECORD_HEADER_BASIC) - -typedef struct TS_RECORD_HEADER -{ - TS_RECORD_HEADER_INFO info; - TS_RECORD_HEADER_BASIC basic; -}TS_RECORD_HEADER; - -// header֣header-info + header-basic = 512B -#define ts_record_header_size sizeof(TS_RECORD_HEADER) - - -// һݰͷ -typedef struct TS_RECORD_PKG -{ - ex_u8 type; // - ex_u32 size; // ܴСͷ - ex_u32 time_ms; // ʼʱʱ룬ζһӲܳ49죩 - ex_u8 _reserve[3]; // -}TS_RECORD_PKG; - -#pragma pack(pop) - -class TppRecBase -{ -public: - TppRecBase(); - virtual ~TppRecBase(); - - bool begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info); - bool end(); - -protected: - virtual bool _on_begin(const TPP_CONNECT_INFO* info) = 0; - virtual bool _on_end() = 0; - -protected: - ex_wstr m_base_path; // ¼ļ· /usr/local/teleport/data/replay/ssh/123ֱڲӵģΪλỰ¼ļĿ¼ - ex_wstr m_base_fname; // ¼ļļչ֣ڲԴΪϳļȫ¼ļ m_base_path ָĿ¼ - - ex_u64 m_start_time; - - MemBuffer m_cache; -}; - -#endif // __TS_BASE_RECORD_H__ +#ifndef __TS_BASE_RECORD_H__ +#define __TS_BASE_RECORD_H__ + +#include "base_env.h" +#include "ts_membuf.h" +#include "protocol_interface.h" + +#include + +#define MAX_SIZE_PER_FILE 4194304 // 4M = 1024*1024*4 + +#pragma pack(push,1) + +/* + * 录像 + * + * 一个录像分为两个文件,一个信息文件,一个数据文件。 + * 服务内部缓存最大4M,或者5秒,就将数据写入数据文件中,并同时更新信息文件。 + * + */ + + +// 录像文件头(随着录像数据写入,会改变的部分) +typedef struct TS_RECORD_HEADER_INFO +{ + ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record + ex_u16 ver; // 录像文件版本,目前为3 + ex_u32 packages; // 总包数 + ex_u32 time_ms; // 总耗时(毫秒) + //ex_u32 file_size; // 数据文件大小 +}TS_RECORD_HEADER_INFO; +#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO) + +// 录像文件头(固定不变部分) +typedef struct TS_RECORD_HEADER_BASIC +{ + ex_u16 protocol_type; // 协议:1=RDP, 2=SSH, 3=Telnet + ex_u16 protocol_sub_type; // 子协议:100=RDP-DESKTOP, 200=SSH-SHELL, 201=SSH-SFTP, 300=Telnet + ex_u64 timestamp; // 本次录像的起始时间(UTC时间戳) + ex_u16 width; // 初始屏幕尺寸:宽 + ex_u16 height; // 初始屏幕尺寸:高 + char user_username[64]; // teleport账号 + char acc_username[64]; // 远程主机用户名 + + char host_ip[40]; // 远程主机IP + char conn_ip[40]; // 远程主机IP + ex_u16 conn_port; // 远程主机端口 + + char client_ip[40]; // 客户端IP + + // RDP专有 + ex_u8 rdp_security; // 0 = RDP, 1 = TLS + + ex_u8 _reserve[512 - 2 - 2 - 8 - 2 - 2 - 64 - 64 - 40 - 40 - 2 - 40 - 1 - ts_record_header_info_size]; +}TS_RECORD_HEADER_BASIC; +#define ts_record_header_basic_size sizeof(TS_RECORD_HEADER_BASIC) + +typedef struct TS_RECORD_HEADER +{ + TS_RECORD_HEADER_INFO info; + TS_RECORD_HEADER_BASIC basic; +}TS_RECORD_HEADER; + +// header部分(header-info + header-basic) = 512B +#define ts_record_header_size sizeof(TS_RECORD_HEADER) + + +// 一个数据包的头 +typedef struct TS_RECORD_PKG +{ + ex_u8 type; // 包的数据类型 + ex_u32 size; // 这个包的总大小(不含包头) + ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天) + ex_u8 _reserve[3]; // 保留 +}TS_RECORD_PKG; + +#pragma pack(pop) + +class TppRecBase +{ +public: + TppRecBase(); + virtual ~TppRecBase(); + + bool begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info); + bool end(); + +protected: + virtual bool _on_begin(const TPP_CONNECT_INFO* info) = 0; + virtual bool _on_end() = 0; + +protected: + ex_wstr m_base_path; // 录像文件基础路径,例如 /usr/local/teleport/data/replay/ssh/123,数字编号是内部附加的,作为本次会话录像文件的目录名称 + ex_wstr m_base_fname; // 录像文件的文件名,不含扩展名部分,内部会以此为基础合成文件全名,并将录像文件存放在 m_base_path 指向的目录中 + + ex_u64 m_start_time; + + MemBuffer m_cache; +}; + +#endif // __TS_BASE_RECORD_H__ diff --git a/server/tp_core/common/protocol_interface.h b/server/tp_core/common/protocol_interface.h index 50051c6..bc201ec 100644 --- a/server/tp_core/common/protocol_interface.h +++ b/server/tp_core/common/protocol_interface.h @@ -1,100 +1,100 @@ -#ifndef __TP_PROTOCOL_INTERFACE_H__ -#define __TP_PROTOCOL_INTERFACE_H__ - -#include "ts_const.h" -#include - -#ifdef EX_OS_WIN32 -# ifdef TPP_EXPORTS -# define TPP_API __declspec(dllexport) -# else -# define TPP_API __declspec(dllimport) -# endif -#else -# define TPP_API -#endif - -#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; - - // ϢصҪصID - int user_id; - int host_id; - int acc_id; - - char* user_username; // 뱾ӵû - - 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 - - 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 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; - -#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_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_COMMAND_FUNC)(ex_u32 cmd, const char* param); // param is a JSON formatted string. - -#endif // __TP_PROTOCOL_INTERFACE_H__ +#ifndef __TP_PROTOCOL_INTERFACE_H__ +#define __TP_PROTOCOL_INTERFACE_H__ + +#include "ts_const.h" +#include + +#ifdef EX_OS_WIN32 +# ifdef TPP_EXPORTS +# define TPP_API __declspec(dllexport) +# else +# define TPP_API __declspec(dllimport) +# endif +#else +# define TPP_API +#endif + +#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; + + // 与此连接信息相关的三个要素的ID + int user_id; + int host_id; + int acc_id; + + char* user_username; // 申请本次连接的用户名 + + 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 + + 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 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; + +#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_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_COMMAND_FUNC)(ex_u32 cmd, const char* param); // param is a JSON formatted string. + +#endif // __TP_PROTOCOL_INTERFACE_H__ diff --git a/server/tp_core/common/ts_const.h b/server/tp_core/common/ts_const.h index da1fc45..be55510 100644 --- a/server/tp_core/common/ts_const.h +++ b/server/tp_core/common/ts_const.h @@ -1,26 +1,26 @@ -#ifndef __TS_ERRNO_H__ -#define __TS_ERRNO_H__ - -//#include "ts_types.h" - -#define TS_RDP_PROXY_PORT 52089 -#define TS_RDP_PROXY_HOST "0.0.0.0" - -#define TS_SSH_PROXY_PORT 52189 -#define TS_SSH_PROXY_HOST "0.0.0.0" - -#define TS_TELNET_PROXY_PORT 52389 -#define TS_TELNET_PROXY_HOST "0.0.0.0" - -#define TS_HTTP_RPC_PORT 52080 -//#define TS_HTTP_RPC_HOST "127.0.0.1" -#define TS_HTTP_RPC_HOST "localhost" - - -#define TS_RDP_PROTOCOL_RDP 0 -#define TS_RDP_PROTOCOL_TLS 1 -#define TS_RDP_PROTOCOL_HYBRID 2 -#define TS_RDP_PROTOCOL_RDSTLS 4 -#define TS_RDP_PROTOCOL_HYBRID_EX 8 - -#endif // __TS_ERRNO_H__ +#ifndef __TS_ERRNO_H__ +#define __TS_ERRNO_H__ + +//#include "ts_types.h" + +#define TS_RDP_PROXY_PORT 52089 +#define TS_RDP_PROXY_HOST "0.0.0.0" + +#define TS_SSH_PROXY_PORT 52189 +#define TS_SSH_PROXY_HOST "0.0.0.0" + +#define TS_TELNET_PROXY_PORT 52389 +#define TS_TELNET_PROXY_HOST "0.0.0.0" + +#define TS_HTTP_RPC_PORT 52080 +//#define TS_HTTP_RPC_HOST "127.0.0.1" +#define TS_HTTP_RPC_HOST "localhost" + + +#define TS_RDP_PROTOCOL_RDP 0 +#define TS_RDP_PROTOCOL_TLS 1 +#define TS_RDP_PROTOCOL_HYBRID 2 +#define TS_RDP_PROTOCOL_RDSTLS 4 +#define TS_RDP_PROTOCOL_HYBRID_EX 8 + +#endif // __TS_ERRNO_H__ diff --git a/server/tp_core/common/ts_membuf.cpp b/server/tp_core/common/ts_membuf.cpp index c5f063f..f601f6a 100644 --- a/server/tp_core/common/ts_membuf.cpp +++ b/server/tp_core/common/ts_membuf.cpp @@ -1,4 +1,4 @@ -#include "ts_membuf.h" +#include "ts_membuf.h" #include MemBuffer::MemBuffer()// : m_buffer(NULL), m_data_size(0), m_buffer_size(0) @@ -45,7 +45,7 @@ void MemBuffer::reserve(size_t size) return; } - // µĻСȡ MEMBUF_BLOCK_SIZE + // 将新的缓冲区大小取整到 MEMBUF_BLOCK_SIZE 的整数倍 size_t new_size = (size + MEMBUF_BLOCK_SIZE - 1) & ~(MEMBUF_BLOCK_SIZE - 1); //EXLOGD("[mbuf:%p] reserve(2): m_buf: %p, m_buf_size: %d, size: %d, new size: %d.\n", this, m_buffer, m_buffer_size, size, new_size); diff --git a/server/tp_core/common/ts_membuf.h b/server/tp_core/common/ts_membuf.h index 0d7d283..95fa44c 100644 --- a/server/tp_core/common/ts_membuf.h +++ b/server/tp_core/common/ts_membuf.h @@ -1,4 +1,4 @@ -#ifndef __TS_MEMBUF_H__ +#ifndef __TS_MEMBUF_H__ #define __TS_MEMBUF_H__ #include @@ -11,15 +11,15 @@ public: MemBuffer(); virtual ~MemBuffer(); - // sizeֽڵݵĩβܻᵼ» + // 附加size字节的数据到缓冲区末尾(可能会导致缓冲区扩大) void append(const ex_u8* data, size_t size); - // Ϊָֽܻ󻺳С֤Чݲᱻı䣩 + // 缓冲区至少为指定字节数(可能会扩大缓冲区,但不会缩小缓冲区,保证有效数据不会被改变) void reserve(size_t size); - // mЧݸӵԼЧĩβܻ󻺳mݲ + // 将m的有效数据附加到自己的有效数据末尾,可能会扩大缓冲区,m内容不变 void concat(const MemBuffer& m); - // ӻͷƳsizeֽڣСܲʣµЧǰơ + // 从缓冲区头部移除size字节(缓冲区大小可能并不会收缩),剩下的有效数据前移。 void pop(size_t size); - // ջЧΪ0ֽڣ䣩 + // 清空缓冲区(有效数据为0字节,缓冲区不变) void empty(void) { m_data_size = 0; } bool is_empty(void) { return m_data_size == 0; } diff --git a/server/tp_core/common/ts_memstream.cpp b/server/tp_core/common/ts_memstream.cpp index e51c142..64388cb 100644 --- a/server/tp_core/common/ts_memstream.cpp +++ b/server/tp_core/common/ts_memstream.cpp @@ -1,222 +1,222 @@ -#include "ts_memstream.h" - -MemStream::MemStream(MemBuffer& mbuf) : m_mbuf(mbuf) -{ - m_offset = 0; -} - -MemStream::~MemStream() -{} - -void MemStream::reset(void) -{ - m_mbuf.empty(); - rewind(); -} - - -bool MemStream::seek(size_t offset) -{ - if (offset > m_mbuf.size()) - return false; - - m_offset = offset; - return true; -} - -bool MemStream::skip(size_t n) -{ - if (0 == n) - return true; - - if (m_offset + n > m_mbuf.size()) - return false; - m_offset += n; - return true; -} - -bool MemStream::rewind(size_t n) -{ - if (m_offset < n) - return false; - - if (0 == n) - m_offset = 0; - else - m_offset -= n; - return true; -} - -ex_u8 MemStream::get_u8(void) -{ - ASSERT(m_offset + 1 <= m_mbuf.size()); - - ex_u8 v = (m_mbuf.data() + m_offset)[0]; - m_offset++; - return v; -} - -ex_u16 MemStream::get_u16_le(void) -{ - ASSERT(m_offset + 2 <= m_mbuf.size()); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - ex_u16 v = (ex_u16)(p[0] | (p[1] << 8)); -#else - ex_u16 v = ((ex_u16*)p)[0]; -#endif - m_offset += 2; - return v; -} - -ex_u16 MemStream::get_u16_be(void) -{ - ASSERT(m_offset + 2 <= m_mbuf.size()); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - ex_u16 v = ((ex_u16*)p)[0]; -#else - ex_u16 v = (ex_u16)((p[0] << 8) | p[1]); -#endif - m_offset += 2; - return v; -} - - -ex_u32 MemStream::get_u32_le(void) -{ - ASSERT(m_offset + 4 <= m_mbuf.size()); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - ex_u32 v = (ex_u32)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); -#else - ex_u32 v = ((ex_u32*)p)[0]; -#endif - m_offset += 4; - return v; -} - -ex_u32 MemStream::get_u32_be(void) -{ - ASSERT(m_offset + 4 <= m_mbuf.size()); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - ex_u32 v = ((ex_u32*)p)[0]; -#else - ex_u32 v = (ex_u32)((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); -#endif - m_offset += 4; - return v; -} - -ex_u8* MemStream::get_bin(size_t n) -{ - ASSERT(m_offset + 4 <= m_mbuf.size()); - ex_u8* p = m_mbuf.data() + m_offset; - m_offset += n; - return p; -} - - -void MemStream::put_zero(size_t n) -{ - m_mbuf.reserve(m_mbuf.size() + n); - memset(m_mbuf.data() + m_offset, 0, n); - m_offset += n; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - -void MemStream::put_u8(ex_u8 v) -{ - m_mbuf.reserve(m_mbuf.size() + 1); - - (m_mbuf.data() + m_offset)[0] = v; - m_offset++; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - -void MemStream::put_u16_le(ex_u16 v) -{ - m_mbuf.reserve(m_mbuf.size() + 2); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - p[0] = (ex_u8)v; - p[1] = (ex_u8)(v >> 8); -#else - ((ex_u16*)p)[0] = v; -#endif - m_offset += 2; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - -void MemStream::put_u16_be(ex_u16 v) -{ - m_mbuf.reserve(m_mbuf.size() + 2); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - ((ex_u16*)p)[0] = v; -#else - ex_u8* _v = (ex_u8*)&v; - p[0] = _v[1]; - p[1] = _v[0]; -#endif - m_offset += 2; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - -void MemStream::put_u32_le(ex_u32 v) -{ - m_mbuf.reserve(m_mbuf.size() + 4); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - p[0] = (ex_u8)v; - p[1] = (ex_u8)(v >> 8); - p[2] = (ex_u8)(v >> 16); - p[3] = (ex_u8)(v >> 24); -#else - ((ex_u32*)p)[0] = v; -#endif - m_offset += 4; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - -void MemStream::put_u32_be(ex_u32 v) -{ - m_mbuf.reserve(m_mbuf.size() + 4); - - ex_u8* p = m_mbuf.data() + m_offset; -#if defined(B_ENDIAN) - ((ex_u32*)p)[0] = v; -#else - ex_u8* _v = (ex_u8*)&v; - p[0] = _v[3]; - p[1] = _v[2]; - p[2] = _v[1]; - p[3] = _v[0]; -#endif - m_offset += 4; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - -void MemStream::put_bin(const ex_u8* p, size_t n) -{ - m_mbuf.reserve(m_mbuf.size() + n); - memcpy(m_mbuf.data() + m_offset, p, n); - m_offset += n; - if (m_mbuf.size() < m_offset) - m_mbuf.size(m_offset); -} - +#include "ts_memstream.h" + +MemStream::MemStream(MemBuffer& mbuf) : m_mbuf(mbuf) +{ + m_offset = 0; +} + +MemStream::~MemStream() +{} + +void MemStream::reset(void) +{ + m_mbuf.empty(); + rewind(); +} + + +bool MemStream::seek(size_t offset) +{ + if (offset > m_mbuf.size()) + return false; + + m_offset = offset; + return true; +} + +bool MemStream::skip(size_t n) +{ + if (0 == n) + return true; + + if (m_offset + n > m_mbuf.size()) + return false; + m_offset += n; + return true; +} + +bool MemStream::rewind(size_t n) +{ + if (m_offset < n) + return false; + + if (0 == n) + m_offset = 0; + else + m_offset -= n; + return true; +} + +ex_u8 MemStream::get_u8(void) +{ + ASSERT(m_offset + 1 <= m_mbuf.size()); + + ex_u8 v = (m_mbuf.data() + m_offset)[0]; + m_offset++; + return v; +} + +ex_u16 MemStream::get_u16_le(void) +{ + ASSERT(m_offset + 2 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u16 v = (ex_u16)(p[0] | (p[1] << 8)); +#else + ex_u16 v = ((ex_u16*)p)[0]; +#endif + m_offset += 2; + return v; +} + +ex_u16 MemStream::get_u16_be(void) +{ + ASSERT(m_offset + 2 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u16 v = ((ex_u16*)p)[0]; +#else + ex_u16 v = (ex_u16)((p[0] << 8) | p[1]); +#endif + m_offset += 2; + return v; +} + + +ex_u32 MemStream::get_u32_le(void) +{ + ASSERT(m_offset + 4 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u32 v = (ex_u32)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); +#else + ex_u32 v = ((ex_u32*)p)[0]; +#endif + m_offset += 4; + return v; +} + +ex_u32 MemStream::get_u32_be(void) +{ + ASSERT(m_offset + 4 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u32 v = ((ex_u32*)p)[0]; +#else + ex_u32 v = (ex_u32)((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +#endif + m_offset += 4; + return v; +} + +ex_u8* MemStream::get_bin(size_t n) +{ + ASSERT(m_offset + 4 <= m_mbuf.size()); + ex_u8* p = m_mbuf.data() + m_offset; + m_offset += n; + return p; +} + + +void MemStream::put_zero(size_t n) +{ + m_mbuf.reserve(m_mbuf.size() + n); + memset(m_mbuf.data() + m_offset, 0, n); + m_offset += n; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u8(ex_u8 v) +{ + m_mbuf.reserve(m_mbuf.size() + 1); + + (m_mbuf.data() + m_offset)[0] = v; + m_offset++; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u16_le(ex_u16 v) +{ + m_mbuf.reserve(m_mbuf.size() + 2); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + p[0] = (ex_u8)v; + p[1] = (ex_u8)(v >> 8); +#else + ((ex_u16*)p)[0] = v; +#endif + m_offset += 2; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u16_be(ex_u16 v) +{ + m_mbuf.reserve(m_mbuf.size() + 2); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ((ex_u16*)p)[0] = v; +#else + ex_u8* _v = (ex_u8*)&v; + p[0] = _v[1]; + p[1] = _v[0]; +#endif + m_offset += 2; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u32_le(ex_u32 v) +{ + m_mbuf.reserve(m_mbuf.size() + 4); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + p[0] = (ex_u8)v; + p[1] = (ex_u8)(v >> 8); + p[2] = (ex_u8)(v >> 16); + p[3] = (ex_u8)(v >> 24); +#else + ((ex_u32*)p)[0] = v; +#endif + m_offset += 4; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u32_be(ex_u32 v) +{ + m_mbuf.reserve(m_mbuf.size() + 4); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ((ex_u32*)p)[0] = v; +#else + ex_u8* _v = (ex_u8*)&v; + p[0] = _v[3]; + p[1] = _v[2]; + p[2] = _v[1]; + p[3] = _v[0]; +#endif + m_offset += 4; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_bin(const ex_u8* p, size_t n) +{ + m_mbuf.reserve(m_mbuf.size() + n); + memcpy(m_mbuf.data() + m_offset, p, n); + m_offset += n; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + diff --git a/server/tp_core/common/ts_memstream.h b/server/tp_core/common/ts_memstream.h index 9ab425c..ddbb45f 100644 --- a/server/tp_core/common/ts_memstream.h +++ b/server/tp_core/common/ts_memstream.h @@ -1,45 +1,45 @@ -#ifndef __TS_MEMSTREAM_H__ -#define __TS_MEMSTREAM_H__ - -#include "ts_membuf.h" - -class MemStream -{ -public: - MemStream(MemBuffer& mbuf); - ~MemStream(); - - void reset(void); // ջݣͷڴ棩ָƶͷ - - bool seek(size_t offset); // ƶָ뵽ָƫƣԽ磬򷵻ش - bool rewind(size_t n = 0); // nֽڣԽ磬شnΪ0˵ʼ - bool skip(size_t n); // nֽڣԽ磬򷵻ش - - ex_u8* ptr(void) { return m_mbuf.data() + m_offset; } // صǰָ - size_t offset(void) { return m_offset; } // صǰָʼƫ - - size_t left(void) { return m_mbuf.size() - m_offset; } // ʣݵĴСӵǰָ뵽β - - ex_u8 get_u8(void); - ex_u16 get_u16_le(void); - ex_u16 get_u16_be(void); - ex_u32 get_u32_le(void); - ex_u32 get_u32_be(void); - ex_u8* get_bin(size_t n); // صǰָݵָ룬ڲƫƻƶnֽ - - void put_zero(size_t n); // nֽڵ0 - void put_u8(ex_u8 v); - void put_u16_le(ex_u16 v); - void put_u16_be(ex_u16 v); - void put_u32_le(ex_u32 v); - void put_u32_be(ex_u32 v); - void put_bin(const ex_u8* p, size_t n); // pָnֽ - - size_t size(void) { return m_mbuf.size(); } - -private: - MemBuffer& m_mbuf; - size_t m_offset; -}; - -#endif // __TS_MEMSTREAM_H__ +#ifndef __TS_MEMSTREAM_H__ +#define __TS_MEMSTREAM_H__ + +#include "ts_membuf.h" + +class MemStream +{ +public: + MemStream(MemBuffer& mbuf); + ~MemStream(); + + void reset(void); // 清空缓冲区数据(但不释放内存),指针移动到头部 + + bool seek(size_t offset); // 移动指针到指定偏移,如果越界,则返回错误 + bool rewind(size_t n = 0); // 回退n字节,如果越界,返回错误,如果n为0,则回退到最开始处 + bool skip(size_t n); // 跳过n字节,如果越界,则返回错误 + + ex_u8* ptr(void) { return m_mbuf.data() + m_offset; } // 返回当前数据指针 + size_t offset(void) { return m_offset; } // 返回当前指针相对数据起始的偏移 + + size_t left(void) { return m_mbuf.size() - m_offset; } // 返回剩余数据的大小(从当前数据指针到缓冲区结尾) + + ex_u8 get_u8(void); + ex_u16 get_u16_le(void); + ex_u16 get_u16_be(void); + ex_u32 get_u32_le(void); + ex_u32 get_u32_be(void); + ex_u8* get_bin(size_t n); // 返回当前指向的数据的指针,内部偏移会向后移动n字节 + + void put_zero(size_t n); // 填充n字节的0 + void put_u8(ex_u8 v); + void put_u16_le(ex_u16 v); + void put_u16_be(ex_u16 v); + void put_u32_le(ex_u32 v); + void put_u32_be(ex_u32 v); + void put_bin(const ex_u8* p, size_t n); // 填充p指向的n字节数据 + + size_t size(void) { return m_mbuf.size(); } + +private: + MemBuffer& m_mbuf; + size_t m_offset; +}; + +#endif // __TS_MEMSTREAM_H__