pull/32/head
Apex Liu 2017-04-06 18:46:58 +08:00
parent 60432f04ae
commit 669fc79eae
12 changed files with 2120 additions and 1392 deletions

2
.gitignore vendored
View File

@ -44,6 +44,7 @@ __pycache__
/external/libssh-win-static/lib
/external/mbedtls
/external/sqlite
/external/libuv
/client/tools/putty
/client/tools/winscp
@ -69,3 +70,4 @@ __pycache__
# for not finished code
/common/libex/test
/client/tp_rdp
/server/tp_core/protocol/rdp

View File

@ -1,118 +1,141 @@
#ifndef __LIB_EX_PLATFORM_H__
#define __LIB_EX_PLATFORM_H__
#if defined(_WIN32) || defined(WIN32)
# define EX_OS_WIN32
#elif defined(__linux__)
# define EX_OS_LINUX
# define EX_OS_UNIX
#elif defined(__APPLE__)
# define EX_OS_MACOS
# define EX_OS_UNIX
#else
# error unsupported platform.
#endif
// compiler
#ifdef EX_OS_WIN32
# ifndef _MSC_VER
# error need VisualStudio on Windows.
# endif
# if _MSC_VER < 1900 // need VisualStudio 2015 and above.
# error need VisualStudio 2015 and above.
# endif
#endif
#ifdef EX_OS_WIN32
# if !defined(UNICODE) && !defined(_UNICODE)
# error "Does not support `Multi-Byte Character Set` on Windows."
# endif
# ifdef _DEBUG
# ifndef EX_DEBUG
# define EX_DEBUG
# endif
# endif
#endif
#ifdef EX_OS_WIN32
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0500 // 0x0500 = Windows2000
# endif
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
# define _CRT_RAND_S // for rand_s().
# include <windows.h>
# include <tchar.h>
# include <shlwapi.h>
# include <shellapi.h>
# define _CSTDIO_
# define _CSTRING_
# define _CWCHAR_
# include <strsafe.h>
# include <WinSock2.h>
# include <direct.h>
#else
# include <locale.h>
# include <string.h>
# include <stdio.h>
# include <stdlib.h> // free()
# include <stdarg.h> // va_start()
# include <unistd.h> // readlink()
# include <wchar.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
#endif
/*
* On Windows PATH_MAX does not exist but MAX_PATH does.
* WinAPI MAX_PATH limit is only 256. MSVCR fuctions does not have this limit.
* Redefine PATH_MAX for Windows to support longer path names.
*/
#if defined(EX_OS_WIN32)
# ifdef PATH_MAX
# undef PATH_MAX /* On Windows override PATH_MAX if defined. */
# endif
# define PATH_MAX 1024
#elif defined(EX_OS_LINUX)
# ifndef PATH_MAX
# define PATH_MAX 1024
# endif
#elif defined(EX_OS_MACOS)
# define PATH_MAX 1024 /* Recommended value for OSX. */
#endif
// assert
#ifdef EX_DEBUG
# define ASSERT(exp)
# define CHECK(exp) do { if (!(exp)) abort(); } while (0)
//# define DEBUG_CHECKS (0)
#else
# include <assert.h>
# define ASSERT(exp) assert(exp)
# define CHECK(exp) assert(exp)
//# define DEBUG_CHECKS (1)
#endif
#ifndef UNUSED
# if defined(_MSC_VER)
# define UNUSED(x) (void)(x)
# elif defined(__GUNC__)
# defined UNUSED(x) UNUSED_ ## x __attribute__((unused))
# elif defined(__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
# elif defined(__cplusplus)
# define UNUSED(x)
# else
# define UNUSED(x) (void)(x)
# endif
#endif
#ifdef EX_OS_WIN32
# pragma comment(lib, "shlwapi.lib")
#endif
#endif // __LIB_EX_PLATFORM_H__
#ifndef __LIB_EX_PLATFORM_H__
#define __LIB_EX_PLATFORM_H__
#if defined(_WIN32) || defined(WIN32)
# define EX_OS_WIN32
#elif defined(__linux__)
# define EX_OS_LINUX
# define EX_OS_UNIX
#elif defined(__APPLE__)
# define EX_OS_MACOS
# define EX_OS_UNIX
#else
# error unsupported platform.
#endif
// compiler
#ifdef EX_OS_WIN32
# ifndef _MSC_VER
# error need VisualStudio on Windows.
# endif
# if _MSC_VER < 1900 // need VisualStudio 2015 and above.
# error need VisualStudio 2015 and above.
# endif
#endif
#ifdef EX_OS_WIN32
# if !defined(UNICODE) && !defined(_UNICODE)
# error "Does not support `Multi-Byte Character Set` on Windows."
# endif
# ifdef _DEBUG
# ifndef EX_DEBUG
# define EX_DEBUG
# endif
# endif
#endif
#ifdef EX_OS_WIN32
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0500 // 0x0500 = Windows2000
# endif
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
# define _CRT_RAND_S // for rand_s().
# include <windows.h>
# include <tchar.h>
# include <shlwapi.h>
# include <shellapi.h>
# define _CSTDIO_
# define _CSTRING_
# define _CWCHAR_
# include <strsafe.h>
# include <WinSock2.h>
# include <direct.h>
#else
# include <locale.h>
# include <string.h>
# include <stdio.h>
# include <stdlib.h> // free()
# include <stdarg.h> // va_start()
# include <unistd.h> // readlink()
# include <wchar.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
#endif
/*
* On Windows PATH_MAX does not exist but MAX_PATH does.
* WinAPI MAX_PATH limit is only 256. MSVCR fuctions does not have this limit.
* Redefine PATH_MAX for Windows to support longer path names.
*/
#if defined(EX_OS_WIN32)
# ifdef PATH_MAX
# undef PATH_MAX /* On Windows override PATH_MAX if defined. */
# endif
# define PATH_MAX 1024
#elif defined(EX_OS_LINUX)
# ifndef PATH_MAX
# define PATH_MAX 1024
# endif
#elif defined(EX_OS_MACOS)
# define PATH_MAX 1024 /* Recommended value for OSX. */
#endif
// assert
#ifdef EX_DEBUG
# define ASSERT(exp)
# define CHECK(exp) do { if (!(exp)) abort(); } while (0)
//# define DEBUG_CHECKS (0)
#else
# include <assert.h>
# define ASSERT(exp) assert(exp)
# define CHECK(exp) assert(exp)
//# define DEBUG_CHECKS (1)
#endif
#ifndef UNUSED
# if defined(_MSC_VER)
# define UNUSED(x) (void)(x)
# elif defined(__GUNC__)
# defined UNUSED(x) UNUSED_ ## x __attribute__((unused))
# elif defined(__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
# elif defined(__cplusplus)
# define UNUSED(x)
# else
# define UNUSED(x) (void)(x)
# endif
#endif
/* check endian */
#if !(defined(L_ENDIAN) || defined(B_ENDIAN))
# if !defined(__BYTE_ORDER) && defined(__linux__)
# include <endian.h>
# endif
# if defined(BYTE_ORDER)
# if BYTE_ORDER == BIG_ENDIAN
# define B_ENDIAN
# else
# define L_ENDIAN
# endif
# endif
# if !(defined(L_ENDIAN) || defined(B_ENDIAN))
# if defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__hppa__)
# define B_ENDIAN
# else
# define L_ENDIAN
# endif
# endif
#endif
#ifdef EX_OS_WIN32
# pragma comment(lib, "shlwapi.lib")
#endif
#endif // __LIB_EX_PLATFORM_H__

View File

@ -1,83 +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 <string>
#include <vector>
typedef std::string ex_astr;
typedef std::wstring ex_wstr;
typedef std::vector<ex_astr> ex_astrs;
typedef std::vector<ex_wstr> ex_wstrs;
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);
#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 <string>
#include <vector>
typedef std::string ex_astr;
typedef std::wstring ex_wstr;
typedef std::vector<ex_astr> ex_astrs;
typedef std::vector<ex_wstr> ex_wstrs;
typedef std::vector<ex_utf16> 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_utf16_le(const std::string& from, ex_str_utf16le& to);
#endif
#endif // __LIB_EX_STR_H__

View File

@ -1,44 +1,44 @@
#ifndef __LIB_EX_TYPE_H__
#define __LIB_EX_TYPE_H__
#include "ex_platform.h"
#include <vector>
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_u16 ex_utf16;
#endif
typedef int EX_BOOL;
#define EX_TRUE 1
#define EX_FALSE 0
typedef std::vector<ex_u8> ex_bin;
typedef std::vector<char> 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 <vector>
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_u16 ex_utf16;
#endif
typedef int EX_BOOL;
#define EX_TRUE 1
#define EX_FALSE 0
typedef std::vector<ex_u8> ex_bin;
typedef std::vector<char> 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__

View File

@ -1,44 +1,45 @@
#ifndef __LIB_EX_UTIL_H__
#define __LIB_EX_UTIL_H__
#include <ex/ex_types.h>
#include <ex/ex_str.h>
#ifdef EX_OS_WIN32
# include <time.h>
//# include <io.h>
//# include <stdio.h>
// #include <direct.h>
#else
// #include <dirent.h>
# include <dlfcn.h>
# include <sys/time.h>
#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_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);
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);
#endif // __LIB_EX_UTIL_H__
#ifndef __LIB_EX_UTIL_H__
#define __LIB_EX_UTIL_H__
#include <ex/ex_types.h>
#include <ex/ex_str.h>
#ifdef EX_OS_WIN32
# include <time.h>
//# include <io.h>
//# include <stdio.h>
// #include <direct.h>
#else
// #include <dirent.h>
# include <dlfcn.h>
# include <sys/time.h>
#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);
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);
#endif // __LIB_EX_UTIL_H__

File diff suppressed because it is too large Load Diff

View File

@ -1,251 +1,264 @@
#include <ex/ex_platform.h>
#include <ex/ex_util.h>
#include <ex/ex_str.h>
#include <ex/ex_log.h>
EX_BOOL ex_initialize(const char* lc_ctype)
{
#ifdef EX_OS_UNIX
const char* _lc_default = "en_US.UTF-8";
const char* _lc_ctype = NULL;
char* _loc = NULL;
if(NULL == lc_ctype)
_lc_ctype = _lc_default;
else
_lc_ctype = lc_ctype;
_loc = setlocale(LC_CTYPE, _lc_ctype);
if(NULL == _loc)
return EX_FALSE;
// if(0 != strcmp(_loc, _lc_ctype))
// return EX_FALSE;
return EX_TRUE;
#else
return EX_TRUE;
#endif
}
void ex_free(void* buffer)
{
if (NULL == buffer)
return;
free(buffer);
}
const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen)
{
const ex_u8* cursor = NULL;
const ex_u8* last_possible_needle_location = haystack + haystacklen - needlelen;
/** Easy answers */
if (needlelen > haystacklen) return(NULL);
if (needle == NULL) return(NULL);
if (haystack == NULL) return(NULL);
if (needlelen == 0) return(NULL);
if (haystacklen == 0) return(NULL);
for (cursor = haystack; cursor <= last_possible_needle_location; cursor++)
{
if (memcmp(needle, cursor, needlelen) == 0)
return cursor;
}
return(NULL);
}
void ex_printf(const char* fmt, ...)
{
if (NULL == fmt || 0 == strlen(fmt))
return;
va_list valist;
va_start(valist, fmt);
//_ts_printf_a(TS_COLOR_GRAY, TS_COLOR_BLACK, fmt, valist);
char _tmp[4096] = { 0 };
#ifdef EX_OS_WIN32
vsnprintf_s(_tmp, 4096, 4095, fmt, valist);
printf_s("%s", _tmp);
fflush(stdout);
#else
vsnprintf(_tmp, 4095, fmt, valist);
printf("%s", _tmp);
fflush(stdout);
#endif
va_end(valist);
}
void ex_wprintf(const wchar_t* fmt, ...)
{
if (NULL == fmt || 0 == wcslen(fmt))
return;
va_list valist;
va_start(valist, fmt);
wchar_t _tmp[4096] = { 0 };
#ifdef EX_OS_WIN32
_vsnwprintf_s(_tmp, 4096, 4095, fmt, valist);
wprintf_s(L"%s", _tmp);
fflush(stdout);
#else
vswprintf(_tmp, 4095, fmt, valist);
ex_astr _astr_tmp;
ex_wstr2astr(_tmp, _astr_tmp);
printf("%s", _astr_tmp.c_str());
fflush(stdout);
#endif
va_end(valist);
}
ex_u64 ex_get_tick_count(void)
{
#ifdef EX_OS_WIN32
# if (_WIN32_WINNT >= 0x0600)
return GetTickCount64();
# else
LARGE_INTEGER TicksPerSecond = { 0 };
LARGE_INTEGER Tick;
if (!TicksPerSecond.QuadPart)
QueryPerformanceFrequency(&TicksPerSecond);
QueryPerformanceCounter(&Tick);
ex_u64 Seconds = Tick.QuadPart / TicksPerSecond.QuadPart;
ex_u64 LeftPart = Tick.QuadPart - (TicksPerSecond.QuadPart*Seconds);
ex_u64 MillSeconds = LeftPart * 1000 / TicksPerSecond.QuadPart;
ex_u64 Ret = Seconds * 1000 + MillSeconds;
return Ret;
# endif
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ((ex_u64)ts.tv_sec * 1000 + (ex_u64)ts.tv_nsec / 1000000);
#endif
}
void ex_sleep_ms(int ms)
{
#ifdef EX_OS_WIN32
Sleep(ms);
#else
usleep(ms * 1000);
#endif
}
EX_BOOL ex_localtime_now(int* t, struct tm* dt)
{
// if (NULL == dt)
// return EX_FALSE;
//struct tm *_tmp;
#ifdef EX_OS_WIN32
struct tm _tmp;
__time32_t timep;
_time32(&timep);
if (0 != _localtime32_s(&_tmp, &timep))
return EX_FALSE;
if(NULL != dt)
memcpy(dt, &_tmp, sizeof(struct tm));
#else
struct tm *_tmp;
time_t timep;
time(&timep);
_tmp = localtime(&timep); //get server's time
if (_tmp == NULL)
return NULL;
if(NULL != dt)
memcpy(dt, _tmp, sizeof(struct tm));
#endif
if (NULL != t)
*t = (int)timep;
return EX_TRUE;
}
FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode)
{
FILE* f = NULL;
#ifdef EX_OS_WIN32
errno_t err = 0;
err = _wfopen_s(&f, filename.c_str(), mode);
if (0 == err)
return f;
else
return NULL;
#else
ex_astr _fname;
ex_wstr2astr(filename, _fname);
ex_astr _mode;
ex_wstr2astr(mode, _mode);
f = fopen(_fname.c_str(), _mode.c_str());
return f;
#endif
}
EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path)
{
EX_DYLIB_HANDLE handle = NULL;
#ifdef EX_OS_WIN32
handle = LoadLibraryExW(dylib_path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (NULL == handle)
{
EXLOGE_WIN(L"LoadLibraryEx('%ls') failed.\n", dylib_path);
return NULL;
}
#else
ex_astr path;
if (!ex_wstr2astr(dylib_path, path, EX_CODEPAGE_UTF8))
{
EXLOGE("convert dylib_path failed.\n");
return NULL;
}
handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (NULL == handle)
{
EXLOGE("dlopen() failed: %s.\n", dlerror());
return NULL;
}
#endif
return handle;
}
void ex_dlclose(EX_DYLIB_HANDLE dylib)
{
#ifdef EX_OS_WIN32
FreeLibrary(dylib);
#else
dlclose(dylib);
#endif
}
static int _inet_ntop4(const unsigned char *src, char *dst, size_t size) {
static const char fmt[] = "%u.%u.%u.%u";
char tmp[32];
int l;
l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
if (l <= 0 || (size_t)l >= size) {
return -1;
}
ex_strcpy(dst, size, tmp);
dst[size - 1] = '\0';
return 0;
}
int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size)
{
return _inet_ntop4((const unsigned char*)&(src->sin_addr), dst, size);
}
#include <ex/ex_platform.h>
#include <ex/ex_util.h>
#include <ex/ex_str.h>
#include <ex/ex_log.h>
EX_BOOL ex_initialize(const char* lc_ctype)
{
#ifdef EX_OS_UNIX
const char* _lc_default = "en_US.UTF-8";
const char* _lc_ctype = NULL;
char* _loc = NULL;
if(NULL == lc_ctype)
_lc_ctype = _lc_default;
else
_lc_ctype = lc_ctype;
_loc = setlocale(LC_CTYPE, _lc_ctype);
if(NULL == _loc)
return EX_FALSE;
// if(0 != strcmp(_loc, _lc_ctype))
// return EX_FALSE;
return EX_TRUE;
#else
return EX_TRUE;
#endif
}
void ex_free(void* buffer)
{
if (NULL == buffer)
return;
free(buffer);
}
const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen)
{
const ex_u8* cursor = NULL;
const ex_u8* last_possible_needle_location = haystack + haystacklen - needlelen;
/** Easy answers */
if (needlelen > haystacklen) return(NULL);
if (needle == NULL) return(NULL);
if (haystack == NULL) return(NULL);
if (needlelen == 0) return(NULL);
if (haystacklen == 0) return(NULL);
for (cursor = haystack; cursor <= last_possible_needle_location; cursor++)
{
if (memcmp(needle, cursor, needlelen) == 0)
return cursor;
}
return(NULL);
}
void ex_mem_reverse(ex_u8* p, size_t l)
{
ex_u8 temp = 0;
size_t i = 0, j = 0;
for (i = 0, j = l - 1; i < j; i++, j--)
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
void ex_printf(const char* fmt, ...)
{
if (NULL == fmt || 0 == strlen(fmt))
return;
va_list valist;
va_start(valist, fmt);
//_ts_printf_a(TS_COLOR_GRAY, TS_COLOR_BLACK, fmt, valist);
char _tmp[4096] = { 0 };
#ifdef EX_OS_WIN32
vsnprintf_s(_tmp, 4096, 4095, fmt, valist);
printf_s("%s", _tmp);
fflush(stdout);
#else
vsnprintf(_tmp, 4095, fmt, valist);
printf("%s", _tmp);
fflush(stdout);
#endif
va_end(valist);
}
void ex_wprintf(const wchar_t* fmt, ...)
{
if (NULL == fmt || 0 == wcslen(fmt))
return;
va_list valist;
va_start(valist, fmt);
wchar_t _tmp[4096] = { 0 };
#ifdef EX_OS_WIN32
_vsnwprintf_s(_tmp, 4096, 4095, fmt, valist);
wprintf_s(L"%s", _tmp);
fflush(stdout);
#else
vswprintf(_tmp, 4095, fmt, valist);
ex_astr _astr_tmp;
ex_wstr2astr(_tmp, _astr_tmp);
printf("%s", _astr_tmp.c_str());
fflush(stdout);
#endif
va_end(valist);
}
ex_u64 ex_get_tick_count(void)
{
#ifdef EX_OS_WIN32
# if (_WIN32_WINNT >= 0x0600)
return GetTickCount64();
# else
LARGE_INTEGER TicksPerSecond = { 0 };
LARGE_INTEGER Tick;
if (!TicksPerSecond.QuadPart)
QueryPerformanceFrequency(&TicksPerSecond);
QueryPerformanceCounter(&Tick);
ex_u64 Seconds = Tick.QuadPart / TicksPerSecond.QuadPart;
ex_u64 LeftPart = Tick.QuadPart - (TicksPerSecond.QuadPart*Seconds);
ex_u64 MillSeconds = LeftPart * 1000 / TicksPerSecond.QuadPart;
ex_u64 Ret = Seconds * 1000 + MillSeconds;
return Ret;
# endif
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ((ex_u64)ts.tv_sec * 1000 + (ex_u64)ts.tv_nsec / 1000000);
#endif
}
void ex_sleep_ms(int ms)
{
#ifdef EX_OS_WIN32
Sleep(ms);
#else
usleep(ms * 1000);
#endif
}
EX_BOOL ex_localtime_now(int* t, struct tm* dt)
{
// if (NULL == dt)
// return EX_FALSE;
//struct tm *_tmp;
#ifdef EX_OS_WIN32
struct tm _tmp;
__time32_t timep;
_time32(&timep);
if (0 != _localtime32_s(&_tmp, &timep))
return EX_FALSE;
if(NULL != dt)
memcpy(dt, &_tmp, sizeof(struct tm));
#else
struct tm *_tmp;
time_t timep;
time(&timep);
_tmp = localtime(&timep); //get server's time
if (_tmp == NULL)
return NULL;
if(NULL != dt)
memcpy(dt, _tmp, sizeof(struct tm));
#endif
if (NULL != t)
*t = (int)timep;
return EX_TRUE;
}
FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode)
{
FILE* f = NULL;
#ifdef EX_OS_WIN32
errno_t err = 0;
err = _wfopen_s(&f, filename.c_str(), mode);
if (0 == err)
return f;
else
return NULL;
#else
ex_astr _fname;
ex_wstr2astr(filename, _fname);
ex_astr _mode;
ex_wstr2astr(mode, _mode);
f = fopen(_fname.c_str(), _mode.c_str());
return f;
#endif
}
EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path)
{
EX_DYLIB_HANDLE handle = NULL;
#ifdef EX_OS_WIN32
handle = LoadLibraryExW(dylib_path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (NULL == handle)
{
EXLOGE_WIN(L"LoadLibraryEx('%ls') failed.\n", dylib_path);
return NULL;
}
#else
ex_astr path;
if (!ex_wstr2astr(dylib_path, path, EX_CODEPAGE_UTF8))
{
EXLOGE("convert dylib_path failed.\n");
return NULL;
}
handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (NULL == handle)
{
EXLOGE("dlopen() failed: %s.\n", dlerror());
return NULL;
}
#endif
return handle;
}
void ex_dlclose(EX_DYLIB_HANDLE dylib)
{
#ifdef EX_OS_WIN32
FreeLibrary(dylib);
#else
dlclose(dylib);
#endif
}
static int _inet_ntop4(const unsigned char *src, char *dst, size_t size) {
static const char fmt[] = "%u.%u.%u.%u";
char tmp[32];
int l;
l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
if (l <= 0 || (size_t)l >= size) {
return -1;
}
ex_strcpy(dst, size, tmp);
dst[size - 1] = '\0';
return 0;
}
int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size)
{
return _inet_ntop4((const unsigned char*)&(src->sin_addr), dst, size);
}

8
external/readme.md vendored
View File

@ -31,5 +31,13 @@ teleport项目用到的第三方库
https://git.libssh.org/projects/libssh.git/snapshot
libssh-0.7.4.zip
Windows平台使用预制的libssh-static工程进行编译。
- libuv
https://github.com/libuv/libuv
v1.11.0.zip
注意teleport项目使用源代码直接编译因此解压缩源代码到此即可。

View File

@ -0,0 +1,219 @@
#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 (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);
}

View File

@ -0,0 +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__

View File

@ -1,255 +1,255 @@
#include "ssh_proxy.h"
#include "tpp_env.h"
SshProxy g_ssh_proxy;
SshProxy::SshProxy() :
ExThreadBase("ssh-proxy-thread"),
m_bind(NULL)
{
}
SshProxy::~SshProxy()
{
if (NULL != m_bind)
ssh_bind_free(m_bind);
ssh_finalize();
ts_sftp_sessions::iterator it = m_sftp_sessions.begin();
for (; it != m_sftp_sessions.end(); ++it)
{
delete it->second;
}
m_sftp_sessions.clear();
}
bool SshProxy::init(void)
{
m_host_ip = g_ssh_env.bind_ip;
m_host_port = g_ssh_env.bind_port;
m_bind = ssh_bind_new();
if (NULL == m_bind)
{
EXLOGE("[ssh] can not create bind.\n");
return false;
}
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDADDR, m_host_ip.c_str()))
{
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDADDR.\n");
return false;
}
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDPORT, &m_host_port))
{
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDPORT.\n");
return false;
}
ex_wstr _key_file = g_ssh_env.etc_path;
ex_path_join(_key_file, false, L"tp_ssh_server.key", NULL);
ex_astr key_file;
ex_wstr2astr(_key_file, key_file);
EXLOGV("[ssh] try to load ssh-server-key: %s\n", key_file.c_str());
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_RSAKEY, key_file.c_str()))
{
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_RSAKEY.\n");
return false;
}
if (ssh_bind_listen(m_bind) < 0)
{
EXLOGE("[ssh] listening to socket: %s\n", ssh_get_error(m_bind));
return false;
}
return true;
}
void SshProxy::_thread_loop(void)
{
EXLOGV("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
_run();
EXLOGV("[ssh] main-loop end.\n");
}
void SshProxy::_set_stop_flag(void)
{
m_stop_flag = true;
if (m_is_running)
{
// 用一个变通的方式来结束阻塞中的监听,就是连接一下它。
ex_astr host_ip = m_host_ip;
if (host_ip == "0.0.0.0")
host_ip = "127.0.0.1";
ssh_session _session = ssh_new();
ssh_options_set(_session, SSH_OPTIONS_HOST, host_ip.c_str());
ssh_options_set(_session, SSH_OPTIONS_PORT, &m_host_port);
int _timeout_us = 100000;
ssh_options_set(_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us);
ssh_connect(_session);
ssh_free(_session);
}
m_thread_mgr.stop_all();
}
void SshProxy::_run(void)
{
for (;;)
{
// 注意ssh_new()出来的指针如果遇到停止标志本函数内部就释放了否则这个指针交给了SshSession类实例管理其析构时会释放。
ssh_session sess_to_client = ssh_new();
struct sockaddr_storage sock_client;
char ip[32] = { 0 };
int len = sizeof(ip);
if (ssh_bind_accept(m_bind, sess_to_client) != SSH_OK)
{
EXLOGE("[ssh] accepting a connection failed: %s.\n", ssh_get_error(m_bind));
continue;
}
EXLOGD("[ssh] ssh_bind_accept() returned...\n");
if (m_stop_flag)
{
ssh_free(sess_to_client);
break;
}
SshSession* sess = new SshSession(this, sess_to_client);
#ifdef EX_OS_WIN32
getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, &len);
#else
getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, (unsigned int*)&len);
#endif
sockaddr_in* addrin = (sockaddr_in*)&sock_client;
if (0 == ex_ip4_name(addrin, ip, sizeof(ip)))
{
sess->client_ip(ip);
sess->client_port(addrin->sin_port);
}
EXLOGV("[ssh] ------ NEW SSH CLIENT [%s:%d] ------\n", sess->client_ip(), sess->client_port());
{
ExThreadSmartLock locker(m_lock);
m_sessions.insert(std::make_pair(sess, 0));
}
sess->start();
}
// 等待所有工作线程退出
m_thread_mgr.stop_all();
}
void SshProxy::_dump_sftp_sessions(void)
{
ts_sftp_sessions::iterator it = m_sftp_sessions.begin();
for (; it != m_sftp_sessions.end(); ++it)
{
EXLOGD("ssh-proxy session: sid: %s\n", it->first.c_str());
}
}
void SshProxy::add_sftp_session_info(const ex_astr& sid, const ex_astr& host_ip, int host_port, const ex_astr& user_name, const ex_astr& user_auth, int auth_mode)
{
ExThreadSmartLock locker(m_lock);
EXLOGD("[ssh] add sftp session-id: %s\n", sid.c_str());
ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid);
if (it != m_sftp_sessions.end())
{
EXLOGD("[ssh] sftp-session-id '%s' already exists.\n", sid.c_str());
it->second->ref_count++;
return;
}
TS_SFTP_SESSION_INFO* info = new TS_SFTP_SESSION_INFO;
info->host_ip = host_ip;
info->host_port = host_port;
info->user_name = user_name;
info->user_auth = user_auth;
info->auth_mode = auth_mode;
info->ref_count = 1;
if (!m_sftp_sessions.insert(std::make_pair(sid, info)).second)
{
EXLOGE("[ssh] ssh-proxy can not insert a sftp-session-id.\n");
}
_dump_sftp_sessions();
}
bool SshProxy::get_sftp_session_info(const ex_astr& sid, TS_SFTP_SESSION_INFO& info)
{
ExThreadSmartLock locker(m_lock);
EXLOGD("[ssh] try to get info by sftp session-id: %s\n", sid.c_str());
_dump_sftp_sessions();
ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid);
if (it == m_sftp_sessions.end())
{
EXLOGD("sftp-session '%s' not exists.\n", sid.c_str());
return false;
}
info.host_ip = it->second->host_ip;
info.host_port = it->second->host_port;
info.user_name = it->second->user_name;
info.user_auth = it->second->user_auth;
info.auth_mode = it->second->auth_mode;
info.ref_count = it->second->ref_count;
return true;
}
void SshProxy::remove_sftp_sid(const ex_astr& sid)
{
EXLOGD("[ssh] try to remove sftp session-id: %s\n", sid.c_str());
ExThreadSmartLock locker(m_lock);
ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid);
if (it == m_sftp_sessions.end())
{
EXLOGE("[ssh] ssh-proxy when remove sftp sid, it not in charge.\n");
return;
}
it->second->ref_count--;
if (it->second->ref_count <= 0)
{
delete it->second;
m_sftp_sessions.erase(it);
EXLOGD("[ssh] sftp session-id '%s' removed.\n", sid.c_str());
}
}
void SshProxy::session_finished(SshSession* sess)
{
ExThreadSmartLock locker(m_lock);
ts_ssh_sessions::iterator it = m_sessions.find(sess);
if (it != m_sessions.end())
{
m_sessions.erase(it);
EXLOGV("[ssh] client %s:%d session removed.\n", sess->client_ip(), sess->client_port());
}
else
{
EXLOGW("[ssh] when session %s:%d end, it not in charge.\n", sess->client_ip(), sess->client_port());
}
delete sess;
}
#include "ssh_proxy.h"
#include "tpp_env.h"
SshProxy g_ssh_proxy;
SshProxy::SshProxy() :
ExThreadBase("ssh-proxy-thread"),
m_bind(NULL)
{
}
SshProxy::~SshProxy()
{
if (NULL != m_bind)
ssh_bind_free(m_bind);
ssh_finalize();
ts_sftp_sessions::iterator it = m_sftp_sessions.begin();
for (; it != m_sftp_sessions.end(); ++it)
{
delete it->second;
}
m_sftp_sessions.clear();
}
bool SshProxy::init(void)
{
m_host_ip = g_ssh_env.bind_ip;
m_host_port = g_ssh_env.bind_port;
m_bind = ssh_bind_new();
if (NULL == m_bind)
{
EXLOGE("[ssh] can not create bind.\n");
return false;
}
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDADDR, m_host_ip.c_str()))
{
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDADDR.\n");
return false;
}
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDPORT, &m_host_port))
{
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDPORT.\n");
return false;
}
ex_wstr _key_file = g_ssh_env.etc_path;
ex_path_join(_key_file, false, L"tp_ssh_server.key", NULL);
ex_astr key_file;
ex_wstr2astr(_key_file, key_file);
EXLOGV("[ssh] try to load ssh-server-key: %s\n", key_file.c_str());
if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_RSAKEY, key_file.c_str()))
{
EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_RSAKEY.\n");
return false;
}
if (ssh_bind_listen(m_bind) < 0)
{
EXLOGE("[ssh] listening to socket: %s\n", ssh_get_error(m_bind));
return false;
}
return true;
}
void SshProxy::_thread_loop(void)
{
EXLOGV("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
_run();
EXLOGV("[ssh] main-loop end.\n");
}
void SshProxy::_set_stop_flag(void)
{
m_stop_flag = true;
if (m_is_running)
{
// 用一个变通的方式来结束阻塞中的监听,就是连接一下它。
ex_astr host_ip = m_host_ip;
if (host_ip == "0.0.0.0")
host_ip = "127.0.0.1";
ssh_session _session = ssh_new();
ssh_options_set(_session, SSH_OPTIONS_HOST, host_ip.c_str());
ssh_options_set(_session, SSH_OPTIONS_PORT, &m_host_port);
int _timeout_us = 100000;
ssh_options_set(_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us);
ssh_connect(_session);
ssh_free(_session);
}
m_thread_mgr.stop_all();
}
void SshProxy::_run(void)
{
for (;;)
{
// 注意ssh_new()出来的指针如果遇到停止标志本函数内部就释放了否则这个指针交给了SshSession类实例管理其析构时会释放。
ssh_session sess_to_client = ssh_new();
struct sockaddr_storage sock_client;
char ip[32] = { 0 };
int len = sizeof(ip);
if (ssh_bind_accept(m_bind, sess_to_client) != SSH_OK)
{
EXLOGE("[ssh] accepting a connection failed: %s.\n", ssh_get_error(m_bind));
continue;
}
EXLOGD("[ssh] ssh_bind_accept() returned...\n");
if (m_stop_flag)
{
ssh_free(sess_to_client);
break;
}
SshSession* sess = new SshSession(this, sess_to_client);
#ifdef EX_OS_WIN32
getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, &len);
#else
getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, (unsigned int*)&len);
#endif
sockaddr_in* addrin = (sockaddr_in*)&sock_client;
if (0 == ex_ip4_name(addrin, ip, sizeof(ip)))
{
sess->client_ip(ip);
sess->client_port(addrin->sin_port);
}
EXLOGV("[ssh] ------ NEW SSH CLIENT [%s:%d] ------\n", sess->client_ip(), sess->client_port());
{
ExThreadSmartLock locker(m_lock);
m_sessions.insert(std::make_pair(sess, 0));
}
sess->start();
}
// 等待所有工作线程退出
m_thread_mgr.stop_all();
}
void SshProxy::_dump_sftp_sessions(void)
{
ts_sftp_sessions::iterator it = m_sftp_sessions.begin();
for (; it != m_sftp_sessions.end(); ++it)
{
EXLOGD("ssh-proxy session: sid: %s\n", it->first.c_str());
}
}
void SshProxy::add_sftp_session_info(const ex_astr& sid, const ex_astr& host_ip, int host_port, const ex_astr& user_name, const ex_astr& user_auth, int auth_mode)
{
ExThreadSmartLock locker(m_lock);
EXLOGD("[ssh] add sftp session-id: %s\n", sid.c_str());
ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid);
if (it != m_sftp_sessions.end())
{
EXLOGD("[ssh] sftp-session-id '%s' already exists.\n", sid.c_str());
it->second->ref_count++;
return;
}
TS_SFTP_SESSION_INFO* info = new TS_SFTP_SESSION_INFO;
info->host_ip = host_ip;
info->host_port = host_port;
info->user_name = user_name;
info->user_auth = user_auth;
info->auth_mode = auth_mode;
info->ref_count = 1;
if (!m_sftp_sessions.insert(std::make_pair(sid, info)).second)
{
EXLOGE("[ssh] ssh-proxy can not insert a sftp-session-id.\n");
}
_dump_sftp_sessions();
}
bool SshProxy::get_sftp_session_info(const ex_astr& sid, TS_SFTP_SESSION_INFO& info)
{
ExThreadSmartLock locker(m_lock);
EXLOGD("[ssh] try to get info by sftp session-id: %s\n", sid.c_str());
_dump_sftp_sessions();
ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid);
if (it == m_sftp_sessions.end())
{
EXLOGD("sftp-session '%s' not exists.\n", sid.c_str());
return false;
}
info.host_ip = it->second->host_ip;
info.host_port = it->second->host_port;
info.user_name = it->second->user_name;
info.user_auth = it->second->user_auth;
info.auth_mode = it->second->auth_mode;
info.ref_count = it->second->ref_count;
return true;
}
void SshProxy::remove_sftp_sid(const ex_astr& sid)
{
EXLOGD("[ssh] try to remove sftp session-id: %s\n", sid.c_str());
ExThreadSmartLock locker(m_lock);
ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid);
if (it == m_sftp_sessions.end())
{
EXLOGE("[ssh] ssh-proxy when remove sftp sid, it not in charge.\n");
return;
}
it->second->ref_count--;
if (it->second->ref_count <= 0)
{
delete it->second;
m_sftp_sessions.erase(it);
EXLOGD("[ssh] sftp session-id '%s' removed.\n", sid.c_str());
}
}
void SshProxy::session_finished(SshSession* sess)
{
ExThreadSmartLock locker(m_lock);
ts_ssh_sessions::iterator it = m_sessions.find(sess);
if (it != m_sessions.end())
{
m_sessions.erase(it);
EXLOGV("[ssh] client %s:%d session removed.\n", sess->client_ip(), sess->client_port());
}
else
{
EXLOGW("[ssh] when session %s:%d end, it not in charge.\n", sess->client_ip(), sess->client_port());
}
delete sess;
}

View File

@ -1,218 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FDA16D20-09B7-45AF-ADF1-DAF3EF2C0531}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>tpssh</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>tpssh</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;TPSSH_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;TPSSH_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\common\libex\include\ex.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_const.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_ini.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_log.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_path.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_platform.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_str.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_thread.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\sftp.h" />
<ClInclude Include="..\..\common\base_env.h" />
<ClInclude Include="..\..\common\base_record.h" />
<ClInclude Include="..\..\common\protocol_interface.h" />
<ClInclude Include="..\..\common\ts_const.h" />
<ClInclude Include="..\..\common\ts_membuf.h" />
<ClInclude Include="ssh_proxy.h" />
<ClInclude Include="ssh_recorder.h" />
<ClInclude Include="ssh_session.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="tpp_env.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\common\libex\src\ex_ini.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_log.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_path.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_str.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_thread.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_util.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_winsrv.cpp" />
<ClCompile Include="..\..\common\base_env.cpp" />
<ClCompile Include="..\..\common\base_record.cpp" />
<ClCompile Include="..\..\common\ts_membuf.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ssh_proxy.cpp" />
<ClCompile Include="ssh_recorder.cpp" />
<ClCompile Include="ssh_session.cpp" />
<ClCompile Include="stdafx.cpp" />
<ClCompile Include="tpp_env.cpp" />
<ClCompile Include="tpssh.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FDA16D20-09B7-45AF-ADF1-DAF3EF2C0531}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>tpssh</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>tpssh</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\common\libex\include\ex.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_const.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_ini.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_log.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_path.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_platform.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_str.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_thread.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" />
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h" />
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\sftp.h" />
<ClInclude Include="..\..\common\base_env.h" />
<ClInclude Include="..\..\common\base_record.h" />
<ClInclude Include="..\..\common\protocol_interface.h" />
<ClInclude Include="..\..\common\ts_const.h" />
<ClInclude Include="..\..\common\ts_membuf.h" />
<ClInclude Include="ssh_proxy.h" />
<ClInclude Include="ssh_recorder.h" />
<ClInclude Include="ssh_session.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="tpp_env.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\common\libex\src\ex_ini.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_log.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_path.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_str.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_thread.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_util.cpp" />
<ClCompile Include="..\..\..\..\common\libex\src\ex_winsrv.cpp" />
<ClCompile Include="..\..\common\base_env.cpp" />
<ClCompile Include="..\..\common\base_record.cpp" />
<ClCompile Include="..\..\common\ts_membuf.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ssh_proxy.cpp" />
<ClCompile Include="ssh_recorder.cpp" />
<ClCompile Include="ssh_session.cpp" />
<ClCompile Include="stdafx.cpp" />
<ClCompile Include="tpp_env.cpp" />
<ClCompile Include="tpssh.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>