FBIagent
Erfahrenes Mitglied
Guten tag,
ich habe mir ein paar Klassen für Overlapped-Sockets und IOCP geschrieben. Soweit sogut,
die Verbindung wird angenommen, und die erste Notifikation kommt beim
IOCP-WorkerThread an. Wenn ich nun WSASend/Recv, WSA_IO_PENDING zurück
bekomme, kommt beim IOCP-WorkerThread leider keine weitere Notifikation an.
OverlappedOperationData:
IOCP:
IOCPHandleData:
IOCPWorker:
BaseSocket:
OverlappedTCPSocket:
OverlappedTCPClient:
LoginIOCPWorker:
L2LoginClient:
Ja da hab ich mir bisl was zusammen gebaut, wäre nett wenn mal jemand schaun kann
und eventuell einen Vorschlag hatt.
Best wishes
FBIagent
ich habe mir ein paar Klassen für Overlapped-Sockets und IOCP geschrieben. Soweit sogut,
die Verbindung wird angenommen, und die erste Notifikation kommt beim
IOCP-WorkerThread an. Wenn ich nun WSASend/Recv, WSA_IO_PENDING zurück
bekomme, kommt beim IOCP-WorkerThread leider keine weitere Notifikation an.
OverlappedOperationData:
C++:
#ifndef __UTILS_WINAPI_IO_OVERLAPPEDOPERATIONDATA_H__
#define __UTILS_WINAPI_IO_OVERLAPPEDOPERATIONDATA_H__
namespace Utils {
namespace WinAPI {
namespace IO {
struct OverlappedOperationData {
OVERLAPPED Overlapped;
};
} // namespace IO
} // namespace WinAPI
} // namespace Utils
#endif
C++:
#ifndef __UTILS_WINAPI_IOCP_IOCP_H__
#define __UTILS_WINAPI_IOCP_IOCP_H__
#include <vector>
#include <windows.h>
namespace Utils {
namespace WinAPI {
namespace IOCP {
class IOCPWorker;
class IOCPHandleData;
typedef std::vector< IOCPWorker* > IOCPWorkersVector;
class IOCP {
public:
IOCP();
virtual ~IOCP();
void AddWorker( IOCPWorker *Worker );
void StartWorkers();
void NotifyWorkersToTerminate();
void WaitForWorkersToTerminate();
void AssociateIOHandle( IOCPHandleData *HandleData );
HANDLE GetHandle();
private:
HANDLE m_IOCPHandle;
IOCPWorkersVector m_Workers;
};
} // namespace IOCP
} // namespace WinAPI
} // namespace Utils
#endif
#include ".\IOCP.h"
#include ".\IOCPWorker.h"
#include ".\IOCPHandleData.h"
#include ".\IOCPException.h"
namespace Utils {
namespace WinAPI {
namespace IOCP {
IOCP::IOCP()
: m_Workers() {
m_IOCPHandle = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );
if ( m_IOCPHandle == NULL ) {
throw mIOCPException( GetLastError() );
}
}
IOCP::~IOCP() {
NotifyWorkersToTerminate();
WaitForWorkersToTerminate();
CloseHandle( m_IOCPHandle );
for ( IOCPWorkersVector::size_type i = 0;i < m_Workers.size();++ i ) {
delete m_Workers[ i ];
}
}
void IOCP::AddWorker( IOCPWorker *Worker ) {
m_Workers.push_back( Worker );
}
void IOCP::StartWorkers() {
for ( IOCPWorkersVector::size_type i = 0;i < m_Workers.size();++ i ) {
m_Workers[ i ]->Start();
}
}
void IOCP::NotifyWorkersToTerminate() {
for ( IOCPWorkersVector::size_type i = 0;i < m_Workers.size();++ i ) {
PostQueuedCompletionStatus( m_IOCPHandle, 0, NULL, NULL );
}
}
void IOCP::WaitForWorkersToTerminate() {
for ( IOCPWorkersVector::size_type i = 0;i < m_Workers.size();++ i ) {
m_Workers[ i ]->Wait();
}
}
void IOCP::AssociateIOHandle( IOCPHandleData *HandleData ) {
if ( CreateIoCompletionPort( HandleData->GetIOHandle(), m_IOCPHandle, ( ULONG_PTR )HandleData, 1 ) == NULL ) {
throw mIOCPException( GetLastError() );
}
}
HANDLE IOCP::GetHandle() {
return m_IOCPHandle;
}
} // namespace IOCP
} // namespace WinAPI
} // namespace Utils
C++:
#ifndef __UTILS_WINAPI_IOCP_IOCPHANDLEDATA_H__
#define __UTILS_WINAPI_IOCP_IOCPHANDLEDATA_H__
#include <windows.h>
namespace Utils {
namespace WinAPI {
namespace IOCP {
enum IOCPOpCode {
IOCP_OP_READ,
IOCP_OP_WRITE
};
class IOCPHandleData {
public:
IOCPHandleData( HANDLE IOHandle, IOCPOpCode OpCode );
virtual ~IOCPHandleData();
void SetOpCode( IOCPOpCode OpCode );
HANDLE GetIOHandle() const ;
IOCPOpCode GetOpCode() const ;
private:
HANDLE m_IOHandle;
IOCPOpCode m_OpCode;
};
} // namespace IOCP
} // namespace WinAPI
} // namespace Utils
#endif
#include ".\IOCPHandleData.h"
namespace Utils {
namespace WinAPI {
namespace IOCP {
IOCPHandleData::IOCPHandleData( HANDLE IOHandle, IOCPOpCode OpCode )
: m_IOHandle( IOHandle ), m_OpCode( OpCode ) {
}
IOCPHandleData::~IOCPHandleData() {
}
void IOCPHandleData::SetOpCode( IOCPOpCode OpCode ) {
m_OpCode = OpCode;
}
HANDLE IOCPHandleData::GetIOHandle() const {
return m_IOHandle;
}
IOCPOpCode IOCPHandleData::GetOpCode() const {
return m_OpCode;
}
} // namespace IOCP
} // namespace WinAPI
} // namespace Utils
C++:
#ifndef __UTILS_WINAPI_IOCP_IOCPWORKER_H__
#define __UTILS_WINAPI_IOCP_IOCPWORKER_H__
#include "..\..\String.h"
#include "..\Parallelism\Thread.h"
#include <windows.h>
namespace Utils {
namespace WinAPI {
namespace IO {
struct OverlappedOperationData;
} // namespace IO
namespace IOCP {
class IOCP;
class IOCPHandleData;
class IOCPWorker
: public Utils::WinAPI::Parallelism::Thread {
public:
IOCPWorker( IOCP *CompletionPort );
virtual ~IOCPWorker();
void Run();
virtual void TerminateSignaled() = 0;
virtual void SucceedIO( DWORD TransferedBytes, IOCPHandleData *HandleData, Utils::WinAPI::IO::OverlappedOperationData *OperationData ) = 0;
virtual void CompletionError( DWORD ErrorNum ) = 0;
virtual void FailedIO( DWORD ErrorNum, Utils::String ErrorStr, DWORD TransferedBytes, IOCPHandleData *HandleData, Utils::WinAPI::IO::OverlappedOperationData *OperationData ) = 0;
IOCP *GetCompletionPort();
private:
IOCP *m_CompletionPort;
};
} // namespace IOCP
} // namespace WinAPI
} // namespace Utils
#endif
#include "IOCPWorker.h"
#include "..\Helper.h"
#include ".\IOCP.h"
namespace Utils {
namespace WinAPI {
namespace IOCP {
IOCPWorker::IOCPWorker( IOCP *CompletionPort )
: Thread(), m_CompletionPort( CompletionPort ) {
}
IOCPWorker::~IOCPWorker() {
}
void IOCPWorker::Run() {
DWORD TransferedBytes = 0;
IOCPHandleData *HandleData = NULL;
Utils::WinAPI::IO::OverlappedOperationData *OperationData = NULL;
while ( true ) {
BOOL Result = GetQueuedCompletionStatus(
m_CompletionPort->GetHandle(),
&TransferedBytes,
( PULONG_PTR )&HandleData,
( LPOVERLAPPED* )&OperationData,
INFINITE
);
if ( TransferedBytes == 0 && HandleData == NULL && OperationData == NULL ) {
// we got notified to terminate
TerminateSignaled();
break;
}
if ( Result == TRUE ) {
// an I/O operation has succeed
SucceedIO( TransferedBytes, HandleData, OperationData );
} else if ( OperationData == NULL ) {
// there was an error with the completion port
CompletionError( GetLastError() );
} else {
// an I/O operation has failed
FailedIO( GetLastError(), Utils::WinAPI::GetErrorString( GetLastError() ), TransferedBytes, HandleData, OperationData );
}
}
}
IOCP *IOCPWorker::GetCompletionPort() {
return m_CompletionPort;
}
} // namespace IOCP
} // namespace WinAPI
} // namespace Utils
C++:
#ifndef __UTILS_WINSOCK_BASESOCKET_H__
#define __UTILS_WINSOCK_BASESOCKET_H__
#include <winsock2.h>
namespace Utils {
namespace WinSock {
class BaseSocket {
public:
BaseSocket();
BaseSocket( SOCKET Socket );
virtual ~BaseSocket();
static void WSAInit();
static void WSADeInit();
void Close();
SOCKET GetSocket() const ;
protected:
static WSADATA m_WSAData;
SOCKET m_Socket;
};
} // namespace WinSock
} // namespace Utils
#endif
#include ".\BaseSocket.h"
#include "..\Macro.h"
#include "..\String.h"
#include "..\WinAPI\Helper.h"
#include ".\WinSockException.h"
namespace Utils {
namespace WinSock {
BaseSocket::BaseSocket()
: m_Socket( INVALID_SOCKET ) {
}
BaseSocket::BaseSocket( SOCKET Socket )
: m_Socket( Socket ) {
}
BaseSocket::~BaseSocket() {
closesocket( m_Socket );
}
void BaseSocket::WSAInit() {
int Result = WSAStartup( MAKEWORD( 2, 2 ), &m_WSAData );
if ( Result != 0 ) {
throw mWinsockException( Result );
}
}
void BaseSocket::WSADeInit() {
if ( WSACleanup() != 0 ) {
throw mWinsockException( WSAGetLastError() );
}
}
void BaseSocket::Close() {
closesocket( m_Socket );
}
SOCKET BaseSocket::GetSocket() const {
return m_Socket;
}
WSADATA BaseSocket::m_WSAData;
} // namespace WinSock
} // namespace Utils
C++:
#ifndef __UTILS_WINSOCK_OVERLAPPEDTCPSOCKET_H__
#define __UTILS_WINSOCK_OVERLAPPEDTCPSOCKET_H__
#include ".\BaseSocket.h"
namespace Utils {
namespace WinAPI {
namespace IO {
struct OverlappedOperationData;
} // namespace IO
} // namespace WinAPI
namespace WinSock {
class OverlappedTCPSocket
: public BaseSocket {
public:
OverlappedTCPSocket();
OverlappedTCPSocket( SOCKET Socket );
virtual ~OverlappedTCPSocket();
const Utils::WinAPI::IO::OverlappedOperationData *GetOverlappedData() const ;
protected:
Utils::WinAPI::IO::OverlappedOperationData *m_OperationData;
};
} // namespace WinSock
} // namespace Utils
#endif
#include ".\OverlappedTCPSocket.h"
#include "..\MemoryException.h"
#include "..\WinAPI\IO\OverlappedOperationData.h"
#include ".\WinSockException.h"
namespace Utils {
namespace WinSock {
OverlappedTCPSocket::OverlappedTCPSocket()
: BaseSocket() {
m_Socket = WSASocket( AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED );
if ( m_Socket == INVALID_SOCKET ) {
throw mWinsockException( WSAGetLastError() );
}
try {
m_OperationData = new Utils::WinAPI::IO::OverlappedOperationData;
memset( &( m_OperationData->Overlapped ), 0, sizeof( m_OperationData->Overlapped ) );
} catch ( std::bad_alloc &e ) {
throw mMemoryException( StaticString( "Failed to allocate memory with new Utils::WinAPI::IO::OverlappedOperationData!" ), sizeof( Utils::WinAPI::IO::OverlappedOperationData ) );
}
}
OverlappedTCPSocket::OverlappedTCPSocket( SOCKET Socket )
: BaseSocket( Socket ) {
try {
m_OperationData = new Utils::WinAPI::IO::OverlappedOperationData;
memset( &( m_OperationData->Overlapped ), 0, sizeof( m_OperationData->Overlapped ) );
} catch ( std::bad_alloc &e ) {
throw mMemoryException( StaticString( "Failed to allocate memory with new Utils::WinAPI::IO::OverlappedOperationData!" ), sizeof( Utils::WinAPI::IO::OverlappedOperationData ) );
}
}
OverlappedTCPSocket::~OverlappedTCPSocket() {
delete m_OperationData;
}
const Utils::WinAPI::IO::OverlappedOperationData *OverlappedTCPSocket::GetOverlappedData() const {
return m_OperationData;
}
} // namespace WinSock
} // namespace Utils
C++:
#ifndef __UTILS_WINSOCK_OVERLAPPEDTCPCLIENT_H__
#define __UTILS_WINSOCK_OVERLAPPEDTCPCLIENT_H__
#include "..\String.h"
#include ".\OverlappedTCPSocket.h"
namespace Utils {
namespace WinSock {
class OverlappedTCPClient
: public OverlappedTCPSocket {
public:
OverlappedTCPClient();
OverlappedTCPClient( SOCKET Socket, SOCKADDR_IN SockAddrIn );
virtual ~OverlappedTCPClient();
void Connect( Utils::String Host, int Port );
void Read( char *Buffer, unsigned long BufferLen, DWORD &ReadBytes );
void Write( char *Buffer, unsigned long BufferLen, DWORD &WrittenBytes );
SOCKADDR_IN GetSockAddrIn() const;
protected:
SOCKADDR_IN m_SockAddrIn;
};
} // namespace WinSock
} // namespace Utils
#endif
#include ".\OverlappedTCPClient.h"
#include "..\Helper.h"
#include ".\WinSockException.h"
#include "..\IOStream.h"
namespace Utils {
namespace WinSock {
OverlappedTCPClient::OverlappedTCPClient()
: OverlappedTCPSocket(), m_SockAddrIn() {
}
OverlappedTCPClient::OverlappedTCPClient( SOCKET Socket, SOCKADDR_IN SockAddrIn )
: OverlappedTCPSocket( Socket ), m_SockAddrIn( SockAddrIn ) {
}
OverlappedTCPClient::~OverlappedTCPClient() {
}
void OverlappedTCPClient::Connect( Utils::String Ip, int Port ) {
m_SockAddrIn.sin_family = AF_INET;
#ifdef _UNICODE
Utils::AChar *ACIp = Utils::WideToMulti( Ip.c_str() );
m_SockAddrIn.sin_addr.s_addr = inet_addr( ACIp );
delete[] ACIp;
#else
m_SockAddrIn.sin_addr.s_addr = inet_addr( Ip.c_str() );
#endif
m_SockAddrIn.sin_port = htons( Port );
if ( connect( GetSocket(), ( SOCKADDR* )&m_SockAddrIn, sizeof ( m_SockAddrIn ) ) == SOCKET_ERROR ) {
throw mWinsockException( WSAGetLastError() );
}
}
void OverlappedTCPClient::Read( char *Buffer, unsigned long BufferLen, DWORD &ReadBytes ) {
WSABUF WSABuf = { BufferLen, Buffer };
DWORD Flags = 0;
if ( WSARecv( GetSocket(), &WSABuf, 1, &ReadBytes, &Flags, ( LPWSAOVERLAPPED )GetOverlappedData(), NULL ) == SOCKET_ERROR ) {
throw mWinsockException( WSAGetLastError() );
}
}
void OverlappedTCPClient::Write( char *Buffer, unsigned long BufferLen, DWORD &WrittenBytes ) {
WSABUF WSABuf = { BufferLen, Buffer };
DWORD Flags = 0;
if ( WSASend( GetSocket(), &WSABuf, 1, &WrittenBytes, Flags, ( LPWSAOVERLAPPED )GetOverlappedData(), NULL ) == SOCKET_ERROR ) {
throw mWinsockException( WSAGetLastError() );
}
}
SOCKADDR_IN OverlappedTCPClient::GetSockAddrIn() const {
return m_SockAddrIn;
}
} // namespace WinSock
} // namespace Utils
C++:
#ifndef __L2KANAK_LOGIN_LOGINIOCPWORKER_H__
#define __L2KANAK_LOGIN_LOGINIOCPWORKER_H__
#include "..\..\Utils\WinAPI\IOCP\IOCPWorker.h"
namespace L2Kanak {
namespace Login {
class LoginIOCPWorker
: public Utils::WinAPI::IOCP::IOCPWorker {
public:
LoginIOCPWorker( Utils::WinAPI::IOCP::IOCP *CompletionPort );
virtual ~LoginIOCPWorker();
void TerminateSignaled();
void SucceedIO( DWORD TransferedBytes, Utils::WinAPI::IOCP::IOCPHandleData *HandleData, Utils::WinAPI::IO::OverlappedOperationData *OperationData );
void CompletionError( DWORD ErrorNum );
void FailedIO( DWORD ErrorNum, Utils::String ErrorStr, DWORD TransferedBytes, Utils::WinAPI::IOCP::IOCPHandleData *HandleData, Utils::WinAPI::IO::OverlappedOperationData *OperationData );
private:
};
} // namespace Login
} // namespace L2Kanak
#endif
#include ".\LoginIOCPWorker.h"
#include "..\..\Utils\IOStream.h"
#include "..\..\Utils\String.h"
#include "..\..\Utils\WinAPI\IOCP\IOCP.h"
#include ".\L2LoginClient.h"
namespace L2Kanak {
namespace Login {
LoginIOCPWorker::LoginIOCPWorker( Utils::WinAPI::IOCP::IOCP *CompletionPort )
: Utils::WinAPI::IOCP::IOCPWorker( CompletionPort ) {
}
LoginIOCPWorker::~LoginIOCPWorker() {
}
void LoginIOCPWorker::TerminateSignaled() {
}
void LoginIOCPWorker::SucceedIO( DWORD TransferedBytes, Utils::WinAPI::IOCP::IOCPHandleData *HandleData, Utils::WinAPI::IO::OverlappedOperationData *OperationData ) {
L2LoginClient *Client = static_cast< L2LoginClient* >( HandleData );
Client->GetMutex()->Lock();
if ( Client->GetState() == CS_BAD_CLIENT ) {
COut << StaticString( "Bad client. Kill it!" ) << std::endl;
delete Client;
return;
}
switch ( Client->GetOpCode() ) {
case Utils::WinAPI::IOCP::IOCP_OP_WRITE:
CErr << StaticString( "write" ) << std::endl;
Client->SetOpCode( Utils::WinAPI::IOCP::IOCP_OP_READ );
Client->WriteSome();
break;
case Utils::WinAPI::IOCP::IOCP_OP_READ:
CErr << StaticString( "read" ) << std::endl;
Client->SetOpCode( Utils::WinAPI::IOCP::IOCP_OP_WRITE );
Client->ReadSome();
break;
}
Client->GetMutex()->Unlock();
}
void LoginIOCPWorker::CompletionError( DWORD ErrorNum ) {
}
void LoginIOCPWorker::FailedIO( DWORD ErrorNum, Utils::String ErrorStr, DWORD TransferedBytes, Utils::WinAPI::IOCP::IOCPHandleData *HandleData, Utils::WinAPI::IO::OverlappedOperationData *OperationData ) {
COut << StaticString( "Failed IO" ) << std::endl;
}
} // namespace Login
} // namespace L2Kanak
C++:
#ifndef __L2KANAK_LOGIN_L2LOGINCLIENT_H__
#define __L2KANAK_LOGIN_L2LOGINCLIENT_H__
#include "..\..\Utils\ByteBuffer.h"
#include "..\..\Utils\WinAPI\IOCP\IOCPHandleData.h"
#include "..\..\Utils\WinAPI\Parallelism\Mutex.h"
#include "..\..\Utils\WinSock\OverlappedTCPClient.h"
#include ".\L2LoginSessionKey.h"
#include ".\LoginCrypt.h"
namespace L2Kanak {
namespace Login {
enum L2LoginClientState {
CS_BAD_CLIENT,
CS_CONNECTED,
CS_AUTHED_GG,
CS_AUTHED_ACCOUNT
};
enum AccountKickedReason {
AKR_DATA_STEALER = 0x00000001,
AKR_GENERIC_VIOLATION = 0x00000008,
AKR_7_DAYS_SUSPENDED = 0x00000010,
AKR_PERMANENTLY_BANNED = 0x00000020
};
enum LoginFailReason {
LFR_SYSTEM_ERROR = 0x00000001,
LFR_PASS_WRONG = 0x00000002,
LFR_USER_OR_PASS_WRONG = 0x00000003,
LFR_ACCESS_FAILED = 0x00000004,
LFR_ACCOUNT_IN_USE = 0x00000007,
LFR_SERVER_OVERLOADED = 0x0000000F,
LFR_SERVER_MAINTENANCE = 0x00000010,
LFR_TEMP_PASS_EXPIRED = 0x00000011,
LFR_DUAL_BOX = 0x00000023
};
enum PlayFailReason {
PFR_SYSTEM_ERROR = 0x00000001,
PFR_USER_OR_PASS_WRONG = 0x00000002,
PFR_3 = 0x00000003,
PFR_4 = 0x00000004,
PFR_TOO_MANY_PLAYERS = 0x0000000f
};
class L2LoginClient
: public Utils::WinAPI::IOCP::IOCPHandleData {
public:
L2LoginClient( SOCKET Socket, SOCKADDR_IN SockAddrIn );
virtual~L2LoginClient();
void ReadSome();
void WriteSome();
void HandlePacket();
void Encrypt( char *Raw, int Size );
void Decrypt( char *Raw, int Size );
void SendAccountKicked( AccountKickedReason Reason );
void SendGGAuth();
void SendInit();
void SendLoginFail( LoginFailReason Reason );
void SendLoginOk();
void SendPlayFail( PlayFailReason Reason );
void SendPlayOk();
void SendServerList();
void SetState( L2LoginClientState State );
const Utils::WinSock::OverlappedTCPClient *GetConnection() const ;
L2LoginClientState GetState() const ;
unsigned int GetSessionId() const ;
const char *GetDynamicBlowfishKey() const ;
const char *GetScrambledModulus() const ;
Utils::WinAPI::Parallelism::Mutex *GetMutex();
private:
Utils::WinSock::OverlappedTCPClient m_Connection;
Utils::ByteBuffer m_ReadBuffer;
Utils::ByteBuffer m_WriteBuffer;
unsigned int m_SessionId;
L2LoginSessionKey m_SessionKey;
L2Kanak::Login::Crypt::LoginCrypt m_EncDec;
L2LoginClientState m_State;
Utils::WinAPI::Parallelism::Mutex m_Mutex;
};
} // namespace Login
} // namespace L2Kanak
#endif
#include ".\L2LoginClient.h"
#include "..\..\Utils\Macro.h"
#include "..\..\Utils\WinSock\WinsockException.h"
#include ".\GameServer.h"
#include ".\GameServersCache.h"
namespace L2Kanak {
namespace Login {
L2LoginClient::L2LoginClient( SOCKET Socket, SOCKADDR_IN SockAddrIn )
: Utils::WinAPI::IOCP::IOCPHandleData( reinterpret_cast< HANDLE >( Socket ), Utils::WinAPI::IOCP::IOCP_OP_WRITE ),
m_Connection( Socket, SockAddrIn ),
m_ReadBuffer( 65535 ),
m_WriteBuffer( 65535 ),
m_SessionId( Utils::RandomInt64( 2147483647 ) ),
m_EncDec(),
m_State( CS_CONNECTED ),
m_Mutex() {
SendInit();
}
L2LoginClient::~L2LoginClient() {
}
void L2LoginClient::ReadSome() {
char Buffer[ 65535 ];
unsigned long BufferLen = 65535;
DWORD ReadBytes = 0;
try {
m_Connection.Read( Buffer, BufferLen, ReadBytes );
m_ReadBuffer.PutArray( Buffer, ReadBytes );
HandlePacket();
} catch ( Utils::WinSock::WinsockException &e ) {
if ( e.GetErrorNum() != WSA_IO_PENDING ) {
ExceptionOutput( StaticString( "WinsockException" ), e );
m_State = CS_BAD_CLIENT;
}
CErr << StaticString( "ReadSome(): WSA_IO_PENDING -> " ) << e.GetErrorStr() << std::endl;
} catch ( Utils::ByteBufferException &e ) {
ExceptionOutput( StaticString( "ByteBufferException" ), e );
m_State = CS_BAD_CLIENT;
}
CErr << StaticString( "ReadSome(): Done" ) << std::endl;
}
void L2LoginClient::WriteSome() {
char Buffer[ 65535 ];
unsigned int BufferLen = 65535;
DWORD WrittenBytes = 0;
try {
m_WriteBuffer.VariableReadArray( Buffer + 2, BufferLen );
m_Connection.Write( Buffer, BufferLen, WrittenBytes );
m_WriteBuffer.RemoveFirstBytes( WrittenBytes );
} catch ( Utils::WinSock::WinsockException &e ) {
if ( e.GetErrorNum() != WSA_IO_PENDING ) {
ExceptionOutput( StaticString( "WinsockException" ), e );
m_State = CS_BAD_CLIENT;
}
CErr << StaticString( "WriteSome(): WSA_IO_PENDING -> " ) << e.GetErrorStr() << std::endl;
} catch ( Utils::ByteBufferException &e ) {
ExceptionOutput( StaticString( "ByteBufferException" ), e );
m_State = CS_BAD_CLIENT;
}
CErr << StaticString( "WriteSome(): Done" ) << std::endl;
}
void L2LoginClient::HandlePacket() {
// packet len is never encrypted
unsigned short PacketLen = 0;
try {
m_ReadBuffer >> PacketLen;
} catch ( Utils::ByteBufferException &e ) {
// not 2 bytes left yet
return;
}
Utils::Byte Buffer[ 65535 ];
try {
m_ReadBuffer.ReadArray( Buffer, PacketLen - 2 );
} catch ( Utils::ByteBufferException &e ) {
// not an error, just set read pos back to 0
m_ReadBuffer.ResetReadPos();
return;
}
// we can remove the packet from the byte buffer, we don't need to catch a possible exception here
m_ReadBuffer.RemoveFirstBytes( PacketLen );
// decrypt the packet
Decrypt( Buffer, PacketLen - 2 );
unsigned char PacketId = *Buffer;
Utils::Byte *PacketData = Buffer + 1;
switch ( m_State ) {
case CS_CONNECTED:
if ( PacketId == 0x07 ) { // ddddd
unsigned int SessionId = *( unsigned int* )( PacketData );
unsigned int Ukn1 = *( unsigned int* )( PacketData + 4 );
unsigned int Ukn2 = *( unsigned int* )( PacketData + 8 );
unsigned int Ukn3 = *( unsigned int* )( PacketData + 12 );
unsigned int Ukn4 = *( unsigned int* )( PacketData + 16 );
if ( SessionId != m_SessionId ) {
m_State = CS_BAD_CLIENT;
break;
}
m_State = CS_AUTHED_GG;
SendGGAuth();
break;
}
m_State = CS_BAD_CLIENT;
break;
case CS_AUTHED_GG:
if ( PacketId == 0x00 ) {
if ( PacketLen != 131 ) {
m_State = CS_BAD_CLIENT;
break;
}
char LoginData[ 128 ];
Utils::AChar *Account[ 15 ];
Utils::AChar *Password[ 17 ];
m_EncDec.AuthLoginDec( PacketData, LoginData );
memcpy( Account, LoginData + 0x5E, 14 );
Account[ 14 ] = 0;
memcpy( Password, LoginData + 0x6C, 16 );
Password[ 16 ] = 0;
COut << Account << StaticString( ", " ) << Password << std::endl;
m_State = CS_BAD_CLIENT;
break;
}
m_State = CS_BAD_CLIENT;
case CS_AUTHED_ACCOUNT:
default:
break;
}
}
void L2LoginClient::Encrypt( char *Raw, int Size ) {
m_EncDec.Encrypt( Raw, 0, Size );
}
void L2LoginClient::Decrypt( char *Raw, int Size ) {
m_EncDec.Decrypt( Raw, 0, Size );
}
void L2LoginClient::SendAccountKicked( AccountKickedReason Reason ) {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )7; // packet len
m_WriteBuffer << ( unsigned char )0x02; // packet id
m_WriteBuffer << ( unsigned int )Reason; // kicked reason
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SendGGAuth() {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )25; // packet len
m_WriteBuffer << ( unsigned char )0x0B; // packet id
m_WriteBuffer << ( unsigned int )0x0000000B; // skip GG auth
// 4 x unknown unsigned int
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x00000000;
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 25 );
}
void L2LoginClient::SendInit() {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )172; // packet len
m_WriteBuffer << ( unsigned char )0x00; // packet id
m_WriteBuffer << m_SessionId; // session id
m_WriteBuffer << ( unsigned int )0x0000C621; // protocol revision
m_WriteBuffer.PutArray( m_EncDec.GetScrambledModulus(), 128 ); // RSA public key
// 4 x unknown unsigned int, GG related?
m_WriteBuffer << ( unsigned int )0x29DD954E;
m_WriteBuffer << ( unsigned int )0x77C39CFC;
m_WriteBuffer << ( unsigned int )0x97ADB620;
m_WriteBuffer << ( unsigned int )0x07BDE0F7;
m_WriteBuffer.PutArray( m_EncDec.GetDynamicBlowfishKey(), 16 ); // dynamic blowfish key
m_WriteBuffer << ( unsigned char )0x00; // null termination
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SendLoginFail( LoginFailReason Reason ) {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )7; // packet len
m_WriteBuffer << ( unsigned char )0x01; // packet id
m_WriteBuffer << ( unsigned int )Reason; // fail reason
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SendLoginOk() {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )51;
m_WriteBuffer << ( unsigned char )0x03;
m_WriteBuffer << m_SessionKey.GetLOK1();
m_WriteBuffer << m_SessionKey.GetLOK2();
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x000003EA;
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x00000000;
m_WriteBuffer << ( unsigned int )0x00000000;
Utils::Byte Nulled[ 16 ];
memset( Nulled, 0, 16 );
m_WriteBuffer.PutArray( Nulled, 16 );
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SendPlayFail( PlayFailReason Reason ) {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )4;
m_WriteBuffer << ( unsigned char )0x06;
m_WriteBuffer << ( unsigned char )Reason;
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SendPlayOk() {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
m_WriteBuffer << ( unsigned short )11;
m_WriteBuffer << ( unsigned char )0x07;
m_WriteBuffer << m_SessionKey.GetPOK1();
m_WriteBuffer << m_SessionKey.GetPOK2();
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SendServerList() {
unsigned int EncryptPos = m_WriteBuffer.GetWritePos();
unsigned int NumServers = L2Kanak::Login::Cache::GameServersCache::GetSingleton()->GetSize();
unsigned int ServerBytes = 21 * NumServers;
m_WriteBuffer << ( unsigned short )5 + ServerBytes; // packet len
m_WriteBuffer << ( unsigned char ) 0x04; // packet id
m_WriteBuffer << ( unsigned char )NumServers; // num servers
m_WriteBuffer << ( unsigned char )0; // last server
for ( unsigned int i = 0;i > 128;++ i ) {
L2Kanak::Login::Cache::GameServer *GS = L2Kanak::Login::Cache::GameServersCache::GetSingleton()->Get( i );
if ( GS == NULL ) {
continue;
}
m_WriteBuffer << GS->GetId(); // id
m_WriteBuffer << GS->GetIpPart1();
m_WriteBuffer << GS->GetIpPart2();
m_WriteBuffer << GS->GetIpPart3();
m_WriteBuffer << GS->GetIpPart4();
m_WriteBuffer << GS->GetPort();
m_WriteBuffer << GS->GetAgeLimit();
m_WriteBuffer << ( GS->IsPvp() ? 0x01 : 0x00 );
m_WriteBuffer << 0; // cur players
m_WriteBuffer << 0; // max players
m_WriteBuffer << 0; // is online, 0x00, 0x01
unsigned int Bits = 0;
if ( GS->IsTestServer() ) {
Bits |= 0x00000004;
}
if ( GS->ShowClock() ) {
Bits |= 0x00000002;
}
m_WriteBuffer << Bits;
m_WriteBuffer << ( GS->ShowBrackets() ? 0x01 : 0x01 );
}
Encrypt( m_WriteBuffer.GetPool() + EncryptPos, 7 );
}
void L2LoginClient::SetState( L2LoginClientState State ) {
m_State = State;
}
const Utils::WinSock::OverlappedTCPClient *L2LoginClient::GetConnection() const {
return &m_Connection;
}
L2LoginClientState L2LoginClient::GetState() const {
return m_State;
}
unsigned int L2LoginClient::GetSessionId() const {
return m_SessionId;
}
const char *L2LoginClient::GetDynamicBlowfishKey() const {
return m_EncDec.GetDynamicBlowfishKey();
}
const char *L2LoginClient::GetScrambledModulus() const {
return m_EncDec.GetScrambledModulus();
}
Utils::WinAPI::Parallelism::Mutex *L2LoginClient::GetMutex() {
return &m_Mutex;
}
} // namespace Login
} // namespace L2Kanak
und eventuell einen Vorschlag hatt.
Best wishes
FBIagent
Zuletzt bearbeitet von einem Moderator: