WSASend/Recv gibt keine weitere Notifikation an IO Completion Port

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:
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
IOCP:
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
IOCPHandleData:
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
IOCPWorker:
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
BaseSocket:
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
OverlappedTCPSocket:
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
OverlappedTCPClient:
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
LoginIOCPWorker:
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
L2LoginClient:
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
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
 
Zuletzt bearbeitet von einem Moderator:
Ich bin wirklich nicht der Socket Experte, deinem Code nach bist du mir weit voraus, aber einfach mal ins Blaue geraten:

Kann es sein, dass deine Sockets nach der Pending Nachricht im blocking Mode hängen bleiben?
 

Neue Beiträge

Zurück