276 lines
7.5 KiB
C++
276 lines
7.5 KiB
C++
#include "stdafx.h"
|
|
#include "ConfigIni.h"
|
|
#include "Logger.h"
|
|
#include "LoginListener.h"
|
|
#include "LoginClient.h"
|
|
#include "GameListener.h"
|
|
|
|
extern class CConfig g_cfg; // declared in main.cpp
|
|
extern class GameListener *g_pgame; // declared in main.cpp
|
|
extern HWND g_radardll_hwnd; // declared in RadarDllWnd.cpp
|
|
|
|
struct FLLT_INFO
|
|
{
|
|
class LoginListener *cls;
|
|
};
|
|
|
|
void FLS_Thread_freeInfo( struct FLLT_INFO *pinfo )
|
|
{
|
|
if( pinfo->cls->m_listen_socket != INVALID_SOCKET )
|
|
{
|
|
L2PNet_shutdown( pinfo->cls->m_listen_socket );
|
|
L2PNet_closesocket( pinfo->cls->m_listen_socket );
|
|
pinfo->cls->m_listen_socket = INVALID_SOCKET;
|
|
}
|
|
if( pinfo->cls->m_hThread ) CloseHandle( pinfo->cls->m_hThread );
|
|
pinfo->cls->m_hThread = NULL;
|
|
pinfo->cls->m_signal = 0;
|
|
free( pinfo );
|
|
log_error( LOG_DEBUG, "FLS_Thread(): thread info struct freed\n" );
|
|
}
|
|
|
|
DWORD WINAPI LoginListener::FLS_Thread( LPVOID lpParam )
|
|
{
|
|
struct FLLT_INFO *pinfo = (struct FLLT_INFO *)lpParam;
|
|
lpParam = NULL;
|
|
if( !pinfo )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): lpParam is NULL! Exit\n" );
|
|
return 0;
|
|
}
|
|
class LoginListener *cls = pinfo->cls;
|
|
if( !cls )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): pinfo->cls is NULL! Exit\n" );
|
|
FLS_Thread_freeInfo( pinfo );
|
|
return 0;
|
|
}
|
|
cls->m_listen_socket = INVALID_SOCKET;
|
|
//DWORD wait_res = 0;
|
|
//SOCKET s = sock_tcp_create();
|
|
SOCKET s = L2PNet_TCPsocket_create( true );
|
|
if( s == INVALID_SOCKET )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): socket create failed!\n" );
|
|
FLS_Thread_freeInfo( pinfo );
|
|
return 0;
|
|
}
|
|
|
|
int mb_yes = 0;
|
|
int bind_fail = 0;
|
|
ll_bind:
|
|
bind_fail = L2PNet_bind( s, g_cfg.FakeListenLoginIP, (unsigned short)g_cfg.FakeListenLoginPort );
|
|
if( bind_fail )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): socket bind at %s:%d failed\n",
|
|
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
|
int wsaerr = L2PNet_WSAGetLastError();
|
|
if( wsaerr == WSAEADDRINUSE )
|
|
{
|
|
wchar_t errmsg[256];
|
|
wsprintfW( errmsg, L"Ïîðò %S:%d óæå èñïîëüçóåòñÿ äðóãèì ïðîöåññîì!\n"
|
|
L"Ïîïðîáîâàòü åù¸ ðàç?",
|
|
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
|
mb_yes = MessageBoxW( g_radardll_hwnd, errmsg, L"L2Detect: Îøèáêà!", MB_ICONSTOP | MB_YESNO );
|
|
if( mb_yes == IDYES ) goto ll_bind;
|
|
}
|
|
FLS_Thread_freeInfo( pinfo );
|
|
return 0;
|
|
}
|
|
|
|
if( L2PNet_listen( s ) )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): listen() failed\n" );
|
|
FLS_Thread_freeInfo( pinfo );
|
|
return 0;
|
|
}
|
|
|
|
cls->m_listen_socket = s;
|
|
|
|
log_error( LOG_DEBUG, "FLS_Thread(): started, listening at %s:%d\n",
|
|
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
|
|
|
// raise thread priority
|
|
if( !SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL ) )
|
|
log_error( LOG_WARNING, "FLS_Thread(): raise thread priority failed!\n" );
|
|
|
|
int r = 0;
|
|
char clientIP[32] = {0};
|
|
unsigned short clientPort = 0;
|
|
SOCKET scl = INVALID_SOCKET;
|
|
int rdyR = 0, rdyW = 0; // ready to recv/send
|
|
unsigned int scode = 0; // signal to thread
|
|
int should_exit = 0;
|
|
|
|
while( 1 )
|
|
{
|
|
should_exit = 0;
|
|
//r = sock_tcp_wait_ready_to_recv( s, 0, 500000 );
|
|
rdyR = 0;
|
|
r = L2PNet_select( s, L2PNET_SELECT_READ, 500, &rdyR, &rdyW );
|
|
scode = cls->getLastSignal();
|
|
if( scode == FLLS_STOP )
|
|
{
|
|
log_error( LOG_DEBUG, "FLS_Thread(): exit signal\n" );
|
|
should_exit = 1;
|
|
}
|
|
if( should_exit ) break; // break while()
|
|
if( r == -1 )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): socket select() error\n" );
|
|
break;
|
|
}
|
|
if( r == 1 && rdyR )
|
|
{
|
|
//log_error( LOG_DEBUG, "FLS_Thread(): Somebody connected? :)\n" );
|
|
clientIP[0] = 0;
|
|
clientPort = 0;
|
|
scl = INVALID_SOCKET;
|
|
//scl = sock_tcp_accept( s, clientIP, &clientPort );
|
|
scl = L2PNet_accept( s, clientIP, &clientPort );
|
|
if( scl == INVALID_SOCKET )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): accept() failed...\n" );
|
|
}
|
|
else
|
|
{
|
|
//log_error( LOG_DEBUG, "FLS_Thread(): accepted client %s:%d\n", clientIP, clientPort );
|
|
log_error( LOG_OK, "LoginListener: accepted client %s:%d\n", clientIP, clientPort );
|
|
LoginClient lc;
|
|
if( lc.ProcessClient( scl ) )
|
|
{
|
|
unsigned char sKey1[8] = {0,0,0,0, 0,0,0,0};
|
|
unsigned char sKey2[8] = {0,0,0,0, 0,0,0,0};
|
|
struct PlayServerInfo sinfo;
|
|
lc.getSessionKeys( sKey1, sKey2 );
|
|
lc.getPlayServerAddress( sinfo.ip, &(sinfo.port) );
|
|
|
|
// ONLY IN OUTGAME MODE stop listener after successful client acception
|
|
if( g_cfg.isInGameMode == false )
|
|
{
|
|
// stop listener after successful client acception
|
|
log_error( LOG_DEBUG, "FLS_Thread(): LoginListener stopping self in outgame mode, "
|
|
"after client accepted, freeing port %s:%d\n",
|
|
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
|
//cls->signalStop();
|
|
should_exit = 1;
|
|
}
|
|
|
|
if( !g_pgame )
|
|
{
|
|
log_error( LOG_ERROR, "FLS_Thread(): Game listener is NULL????" );
|
|
}
|
|
else
|
|
{
|
|
// set play server info to game listener
|
|
g_pgame->setPlayServerInfo( &sinfo );
|
|
}
|
|
}
|
|
}
|
|
} // somebody connected?
|
|
if( should_exit ) break; // break while()
|
|
} // while(1)
|
|
|
|
//sock_tcp_close_shutdown( s, SD_BOTH );
|
|
// network sockets clenup done by FLS_Thread_freeInfo()
|
|
|
|
FLS_Thread_freeInfo( pinfo );
|
|
log_error( LOG_DEBUG, "FLS_Thread() ended\n" );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/// class
|
|
|
|
|
|
LoginListener::LoginListener()
|
|
{
|
|
this->_initNull();
|
|
}
|
|
|
|
LoginListener::~LoginListener()
|
|
{
|
|
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
|
this->_initNull();
|
|
}
|
|
|
|
|
|
bool LoginListener::start()
|
|
{
|
|
// cleanup ?
|
|
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
|
this->_initNull();
|
|
// alloc thread info struct
|
|
struct FLLT_INFO *pinfo = (struct FLLT_INFO *)malloc( sizeof( struct FLLT_INFO ) );
|
|
if( !pinfo ) return false;
|
|
// fill info
|
|
pinfo->cls = this;
|
|
// create thread object
|
|
this->m_hThread = NULL;
|
|
DWORD dwTID = 0;
|
|
this->m_hThread = (HANDLE)_beginthreadex(
|
|
NULL, // security
|
|
0, // stack size
|
|
(unsigned int (__stdcall*)(void *))FLS_Thread, // thread function
|
|
(void *)pinfo, // thread function argument - lpParam
|
|
0, // flags
|
|
(unsigned int *)(&dwTID) );
|
|
if( !this->m_hThread )
|
|
{
|
|
free( pinfo );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LoginListener::waitStopped( unsigned int timeoutMsec )
|
|
{
|
|
if( !this->m_hThread ) return true;
|
|
DWORD wait_res = WaitForSingleObject( this->m_hThread, (DWORD)timeoutMsec );
|
|
if( wait_res != WAIT_OBJECT_0 )
|
|
{
|
|
log_error( LOG_DEBUG, "LoginListener::waitStopped(): WaitForSingleObject() returned 0x%08X\n", wait_res );
|
|
if( wait_res == WAIT_TIMEOUT ) log_error( LOG_DEBUG, "LoginListener::waitStopped(): WAIT_TIMEOUT\n" );
|
|
return false;
|
|
}
|
|
// wait OK, close kernel objects
|
|
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
|
// initialize self
|
|
this->_initNull();
|
|
return true;
|
|
}
|
|
|
|
void LoginListener::terminateThread()
|
|
{
|
|
if( this->m_hThread )
|
|
{
|
|
TerminateThread( this->m_hThread, 0xBAADF00D );
|
|
CloseHandle( this->m_hThread );
|
|
this->m_hThread = NULL;
|
|
this->m_signal = 0;
|
|
// thread resources
|
|
if( m_listen_socket != INVALID_SOCKET )
|
|
{
|
|
//sock_tcp_close_shutdown( m_listen_socket, SD_BOTH );
|
|
L2PNet_shutdown( m_listen_socket );
|
|
L2PNet_closesocket( m_listen_socket );
|
|
}
|
|
m_listen_socket = INVALID_SOCKET;
|
|
}
|
|
}
|
|
|
|
void LoginListener::_initNull()
|
|
{
|
|
m_hThread = NULL;
|
|
m_signal = 0;
|
|
// thread resources
|
|
m_listen_socket = INVALID_SOCKET;
|
|
}
|
|
|
|
bool LoginListener::isRunning() const
|
|
{
|
|
if( this->m_hThread != NULL ) return true;
|
|
return false;
|
|
}
|
|
|