mirror of https://github.com/tp4a/teleport
try to fix thread problem when use libuv.
parent
25d562ccf4
commit
b1524fd6a0
|
@ -31,10 +31,12 @@ public:
|
||||||
bool terminate(void);
|
bool terminate(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// 线程循环
|
// main loop of this thread.
|
||||||
virtual void _thread_loop(void) = 0;
|
virtual void _thread_loop(void) = 0;
|
||||||
// 设置停止标志,让线程能够正常结束
|
// called by another thread when thread ready to stop.
|
||||||
virtual void _set_stop_flag(void) = 0;
|
virtual void _on_stop(void) {};
|
||||||
|
// called inside thread when thread fully stopped.
|
||||||
|
virtual void _on_stopped(void) {};
|
||||||
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
static unsigned int WINAPI _thread_func(LPVOID lpParam);
|
static unsigned int WINAPI _thread_func(LPVOID lpParam);
|
||||||
|
@ -46,7 +48,7 @@ protected:
|
||||||
ex_astr m_thread_name;
|
ex_astr m_thread_name;
|
||||||
EX_THREAD_HANDLE m_handle;
|
EX_THREAD_HANDLE m_handle;
|
||||||
bool m_is_running;
|
bool m_is_running;
|
||||||
bool m_stop_flag;
|
bool m_need_stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,36 +9,38 @@
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
unsigned int WINAPI ExThreadBase::_thread_func(LPVOID pParam)
|
unsigned int WINAPI ExThreadBase::_thread_func(LPVOID pParam)
|
||||||
#else
|
#else
|
||||||
void* ExThreadBase::_thread_func(void* pParam)
|
|
||||||
|
void *ExThreadBase::_thread_func(void *pParam)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ExThreadBase* p = (ExThreadBase*)pParam;
|
ExThreadBase *_this = (ExThreadBase *) pParam;
|
||||||
ex_astr thread_name = p->m_thread_name;
|
|
||||||
p->m_is_running = true;
|
|
||||||
p->_thread_loop();
|
|
||||||
p->m_is_running = false;
|
|
||||||
// if(!p->m_stop_by_request)
|
|
||||||
// p->m_thread_manager->_remove_thread(p);
|
|
||||||
|
|
||||||
EXLOGV(" # thread [%s] end.\n", thread_name.c_str());
|
_this->m_is_running = true;
|
||||||
|
_this->_thread_loop();
|
||||||
|
_this->m_is_running = false;
|
||||||
|
_this->m_handle = 0;
|
||||||
|
|
||||||
|
_this->_on_stopped();
|
||||||
|
|
||||||
|
EXLOGV(" # thread [%s] exit.\n", _this->m_thread_name.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExThreadBase::ExThreadBase(const char* thread_name) :
|
ExThreadBase::ExThreadBase(const char *thread_name) :
|
||||||
m_handle(0),
|
m_handle(0),
|
||||||
m_is_running(false),
|
m_is_running(false),
|
||||||
m_stop_flag(false)
|
m_need_stop(false) {
|
||||||
{
|
|
||||||
m_thread_name = thread_name;
|
m_thread_name = thread_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExThreadBase::~ExThreadBase()
|
ExThreadBase::~ExThreadBase() {
|
||||||
{
|
if(m_is_running) {
|
||||||
|
EXLOGE(" # thread [%s] not stop before destroy.\n", m_thread_name.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExThreadBase::start(void)
|
bool ExThreadBase::start(void) {
|
||||||
{
|
m_need_stop = false;
|
||||||
EXLOGV(" . thread [%s] starting.\n", m_thread_name.c_str());
|
EXLOGV(" . thread [%s] starting.\n", m_thread_name.c_str());
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, _thread_func, (void*)this, 0, NULL);
|
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, _thread_func, (void*)this, 0, NULL);
|
||||||
|
@ -47,12 +49,11 @@ bool ExThreadBase::start(void)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_handle = h;
|
m_listener_handle = h;
|
||||||
#else
|
#else
|
||||||
pthread_t ptid = 0;
|
pthread_t ptid = 0;
|
||||||
int ret = pthread_create(&ptid, NULL, _thread_func, (void*)this);
|
int ret = pthread_create(&ptid, NULL, _thread_func, (void *) this);
|
||||||
if (ret != 0)
|
if (ret != 0) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_handle = ptid;
|
m_handle = ptid;
|
||||||
|
@ -62,24 +63,25 @@ bool ExThreadBase::start(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExThreadBase::stop(void)
|
bool ExThreadBase::stop(void) {
|
||||||
{
|
if (m_handle == 0) {
|
||||||
EXLOGV("[thread] try to stop thread [%s].\n", m_thread_name.c_str());
|
EXLOGW("[thread] thread [%s] already stopped.\n", m_thread_name.c_str());
|
||||||
_set_stop_flag();
|
|
||||||
|
|
||||||
EXLOGV("[thread] wait thread [%s] end.\n", m_thread_name.c_str());
|
|
||||||
|
|
||||||
if(m_handle == 0)
|
|
||||||
return true;
|
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
|
#ifdef EX_OS_WIN32
|
||||||
if (WaitForSingleObject(m_handle, INFINITE) != WAIT_OBJECT_0)
|
if (WaitForSingleObject(m_listener_handle, INFINITE) != WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (pthread_join(m_handle, NULL) != 0)
|
if (pthread_join(m_handle, NULL) != 0) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,12 +89,11 @@ bool ExThreadBase::stop(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExThreadBase::terminate(void)
|
bool ExThreadBase::terminate(void) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
return TerminateThread(m_handle, 1) ? true : false;
|
return (TerminateThread(m_listener_handle, 1) == TRUE);
|
||||||
#else
|
#else
|
||||||
return pthread_cancel(m_handle) == 0 ? true : false;
|
return (pthread_cancel(m_handle) == 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,39 +101,31 @@ bool ExThreadBase::terminate(void)
|
||||||
//
|
//
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
ExThreadManager::ExThreadManager()
|
ExThreadManager::ExThreadManager() {}
|
||||||
{}
|
|
||||||
|
|
||||||
ExThreadManager::~ExThreadManager()
|
ExThreadManager::~ExThreadManager() {
|
||||||
{
|
if (!m_threads.empty()) {
|
||||||
if (m_threads.size() > 0)
|
|
||||||
{
|
|
||||||
EXLOGE("when destroy thread manager, there are %d thread not exit.\n", m_threads.size());
|
EXLOGE("when destroy thread manager, there are %d thread not exit.\n", m_threads.size());
|
||||||
stop_all();
|
stop_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExThreadManager::stop_all(void)
|
void ExThreadManager::stop_all(void) {
|
||||||
{
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
ex_threads::iterator it = m_threads.begin();
|
ex_threads::iterator it = m_threads.begin();
|
||||||
for (; it != m_threads.end(); ++it)
|
for (; it != m_threads.end(); ++it) {
|
||||||
{
|
|
||||||
(*it)->stop();
|
(*it)->stop();
|
||||||
}
|
}
|
||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExThreadManager::add(ExThreadBase* tb)
|
void ExThreadManager::add(ExThreadBase *tb) {
|
||||||
{
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
ex_threads::iterator it = m_threads.begin();
|
ex_threads::iterator it = m_threads.begin();
|
||||||
for (; it != m_threads.end(); ++it)
|
for (; it != m_threads.end(); ++it) {
|
||||||
{
|
if ((*it) == tb) {
|
||||||
if ((*it) == tb)
|
|
||||||
{
|
|
||||||
EXLOGE("when add thread to manager, it already exist.\n");
|
EXLOGE("when add thread to manager, it already exist.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -141,29 +134,24 @@ void ExThreadManager::add(ExThreadBase* tb)
|
||||||
m_threads.push_back(tb);
|
m_threads.push_back(tb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExThreadManager::remove(ExThreadBase* tb)
|
void ExThreadManager::remove(ExThreadBase *tb) {
|
||||||
{
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
ex_threads::iterator it = m_threads.begin();
|
ex_threads::iterator it = m_threads.begin();
|
||||||
for (; it != m_threads.end(); ++it)
|
for (; it != m_threads.end(); ++it) {
|
||||||
{
|
if ((*it) == tb) {
|
||||||
if ((*it) == tb)
|
|
||||||
{
|
|
||||||
//delete (*it);
|
|
||||||
m_threads.erase(it);
|
m_threads.erase(it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXLOGE("when remove thread from manager, it not exist.\n");
|
EXLOGE("thread not hold by thread-manager while remove it.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
//
|
//
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
ExThreadLock::ExThreadLock()
|
ExThreadLock::ExThreadLock() {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
InitializeCriticalSection(&m_locker);
|
InitializeCriticalSection(&m_locker);
|
||||||
#else
|
#else
|
||||||
|
@ -175,8 +163,7 @@ ExThreadLock::ExThreadLock()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ExThreadLock::~ExThreadLock()
|
ExThreadLock::~ExThreadLock() {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
DeleteCriticalSection(&m_locker);
|
DeleteCriticalSection(&m_locker);
|
||||||
#else
|
#else
|
||||||
|
@ -184,8 +171,7 @@ ExThreadLock::~ExThreadLock()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExThreadLock::lock(void)
|
void ExThreadLock::lock(void) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
EnterCriticalSection(&m_locker);
|
EnterCriticalSection(&m_locker);
|
||||||
#else
|
#else
|
||||||
|
@ -193,8 +179,7 @@ void ExThreadLock::lock(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExThreadLock::unlock(void)
|
void ExThreadLock::unlock(void) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
LeaveCriticalSection(&m_locker);
|
LeaveCriticalSection(&m_locker);
|
||||||
#else
|
#else
|
||||||
|
@ -206,8 +191,7 @@ void ExThreadLock::unlock(void)
|
||||||
//
|
//
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
int ex_atomic_add(volatile int* pt, int t)
|
int ex_atomic_add(volatile int *pt, int t) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
return (int)InterlockedExchangeAdd((long*)pt, (long)t);
|
return (int)InterlockedExchangeAdd((long*)pt, (long)t);
|
||||||
#else
|
#else
|
||||||
|
@ -215,8 +199,7 @@ int ex_atomic_add(volatile int* pt, int t)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ex_atomic_inc(volatile int* pt)
|
int ex_atomic_inc(volatile int *pt) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
return (int)InterlockedIncrement((long*)pt);
|
return (int)InterlockedIncrement((long*)pt);
|
||||||
#else
|
#else
|
||||||
|
@ -224,8 +207,7 @@ int ex_atomic_inc(volatile int* pt)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ex_atomic_dec(volatile int* pt)
|
int ex_atomic_dec(volatile int *pt) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
return (int)InterlockedDecrement((long*)pt);
|
return (int)InterlockedDecrement((long*)pt);
|
||||||
#else
|
#else
|
||||||
|
@ -234,11 +216,10 @@ int ex_atomic_dec(volatile int* pt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ex_u64 ex_get_thread_id(void)
|
ex_u64 ex_get_thread_id(void) {
|
||||||
{
|
|
||||||
#ifdef EX_OS_WIN32
|
#ifdef EX_OS_WIN32
|
||||||
return GetCurrentThreadId();
|
return GetCurrentThreadId();
|
||||||
#else
|
#else
|
||||||
return (ex_u64)pthread_self();
|
return (ex_u64) pthread_self();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,9 @@
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/core/ts_web_rpc.h" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/core/ts_web_rpc.h" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_conn.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_conn.cpp" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_conn.h" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_conn.h" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_keys.cpp" charset="GBK" />
|
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_package.cpp" charset="GBK" />
|
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_package.h" charset="GBK" />
|
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_proxy.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_proxy.cpp" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_session.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_session.cpp" charset="GBK" />
|
||||||
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_session.h" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_proxy.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_proxy.cpp" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_proxy.h" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_proxy.h" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_recorder.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_recorder.cpp" charset="GBK" />
|
||||||
|
@ -43,7 +41,10 @@
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_session.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_session.cpp" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_session.h" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_session.h" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_conn.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_conn.cpp" charset="GBK" />
|
||||||
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_conn.h" charset="GBK" />
|
||||||
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_proxy.cpp" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_session.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_session.cpp" charset="GBK" />
|
||||||
|
<file url="file://$PROJECT_DIR$/tp_core/protocol/telnet/telnet_session.h" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_web/src/main.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_web/src/main.cpp" charset="GBK" />
|
||||||
<file url="file://$PROJECT_DIR$/tp_web/src/ts_env.cpp" charset="GBK" />
|
<file url="file://$PROJECT_DIR$/tp_web/src/ts_env.cpp" charset="GBK" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -4,7 +4,8 @@ project(teleport)
|
||||||
MESSAGE(STATUS "operation system is ${CMAKE_SYSTEM}")
|
MESSAGE(STATUS "operation system is ${CMAKE_SYSTEM}")
|
||||||
MESSAGE(STATUS "current source directory is ${CMAKE_CURRENT_SOURCE_DIR}")
|
MESSAGE(STATUS "current source directory is ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${teleport_SOURCE_DIR}/../out/server/x64/bin")
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../out/server/x64/bin")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../out/server/x64/bin")
|
||||||
|
|
||||||
set(CMAKE_CONFIGURATION_TYPES Debug Release)
|
set(CMAKE_CONFIGURATION_TYPES Debug Release)
|
||||||
|
|
||||||
|
@ -13,13 +14,13 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||||
MESSAGE(STATUS "build on macOS...")
|
MESSAGE(STATUS "build on macOS...")
|
||||||
set(OS_MACOS 1)
|
set(OS_MACOS 1)
|
||||||
set(OS_POSIX 1)
|
set(OS_POSIX 1)
|
||||||
set(TP_EXTERNAL_RELEASE_DIR "${teleport_SOURCE_DIR}/../external/macos/release")
|
set(TP_EXTERNAL_RELEASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../external/macos/release")
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||||
set(OS_LINUX 1)
|
set(OS_LINUX 1)
|
||||||
set(OS_POSIX 1)
|
set(OS_POSIX 1)
|
||||||
MESSAGE(STATUS "build on Linux...")
|
MESSAGE(STATUS "build on Linux...")
|
||||||
add_subdirectory(tp_web/src)
|
add_subdirectory(tp_web/src)
|
||||||
set(TP_EXTERNAL_RELEASE_DIR "${teleport_SOURCE_DIR}/../external/linux/release")
|
set(TP_EXTERNAL_RELEASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../external/linux/release")
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||||
MESSAGE(FATAL_ERROR "unsupported platform: Windows")
|
MESSAGE(FATAL_ERROR "unsupported platform: Windows")
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -359,9 +359,8 @@ void _sig_handler(int signum, siginfo_t* info, void* ptr)
|
||||||
{
|
{
|
||||||
if (signum == SIGINT || signum == SIGTERM)
|
if (signum == SIGINT || signum == SIGTERM)
|
||||||
{
|
{
|
||||||
EXLOGW("[core] received signal SIGINT, exit now.\n");
|
EXLOGW("\n[core] received signal SIGINT, exit now.\n");
|
||||||
g_exit_flag = true;
|
g_exit_flag = true;
|
||||||
// exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ void TsHttpRpc::_thread_loop(void)
|
||||||
{
|
{
|
||||||
EXLOGI("[core] TeleportServer-RPC ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
EXLOGI("[core] TeleportServer-RPC ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
||||||
|
|
||||||
while (!m_stop_flag)
|
while (!m_need_stop)
|
||||||
{
|
{
|
||||||
mg_mgr_poll(&m_mg_mgr, 500);
|
mg_mgr_poll(&m_mg_mgr, 500);
|
||||||
}
|
}
|
||||||
|
@ -70,10 +70,6 @@ void TsHttpRpc::_thread_loop(void)
|
||||||
EXLOGV("[core] rpc main loop end.\n");
|
EXLOGV("[core] rpc main loop end.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TsHttpRpc::_set_stop_flag(void)
|
|
||||||
{
|
|
||||||
m_stop_flag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TsHttpRpc::init(void)
|
bool TsHttpRpc::init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _thread_loop(void);
|
void _thread_loop(void);
|
||||||
void _set_stop_flag(void);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ex_rv _parse_request(struct http_message* req, ex_astr& func_cmd, Json::Value& json_param);
|
ex_rv _parse_request(struct http_message* req, ex_astr& func_cmd, Json::Value& json_param);
|
||||||
|
|
|
@ -10,32 +10,31 @@
|
||||||
|
|
||||||
bool g_exit_flag = false;
|
bool g_exit_flag = false;
|
||||||
|
|
||||||
TPP_CONNECT_INFO* tpp_get_connect_info(const char* sid)
|
TPP_CONNECT_INFO *tpp_get_connect_info(const char *sid) {
|
||||||
{
|
|
||||||
TS_CONNECT_INFO sinfo;
|
TS_CONNECT_INFO sinfo;
|
||||||
bool ret = g_session_mgr.get_connect_info(sid, sinfo);
|
bool ret = g_session_mgr.get_connect_info(sid, sinfo);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
TPP_CONNECT_INFO* info = (TPP_CONNECT_INFO*)calloc(1, sizeof(TPP_CONNECT_INFO));
|
TPP_CONNECT_INFO *info = (TPP_CONNECT_INFO *) calloc(1, sizeof(TPP_CONNECT_INFO));
|
||||||
|
|
||||||
info->sid = (char*)calloc(1, sinfo.sid.length() + 1);
|
info->sid = (char *) calloc(1, sinfo.sid.length() + 1);
|
||||||
ex_strcpy(info->sid, sinfo.sid.length() + 1, sinfo.sid.c_str());
|
ex_strcpy(info->sid, sinfo.sid.length() + 1, sinfo.sid.c_str());
|
||||||
info->user_username = (char*)calloc(1, sinfo.user_username.length() + 1);
|
info->user_username = (char *) calloc(1, sinfo.user_username.length() + 1);
|
||||||
ex_strcpy(info->user_username, sinfo.user_username.length() + 1, sinfo.user_username.c_str());
|
ex_strcpy(info->user_username, sinfo.user_username.length() + 1, sinfo.user_username.c_str());
|
||||||
info->host_ip = (char*)calloc(1, sinfo.host_ip.length() + 1);
|
info->host_ip = (char *) calloc(1, sinfo.host_ip.length() + 1);
|
||||||
ex_strcpy(info->host_ip, sinfo.host_ip.length() + 1, sinfo.host_ip.c_str());
|
ex_strcpy(info->host_ip, sinfo.host_ip.length() + 1, sinfo.host_ip.c_str());
|
||||||
info->conn_ip = (char*)calloc(1, sinfo.conn_ip.length() + 1);
|
info->conn_ip = (char *) calloc(1, sinfo.conn_ip.length() + 1);
|
||||||
ex_strcpy(info->conn_ip, sinfo.conn_ip.length() + 1, sinfo.conn_ip.c_str());
|
ex_strcpy(info->conn_ip, sinfo.conn_ip.length() + 1, sinfo.conn_ip.c_str());
|
||||||
info->client_ip = (char*)calloc(1, sinfo.client_ip.length() + 1);
|
info->client_ip = (char *) calloc(1, sinfo.client_ip.length() + 1);
|
||||||
ex_strcpy(info->client_ip, sinfo.client_ip.length() + 1, sinfo.client_ip.c_str());
|
ex_strcpy(info->client_ip, sinfo.client_ip.length() + 1, sinfo.client_ip.c_str());
|
||||||
info->acc_username = (char*)calloc(1, sinfo.acc_username.length() + 1);
|
info->acc_username = (char *) calloc(1, sinfo.acc_username.length() + 1);
|
||||||
ex_strcpy(info->acc_username, sinfo.acc_username.length() + 1, sinfo.acc_username.c_str());
|
ex_strcpy(info->acc_username, sinfo.acc_username.length() + 1, sinfo.acc_username.c_str());
|
||||||
info->acc_secret = (char*)calloc(1, sinfo.acc_secret.length() + 1);
|
info->acc_secret = (char *) calloc(1, sinfo.acc_secret.length() + 1);
|
||||||
ex_strcpy(info->acc_secret, sinfo.acc_secret.length() + 1, sinfo.acc_secret.c_str());
|
ex_strcpy(info->acc_secret, sinfo.acc_secret.length() + 1, sinfo.acc_secret.c_str());
|
||||||
info->username_prompt = (char*)calloc(1, sinfo.username_prompt.length() + 1);
|
info->username_prompt = (char *) calloc(1, sinfo.username_prompt.length() + 1);
|
||||||
ex_strcpy(info->username_prompt, sinfo.username_prompt.length() + 1, sinfo.username_prompt.c_str());
|
ex_strcpy(info->username_prompt, sinfo.username_prompt.length() + 1, sinfo.username_prompt.c_str());
|
||||||
info->password_prompt = (char*)calloc(1, sinfo.password_prompt.length() + 1);
|
info->password_prompt = (char *) calloc(1, sinfo.password_prompt.length() + 1);
|
||||||
ex_strcpy(info->password_prompt, sinfo.password_prompt.length() + 1, sinfo.password_prompt.c_str());
|
ex_strcpy(info->password_prompt, sinfo.password_prompt.length() + 1, sinfo.password_prompt.c_str());
|
||||||
|
|
||||||
info->user_id = sinfo.user_id;
|
info->user_id = sinfo.user_id;
|
||||||
|
@ -46,13 +45,12 @@ TPP_CONNECT_INFO* tpp_get_connect_info(const char* sid)
|
||||||
info->protocol_sub_type = sinfo.protocol_sub_type;
|
info->protocol_sub_type = sinfo.protocol_sub_type;
|
||||||
info->protocol_flag = sinfo.protocol_flag;
|
info->protocol_flag = sinfo.protocol_flag;
|
||||||
info->record_flag = sinfo.record_flag;
|
info->record_flag = sinfo.record_flag;
|
||||||
info->auth_type= sinfo.auth_type;
|
info->auth_type = sinfo.auth_type;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tpp_free_connect_info(TPP_CONNECT_INFO* info)
|
void tpp_free_connect_info(TPP_CONNECT_INFO *info) {
|
||||||
{
|
|
||||||
if (NULL == info)
|
if (NULL == info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -70,8 +68,7 @@ void tpp_free_connect_info(TPP_CONNECT_INFO* info)
|
||||||
free(info);
|
free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tpp_session_begin(const TPP_CONNECT_INFO* info, int* db_id)
|
bool tpp_session_begin(const TPP_CONNECT_INFO *info, int *db_id) {
|
||||||
{
|
|
||||||
if (NULL == info || NULL == db_id)
|
if (NULL == info || NULL == db_id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -98,7 +95,7 @@ bool tpp_session_update(int db_id, int protocol_sub_type, int state) {
|
||||||
return ts_web_rpc_session_update(db_id, protocol_sub_type, state);
|
return ts_web_rpc_session_update(db_id, protocol_sub_type, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tpp_session_end(const char* sid, int db_id, int ret) {
|
bool tpp_session_end(const char *sid, int db_id, int ret) {
|
||||||
return ts_web_rpc_session_end(sid, db_id, ret);
|
return ts_web_rpc_session_end(sid, db_id, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,55 +243,48 @@ bool tpp_session_end(const char* sid, int db_id, int ret) {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
int ts_main(void)
|
int ts_main(void) {
|
||||||
{
|
ExIniFile &ini = g_env.get_ini();
|
||||||
ExIniFile& ini = g_env.get_ini();
|
|
||||||
|
|
||||||
EXLOGI(L"\n");
|
EXLOGI(L"\n");
|
||||||
EXLOGI(L"###############################################################\n");
|
EXLOGI(L"###############################################################\n");
|
||||||
EXLOGI(L"Load config file: %ls.\n", ini.get_filename().c_str());
|
EXLOGI(L"Load config file: %ls.\n", ini.get_filename().c_str());
|
||||||
EXLOGI(L"Teleport Core Server starting ...\n");
|
EXLOGI(L"Teleport Core Server starting ...\n");
|
||||||
|
|
||||||
ex_ini_sections& secs = ini.GetAllSections();
|
ex_ini_sections &secs = ini.GetAllSections();
|
||||||
TsHttpRpc rpc;
|
TsHttpRpc rpc;
|
||||||
|
|
||||||
// 枚举配置文件中的[protocol-xxx]小节,加载对应的协议动态库
|
// 枚举配置文件中的[protocol-xxx]小节,加载对应的协议动态库
|
||||||
bool all_ok = true;
|
bool all_ok = true;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!g_session_mgr.start())
|
if (!g_session_mgr.start()) {
|
||||||
{
|
|
||||||
EXLOGE(L"[core] failed to start session-id manager.\n");
|
EXLOGE(L"[core] failed to start session-id manager.\n");
|
||||||
all_ok = false;
|
all_ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpc.init() || !rpc.start())
|
if (!rpc.init() || !rpc.start()) {
|
||||||
{
|
|
||||||
EXLOGE(L"[core] rpc init/start failed.\n");
|
EXLOGE(L"[core] rpc init/start failed.\n");
|
||||||
all_ok = false;
|
all_ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ex_ini_sections::iterator it = secs.begin();
|
ex_ini_sections::iterator it = secs.begin();
|
||||||
for (; it != secs.end(); ++it)
|
for (; it != secs.end(); ++it) {
|
||||||
{
|
if (it->first.length() > 9 && 0 == wcsncmp(it->first.c_str(), L"protocol-", 9)) {
|
||||||
if (it->first.length() > 9 && 0 == wcsncmp(it->first.c_str(), L"protocol-", 9))
|
|
||||||
{
|
|
||||||
ex_wstr libname;
|
ex_wstr libname;
|
||||||
if (!it->second->GetStr(L"lib", libname))
|
if (!it->second->GetStr(L"lib", libname))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
it->second->GetBool(L"enabled", enabled, false);
|
it->second->GetBool(L"enabled", enabled, false);
|
||||||
if (!enabled)
|
if (!enabled) {
|
||||||
{
|
|
||||||
EXLOGV(L"[core] `%ls` not enabled.\n", libname.c_str());
|
EXLOGV(L"[core] `%ls` not enabled.\n", libname.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_tpp_mgr.load_tpp(libname))
|
if (!g_tpp_mgr.load_tpp(libname)) {
|
||||||
{
|
|
||||||
all_ok = false;
|
all_ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -303,13 +293,11 @@ int ts_main(void)
|
||||||
|
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
if (0 == g_tpp_mgr.count())
|
if (0 == g_tpp_mgr.count()) {
|
||||||
{
|
|
||||||
all_ok = false;
|
all_ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!all_ok)
|
if (!all_ok) {
|
||||||
{
|
|
||||||
g_exit_flag = true;
|
g_exit_flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,13 +305,13 @@ int ts_main(void)
|
||||||
ts_web_rpc_register_core();
|
ts_web_rpc_register_core();
|
||||||
|
|
||||||
EXLOGV("[core] ---- initialized, ready for service ----\n");
|
EXLOGV("[core] ---- initialized, ready for service ----\n");
|
||||||
while (!g_exit_flag)
|
while (!g_exit_flag) {
|
||||||
{
|
|
||||||
ex_sleep_ms(1000);
|
ex_sleep_ms(1000);
|
||||||
g_tpp_mgr.timer();
|
g_tpp_mgr.timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXLOGW("[core] try to stop all thread and exit.\n");
|
||||||
g_tpp_mgr.stop_all();
|
g_tpp_mgr.stop_all();
|
||||||
rpc.stop();
|
rpc.stop();
|
||||||
g_session_mgr.stop();
|
g_session_mgr.stop();
|
||||||
|
|
|
@ -7,64 +7,47 @@
|
||||||
TsSessionManager g_session_mgr;
|
TsSessionManager g_session_mgr;
|
||||||
|
|
||||||
TsSessionManager::TsSessionManager() :
|
TsSessionManager::TsSessionManager() :
|
||||||
ExThreadBase("sid-mgr-thread")
|
ExThreadBase("sid-mgr-thread") {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TsSessionManager::~TsSessionManager()
|
TsSessionManager::~TsSessionManager() {
|
||||||
{
|
|
||||||
ts_connections::iterator it_conn = m_connections.begin();
|
ts_connections::iterator it_conn = m_connections.begin();
|
||||||
for (; it_conn != m_connections.end(); ++it_conn)
|
for (; it_conn != m_connections.end(); ++it_conn) {
|
||||||
{
|
|
||||||
delete it_conn->second;
|
delete it_conn->second;
|
||||||
}
|
}
|
||||||
m_connections.clear();
|
m_connections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TsSessionManager::_thread_loop(void)
|
void TsSessionManager::_thread_loop(void) {
|
||||||
{
|
for (;;) {
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
ex_sleep_ms(1000);
|
ex_sleep_ms(1000);
|
||||||
if (m_stop_flag)
|
if (m_need_stop)
|
||||||
return;
|
return;
|
||||||
_remove_expired_connect_info();
|
_remove_expired_connect_info();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TsSessionManager::_set_stop_flag(void)
|
void TsSessionManager::_remove_expired_connect_info(void) {
|
||||||
{
|
|
||||||
m_stop_flag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TsSessionManager::_remove_expired_connect_info(void)
|
|
||||||
{
|
|
||||||
// 超过15秒未进行连接的connect-info会被移除
|
// 超过15秒未进行连接的connect-info会被移除
|
||||||
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
ex_u64 _now = ex_get_tick_count();
|
ex_u64 _now = ex_get_tick_count();
|
||||||
ts_connections::iterator it = m_connections.begin();
|
ts_connections::iterator it = m_connections.begin();
|
||||||
for (; it != m_connections.end(); )
|
for (; it != m_connections.end();) {
|
||||||
{
|
|
||||||
//EXLOGD("[core] check expired connect info: [%s] %d, %d %d %d\n", it->first.c_str(), it->second->ref_count, int(_now), int(it->second->ticket_start), int(_now - it->second->ticket_start));
|
//EXLOGD("[core] check expired connect info: [%s] %d, %d %d %d\n", it->first.c_str(), it->second->ref_count, int(_now), int(it->second->ticket_start), int(_now - it->second->ticket_start));
|
||||||
if (it->second->ref_count == 0 && _now - 15000 > it->second->ticket_start)
|
if (it->second->ref_count == 0 && _now - 15000 > it->second->ticket_start) {
|
||||||
{
|
|
||||||
EXLOGD("[core] remove connection info, because timeout: %s\n", it->first.c_str());
|
EXLOGD("[core] remove connection info, because timeout: %s\n", it->first.c_str());
|
||||||
delete it->second;
|
delete it->second;
|
||||||
m_connections.erase(it++);
|
m_connections.erase(it++);
|
||||||
EXLOGD("[core] there are %d connection info exists.\n", m_connections.size());
|
EXLOGD("[core] there are %d connection info exists.\n", m_connections.size());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TsSessionManager::get_connect_info(const ex_astr& sid, TS_CONNECT_INFO& info)
|
bool TsSessionManager::get_connect_info(const ex_astr &sid, TS_CONNECT_INFO &info) {
|
||||||
{
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
ts_connections::iterator it = m_connections.find(sid);
|
ts_connections::iterator it = m_connections.find(sid);
|
||||||
|
@ -95,7 +78,7 @@ bool TsSessionManager::get_connect_info(const ex_astr& sid, TS_CONNECT_INFO& inf
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TsSessionManager::free_connect_info(const ex_astr& sid) {
|
bool TsSessionManager::free_connect_info(const ex_astr &sid) {
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
ts_connections::iterator it = m_connections.find(sid);
|
ts_connections::iterator it = m_connections.find(sid);
|
||||||
|
@ -113,8 +96,7 @@ bool TsSessionManager::free_connect_info(const ex_astr& sid) {
|
||||||
m_connections.erase(it);
|
m_connections.erase(it);
|
||||||
EXLOGD("[core] there are %d connection info exists.\n", m_connections.size());
|
EXLOGD("[core] there are %d connection info exists.\n", m_connections.size());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (it->second->ref_count == 1)
|
if (it->second->ref_count == 1)
|
||||||
it->second->ref_count = 0;
|
it->second->ref_count = 0;
|
||||||
it->second->ticket_start = ex_get_tick_count() + 45000; // 我们将时间向后移动45秒,这样如果没有发生RDP的第二次连接,这个连接信息就会在一分钟后被清除。
|
it->second->ticket_start = ex_get_tick_count() + 45000; // 我们将时间向后移动45秒,这样如果没有发生RDP的第二次连接,这个连接信息就会在一分钟后被清除。
|
||||||
|
@ -124,17 +106,16 @@ bool TsSessionManager::free_connect_info(const ex_astr& sid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TsSessionManager::request_session(ex_astr& sid, TS_CONNECT_INFO* info)
|
bool TsSessionManager::request_session(ex_astr &sid, TS_CONNECT_INFO *info) {
|
||||||
{
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
EXLOGD("[core] request session: account: [%s], protocol: [%d], auth-mode: [%d]\n", info->acc_username.c_str(), info->protocol_type, info->auth_type);
|
EXLOGD("[core] request session: account: [%s], protocol: [%d], auth-mode: [%d]\n", info->acc_username.c_str(),
|
||||||
|
info->protocol_type, info->auth_type);
|
||||||
|
|
||||||
ex_astr _sid;
|
ex_astr _sid;
|
||||||
int retried = 0;
|
int retried = 0;
|
||||||
ts_connections::iterator it;
|
ts_connections::iterator it;
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
_gen_session_id(_sid, info, 6);
|
_gen_session_id(_sid, info, 6);
|
||||||
it = m_connections.find(_sid);
|
it = m_connections.find(_sid);
|
||||||
if (it == m_connections.end())
|
if (it == m_connections.end())
|
||||||
|
@ -151,41 +132,38 @@ bool TsSessionManager::request_session(ex_astr& sid, TS_CONNECT_INFO* info)
|
||||||
m_connections.insert(std::make_pair(_sid, info));
|
m_connections.insert(std::make_pair(_sid, info));
|
||||||
|
|
||||||
sid = _sid;
|
sid = _sid;
|
||||||
if (info->protocol_type == TP_PROTOCOL_TYPE_RDP)
|
if (info->protocol_type == TP_PROTOCOL_TYPE_RDP) {
|
||||||
{
|
|
||||||
info->ref_count = 1; // 因为RDP连接之前可能会有很长时间用于确认是否连接、是否信任证书,所以很容易超时,我们认为将引用计数+1,防止因超时被清除。
|
info->ref_count = 1; // 因为RDP连接之前可能会有很长时间用于确认是否连接、是否信任证书,所以很容易超时,我们认为将引用计数+1,防止因超时被清除。
|
||||||
char szTmp[8] = { 0 };
|
char szTmp[8] = {0};
|
||||||
snprintf(szTmp, 8, "%02X", (unsigned char)(info->acc_username.length() + info->acc_secret.length()));
|
snprintf(szTmp, 8, "%02X", (unsigned char) (info->acc_username.length() + info->acc_secret.length()));
|
||||||
sid += szTmp;
|
sid += szTmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TsSessionManager::_gen_session_id(ex_astr& sid, const TS_CONNECT_INFO* info, int len)
|
void TsSessionManager::_gen_session_id(ex_astr &sid, const TS_CONNECT_INFO *info, int len) {
|
||||||
{
|
|
||||||
mbedtls_sha1_context sha;
|
mbedtls_sha1_context sha;
|
||||||
ex_u8 sha_digist[20] = { 0 };
|
ex_u8 sha_digist[20] = {0};
|
||||||
|
|
||||||
ex_u64 _tick = ex_get_tick_count();
|
ex_u64 _tick = ex_get_tick_count();
|
||||||
ex_u64 _tid = ex_get_thread_id();
|
ex_u64 _tid = ex_get_thread_id();
|
||||||
|
|
||||||
mbedtls_sha1_init(&sha);
|
mbedtls_sha1_init(&sha);
|
||||||
mbedtls_sha1_starts(&sha);
|
mbedtls_sha1_starts(&sha);
|
||||||
mbedtls_sha1_update(&sha, (const unsigned char*)&_tick, sizeof(ex_u64));
|
mbedtls_sha1_update(&sha, (const unsigned char *) &_tick, sizeof(ex_u64));
|
||||||
mbedtls_sha1_update(&sha, (const unsigned char*)&_tid, sizeof(ex_u64));
|
mbedtls_sha1_update(&sha, (const unsigned char *) &_tid, sizeof(ex_u64));
|
||||||
mbedtls_sha1_update(&sha, (const unsigned char*)info->conn_ip.c_str(), info->conn_ip.length());
|
mbedtls_sha1_update(&sha, (const unsigned char *) info->conn_ip.c_str(), info->conn_ip.length());
|
||||||
mbedtls_sha1_update(&sha, (const unsigned char*)info->client_ip.c_str(), info->client_ip.length());
|
mbedtls_sha1_update(&sha, (const unsigned char *) info->client_ip.c_str(), info->client_ip.length());
|
||||||
mbedtls_sha1_update(&sha, (const unsigned char*)info->acc_username.c_str(), info->acc_username.length());
|
mbedtls_sha1_update(&sha, (const unsigned char *) info->acc_username.c_str(), info->acc_username.length());
|
||||||
mbedtls_sha1_finish(&sha, sha_digist);
|
mbedtls_sha1_finish(&sha, sha_digist);
|
||||||
mbedtls_sha1_free(&sha);
|
mbedtls_sha1_free(&sha);
|
||||||
|
|
||||||
char szTmp[64] = { 0 };
|
char szTmp[64] = {0};
|
||||||
int _len = len / 2 + 1;
|
int _len = len / 2 + 1;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (i = 0; i < _len; ++i)
|
for (i = 0; i < _len; ++i) {
|
||||||
{
|
|
||||||
snprintf(szTmp + offset, 64 - offset, "%02X", sha_digist[i]);
|
snprintf(szTmp + offset, 64 - offset, "%02X", sha_digist[i]);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,7 @@ public:
|
||||||
bool free_connect_info(const ex_astr& sid);
|
bool free_connect_info(const ex_astr& sid);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// 线程循环
|
|
||||||
void _thread_loop(void);
|
void _thread_loop(void);
|
||||||
// 设置停止标志,让线程能够正常结束
|
|
||||||
void _set_stop_flag(void);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _gen_session_id(ex_astr& sid, const TS_CONNECT_INFO* info, int len);
|
void _gen_session_id(ex_astr& sid, const TS_CONNECT_INFO* info, int len);
|
||||||
|
|
|
@ -34,4 +34,4 @@ if (OS_LINUX)
|
||||||
target_link_libraries(tptelnet uv dl pthread rt util)
|
target_link_libraries(tptelnet uv dl pthread rt util)
|
||||||
elseif (OS_MACOS)
|
elseif (OS_MACOS)
|
||||||
target_link_libraries(tptelnet uv dl pthread util)
|
target_link_libraries(tptelnet uv dl pthread util)
|
||||||
endif()
|
endif ()
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
#include "../../common/ts_const.h"
|
#include "../../common/ts_const.h"
|
||||||
#include <teleport_const.h>
|
#include <teleport_const.h>
|
||||||
|
|
||||||
ex_astr _uv_str_error(int retcode)
|
ex_astr _uv_str_error(int retcode) {
|
||||||
{
|
|
||||||
ex_astr err;
|
ex_astr err;
|
||||||
err = uv_err_name(retcode);
|
err = uv_err_name(retcode);
|
||||||
err += ":";
|
err += ":";
|
||||||
|
@ -17,8 +16,7 @@ TelnetConn::TelnetConn(TelnetSession *sess, bool is_server_side) : m_session(ses
|
||||||
if (is_server_side) {
|
if (is_server_side) {
|
||||||
m_name = "cli<->tp";
|
m_name = "cli<->tp";
|
||||||
m_state = TELNET_CONN_STATE_CONNECTED;
|
m_state = TELNET_CONN_STATE_CONNECTED;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_name = "tp<->srv";
|
m_name = "tp<->srv";
|
||||||
m_state = TELNET_CONN_STATE_FREE;
|
m_state = TELNET_CONN_STATE_FREE;
|
||||||
}
|
}
|
||||||
|
@ -27,13 +25,15 @@ TelnetConn::TelnetConn(TelnetSession *sess, bool is_server_side) : m_session(ses
|
||||||
|
|
||||||
uv_tcp_init(sess->get_loop(), &m_handle);
|
uv_tcp_init(sess->get_loop(), &m_handle);
|
||||||
m_handle.data = this;
|
m_handle.data = this;
|
||||||
|
uv_async_init(sess->get_loop(), &m_stop_handle, _on_stop_cb);
|
||||||
|
m_stop_handle.data = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TelnetConn::~TelnetConn() {
|
TelnetConn::~TelnetConn() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetConn::start_recv() {
|
bool TelnetConn::start_recv() {
|
||||||
int err = uv_read_start((uv_stream_t *)&m_handle, _on_alloc, _on_recv);
|
int err = uv_read_start((uv_stream_t *) &m_handle, _on_alloc, _on_recv);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
EXLOGE("[telnet] [%s] can not start to read.\n", m_name);
|
EXLOGE("[telnet] [%s] can not start to read.\n", m_name);
|
||||||
m_session->close(TP_SESS_STAT_ERR_IO);
|
m_session->close(TP_SESS_STAT_ERR_IO);
|
||||||
|
@ -44,6 +44,12 @@ bool TelnetConn::start_recv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetConn::close() {
|
void TelnetConn::close() {
|
||||||
|
if (m_state == TELNET_CONN_STATE_FREE || m_state == TELNET_CONN_STATE_CLOSING)
|
||||||
|
return;
|
||||||
|
uv_async_send(&m_stop_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelnetConn::_do_close() {
|
||||||
if (m_state == TELNET_CONN_STATE_FREE || m_state == TELNET_CONN_STATE_CLOSING)
|
if (m_state == TELNET_CONN_STATE_FREE || m_state == TELNET_CONN_STATE_CLOSING)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -58,18 +64,30 @@ void TelnetConn::close() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_read_stop((uv_stream_t*)&m_handle);
|
uv_read_stop((uv_stream_t *) &m_handle);
|
||||||
uv_close(handle() , _uv_on_closed);
|
uv_close(handle(), _uv_on_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
void TelnetConn::_on_stop_cb(uv_async_t *handle) {
|
||||||
|
TelnetConn *_this = (TelnetConn *) handle->data;
|
||||||
|
uv_close((uv_handle_t *) &_this->m_stop_handle, _this->_on_stop_handler_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
void TelnetConn::_on_stop_handler_closed(uv_handle_t *handle) {
|
||||||
|
TelnetConn *_this = (TelnetConn *) handle->data;
|
||||||
|
_this->_do_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetConn::_uv_on_closed(uv_handle_t *handle) {
|
void TelnetConn::_uv_on_closed(uv_handle_t *handle) {
|
||||||
TelnetConn *_this = (TelnetConn *)handle->data;
|
TelnetConn *_this = (TelnetConn *) handle->data;
|
||||||
_this->m_state = TELNET_CONN_STATE_FREE;
|
_this->m_state = TELNET_CONN_STATE_FREE;
|
||||||
_this->m_session->on_conn_close();
|
_this->m_session->on_conn_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetConn::_on_alloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
void TelnetConn::_on_alloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||||
TelnetConn *_this = (TelnetConn *) handle->data;
|
// TelnetConn *_this = (TelnetConn *) handle->data;
|
||||||
buf->base = (char *) calloc(1, suggested_size);
|
buf->base = (char *) calloc(1, suggested_size);
|
||||||
buf->len = suggested_size;
|
buf->len = suggested_size;
|
||||||
}
|
}
|
||||||
|
@ -80,13 +98,12 @@ void TelnetConn::_on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *bu
|
||||||
if (nread == 0) {
|
if (nread == 0) {
|
||||||
free(buf->base);
|
free(buf->base);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (nread < 0) {
|
||||||
else if (nread < 0) {
|
|
||||||
free(buf->base);
|
free(buf->base);
|
||||||
|
|
||||||
if (nread == UV_EOF)
|
if (nread == UV_EOF)
|
||||||
EXLOGD("[telnet] [%s] [recv] disconnected.\n", _this->m_name);
|
EXLOGD("[telnet] [%s] [recv] disconnected.\n", _this->m_name);
|
||||||
else if(nread == UV_ECONNRESET)
|
else if (nread == UV_ECONNRESET)
|
||||||
EXLOGD("[telnet] [%s] [recv] connection reset by peer.\n", _this->m_name);
|
EXLOGD("[telnet] [%s] [recv] connection reset by peer.\n", _this->m_name);
|
||||||
else
|
else
|
||||||
EXLOGD("[telnet] [%s] [recv] %s.\n", _this->m_name, _uv_str_error(nread).c_str());
|
EXLOGD("[telnet] [%s] [recv] %s.\n", _this->m_name, _uv_str_error(nread).c_str());
|
||||||
|
@ -101,8 +118,7 @@ void TelnetConn::_on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *bu
|
||||||
|
|
||||||
_this->m_session->close(TP_SESS_STAT_END);
|
_this->m_session->close(TP_SESS_STAT_END);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// #ifdef LOG_DATA
|
// #ifdef LOG_DATA
|
||||||
// if(!_this->m_session->is_relay())
|
// if(!_this->m_session->is_relay())
|
||||||
// EXLOG_BIN((ex_u8*)buf->base, nread, "[telnet] [%s] RECV %d.", _this->m_name, nread);
|
// EXLOG_BIN((ex_u8*)buf->base, nread, "[telnet] [%s] RECV %d.", _this->m_name, nread);
|
||||||
|
@ -170,13 +186,14 @@ void TelnetConn::connect(const char *server_ip, ex_u16 server_port) {
|
||||||
|
|
||||||
if (m_state == TELNET_CONN_STATE_CONNECTED) {
|
if (m_state == TELNET_CONN_STATE_CONNECTED) {
|
||||||
// 当前已经连接上了服务器了,断开重连
|
// 当前已经连接上了服务器了,断开重连
|
||||||
EXLOGV("[telnet] [%s] [%s] try to disconnect. %s:%d\n", m_name, m_session->client_addr(), server_ip, server_port);
|
EXLOGV("[telnet] [%s] [%s] try to disconnect from real TELNET server %s:%d and reconnect.\n", m_name,
|
||||||
|
m_session->client_addr(), server_ip, server_port);
|
||||||
m_state = TELNET_CONN_STATE_CLOSING;
|
m_state = TELNET_CONN_STATE_CLOSING;
|
||||||
uv_close((uv_handle_t *) &m_handle, _uv_on_reconnect);
|
uv_close((uv_handle_t *) &m_handle, _uv_on_reconnect);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
EXLOGV("[telnet] [%s] [%s] try to connect to real TELNET server %s:%d\n", m_name, m_session->client_addr(),
|
||||||
EXLOGV("[telnet] [%s] [%s] try to connect to real TELNET server at %s:%d\n", m_name, m_session->client_addr(), server_ip, server_port);
|
server_ip, server_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
@ -197,7 +214,6 @@ void TelnetConn::connect(const char *server_ip, ex_u16 server_port) {
|
||||||
|
|
||||||
m_timer_running = true;
|
m_timer_running = true;
|
||||||
|
|
||||||
//m_is_connecting = true;
|
|
||||||
m_state = TELNET_CONN_STATE_CONNECTING;
|
m_state = TELNET_CONN_STATE_CONNECTING;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if ((err = uv_tcp_connect(conn_req, &m_handle, (const struct sockaddr *) &addr, _uv_on_connected)) != 0) {
|
if ((err = uv_tcp_connect(conn_req, &m_handle, (const struct sockaddr *) &addr, _uv_on_connected)) != 0) {
|
||||||
|
@ -206,31 +222,30 @@ void TelnetConn::connect(const char *server_ip, ex_u16 server_port) {
|
||||||
|
|
||||||
m_timer_running = false;
|
m_timer_running = false;
|
||||||
uv_timer_stop(&m_timer_connect_timeout);
|
uv_timer_stop(&m_timer_connect_timeout);
|
||||||
uv_close((uv_handle_t*)&m_timer_connect_timeout, _uv_on_timer_connect_timeout_closed);
|
uv_close((uv_handle_t *) &m_timer_connect_timeout, NULL);
|
||||||
|
|
||||||
m_state = TELNET_CONN_STATE_FREE;
|
m_state = TELNET_CONN_STATE_FREE;
|
||||||
m_session->close(TP_SESS_STAT_ERR_CONNECT);
|
m_session->close(TP_SESS_STAT_ERR_CONNECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetConn::_uv_on_connect_timeout(uv_timer_t *timer)
|
void TelnetConn::_uv_on_connect_timeout(uv_timer_t *timer) {
|
||||||
{
|
TelnetConn *_this = (TelnetConn *) timer->data;
|
||||||
TelnetConn *_this = (TelnetConn *)timer->data;
|
|
||||||
|
|
||||||
if (_this->m_timer_running) {
|
if (_this->m_timer_running) {
|
||||||
_this->m_timer_running = false;
|
_this->m_timer_running = false;
|
||||||
uv_timer_stop(&_this->m_timer_connect_timeout);
|
uv_timer_stop(&_this->m_timer_connect_timeout);
|
||||||
uv_close((uv_handle_t*)&_this->m_timer_connect_timeout, _this->_uv_on_timer_connect_timeout_closed);
|
uv_close((uv_handle_t *) &_this->m_timer_connect_timeout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果在连接成功之前就超时了,则关闭连接
|
// 如果在连接成功之前就超时了,则关闭连接
|
||||||
EXLOGE("[telnet] [%s] timeout when connect to real TELNET server, cancel connection.\n", _this->m_name);
|
EXLOGE("[telnet] [%s] timeout when connect to real TELNET server.\n", _this->m_name);
|
||||||
_this->m_state = TELNET_CONN_STATE_CLOSING;
|
_this->m_state = TELNET_CONN_STATE_CLOSING;
|
||||||
uv_close(_this->handle(), _uv_on_closed);
|
uv_close(_this->handle(), _uv_on_closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetConn::_uv_on_reconnect(uv_handle_t *handle) {
|
void TelnetConn::_uv_on_reconnect(uv_handle_t *handle) {
|
||||||
TelnetConn *_this = (TelnetConn *)handle->data;
|
TelnetConn *_this = (TelnetConn *) handle->data;
|
||||||
_this->m_state = TELNET_CONN_STATE_FREE;
|
_this->m_state = TELNET_CONN_STATE_FREE;
|
||||||
|
|
||||||
uv_tcp_init(_this->m_session->get_loop(), &_this->m_handle);
|
uv_tcp_init(_this->m_session->get_loop(), &_this->m_handle);
|
||||||
|
@ -240,13 +255,13 @@ void TelnetConn::_uv_on_reconnect(uv_handle_t *handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetConn::_uv_on_connected(uv_connect_t *req, int status) {
|
void TelnetConn::_uv_on_connected(uv_connect_t *req, int status) {
|
||||||
TelnetConn *_this = (TelnetConn *)req->data;
|
TelnetConn *_this = (TelnetConn *) req->data;
|
||||||
free(req);
|
free(req);
|
||||||
|
|
||||||
if (_this->m_timer_running) {
|
if (_this->m_timer_running) {
|
||||||
_this->m_timer_running = false;
|
_this->m_timer_running = false;
|
||||||
uv_timer_stop(&_this->m_timer_connect_timeout);
|
uv_timer_stop(&_this->m_timer_connect_timeout);
|
||||||
uv_close((uv_handle_t*)&_this->m_timer_connect_timeout, _this->_uv_on_timer_connect_timeout_closed);
|
uv_close((uv_handle_t *) &_this->m_timer_connect_timeout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
|
@ -268,5 +283,5 @@ void TelnetConn::_uv_on_connected(uv_connect_t *req, int status) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
void TelnetConn::_uv_on_timer_connect_timeout_closed(uv_handle_t *handle) {
|
//void TelnetConn::_uv_on_timer_connect_timeout_closed(uv_handle_t *handle) {
|
||||||
}
|
//}
|
||||||
|
|
|
@ -19,6 +19,7 @@ class TelnetSession;
|
||||||
class TelnetConn {
|
class TelnetConn {
|
||||||
public:
|
public:
|
||||||
TelnetConn(TelnetSession *sess, bool is_server_side);
|
TelnetConn(TelnetSession *sess, bool is_server_side);
|
||||||
|
|
||||||
~TelnetConn();
|
~TelnetConn();
|
||||||
|
|
||||||
TelnetSession *session() { return m_session; }
|
TelnetSession *session() { return m_session; }
|
||||||
|
@ -27,32 +28,50 @@ public:
|
||||||
const char *name() const { return m_name; }
|
const char *name() const { return m_name; }
|
||||||
|
|
||||||
bool is_server_side() const { return m_is_server; }
|
bool is_server_side() const { return m_is_server; }
|
||||||
|
|
||||||
ex_u8 state() const { return m_state; }
|
ex_u8 state() const { return m_state; }
|
||||||
|
|
||||||
uv_handle_t *handle() { return (uv_handle_t *) &m_handle; }
|
uv_handle_t *handle() { return (uv_handle_t *) &m_handle; }
|
||||||
|
|
||||||
uv_tcp_t *tcp_handle() { return &m_handle; }
|
uv_tcp_t *tcp_handle() { return &m_handle; }
|
||||||
|
|
||||||
uv_stream_t *stream_handle() { return (uv_stream_t *) &m_handle; }
|
uv_stream_t *stream_handle() { return (uv_stream_t *) &m_handle; }
|
||||||
|
|
||||||
MemBuffer &data() { return m_buf_data; }
|
MemBuffer &data() { return m_buf_data; }
|
||||||
|
|
||||||
bool send(MemBuffer &mbuf);
|
bool send(MemBuffer &mbuf);
|
||||||
|
|
||||||
bool send(const ex_u8 *data, size_t size);
|
bool send(const ex_u8 *data, size_t size);
|
||||||
|
|
||||||
// connect to real server, for proxy-client-side only.
|
// connect to real server, for proxy-client-side only.
|
||||||
void connect(const char *server_ip, ex_u16 server_port = 3389);
|
void connect(const char *server_ip, ex_u16 server_port = 3389);
|
||||||
|
|
||||||
// try to close this connection. return current TELNET_CONN_STATE_XXXX.
|
// try to close this connection. return current TELNET_CONN_STATE_XXXX.
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
bool start_recv();
|
bool start_recv();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _on_alloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
static void _on_alloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
||||||
|
|
||||||
static void _on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf);
|
static void _on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf);
|
||||||
|
|
||||||
static void _on_send_done(uv_write_t *req, int status);
|
static void _on_send_done(uv_write_t *req, int status);
|
||||||
|
|
||||||
static void _uv_on_connect_timeout(uv_timer_t *timer);
|
static void _uv_on_connect_timeout(uv_timer_t *timer);
|
||||||
|
|
||||||
static void _uv_on_connected(uv_connect_t *req, int status);
|
static void _uv_on_connected(uv_connect_t *req, int status);
|
||||||
|
|
||||||
static void _uv_on_reconnect(uv_handle_t *handle);
|
static void _uv_on_reconnect(uv_handle_t *handle);
|
||||||
|
|
||||||
static void _uv_on_closed(uv_handle_t *handle);
|
static void _uv_on_closed(uv_handle_t *handle);
|
||||||
static void _uv_on_timer_connect_timeout_closed(uv_handle_t *handle);
|
|
||||||
|
// static void _uv_on_timer_connect_timeout_closed(uv_handle_t *handle);
|
||||||
|
static void _on_stop_cb(uv_async_t *handle);
|
||||||
|
|
||||||
|
static void _on_stop_handler_closed(uv_handle_t *handle);
|
||||||
|
|
||||||
|
void _do_close();
|
||||||
|
|
||||||
bool _raw_send(const ex_u8 *data, size_t size);
|
bool _raw_send(const ex_u8 *data, size_t size);
|
||||||
|
|
||||||
|
@ -66,6 +85,7 @@ private:
|
||||||
uv_tcp_t m_handle;
|
uv_tcp_t m_handle;
|
||||||
uv_timer_t m_timer_connect_timeout;
|
uv_timer_t m_timer_connect_timeout;
|
||||||
bool m_timer_running; // does m_timer_connect_timeout initialized and started.
|
bool m_timer_running; // does m_timer_connect_timeout initialized and started.
|
||||||
|
uv_async_t m_stop_handle; // event for stop whole listener handler.
|
||||||
|
|
||||||
ex_u8 m_state; // TELNET_CONN_STATE_XXXX
|
ex_u8 m_state; // TELNET_CONN_STATE_XXXX
|
||||||
|
|
||||||
|
|
|
@ -4,21 +4,18 @@
|
||||||
|
|
||||||
TelnetProxy g_telnet_proxy;
|
TelnetProxy g_telnet_proxy;
|
||||||
|
|
||||||
TelnetProxy::TelnetProxy() : ExThreadBase("telnet-proxy-thread")
|
TelnetProxy::TelnetProxy() : ExThreadBase("telnet-proxy-thread") {
|
||||||
{
|
|
||||||
memset(&m_loop, 0, sizeof(uv_loop_t));
|
memset(&m_loop, 0, sizeof(uv_loop_t));
|
||||||
m_timer_counter = 0;
|
m_timer_counter = 0;
|
||||||
m_noop_timeout_sec = 900;
|
m_noop_timeout_sec = 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
TelnetProxy::~TelnetProxy()
|
TelnetProxy::~TelnetProxy() {
|
||||||
{
|
if (!m_sessions.empty())
|
||||||
if (m_sessions.size() > 0)
|
|
||||||
EXLOGE("[telnet] not all session stopped.\n");
|
EXLOGE("[telnet] not all session stopped.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetProxy::init()
|
bool TelnetProxy::init() {
|
||||||
{
|
|
||||||
if (0 != uv_loop_init(&m_loop))
|
if (0 != uv_loop_init(&m_loop))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -26,12 +23,16 @@ bool TelnetProxy::init()
|
||||||
return false;
|
return false;
|
||||||
m_clean_session_handle.data = this;
|
m_clean_session_handle.data = this;
|
||||||
|
|
||||||
|
if (0 != uv_async_init(&m_loop, &m_stop_handle, _on_stop_cb))
|
||||||
|
return false;
|
||||||
|
m_stop_handle.data = this;
|
||||||
|
|
||||||
m_host_ip = g_telnet_env.bind_ip;
|
m_host_ip = g_telnet_env.bind_ip;
|
||||||
m_host_port = g_telnet_env.bind_port;
|
m_host_port = g_telnet_env.bind_port;
|
||||||
|
|
||||||
if (0 != uv_tcp_init(&m_loop, &m_handle))
|
if (0 != uv_tcp_init(&m_loop, &m_listener_handle))
|
||||||
return false;
|
return false;
|
||||||
m_handle.data = this;
|
m_listener_handle.data = this;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -45,12 +46,11 @@ void TelnetProxy::timer() {
|
||||||
m_timer_counter = 0;
|
m_timer_counter = 0;
|
||||||
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
ex_u32 t_now = (ex_u32)time(NULL);
|
ex_u32 t_now = (ex_u32) time(NULL);
|
||||||
ts_telnet_sessions::iterator it = m_sessions.begin();
|
ts_telnet_sessions::iterator it = m_sessions.begin();
|
||||||
for (; it != m_sessions.end(); ++it)
|
for (; it != m_sessions.end(); ++it) {
|
||||||
{
|
|
||||||
it->first->save_record();
|
it->first->save_record();
|
||||||
if(0 != m_noop_timeout_sec)
|
if (0 != m_noop_timeout_sec)
|
||||||
it->first->check_noop_timeout(t_now, m_noop_timeout_sec);
|
it->first->check_noop_timeout(t_now, m_noop_timeout_sec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ void TelnetProxy::set_cfg(ex_u32 noop_timeout) {
|
||||||
m_noop_timeout_sec = noop_timeout;
|
m_noop_timeout_sec = noop_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetProxy::kill_sessions(const ex_astrs& sessions) {
|
void TelnetProxy::kill_sessions(const ex_astrs &sessions) {
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
ts_telnet_sessions::iterator it = m_sessions.begin();
|
ts_telnet_sessions::iterator it = m_sessions.begin();
|
||||||
for (; it != m_sessions.end(); ++it) {
|
for (; it != m_sessions.end(); ++it) {
|
||||||
|
@ -72,21 +72,20 @@ void TelnetProxy::kill_sessions(const ex_astrs& sessions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetProxy::_thread_loop(void)
|
void TelnetProxy::_thread_loop(void) {
|
||||||
{
|
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
if (0 != uv_ip4_addr(m_host_ip.c_str(), m_host_port, &addr)) {
|
if (0 != uv_ip4_addr(m_host_ip.c_str(), m_host_port, &addr)) {
|
||||||
EXLOGE("[telnet] invalid ip/port for TELNET listener.\n");
|
EXLOGE("[telnet] invalid ip/port for TELNET listener.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != uv_tcp_bind(&m_handle, (const struct sockaddr*) &addr, 0)) {
|
if (0 != uv_tcp_bind(&m_listener_handle, (const struct sockaddr *) &addr, 0)) {
|
||||||
EXLOGE("[telnet] can not bind %s:%d.\n", m_host_ip.c_str(), m_host_port);
|
EXLOGE("[telnet] can not bind %s:%d.\n", m_host_ip.c_str(), m_host_port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始监听,有客户端连接到来时,会回调 _on_client_connect()
|
// 开始监听,有客户端连接到来时,会回调 _on_client_connect()
|
||||||
if (0 != uv_listen((uv_stream_t*)&m_handle, 8, _on_client_connect)) {
|
if (0 != uv_listen((uv_stream_t *) &m_listener_handle, 8, _on_client_connect)) {
|
||||||
EXLOGE("[telnet] can not listen on %s:%d.\n", m_host_ip.c_str(), m_host_port);
|
EXLOGE("[telnet] can not listen on %s:%d.\n", m_host_ip.c_str(), m_host_port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -98,103 +97,117 @@ void TelnetProxy::_thread_loop(void)
|
||||||
EXLOGE("[telnet] main-loop end. %s\n", uv_strerror(err));
|
EXLOGE("[telnet] main-loop end. %s\n", uv_strerror(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/libuv/libuv/issues/709
|
||||||
|
//
|
||||||
|
// uv_close is not thread safe (see the docs here. That means you cannot call it from outside of the loop thread.
|
||||||
|
// http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop
|
||||||
|
//
|
||||||
|
// The usual way to approach this when the loop is running in another thread is to use a uv_async_t handle,
|
||||||
|
// because uv_async_send is thread safe. You could have one such handle and call uv_stop in its callback.
|
||||||
|
// Then, after uv_run returns you can use uv_walk to close all handles and run the loop one last time so
|
||||||
|
// that close callbacks are called.
|
||||||
|
|
||||||
// 注意,如果在 uv_loop_close() 内部崩溃,可能某个uv的handle未关闭。
|
// 注意,如果在 uv_loop_close() 内部崩溃,可能某个uv的handle未关闭。
|
||||||
uv_loop_close(&m_loop);
|
uv_loop_close(&m_loop);
|
||||||
|
|
||||||
EXLOGV("[telnet] main-loop end.\n");
|
EXLOGV("[telnet] main-loop end.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetProxy::_set_stop_flag(void) {
|
// static
|
||||||
m_stop_flag = true;
|
void TelnetProxy::_on_stop(void) {
|
||||||
|
ExThreadBase::_on_stop();
|
||||||
|
|
||||||
if (m_is_running) {
|
if (m_is_running) {
|
||||||
uv_close((uv_handle_t*)&m_handle, _on_listener_closed);
|
uv_async_send(&m_stop_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void TelnetProxy::_on_listener_closed(uv_handle_t* handle)
|
void TelnetProxy::_on_listener_closed(uv_handle_t *handle) {
|
||||||
{
|
TelnetProxy *_this = (TelnetProxy *) handle->data;
|
||||||
TelnetProxy* _this = (TelnetProxy*)handle->data;
|
|
||||||
EXLOGV("[telnet] listener close.\n");
|
EXLOGV("[telnet] listener close.\n");
|
||||||
|
|
||||||
_this->_close_all_sessions();
|
uv_close((uv_handle_t *) &_this->m_stop_handle, _on_stop_handle_closed);
|
||||||
|
// _this->_close_all_sessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetProxy::clean_session() {
|
void TelnetProxy::clean_session() {
|
||||||
uv_async_send(&m_clean_session_handle);
|
uv_async_send(&m_clean_session_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetProxy::_close_all_sessions(void)
|
void TelnetProxy::_close_all_sessions(void) {
|
||||||
{
|
|
||||||
ExThreadSmartLock locker(m_lock);
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
|
||||||
if (m_sessions.size() == 0) {
|
if (m_sessions.empty()) {
|
||||||
_close_clean_session_handle();
|
_close_clean_session_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_telnet_sessions::iterator it = m_sessions.begin();
|
ts_telnet_sessions::iterator it = m_sessions.begin();
|
||||||
for (; it != m_sessions.end(); ++it)
|
for (; it != m_sessions.end(); ++it) {
|
||||||
{
|
|
||||||
it->first->close(TP_SESS_STAT_ERR_RESET);
|
it->first->close(TP_SESS_STAT_ERR_RESET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void TelnetProxy::_on_clean_session_cb(uv_async_t* handle)
|
void TelnetProxy::_on_clean_session_cb(uv_async_t *handle) {
|
||||||
{
|
TelnetProxy *_this = (TelnetProxy *) handle->data;
|
||||||
TelnetProxy* _this = (TelnetProxy*)handle->data;
|
|
||||||
|
|
||||||
// check closed session
|
// check closed session
|
||||||
ExThreadSmartLock locker(_this->m_lock);
|
ExThreadSmartLock locker(_this->m_lock);
|
||||||
|
|
||||||
ts_telnet_sessions::iterator it = _this->m_sessions.begin();
|
ts_telnet_sessions::iterator it = _this->m_sessions.begin();
|
||||||
for (; it != _this->m_sessions.end(); )
|
for (; it != _this->m_sessions.end();) {
|
||||||
{
|
|
||||||
if (it->first->is_closed()) {
|
if (it->first->is_closed()) {
|
||||||
delete it->first;
|
delete it->first;
|
||||||
_this->m_sessions.erase(it++);
|
_this->m_sessions.erase(it++);
|
||||||
EXLOGD("[telnet] - removed one session.\n");
|
EXLOGD("[telnet] - removed one session.\n");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_this->m_stop_flag && _this->m_sessions.size() == 0) {
|
if (_this->m_need_stop && _this->m_sessions.empty()) {
|
||||||
_this->_close_clean_session_handle();
|
_this->_close_clean_session_handle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////static
|
||||||
|
//void TelnetProxy::_on_clean_session_handle_closed(uv_handle_t *handle) {
|
||||||
|
//}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
void TelnetProxy::_on_clean_session_handle_closed(uv_handle_t *handle) {
|
void TelnetProxy::_on_stop_handle_closed(uv_handle_t *handle) {
|
||||||
|
TelnetProxy *_this = (TelnetProxy *) handle->data;
|
||||||
|
_this->_close_all_sessions();
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
void TelnetProxy::_on_stop_cb(uv_async_t *handle) {
|
||||||
|
TelnetProxy *_this = (TelnetProxy *) handle->data;
|
||||||
|
uv_close((uv_handle_t *) &_this->m_listener_handle, _on_listener_closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void TelnetProxy::_on_client_connect(uv_stream_t* server, int status)
|
void TelnetProxy::_on_client_connect(uv_stream_t *server, int status) {
|
||||||
{
|
|
||||||
if (0 != status)
|
if (0 != status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TelnetProxy* _this = (TelnetProxy*)server->data;
|
TelnetProxy *_this = (TelnetProxy *) server->data;
|
||||||
_this->_on_accept(server);
|
_this->_on_accept(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetProxy::_on_accept(uv_stream_t* server)
|
bool TelnetProxy::_on_accept(uv_stream_t *server) {
|
||||||
{
|
TelnetSession *sess = new TelnetSession(this);
|
||||||
TelnetSession* sess = new TelnetSession(this);
|
|
||||||
|
|
||||||
if (0 != uv_accept(server, sess->client()->stream_handle()))
|
if (0 != uv_accept(server, sess->client()->stream_handle())) {
|
||||||
{
|
|
||||||
EXLOGE("[telnet] socket accept failed.\n");
|
EXLOGE("[telnet] socket accept failed.\n");
|
||||||
delete sess;
|
delete sess;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_stop_flag)
|
if (m_need_stop) {
|
||||||
{
|
|
||||||
delete sess;
|
delete sess;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -202,13 +215,11 @@ bool TelnetProxy::_on_accept(uv_stream_t* server)
|
||||||
// 获取客户端IP地址和端口号
|
// 获取客户端IP地址和端口号
|
||||||
struct sockaddr sock_client;
|
struct sockaddr sock_client;
|
||||||
int namelen = sizeof(sock_client);
|
int namelen = sizeof(sock_client);
|
||||||
if (0 == uv_tcp_getpeername(sess->client()->tcp_handle(), &sock_client, &namelen))
|
if (0 == uv_tcp_getpeername(sess->client()->tcp_handle(), &sock_client, &namelen)) {
|
||||||
{
|
sockaddr_in *addrin = (sockaddr_in *) &sock_client;
|
||||||
sockaddr_in* addrin = (sockaddr_in*)&sock_client;
|
char ip[17] = {0};
|
||||||
char ip[17] = { 0 };
|
if (0 == uv_ip4_name(addrin, ip, sizeof(ip))) {
|
||||||
if (0 == uv_ip4_name(addrin, ip, sizeof(ip)))
|
char client_addr[64] = {0};
|
||||||
{
|
|
||||||
char client_addr[64] = { 0 };
|
|
||||||
snprintf(client_addr, 64, "%s:%d", ip, addrin->sin_port);
|
snprintf(client_addr, 64, "%s:%d", ip, addrin->sin_port);
|
||||||
sess->client_addr(client_addr);
|
sess->client_addr(client_addr);
|
||||||
}
|
}
|
||||||
|
@ -227,5 +238,5 @@ bool TelnetProxy::_on_accept(uv_stream_t* server)
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetProxy::_close_clean_session_handle() {
|
void TelnetProxy::_close_clean_session_handle() {
|
||||||
uv_close((uv_handle_t*)&m_clean_session_handle, _on_clean_session_handle_closed);
|
uv_close((uv_handle_t *) &m_clean_session_handle, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,46 +6,58 @@
|
||||||
|
|
||||||
#include "telnet_session.h"
|
#include "telnet_session.h"
|
||||||
|
|
||||||
typedef std::map<TelnetSession*, unsigned char> ts_telnet_sessions;
|
typedef std::map<TelnetSession *, unsigned char> ts_telnet_sessions;
|
||||||
|
|
||||||
class TelnetProxy : public ExThreadBase
|
class TelnetProxy : public ExThreadBase {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
TelnetProxy();
|
TelnetProxy();
|
||||||
|
|
||||||
~TelnetProxy();
|
~TelnetProxy();
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
void timer();
|
|
||||||
void set_cfg(ex_u32 noop_timeout);
|
|
||||||
void kill_sessions(const ex_astrs& sessions);
|
|
||||||
|
|
||||||
uv_loop_t* get_loop() { return &m_loop; }
|
void timer();
|
||||||
|
|
||||||
|
void set_cfg(ex_u32 noop_timeout);
|
||||||
|
|
||||||
|
void kill_sessions(const ex_astrs &sessions);
|
||||||
|
|
||||||
|
uv_loop_t *get_loop() { return &m_loop; }
|
||||||
|
|
||||||
void clean_session();
|
void clean_session();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _thread_loop();
|
void _thread_loop();
|
||||||
void _set_stop_flag();
|
|
||||||
|
void _on_stop();
|
||||||
|
|
||||||
void _close_all_sessions();
|
void _close_all_sessions();
|
||||||
|
|
||||||
void _close_clean_session_handle();
|
void _close_clean_session_handle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _on_client_connect(uv_stream_t* server, int status);
|
static void _on_client_connect(uv_stream_t *server, int status);
|
||||||
static void _on_listener_closed(uv_handle_t* handle);
|
|
||||||
static void _on_clean_session_cb(uv_async_t* handle);
|
|
||||||
static void _on_clean_session_handle_closed(uv_handle_t *handle);
|
|
||||||
|
|
||||||
bool _on_accept(uv_stream_t* server);
|
static void _on_listener_closed(uv_handle_t *handle);
|
||||||
|
|
||||||
|
static void _on_clean_session_cb(uv_async_t *handle);
|
||||||
|
|
||||||
|
// static void _on_clean_session_handle_closed(uv_handle_t *handle);
|
||||||
|
|
||||||
|
static void _on_stop_cb(uv_async_t *handle);
|
||||||
|
|
||||||
|
static void _on_stop_handle_closed(uv_handle_t *handle);
|
||||||
|
|
||||||
|
bool _on_accept(uv_stream_t *server);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_stop_flag;
|
|
||||||
int m_timer_counter;
|
int m_timer_counter;
|
||||||
//
|
|
||||||
ex_u32 m_noop_timeout_sec;
|
ex_u32 m_noop_timeout_sec;
|
||||||
|
|
||||||
uv_loop_t m_loop;
|
uv_loop_t m_loop;
|
||||||
uv_tcp_t m_handle;
|
uv_tcp_t m_listener_handle;
|
||||||
uv_async_t m_clean_session_handle;
|
uv_async_t m_clean_session_handle;
|
||||||
|
uv_async_t m_stop_handle; // event for stop whole listener handler.
|
||||||
|
|
||||||
ExThreadLock m_lock;
|
ExThreadLock m_lock;
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,14 @@
|
||||||
|
|
||||||
TelnetSession::TelnetSession(TelnetProxy *proxy) :
|
TelnetSession::TelnetSession(TelnetProxy *proxy) :
|
||||||
m_proxy(proxy),
|
m_proxy(proxy),
|
||||||
m_conn_info(NULL)
|
m_conn_info(NULL) {
|
||||||
{
|
|
||||||
m_state = TP_SESS_STAT_RUNNING;
|
m_state = TP_SESS_STAT_RUNNING;
|
||||||
m_startup_win_size_recorded = false;
|
m_startup_win_size_recorded = false;
|
||||||
m_db_id = 0;
|
m_db_id = 0;
|
||||||
m_is_relay = false;
|
m_is_relay = false;
|
||||||
m_is_closed = false;
|
m_is_closed = false;
|
||||||
m_first_client_pkg = true;
|
m_first_client_pkg = true;
|
||||||
m_last_access_timestamp = (ex_u32)time(NULL);
|
m_last_access_timestamp = (ex_u32) time(NULL);
|
||||||
|
|
||||||
m_win_width = 0;
|
m_win_width = 0;
|
||||||
m_win_height = 0;
|
m_win_height = 0;
|
||||||
|
@ -66,8 +65,7 @@ void TelnetSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
|
||||||
|
|
||||||
void TelnetSession::_session_error(int err_code) {
|
void TelnetSession::_session_error(int err_code) {
|
||||||
int db_id = 0;
|
int db_id = 0;
|
||||||
if (!g_telnet_env.session_begin(m_conn_info, &db_id) || db_id == 0)
|
if (!g_telnet_env.session_begin(m_conn_info, &db_id) || db_id == 0) {
|
||||||
{
|
|
||||||
EXLOGE("[telnet] can not write session error to database.\n");
|
EXLOGE("[telnet] can not write session error to database.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,10 +89,8 @@ bool TelnetSession::_on_session_begin() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetSession::_on_session_end()
|
bool TelnetSession::_on_session_end() {
|
||||||
{
|
if (m_db_id > 0) {
|
||||||
if (m_db_id > 0)
|
|
||||||
{
|
|
||||||
// 如果会话过程中没有发生错误,则将其状态改为结束,否则记录下错误值
|
// 如果会话过程中没有发生错误,则将其状态改为结束,否则记录下错误值
|
||||||
if (m_state == TP_SESS_STAT_RUNNING || m_state == TP_SESS_STAT_STARTED)
|
if (m_state == TP_SESS_STAT_RUNNING || m_state == TP_SESS_STAT_STARTED)
|
||||||
m_state = TP_SESS_STAT_END;
|
m_state = TP_SESS_STAT_END;
|
||||||
|
@ -183,14 +179,14 @@ sess_state TelnetSession::_do_close(int state) {
|
||||||
m_state = TP_SESS_STAT_ERR_INTERNAL;
|
m_state = TP_SESS_STAT_ERR_INTERNAL;
|
||||||
else
|
else
|
||||||
m_state = state;
|
m_state = state;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!m_is_relay)
|
if (!m_is_relay)
|
||||||
_session_error(state);
|
_session_error(state);
|
||||||
m_state = state;
|
m_state = state;
|
||||||
}
|
}
|
||||||
EXLOGV("[telnet] close session.\n");
|
EXLOGV("[telnet] close session.\n");
|
||||||
EXLOGD("[telnet] _do_close(), conn_client::state=%d, conn_server:state=%d\n", m_conn_client->state(), m_conn_server->state());
|
EXLOGD("[telnet] _do_close(), conn_client::state=%d, conn_server:state=%d\n", m_conn_client->state(),
|
||||||
|
m_conn_server->state());
|
||||||
|
|
||||||
m_conn_client->close();
|
m_conn_client->close();
|
||||||
m_conn_server->close();
|
m_conn_server->close();
|
||||||
|
@ -206,19 +202,20 @@ sess_state TelnetSession::_do_check_closing() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetSession::on_conn_close() {
|
void TelnetSession::on_conn_close() {
|
||||||
EXLOGD("[telnet] on_conn_close(), conn_client::state=%d, conn_server:state=%d\n", m_conn_client->state(), m_conn_server->state());
|
EXLOGD("[telnet] on_conn_close(), conn_client::state=%d, conn_server:state=%d\n", m_conn_client->state(),
|
||||||
|
m_conn_server->state());
|
||||||
if (m_conn_client->state() == TELNET_CONN_STATE_FREE && m_conn_server->state() == TELNET_CONN_STATE_FREE) {
|
if (m_conn_client->state() == TELNET_CONN_STATE_FREE && m_conn_server->state() == TELNET_CONN_STATE_FREE) {
|
||||||
m_status = s_all_conn_closed;
|
m_status = s_all_conn_closed;
|
||||||
do_next(m_conn_client);
|
do_next(m_conn_client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sess_state TelnetSession::_do_client_connect(TelnetConn* conn) {
|
sess_state TelnetSession::_do_client_connect(TelnetConn *conn) {
|
||||||
// putty会率先发第一个包,SecureCRT会通过脚本发第一个包
|
// putty会率先发第一个包,SecureCRT会通过脚本发第一个包
|
||||||
return _do_negotiation_with_client(conn);
|
return _do_negotiation_with_client(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
sess_state TelnetSession::_do_negotiation_with_client(TelnetConn* conn) {
|
sess_state TelnetSession::_do_negotiation_with_client(TelnetConn *conn) {
|
||||||
if (NULL == conn)
|
if (NULL == conn)
|
||||||
return s_negotiation_with_client;
|
return s_negotiation_with_client;
|
||||||
|
|
||||||
|
@ -228,25 +225,24 @@ sess_state TelnetSession::_do_negotiation_with_client(TelnetConn* conn) {
|
||||||
if (m_first_client_pkg) {
|
if (m_first_client_pkg) {
|
||||||
m_first_client_pkg = false;
|
m_first_client_pkg = false;
|
||||||
|
|
||||||
MemBuffer& mbuf = conn->data();
|
MemBuffer &mbuf = conn->data();
|
||||||
|
|
||||||
if (mbuf.size() > 14 && 0 == memcmp(mbuf.data(), "session:", 8)) {
|
if (mbuf.size() > 14 && 0 == memcmp(mbuf.data(), "session:", 8)) {
|
||||||
m_is_putty_mode = false;
|
m_is_putty_mode = false;
|
||||||
|
|
||||||
mbuf.pop(8);
|
mbuf.pop(8);
|
||||||
for (; mbuf.size() > 0; ) {
|
for (; mbuf.size() > 0;) {
|
||||||
if (mbuf.data()[mbuf.size() - 1] == 0x0a || mbuf.data()[mbuf.size() - 1] == 0x0d)
|
if (mbuf.data()[mbuf.size() - 1] == 0x0a || mbuf.data()[mbuf.size() - 1] == 0x0d)
|
||||||
mbuf.size(mbuf.size() - 1);
|
mbuf.size(mbuf.size() - 1);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbuf.append((ex_u8*)"\x00", 1);
|
mbuf.append((ex_u8 *) "\x00", 1);
|
||||||
m_sid = (char*)mbuf.data();
|
m_sid = (char *) mbuf.data();
|
||||||
|
|
||||||
return _do_connect_server();
|
return _do_connect_server();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_is_putty_mode = true;
|
m_is_putty_mode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,96 +263,71 @@ sess_state TelnetSession::_do_negotiation_with_client(TelnetConn* conn) {
|
||||||
MemStream s(conn->data());
|
MemStream s(conn->data());
|
||||||
ex_u8 ch = 0;
|
ex_u8 ch = 0;
|
||||||
ex_u8 ch_cmd = 0;
|
ex_u8 ch_cmd = 0;
|
||||||
for (; s.left() > 0;)
|
for (; s.left() > 0;) {
|
||||||
{
|
|
||||||
ch = s.get_u8();
|
ch = s.get_u8();
|
||||||
if (ch == TELNET_IAC)
|
if (ch == TELNET_IAC) {
|
||||||
{
|
|
||||||
if (s.left() < 2)
|
if (s.left() < 2)
|
||||||
return _do_close(TP_SESS_STAT_ERR_BAD_PKG);
|
return _do_close(TP_SESS_STAT_ERR_BAD_PKG);
|
||||||
|
|
||||||
if (mbuf_sub.size() > 0)
|
if (mbuf_sub.size() > 0) {
|
||||||
{
|
|
||||||
// 已经得到一个sub negotiation,在处理新的数据前,先处理掉旧的
|
// 已经得到一个sub negotiation,在处理新的数据前,先处理掉旧的
|
||||||
EXLOG_BIN(mbuf_sub.data(), mbuf_sub.size(), "-=-=-=-=-=");
|
EXLOG_BIN(mbuf_sub.data(), mbuf_sub.size(), "-=-=-=-=-=");
|
||||||
ms_sub.reset();
|
ms_sub.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
ch_cmd = s.get_u8();
|
ch_cmd = s.get_u8();
|
||||||
if (ch_cmd == TELNET_SB)
|
if (ch_cmd == TELNET_SB) {
|
||||||
{
|
|
||||||
// SUB NEGOTIATION,变长数据,以 FF F0 结束
|
// SUB NEGOTIATION,变长数据,以 FF F0 结束
|
||||||
bool have_SE = false;
|
bool have_SE = false;
|
||||||
ex_u8 ch_sub = 0;
|
ex_u8 ch_sub = 0;
|
||||||
for (; s.left() > 0;)
|
for (; s.left() > 0;) {
|
||||||
{
|
|
||||||
ch_sub = s.get_u8();
|
ch_sub = s.get_u8();
|
||||||
if (ch_sub == TELNET_IAC)
|
if (ch_sub == TELNET_IAC) {
|
||||||
{
|
if (s.left() > 0) {
|
||||||
if (s.left() > 0)
|
if (s.get_u8() == TELNET_SE) {
|
||||||
{
|
|
||||||
if (s.get_u8() == TELNET_SE)
|
|
||||||
{
|
|
||||||
have_SE = true;
|
have_SE = true;
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return _do_close(TP_SESS_STAT_ERR_BAD_PKG);
|
return _do_close(TP_SESS_STAT_ERR_BAD_PKG);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ms_sub.put_u8(ch_sub);
|
ms_sub.put_u8(ch_sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!have_SE)
|
if (!have_SE)
|
||||||
return _do_close(TP_SESS_STAT_ERR_BAD_PKG);
|
return _do_close(TP_SESS_STAT_ERR_BAD_PKG);
|
||||||
}
|
} else if (ch_cmd == TELNET_DONT) {
|
||||||
else if (ch_cmd == TELNET_DONT)
|
|
||||||
{
|
|
||||||
ms_resp.put_u8(TELNET_IAC);
|
ms_resp.put_u8(TELNET_IAC);
|
||||||
ms_resp.put_u8(TELNET_WONT);
|
ms_resp.put_u8(TELNET_WONT);
|
||||||
ms_resp.put_u8(s.get_u8());
|
ms_resp.put_u8(s.get_u8());
|
||||||
}
|
} else if (ch_cmd == TELNET_DO) {
|
||||||
else if (ch_cmd == TELNET_DO)
|
|
||||||
{
|
|
||||||
ms_resp.put_u8(TELNET_IAC);
|
ms_resp.put_u8(TELNET_IAC);
|
||||||
ms_resp.put_u8(TELNET_WILL);
|
ms_resp.put_u8(TELNET_WILL);
|
||||||
ms_resp.put_u8(s.get_u8());
|
ms_resp.put_u8(s.get_u8());
|
||||||
}
|
} else if (ch_cmd == TELNET_WONT) {
|
||||||
else if (ch_cmd == TELNET_WONT)
|
|
||||||
{
|
|
||||||
ms_resp.put_u8(TELNET_IAC);
|
ms_resp.put_u8(TELNET_IAC);
|
||||||
ms_resp.put_u8(TELNET_DONT);
|
ms_resp.put_u8(TELNET_DONT);
|
||||||
ms_resp.put_u8(s.get_u8());
|
ms_resp.put_u8(s.get_u8());
|
||||||
}
|
} else if (ch_cmd == TELNET_WILL) {
|
||||||
else if (ch_cmd == TELNET_WILL)
|
|
||||||
{
|
|
||||||
ms_resp.put_u8(TELNET_IAC);
|
ms_resp.put_u8(TELNET_IAC);
|
||||||
ms_resp.put_u8(TELNET_DO);
|
ms_resp.put_u8(TELNET_DO);
|
||||||
ms_resp.put_u8(s.get_u8());
|
ms_resp.put_u8(s.get_u8());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
s.skip(1);
|
s.skip(1);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ms_msg.put_u8(ch);
|
ms_msg.put_u8(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->data().empty();
|
conn->data().empty();
|
||||||
|
|
||||||
if (mbuf_resp.size() > 0)
|
if (mbuf_resp.size() > 0) {
|
||||||
{
|
|
||||||
conn->send(mbuf_resp.data(), mbuf_resp.size());
|
conn->send(mbuf_resp.data(), mbuf_resp.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mbuf_sub.size() == 5)
|
if (mbuf_sub.size() == 5) {
|
||||||
{
|
|
||||||
// 客户端窗口大小
|
// 客户端窗口大小
|
||||||
if (0x1f == mbuf_sub.data()[0]) {
|
if (0x1f == mbuf_sub.data()[0]) {
|
||||||
ms_sub.rewind();
|
ms_sub.rewind();
|
||||||
|
@ -379,31 +350,28 @@ sess_state TelnetSession::_do_negotiation_with_client(TelnetConn* conn) {
|
||||||
0x03, 0x53, 0x46, 0x55, 0x54, 0x4c, 0x4e, 0x54, 0x56, 0x45, 0x52, 0x03, 0x53, 0x46, 0x55, 0x54,
|
0x03, 0x53, 0x46, 0x55, 0x54, 0x4c, 0x4e, 0x54, 0x56, 0x45, 0x52, 0x03, 0x53, 0x46, 0x55, 0x54,
|
||||||
0x4c, 0x4e, 0x54, 0x4d, 0x4f, 0x44, 0x45, 0xff, 0xf0
|
0x4c, 0x4e, 0x54, 0x4d, 0x4f, 0x44, 0x45, 0xff, 0xf0
|
||||||
};
|
};
|
||||||
m_conn_client->send((ex_u8*)_d, sizeof(_d));
|
m_conn_client->send((ex_u8 *) _d, sizeof(_d));
|
||||||
return s_negotiation_with_client;
|
return s_negotiation_with_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mbuf_sub.size() > 8)
|
if (mbuf_sub.size() > 8) {
|
||||||
{
|
|
||||||
// 可能含有putty的登录用户名信息(就是SID啦)
|
// 可能含有putty的登录用户名信息(就是SID啦)
|
||||||
if (0 == memcmp(mbuf_sub.data(), "\x27\x00\x00\x55\x53\x45\x52\x01", 8)) // '...USER.
|
if (0 == memcmp(mbuf_sub.data(), "\x27\x00\x00\x55\x53\x45\x52\x01", 8)) // '...USER.
|
||||||
{
|
{
|
||||||
mbuf_sub.pop(8);
|
mbuf_sub.pop(8);
|
||||||
for (; mbuf_sub.size() > 0;)
|
for (; mbuf_sub.size() > 0;) {
|
||||||
{
|
|
||||||
if (mbuf_sub.data()[mbuf_sub.size() - 1] == 0x0a || mbuf_sub.data()[mbuf_sub.size() - 1] == 0x0d)
|
if (mbuf_sub.data()[mbuf_sub.size() - 1] == 0x0a || mbuf_sub.data()[mbuf_sub.size() - 1] == 0x0d)
|
||||||
mbuf_sub.size(mbuf_sub.size() - 1);
|
mbuf_sub.size(mbuf_sub.size() - 1);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbuf_sub.append((ex_u8*)"\x00", 1);
|
mbuf_sub.append((ex_u8 *) "\x00", 1);
|
||||||
m_sid = (char*)mbuf_sub.data();
|
m_sid = (char *) mbuf_sub.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_sid.length() > 0)
|
if (m_sid.length() > 0) {
|
||||||
{
|
|
||||||
return _do_connect_server();
|
return _do_connect_server();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,8 +387,7 @@ sess_state TelnetSession::_do_connect_server() {
|
||||||
if (NULL == m_conn_info) {
|
if (NULL == m_conn_info) {
|
||||||
EXLOGE("[telnet] no such session: %s\n", m_sid.c_str());
|
EXLOGE("[telnet] no such session: %s\n", m_sid.c_str());
|
||||||
return _do_close(TP_SESS_STAT_ERR_SESSION);
|
return _do_close(TP_SESS_STAT_ERR_SESSION);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_conn_ip = m_conn_info->conn_ip;
|
m_conn_ip = m_conn_info->conn_ip;
|
||||||
m_conn_port = m_conn_info->conn_port;
|
m_conn_port = m_conn_info->conn_port;
|
||||||
m_acc_name = m_conn_info->acc_username;
|
m_acc_name = m_conn_info->acc_username;
|
||||||
|
@ -434,7 +401,8 @@ sess_state TelnetSession::_do_connect_server() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_conn_info->auth_type != TP_AUTH_TYPE_NONE) {
|
if (m_conn_info->auth_type != TP_AUTH_TYPE_NONE) {
|
||||||
if (m_acc_name.length() == 0 || m_username_prompt.length() == 0 || m_acc_secret.length() == 0 || m_password_prompt.length() == 0) {
|
if (m_acc_name.length() == 0 || m_username_prompt.length() == 0 || m_acc_secret.length() == 0 ||
|
||||||
|
m_password_prompt.length() == 0) {
|
||||||
EXLOGE("[telnet] invalid connection param.\n");
|
EXLOGE("[telnet] invalid connection param.\n");
|
||||||
return _do_close(TP_SESS_STAT_ERR_SESSION);
|
return _do_close(TP_SESS_STAT_ERR_SESSION);
|
||||||
}
|
}
|
||||||
|
@ -484,7 +452,7 @@ sess_state TelnetSession::_do_server_connected() {
|
||||||
m_rec.record_win_size_startup(m_win_width, m_win_height);
|
m_rec.record_win_size_startup(m_win_width, m_win_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[512] = { 0 };
|
char buf[512] = {0};
|
||||||
|
|
||||||
const char *auth_mode = NULL;
|
const char *auth_mode = NULL;
|
||||||
if (m_conn_info->auth_type == TP_AUTH_TYPE_PASSWORD)
|
if (m_conn_info->auth_type == TP_AUTH_TYPE_PASSWORD)
|
||||||
|
@ -510,16 +478,15 @@ sess_state TelnetSession::_do_server_connected() {
|
||||||
line.c_str()
|
line.c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
m_conn_client->send((ex_u8*)buf, strlen(buf));
|
m_conn_client->send((ex_u8 *) buf, strlen(buf));
|
||||||
|
|
||||||
if (m_is_putty_mode)
|
if (m_is_putty_mode) {
|
||||||
{
|
|
||||||
if (m_conn_info->auth_type != TP_AUTH_TYPE_NONE) {
|
if (m_conn_info->auth_type != TP_AUTH_TYPE_NONE) {
|
||||||
ex_astr login_info = "login: ";
|
ex_astr login_info = "login: ";
|
||||||
login_info += m_conn_info->acc_username;
|
login_info += m_conn_info->acc_username;
|
||||||
login_info += "\r\n";
|
login_info += "\r\n";
|
||||||
m_conn_client->send((ex_u8*)login_info.c_str(), login_info.length());
|
m_conn_client->send((ex_u8 *) login_info.c_str(), login_info.length());
|
||||||
m_rec.record(TS_RECORD_TYPE_TELNET_DATA, (ex_u8*)login_info.c_str(), login_info.length());
|
m_rec.record(TS_RECORD_TYPE_TELNET_DATA, (ex_u8 *) login_info.c_str(), login_info.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
ex_u8 _d[] = "\xff\xfb\x1f\xff\xfb\x20\xff\xfb\x18\xff\xfb\x27\xff\xfd\x01\xff\xfb\x03\xff\xfd\x03";
|
ex_u8 _d[] = "\xff\xfb\x1f\xff\xfb\x20\xff\xfb\x18\xff\xfb\x27\xff\xfd\x01\xff\xfb\x03\xff\xfd\x03";
|
||||||
|
@ -530,27 +497,23 @@ sess_state TelnetSession::_do_server_connected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
||||||
m_last_access_timestamp = (ex_u32)time(NULL);
|
m_last_access_timestamp = (ex_u32) time(NULL);
|
||||||
|
|
||||||
TelnetSession* _this = conn->session();
|
TelnetSession *_this = conn->session();
|
||||||
bool is_processed = false;
|
bool is_processed = false;
|
||||||
|
|
||||||
if (conn->is_server_side())
|
if (conn->is_server_side()) {
|
||||||
{
|
|
||||||
// EXLOG_BIN(m_conn_client->data().data(), m_conn_client->data().size(), "<-- client:");
|
// EXLOG_BIN(m_conn_client->data().data(), m_conn_client->data().size(), "<-- client:");
|
||||||
|
|
||||||
// 收到了客户端发来的数据
|
// 收到了客户端发来的数据
|
||||||
if (_this->m_is_putty_mode && !_this->m_username_sent)
|
if (_this->m_is_putty_mode && !_this->m_username_sent) {
|
||||||
{
|
if (_this->_putty_replace_username(m_conn_client, m_conn_server)) {
|
||||||
if (_this->_putty_replace_username(m_conn_client, m_conn_server))
|
|
||||||
{
|
|
||||||
//_this->m_username_sent = true;
|
//_this->m_username_sent = true;
|
||||||
is_processed = true;
|
is_processed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_processed)
|
if (is_processed) {
|
||||||
{
|
|
||||||
m_conn_client->data().empty();
|
m_conn_client->data().empty();
|
||||||
return s_relay;
|
return s_relay;
|
||||||
}
|
}
|
||||||
|
@ -565,27 +528,23 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
||||||
|
|
||||||
m_conn_server->send(m_conn_client->data().data(), m_conn_client->data().size());
|
m_conn_server->send(m_conn_client->data().data(), m_conn_client->data().size());
|
||||||
m_conn_client->data().empty();
|
m_conn_client->data().empty();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// EXLOG_BIN(m_conn_server->data().data(), m_conn_server->data().size(), "--> server:");
|
// EXLOG_BIN(m_conn_server->data().data(), m_conn_server->data().size(), "--> server:");
|
||||||
|
|
||||||
// 收到了服务端返回的数据
|
// 收到了服务端返回的数据
|
||||||
if (m_conn_server->data().data()[0] != TELNET_IAC)
|
if (m_conn_server->data().data()[0] != TELNET_IAC)
|
||||||
m_rec.record(TS_RECORD_TYPE_TELNET_DATA, m_conn_server->data().data(), m_conn_server->data().size());
|
m_rec.record(TS_RECORD_TYPE_TELNET_DATA, m_conn_server->data().data(), m_conn_server->data().size());
|
||||||
|
|
||||||
if (!_this->m_username_sent && _this->m_acc_name.length() > 0)
|
if (!_this->m_username_sent && _this->m_acc_name.length() > 0) {
|
||||||
{
|
if (_this->_parse_find_and_send(m_conn_server, m_conn_client, _this->m_username_prompt.c_str(),
|
||||||
if (_this->_parse_find_and_send(m_conn_server, m_conn_client, _this->m_username_prompt.c_str(), _this->m_acc_name.c_str()))
|
_this->m_acc_name.c_str())) {
|
||||||
{
|
|
||||||
// _this->m_username_sent = true;
|
// _this->m_username_sent = true;
|
||||||
is_processed = true;
|
is_processed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_this->m_password_sent && _this->m_password_prompt.length() > 0)
|
if (!_this->m_password_sent && _this->m_password_prompt.length() > 0) {
|
||||||
{
|
if (_this->_parse_find_and_send(m_conn_server, m_conn_client, _this->m_password_prompt.c_str(),
|
||||||
if (_this->_parse_find_and_send(m_conn_server, m_conn_client, _this->m_password_prompt.c_str(), _this->m_acc_secret.c_str()))
|
_this->m_acc_secret.c_str())) {
|
||||||
{
|
|
||||||
_this->m_username_sent = true;
|
_this->m_username_sent = true;
|
||||||
_this->m_password_sent = true;
|
_this->m_password_sent = true;
|
||||||
_this->m_username_sent = true;
|
_this->m_username_sent = true;
|
||||||
|
@ -593,8 +552,7 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_processed)
|
if (is_processed) {
|
||||||
{
|
|
||||||
m_conn_server->data().empty();
|
m_conn_server->data().empty();
|
||||||
return s_relay;
|
return s_relay;
|
||||||
}
|
}
|
||||||
|
@ -606,8 +564,8 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
||||||
return s_relay;
|
return s_relay;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetSession::_parse_find_and_send(TelnetConn* conn_recv, TelnetConn* conn_remote, const char* find, const char* send)
|
bool TelnetSession::_parse_find_and_send(TelnetConn *conn_recv, TelnetConn *conn_remote, const char *find,
|
||||||
{
|
const char *send) {
|
||||||
// EXLOGV("find prompt and send: [%s] => [%s]\n", find, send);
|
// EXLOGV("find prompt and send: [%s] => [%s]\n", find, send);
|
||||||
// EXLOG_BIN(conn_recv->data().data(), conn_recv->data().size(), "find prompt in data:");
|
// EXLOG_BIN(conn_recv->data().data(), conn_recv->data().size(), "find prompt in data:");
|
||||||
|
|
||||||
|
@ -618,17 +576,15 @@ bool TelnetSession::_parse_find_and_send(TelnetConn* conn_recv, TelnetConn* conn
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_range = conn_recv->data().size() - find_len;
|
int find_range = conn_recv->data().size() - find_len;
|
||||||
for (int i = 0; i <= find_range; ++i)
|
for (int i = 0; i <= find_range; ++i) {
|
||||||
{
|
if (0 == memcmp(conn_recv->data().data() + i, find, find_len)) {
|
||||||
if (0 == memcmp(conn_recv->data().data() + i, find, find_len))
|
|
||||||
{
|
|
||||||
conn_remote->send(conn_recv->data().data(), conn_recv->data().size());
|
conn_remote->send(conn_recv->data().data(), conn_recv->data().size());
|
||||||
conn_recv->data().empty();
|
conn_recv->data().empty();
|
||||||
|
|
||||||
MemBuffer mbuf_msg;
|
MemBuffer mbuf_msg;
|
||||||
mbuf_msg.reserve(128);
|
mbuf_msg.reserve(128);
|
||||||
mbuf_msg.append((ex_u8*)send, send_len);
|
mbuf_msg.append((ex_u8 *) send, send_len);
|
||||||
mbuf_msg.append((ex_u8*)"\x0d\x0a", 2);
|
mbuf_msg.append((ex_u8 *) "\x0d\x0a", 2);
|
||||||
// EXLOG_BIN(mbuf_msg.data(), mbuf_msg.size(), "find prompt and send:");
|
// EXLOG_BIN(mbuf_msg.data(), mbuf_msg.size(), "find prompt and send:");
|
||||||
conn_recv->send(mbuf_msg.data(), mbuf_msg.size());
|
conn_recv->send(mbuf_msg.data(), mbuf_msg.size());
|
||||||
return true;
|
return true;
|
||||||
|
@ -712,8 +668,7 @@ bool TelnetSession::_parse_find_and_send(TelnetConn* conn_recv, TelnetConn* conn
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetSession::_putty_replace_username(TelnetConn* conn_recv, TelnetConn* conn_remote)
|
bool TelnetSession::_putty_replace_username(TelnetConn *conn_recv, TelnetConn *conn_remote) {
|
||||||
{
|
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
|
|
||||||
MemBuffer mbuf_msg;
|
MemBuffer mbuf_msg;
|
||||||
|
@ -723,17 +678,14 @@ bool TelnetSession::_putty_replace_username(TelnetConn* conn_recv, TelnetConn* c
|
||||||
MemStream s(conn_recv->data());
|
MemStream s(conn_recv->data());
|
||||||
ex_u8 ch = 0;
|
ex_u8 ch = 0;
|
||||||
ex_u8 ch_cmd = 0;
|
ex_u8 ch_cmd = 0;
|
||||||
for (; s.left() > 0;)
|
for (; s.left() > 0;) {
|
||||||
{
|
|
||||||
ch = s.get_u8();
|
ch = s.get_u8();
|
||||||
if (ch == TELNET_IAC)
|
if (ch == TELNET_IAC) {
|
||||||
{
|
|
||||||
if (s.left() < 2)
|
if (s.left() < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ch_cmd = s.get_u8();
|
ch_cmd = s.get_u8();
|
||||||
if (ch_cmd == TELNET_SB)
|
if (ch_cmd == TELNET_SB) {
|
||||||
{
|
|
||||||
size_t _begin = s.offset();
|
size_t _begin = s.offset();
|
||||||
size_t _end = 0;
|
size_t _end = 0;
|
||||||
|
|
||||||
|
@ -741,20 +693,15 @@ bool TelnetSession::_putty_replace_username(TelnetConn* conn_recv, TelnetConn* c
|
||||||
// SUB NEGOTIATION,变长数据,以 FF F0 结束
|
// SUB NEGOTIATION,变长数据,以 FF F0 结束
|
||||||
bool have_SE = false;
|
bool have_SE = false;
|
||||||
ex_u8 ch_sub = 0;
|
ex_u8 ch_sub = 0;
|
||||||
for (; s.left() > 0;)
|
for (; s.left() > 0;) {
|
||||||
{
|
|
||||||
_end = s.offset();
|
_end = s.offset();
|
||||||
ch_sub = s.get_u8();
|
ch_sub = s.get_u8();
|
||||||
if (ch_sub == TELNET_IAC)
|
if (ch_sub == TELNET_IAC) {
|
||||||
{
|
if (s.left() > 0) {
|
||||||
if (s.left() > 0)
|
if (s.get_u8() == TELNET_SE) {
|
||||||
{
|
|
||||||
if (s.get_u8() == TELNET_SE)
|
|
||||||
{
|
|
||||||
have_SE = true;
|
have_SE = true;
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,8 +711,7 @@ bool TelnetSession::_putty_replace_username(TelnetConn* conn_recv, TelnetConn* c
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t len = _end - _begin;
|
size_t len = _end - _begin;
|
||||||
if (len <= 8 || 0 != memcmp("\x27\x00\x00\x55\x53\x45\x52\x01", conn_recv->data().data() + _begin, 8))
|
if (len <= 8 || 0 != memcmp("\x27\x00\x00\x55\x53\x45\x52\x01", conn_recv->data().data() + _begin, 8)) {
|
||||||
{
|
|
||||||
ms_msg.put_u8(TELNET_IAC);
|
ms_msg.put_u8(TELNET_IAC);
|
||||||
ms_msg.put_u8(TELNET_SB);
|
ms_msg.put_u8(TELNET_SB);
|
||||||
ms_msg.put_bin(conn_recv->data().data() + _begin, len);
|
ms_msg.put_bin(conn_recv->data().data() + _begin, len);
|
||||||
|
@ -778,30 +724,25 @@ bool TelnetSession::_putty_replace_username(TelnetConn* conn_recv, TelnetConn* c
|
||||||
|
|
||||||
ms_msg.put_u8(TELNET_IAC);
|
ms_msg.put_u8(TELNET_IAC);
|
||||||
ms_msg.put_u8(TELNET_SB);
|
ms_msg.put_u8(TELNET_SB);
|
||||||
ms_msg.put_bin((ex_u8*)"\x27\x00\x00\x55\x53\x45\x52\x01", 8);
|
ms_msg.put_bin((ex_u8 *) "\x27\x00\x00\x55\x53\x45\x52\x01", 8);
|
||||||
|
|
||||||
ms_msg.put_bin((ex_u8*)m_acc_name.c_str(), m_acc_name.length());
|
ms_msg.put_bin((ex_u8 *) m_acc_name.c_str(), m_acc_name.length());
|
||||||
|
|
||||||
ms_msg.put_u8(TELNET_IAC);
|
ms_msg.put_u8(TELNET_IAC);
|
||||||
ms_msg.put_u8(TELNET_SE);
|
ms_msg.put_u8(TELNET_SE);
|
||||||
|
|
||||||
replaced = true;
|
replaced = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ms_msg.put_u8(ch);
|
ms_msg.put_u8(ch);
|
||||||
ms_msg.put_u8(ch_cmd);
|
ms_msg.put_u8(ch_cmd);
|
||||||
ms_msg.put_u8(s.get_u8());
|
ms_msg.put_u8(s.get_u8());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ms_msg.put_u8(ch);
|
ms_msg.put_u8(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (replaced)
|
if (replaced) {
|
||||||
{
|
|
||||||
conn_remote->send(mbuf_msg.data(), mbuf_msg.size());
|
conn_remote->send(mbuf_msg.data(), mbuf_msg.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -809,7 +750,7 @@ bool TelnetSession::_putty_replace_username(TelnetConn* conn_recv, TelnetConn* c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelnetSession::_parse_win_size(TelnetConn* conn) {
|
bool TelnetSession::_parse_win_size(TelnetConn *conn) {
|
||||||
if (conn->data().size() < 9)
|
if (conn->data().size() < 9)
|
||||||
return false;
|
return false;
|
||||||
if (conn->data().data()[0] != TELNET_IAC)
|
if (conn->data().data()[0] != TELNET_IAC)
|
||||||
|
@ -817,34 +758,26 @@ bool TelnetSession::_parse_win_size(TelnetConn* conn) {
|
||||||
|
|
||||||
bool is_sub = false;
|
bool is_sub = false;
|
||||||
MemStream s(conn->data());
|
MemStream s(conn->data());
|
||||||
for (; s.left() > 0;)
|
for (; s.left() > 0;) {
|
||||||
{
|
if (s.get_u8() == TELNET_IAC) {
|
||||||
if (s.get_u8() == TELNET_IAC)
|
|
||||||
{
|
|
||||||
if (s.left() < 2)
|
if (s.left() < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (s.get_u8() == TELNET_SB)
|
if (s.get_u8() == TELNET_SB) {
|
||||||
{
|
|
||||||
size_t _begin = s.offset();
|
size_t _begin = s.offset();
|
||||||
size_t _end = 0;
|
size_t _end = 0;
|
||||||
|
|
||||||
// SUB NEGOTIATION,变长数据,以 TELNET_IAC+TELNET_SE (FF F0) 结束
|
// SUB NEGOTIATION,变长数据,以 TELNET_IAC+TELNET_SE (FF F0) 结束
|
||||||
bool have_SE = false;
|
bool have_SE = false;
|
||||||
ex_u8 ch_sub = 0;
|
ex_u8 ch_sub = 0;
|
||||||
for (; s.left() > 0;)
|
for (; s.left() > 0;) {
|
||||||
{
|
|
||||||
_end = s.offset();
|
_end = s.offset();
|
||||||
if (s.get_u8() == TELNET_IAC)
|
if (s.get_u8() == TELNET_IAC) {
|
||||||
{
|
if (s.left() > 0) {
|
||||||
if (s.left() > 0)
|
if (s.get_u8() == TELNET_SE) {
|
||||||
{
|
|
||||||
if (s.get_u8() == TELNET_SE)
|
|
||||||
{
|
|
||||||
have_SE = true;
|
have_SE = true;
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue