clean /old/login/client
This commit is contained in:
parent
ffb75045a4
commit
c29ab9cb0a
1840
old/login/client.cpp
1840
old/login/client.cpp
File diff suppressed because it is too large
Load Diff
@ -4,128 +4,357 @@
|
|||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
*/
|
*/
|
||||||
#ifndef CLIENT_H
|
|
||||||
#define CLIENT_H
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Standard library includes
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Project includes
|
||||||
#include "../common/linked_list.h"
|
#include "../common/linked_list.h"
|
||||||
#include "../common/timer.h"
|
#include "../common/timer.h"
|
||||||
#include "../common/TCPConnection.h"
|
#include "../common/TCPConnection.h"
|
||||||
|
#include "../common/PacketStruct.h"
|
||||||
#include "login_structs.h"
|
#include "login_structs.h"
|
||||||
#include "LoginAccount.h"
|
#include "LoginAccount.h"
|
||||||
#include "../common/PacketStruct.h"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
enum eLoginMode { None, Normal, Registration };
|
// Forward declarations
|
||||||
class DelayQue;
|
class DelayQue;
|
||||||
|
class EQStream;
|
||||||
|
class EQ2Packet;
|
||||||
|
class EQApplicationPacket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Login modes for client state management
|
||||||
|
*/
|
||||||
|
enum class LoginMode : std::uint8_t
|
||||||
|
{
|
||||||
|
None, // No login state
|
||||||
|
Normal, // Normal login process
|
||||||
|
Registration // Account registration mode
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Represents a connected client in the login server
|
||||||
|
*
|
||||||
|
* This class manages individual client connections, handling:
|
||||||
|
* - Authentication and login process
|
||||||
|
* - Character selection and creation
|
||||||
|
* - World server communication
|
||||||
|
* - Packet processing and queuing
|
||||||
|
*/
|
||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Client(EQStream* ieqnc);
|
/**
|
||||||
|
* @brief Constructs a new client instance
|
||||||
|
* @param ieqnc The EQStream connection for this client
|
||||||
|
*/
|
||||||
|
explicit Client(EQStream* ieqnc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor - ensures proper cleanup of client resources
|
||||||
|
*/
|
||||||
~Client();
|
~Client();
|
||||||
void SendLoginDenied();
|
|
||||||
void SendLoginDeniedBadVersion();
|
// Disable copy operations
|
||||||
void SendLoginAccepted(int32 account_id = 1, int8 login_response = 0);
|
Client(const Client&) = delete;
|
||||||
void SendWorldList();
|
Client& operator=(const Client&) = delete;
|
||||||
void SendCharList();
|
|
||||||
int16 AddWorldToList2(uchar* buffer, char* name, int32 id, int16* flags);
|
// Login response methods
|
||||||
void GenerateChecksum(EQApplicationPacket* outapp);
|
/**
|
||||||
int8 LoginKey[10];
|
* @brief Sends a login denied message to the client
|
||||||
int8 ClientSession[25];
|
*/
|
||||||
bool Process();
|
void SendLoginDenied();
|
||||||
void SaveErrorsToDB(EQApplicationPacket* app, char* type, int32 version);
|
|
||||||
void CharacterApproved(int32 server_id,int32 char_id);
|
/**
|
||||||
void CharacterRejected(int8 reason_number);
|
* @brief Sends a login denied message due to version mismatch
|
||||||
EQStream* getConnection() { return eqnc; }
|
*/
|
||||||
LoginAccount* GetLoginAccount() { return login_account; }
|
void SendLoginDeniedBadVersion();
|
||||||
void SetLoginAccount(LoginAccount* in_account) {
|
|
||||||
login_account = in_account;
|
/**
|
||||||
if(in_account)
|
* @brief Sends a login accepted message to the client
|
||||||
account_id = in_account->getLoginAccountID();
|
* @param account_id The account ID (default: 1)
|
||||||
}
|
* @param login_response The login response code (default: 0)
|
||||||
int16 GetVersion(){ return version; }
|
*/
|
||||||
char* GetKey() { return key; }
|
void SendLoginAccepted(std::int32_t account_id = 1, std::int8_t login_response = 0);
|
||||||
void SetKey(char* in_key) { strcpy(key,in_key); }
|
|
||||||
int32 GetIP() { return ip; }
|
// World and character list methods
|
||||||
int16 GetPort() { return port; }
|
/**
|
||||||
int32 GetAccountID() { return account_id; }
|
* @brief Sends the world server list to the client
|
||||||
const char* GetAccountName(){ return (char*)account_name.c_str(); }
|
*/
|
||||||
void SetAccountName(const char* name){ account_name = string(name); }
|
void SendWorldList();
|
||||||
void ProcessLogin(char* name, char* pass,int seq=0);
|
|
||||||
void QueuePacket(EQ2Packet* app);
|
/**
|
||||||
void FatalError(int8 response);
|
* @brief Sends the character list to the client
|
||||||
void WorldResponse(int32 worldid, int8 response, char* ip_address, int32 port, int32 access_key);
|
*/
|
||||||
bool AwaitingCharCreationRequest(){
|
void SendCharList();
|
||||||
if(createRequest)
|
|
||||||
return true;
|
/**
|
||||||
else
|
* @brief Adds a world server to the list buffer
|
||||||
return false;
|
* @param buffer Output buffer for world data
|
||||||
}
|
* @param name World server name
|
||||||
Timer* updatetimer;
|
* @param id World server ID
|
||||||
Timer* updatelisttimer;
|
* @param flags World server flags
|
||||||
Timer* disconnectTimer;
|
* @return Size of data written to buffer
|
||||||
//Timer* keepalive;
|
*/
|
||||||
//Timer* logintimer;
|
std::int16_t AddWorldToList2(unsigned char* buffer, const char* name,
|
||||||
int16 packettotal;
|
std::int32_t id, std::int16_t* flags);
|
||||||
int32 requested_server_id;
|
|
||||||
int32 request_num;
|
/**
|
||||||
LinkedList<DelayQue*> delay_que;
|
* @brief Generates checksum for outgoing packet
|
||||||
void SendPlayFailed(int8 response);
|
* @param outapp Packet to generate checksum for
|
||||||
|
*/
|
||||||
void StartDisconnectTimer();
|
void GenerateChecksum(EQApplicationPacket* outapp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main processing loop for the client
|
||||||
|
* @return true if client is still active, false if should be removed
|
||||||
|
*/
|
||||||
|
bool Process();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Saves client error logs to database
|
||||||
|
* @param app Packet containing error data
|
||||||
|
* @param type Type of error log
|
||||||
|
* @param version Client version
|
||||||
|
*/
|
||||||
|
void SaveErrorsToDB(EQApplicationPacket* app, const char* type, std::int32_t version);
|
||||||
|
|
||||||
|
// Character management methods
|
||||||
|
/**
|
||||||
|
* @brief Handles character creation approval from world server
|
||||||
|
* @param server_id World server ID
|
||||||
|
* @param char_id New character ID
|
||||||
|
*/
|
||||||
|
void CharacterApproved(std::int32_t server_id, std::int32_t char_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles character creation rejection
|
||||||
|
* @param reason_number Rejection reason code
|
||||||
|
*/
|
||||||
|
void CharacterRejected(std::int8_t reason_number);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes login attempt
|
||||||
|
* @param name Account name
|
||||||
|
* @param pass Account password
|
||||||
|
* @param seq Sequence number (default: 0)
|
||||||
|
*/
|
||||||
|
void ProcessLogin(const char* name, const char* pass, int seq = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queues a packet for sending to the client
|
||||||
|
* @param app Packet to queue
|
||||||
|
*/
|
||||||
|
void QueuePacket(EQ2Packet* app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a fatal error to the client
|
||||||
|
* @param response Error response code
|
||||||
|
*/
|
||||||
|
void FatalError(std::int8_t response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles world server response for play request
|
||||||
|
* @param worldid World server ID
|
||||||
|
* @param response Response code
|
||||||
|
* @param ip_address World server IP
|
||||||
|
* @param port World server port
|
||||||
|
* @param access_key Access key for world server
|
||||||
|
*/
|
||||||
|
void WorldResponse(std::int32_t worldid, std::int8_t response,
|
||||||
|
char* ip_address, std::int32_t port, std::int32_t access_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends play failed message to client
|
||||||
|
* @param response Failure reason code
|
||||||
|
*/
|
||||||
|
void SendPlayFailed(std::int8_t response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts the disconnect timer
|
||||||
|
*/
|
||||||
|
void StartDisconnectTimer();
|
||||||
|
|
||||||
|
// Getter methods
|
||||||
|
[[nodiscard]] EQStream* getConnection() { return eqnc_; }
|
||||||
|
[[nodiscard]] LoginAccount* GetLoginAccount() { return login_account_.get(); }
|
||||||
|
[[nodiscard]] std::int16_t GetVersion() const { return version_; }
|
||||||
|
[[nodiscard]] char* GetKey() { return key_; }
|
||||||
|
[[nodiscard]] std::int32_t GetIP() const { return ip_; }
|
||||||
|
[[nodiscard]] std::int16_t GetPort() const { return port_; }
|
||||||
|
[[nodiscard]] std::int32_t GetAccountID() const { return account_id_; }
|
||||||
|
[[nodiscard]] const char* GetAccountName() const { return account_name_.c_str(); }
|
||||||
|
[[nodiscard]] bool AwaitingCharCreationRequest() const { return createRequest_ != nullptr; }
|
||||||
|
|
||||||
|
// Setter methods
|
||||||
|
void SetLoginAccount(LoginAccount* in_account)
|
||||||
|
{
|
||||||
|
login_account_.reset(in_account);
|
||||||
|
if (in_account)
|
||||||
|
{
|
||||||
|
account_id_ = in_account->getLoginAccountID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetKey(const char* in_key)
|
||||||
|
{
|
||||||
|
std::strncpy(key_, in_key, sizeof(key_) - 1);
|
||||||
|
key_[sizeof(key_) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAccountName(const char* name) { account_name_ = name; }
|
||||||
|
|
||||||
|
// Public data members (legacy compatibility)
|
||||||
|
std::int8_t LoginKey[10]{}; // Login key for authentication
|
||||||
|
std::int8_t ClientSession[25]{}; // Client session data
|
||||||
|
|
||||||
|
// Timers
|
||||||
|
std::unique_ptr<Timer> updatetimer; // Timer for periodic updates
|
||||||
|
std::unique_ptr<Timer> updatelisttimer; // Timer for world list updates
|
||||||
|
std::unique_ptr<Timer> disconnectTimer; // Timer for disconnect timeout
|
||||||
|
|
||||||
|
// Request tracking
|
||||||
|
std::int16_t packettotal{0}; // Total packets processed
|
||||||
|
std::int32_t requested_server_id{0}; // Requested world server ID
|
||||||
|
std::int32_t request_num{0}; // Current request number
|
||||||
|
|
||||||
|
// Delay queue for packet scheduling
|
||||||
|
LinkedList<DelayQue*> delay_que;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string pending_play_char_name;
|
// Character play state
|
||||||
int32 pending_play_char_id;
|
std::string pending_play_char_name_; // Name of character pending play
|
||||||
int8 update_position;
|
std::int32_t pending_play_char_id_{0}; // ID of character pending play
|
||||||
int16 num_updates;
|
|
||||||
vector<PacketStruct*>* update_packets;
|
// Update state
|
||||||
LoginAccount* login_account;
|
std::int8_t update_position_{0}; // Current position in update sequence
|
||||||
EQStream* eqnc;
|
std::int16_t num_updates_{0}; // Number of updates sent
|
||||||
|
std::vector<PacketStruct*>* update_packets_{nullptr}; // Update packet queue
|
||||||
int32 ip;
|
|
||||||
int16 port;
|
// Account information
|
||||||
|
std::unique_ptr<LoginAccount> login_account_; // Login account data
|
||||||
int32 account_id;
|
EQStream* eqnc_; // Network connection stream
|
||||||
string account_name;
|
|
||||||
char key[10];
|
// Connection details
|
||||||
int8 lsadmin;
|
std::int32_t ip_{0}; // Client IP address
|
||||||
sint16 worldadmin;
|
std::int16_t port_{0}; // Client port
|
||||||
int lsstatus;
|
|
||||||
bool kicked;
|
// Account data
|
||||||
bool verified;
|
std::int32_t account_id_{0}; // Account ID in database
|
||||||
bool start;
|
std::string account_name_; // Account name
|
||||||
bool needs_world_list;
|
char key_[10]{}; // Authentication key
|
||||||
int16 version;
|
std::int8_t lsadmin_{0}; // Login server admin level
|
||||||
char bannedreason[30];
|
std::int16_t worldadmin_{0}; // World server admin level
|
||||||
bool sent_character_list;
|
int lsstatus_{0}; // Login server status
|
||||||
eLoginMode LoginMode;
|
|
||||||
PacketStruct* createRequest;
|
// Client state flags
|
||||||
Timer* playWaitTimer;
|
bool kicked_{false}; // Client has been kicked
|
||||||
|
bool verified_{false}; // Client has been verified
|
||||||
|
bool start_{false}; // Client has started
|
||||||
|
bool needs_world_list_{true}; // Client needs world list
|
||||||
|
bool sent_character_list_{false}; // Character list has been sent
|
||||||
|
|
||||||
|
// Version and mode
|
||||||
|
std::int16_t version_{0}; // Client version
|
||||||
|
LoginMode login_mode_{LoginMode::None}; // Current login mode
|
||||||
|
|
||||||
|
// Character creation
|
||||||
|
char bannedreason_[30]{}; // Ban reason if applicable
|
||||||
|
PacketStruct* createRequest_{nullptr}; // Pending character creation request
|
||||||
|
std::unique_ptr<Timer> playWaitTimer_; // Timer for play request timeout
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Manages all connected clients
|
||||||
|
*
|
||||||
|
* Thread-safe container for managing multiple client connections
|
||||||
|
*/
|
||||||
class ClientList
|
class ClientList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClientList() {}
|
/**
|
||||||
~ClientList() {}
|
* @brief Default constructor
|
||||||
|
*/
|
||||||
void Add(Client* client);
|
ClientList() = default;
|
||||||
Client* Get(int32 ip, int16 port);
|
|
||||||
Client* FindByLSID(int32 lsaccountid);
|
/**
|
||||||
void FindByCreateRequest();
|
* @brief Destructor
|
||||||
void SendPacketToAllClients(EQ2Packet* app);
|
*/
|
||||||
void Process();
|
~ClientList() = default;
|
||||||
|
|
||||||
|
// Disable copy operations
|
||||||
|
ClientList(const ClientList&) = delete;
|
||||||
|
ClientList& operator=(const ClientList&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a client to the list
|
||||||
|
* @param client Client to add
|
||||||
|
*/
|
||||||
|
void Add(Client* client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a client by IP and port
|
||||||
|
* @param ip Client IP address
|
||||||
|
* @param port Client port
|
||||||
|
* @return Pointer to client if found, nullptr otherwise
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Client* Get(std::int32_t ip, std::int16_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a client by login server account ID
|
||||||
|
* @param lsaccountid Login server account ID
|
||||||
|
* @return Pointer to client if found, nullptr otherwise
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Client* FindByLSID(std::int32_t lsaccountid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds clients waiting for character creation response
|
||||||
|
*/
|
||||||
|
void FindByCreateRequest();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a packet to all connected clients
|
||||||
|
* @param app Packet to send
|
||||||
|
*/
|
||||||
|
void SendPacketToAllClients(EQ2Packet* app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes all clients in the list
|
||||||
|
*/
|
||||||
|
void Process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex MClientList;
|
mutable std::mutex mutex_; // Mutex for thread safety
|
||||||
map<Client*, bool> client_list;
|
std::map<Client*, bool> client_list_; // Map of clients to active status
|
||||||
};
|
};
|
||||||
class DelayQue {
|
|
||||||
|
/**
|
||||||
|
* @brief Delayed packet queue entry
|
||||||
|
*
|
||||||
|
* Holds a packet with an associated timer for delayed sending
|
||||||
|
*/
|
||||||
|
class DelayQue
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
DelayQue(Timer* in_timer, EQApplicationPacket* in_packet){
|
/**
|
||||||
timer = in_timer;
|
* @brief Constructs a delayed queue entry
|
||||||
packet = in_packet;
|
* @param in_timer Timer for delay
|
||||||
};
|
* @param in_packet Packet to delay
|
||||||
Timer* timer;
|
*/
|
||||||
EQApplicationPacket* packet;
|
DelayQue(Timer* in_timer, EQApplicationPacket* in_packet)
|
||||||
};
|
: timer(in_timer)
|
||||||
#endif
|
, packet(in_packet)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer* timer; // Timer controlling the delay
|
||||||
|
EQApplicationPacket* packet; // Packet to be sent after delay
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user