mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-08 05:52:26 +00:00
UCS basically works now, really needs to be rewritten.
This commit is contained in:
parent
4bbc22cc24
commit
16a96a2756
@ -79,6 +79,7 @@ SET(common_sources
|
|||||||
net/daybreak_connection.cpp
|
net/daybreak_connection.cpp
|
||||||
net/eqstream.cpp
|
net/eqstream.cpp
|
||||||
net/packet.cpp
|
net/packet.cpp
|
||||||
|
patch/chat.cpp
|
||||||
patch/login_sod.cpp
|
patch/login_sod.cpp
|
||||||
patch/login_titanium.cpp
|
patch/login_titanium.cpp
|
||||||
patch/patch.cpp
|
patch/patch.cpp
|
||||||
@ -226,6 +227,7 @@ SET(common_headers
|
|||||||
net/endian.h
|
net/endian.h
|
||||||
net/eqstream.h
|
net/eqstream.h
|
||||||
net/packet.h
|
net/packet.h
|
||||||
|
patch/chat.h
|
||||||
patch/login_sod.h
|
patch/login_sod.h
|
||||||
patch/login_titanium.h
|
patch/login_titanium.h
|
||||||
patch/patch.h
|
patch/patch.h
|
||||||
@ -303,6 +305,8 @@ SOURCE_GROUP(Net FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
SOURCE_GROUP(Patch FILES
|
SOURCE_GROUP(Patch FILES
|
||||||
|
patch/chat.cpp
|
||||||
|
patch/chat.h
|
||||||
patch/login_sod.cpp
|
patch/login_sod.cpp
|
||||||
patch/login_sod.h
|
patch/login_sod.h
|
||||||
patch/login_titanium.cpp
|
patch/login_titanium.cpp
|
||||||
|
|||||||
@ -84,7 +84,7 @@ EQ::Net::EQStream::~EQStream()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::Net::EQStream::QueuePacket(EmuOpcode type, Packet &p)
|
void EQ::Net::EQStream::QueuePacket(EmuOpcode type, const Packet &p)
|
||||||
{
|
{
|
||||||
if (m_patch) {
|
if (m_patch) {
|
||||||
EQ::Net::WritablePacket trans;
|
EQ::Net::WritablePacket trans;
|
||||||
@ -101,14 +101,14 @@ void EQ::Net::EQStream::Close()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::Net::EQStream::QueuePacket(EQApplicationPacket *p)
|
void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p)
|
||||||
{
|
{
|
||||||
EQ::Net::ReadOnlyPacket out(p->pBuffer, p->size);
|
EQ::Net::ReadOnlyPacket out(p->pBuffer, p->size);
|
||||||
QueuePacket(p->GetOpcode(), out);
|
QueuePacket(p->GetOpcode(), out);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::Net::EQStream::FastQueuePacket(EQApplicationPacket **p)
|
void EQ::Net::EQStream::FastQueuePacket(const EQApplicationPacket **p)
|
||||||
{
|
{
|
||||||
QueuePacket(*p);
|
QueuePacket(*p);
|
||||||
delete *p;
|
delete *p;
|
||||||
|
|||||||
@ -12,11 +12,25 @@ namespace EQ
|
|||||||
struct EQStreamManagerOptions
|
struct EQStreamManagerOptions
|
||||||
{
|
{
|
||||||
EQStreamManagerOptions() {
|
EQStreamManagerOptions() {
|
||||||
compressed = false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EQStreamManagerOptions(bool encoded, bool compressed) {
|
||||||
|
if (encoded) {
|
||||||
|
daybreak_options.encode_passes[0] = EncodeXOR;
|
||||||
|
|
||||||
|
if (compressed) {
|
||||||
|
daybreak_options.encode_passes[1] = EncodeCompression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (compressed) {
|
||||||
|
daybreak_options.encode_passes[0] = EncodeCompression;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DaybreakConnectionManagerOptions daybreak_options;
|
DaybreakConnectionManagerOptions daybreak_options;
|
||||||
bool compressed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EQStream;
|
class EQStream;
|
||||||
@ -55,13 +69,13 @@ namespace EQ
|
|||||||
const std::string& RemoteEndpoint() const { return m_connection->RemoteEndpoint(); }
|
const std::string& RemoteEndpoint() const { return m_connection->RemoteEndpoint(); }
|
||||||
int RemotePort() const { return m_connection->RemotePort(); }
|
int RemotePort() const { return m_connection->RemotePort(); }
|
||||||
|
|
||||||
void QueuePacket(EmuOpcode type, Packet &p);
|
void QueuePacket(EmuOpcode type, const Packet &p);
|
||||||
const DaybreakConnectionStats& GetStats() const { return m_connection->GetStats(); }
|
const DaybreakConnectionStats& GetStats() const { return m_connection->GetStats(); }
|
||||||
void ResetStats();
|
void ResetStats();
|
||||||
size_t GetRollingPing() const { return m_connection->GetRollingPing(); }
|
size_t GetRollingPing() const { return m_connection->GetRollingPing(); }
|
||||||
void Close();
|
void Close();
|
||||||
void QueuePacket(EQApplicationPacket *p);
|
void QueuePacket(const EQApplicationPacket *p);
|
||||||
void FastQueuePacket(EQApplicationPacket **p);
|
void FastQueuePacket(const EQApplicationPacket **p);
|
||||||
|
|
||||||
void RegisterPatch(EQ::Patches::BasePatch *p) { m_patch = p; }
|
void RegisterPatch(EQ::Patches::BasePatch *p) { m_patch = p; }
|
||||||
EQ::Patches::BasePatch *GetRegisteredPatch() { return m_patch; }
|
EQ::Patches::BasePatch *GetRegisteredPatch() { return m_patch; }
|
||||||
|
|||||||
17
common/patch/chat.cpp
Normal file
17
common/patch/chat.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "chat.h"
|
||||||
|
|
||||||
|
EQ::Patches::ChatPatch::ChatPatch()
|
||||||
|
{
|
||||||
|
m_opcode_manager.reset(new RegularOpcodeManager());
|
||||||
|
if (!m_opcode_manager->LoadOpcodes("mail_opcodes.conf")) {
|
||||||
|
m_opcode_manager.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_signature.match_message_opcode = 0x0;
|
||||||
|
m_signature.match_message_size = 0;
|
||||||
|
m_message_size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Patches::ChatPatch::~ChatPatch()
|
||||||
|
{
|
||||||
|
}
|
||||||
15
common/patch/chat.h
Normal file
15
common/patch/chat.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <patch/patch.h>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Patches
|
||||||
|
{
|
||||||
|
class ChatPatch : public BasePatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ChatPatch();
|
||||||
|
virtual ~ChatPatch();
|
||||||
|
virtual std::string GetName() const { return "Chat"; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
EQ::Patches::LoginTitaniumPatch::LoginTitaniumPatch()
|
EQ::Patches::LoginTitaniumPatch::LoginTitaniumPatch()
|
||||||
{
|
{
|
||||||
m_opcode_manager.reset(new RegularOpcodeManager());
|
m_opcode_manager.reset(new RegularOpcodeManager());
|
||||||
if (!m_opcode_manager->LoadOpcodes("login_opcodes_titanium.conf")) {
|
if (!m_opcode_manager->LoadOpcodes("login_opcodes.conf")) {
|
||||||
m_opcode_manager.release();
|
m_opcode_manager.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ EQ::Patches::IdentityMatchStatus EQ::Patches::BasePatch::TryIdentityMatch(const
|
|||||||
return IdentityMatchFailure;
|
return IdentityMatchFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_signature.match_message_opcode != raw_opcode) {
|
if (m_signature.match_message_opcode != 0 && m_signature.match_message_opcode != raw_opcode) {
|
||||||
return IdentityMatchFailure;
|
return IdentityMatchFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,6 @@ ClientManager::ClientManager()
|
|||||||
titanium_patch.reset(new EQ::Patches::LoginTitaniumPatch());
|
titanium_patch.reset(new EQ::Patches::LoginTitaniumPatch());
|
||||||
titanium_stream->RegisterPotentialPatch(titanium_patch.get());
|
titanium_stream->RegisterPotentialPatch(titanium_patch.get());
|
||||||
|
|
||||||
titanium_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
|
||||||
titanium_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionTitanium, this, std::placeholders::_1));
|
titanium_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionTitanium, this, std::placeholders::_1));
|
||||||
titanium_stream->OnConnectionStateChange(std::bind(&ClientManager::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
titanium_stream->OnConnectionStateChange(std::bind(&ClientManager::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
titanium_stream->OnPacketRecv(std::bind(&ClientManager::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
titanium_stream->OnPacketRecv(std::bind(&ClientManager::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
@ -41,12 +40,9 @@ ClientManager::ClientManager()
|
|||||||
sod_patch.reset(new EQ::Patches::LoginSoDPatch());
|
sod_patch.reset(new EQ::Patches::LoginSoDPatch());
|
||||||
sod_stream->RegisterPotentialPatch(sod_patch.get());
|
sod_stream->RegisterPotentialPatch(sod_patch.get());
|
||||||
|
|
||||||
sod_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
|
||||||
sod_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
sod_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
||||||
sod_stream->OnConnectionStateChange(std::bind(&ClientManager::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
sod_stream->OnConnectionStateChange(std::bind(&ClientManager::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
sod_stream->OnPacketRecv(std::bind(&ClientManager::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
sod_stream->OnPacketRecv(std::bind(&ClientManager::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientManager::~ClientManager()
|
ClientManager::~ClientManager()
|
||||||
|
|||||||
@ -23,16 +23,11 @@ INSTALL(TARGETS ucs RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
|||||||
|
|
||||||
ADD_DEFINITIONS(-DUCS)
|
ADD_DEFINITIONS(-DUCS)
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(ucs common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
TARGET_LINK_LIBRARIES(ucs common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt)
|
||||||
|
|
||||||
IF(MSVC)
|
IF(WIN32)
|
||||||
SET_TARGET_PROPERTIES(ucs PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
TARGET_LINK_LIBRARIES(ucs "ws2_32" "psapi" "iphlpapi" "userenv")
|
||||||
TARGET_LINK_LIBRARIES(ucs "Ws2_32.lib")
|
ENDIF(WIN32)
|
||||||
ENDIF(MSVC)
|
|
||||||
|
|
||||||
IF(MINGW)
|
|
||||||
TARGET_LINK_LIBRARIES(ucs "WS2_32")
|
|
||||||
ENDIF(MINGW)
|
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
TARGET_LINK_LIBRARIES(ucs "${CMAKE_DL_LIBS}")
|
TARGET_LINK_LIBRARIES(ucs "${CMAKE_DL_LIBS}")
|
||||||
|
|||||||
@ -17,15 +17,14 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../common/global_define.h"
|
#include <global_define.h>
|
||||||
#include "../common/string_util.h"
|
#include <string_util.h>
|
||||||
#include "../common/eqemu_logsys.h"
|
#include <eqemu_logsys.h>
|
||||||
|
|
||||||
#include "clientlist.h"
|
#include "clientlist.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "chatchannel.h"
|
#include "chatchannel.h"
|
||||||
|
|
||||||
#include "../common/eq_stream_factory.h"
|
|
||||||
#include "../common/emu_tcp_connection.h"
|
#include "../common/emu_tcp_connection.h"
|
||||||
#include "../common/emu_tcp_server.h"
|
#include "../common/emu_tcp_server.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -468,24 +467,20 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
Clientlist::Clientlist(int ChatPort) {
|
Clientlist::Clientlist(int ChatPort) {
|
||||||
|
EQ::Net::EQStreamManagerOptions opts(true, false);
|
||||||
|
opts.daybreak_options.port = ChatPort;
|
||||||
|
|
||||||
chatsf = new EQStreamFactory(ChatStream, ChatPort, 45000);
|
chatsf.reset(new EQ::Net::EQStreamManager(opts));
|
||||||
|
chat_patch.reset(new EQ::Patches::ChatPatch());
|
||||||
|
chatsf->RegisterPotentialPatch(chat_patch.get());
|
||||||
|
|
||||||
ChatOpMgr = new RegularOpcodeManager;
|
chatsf->OnNewConnection(std::bind(&Clientlist::HandleNewConnection, this, std::placeholders::_1));
|
||||||
|
chatsf->OnConnectionStateChange(std::bind(&Clientlist::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
if(!ChatOpMgr->LoadOpcodes("mail_opcodes.conf"))
|
chatsf->OnPacketRecv(std::bind(&Clientlist::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
exit(1);
|
|
||||||
|
|
||||||
if (chatsf->Open())
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server,"Client (UDP) Chat listener started on port %i.", ChatPort);
|
|
||||||
else {
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server,"Failed to start client (UDP) listener (port %-4i)", ChatPort);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::Client(std::shared_ptr<EQStream> eqs) {
|
Client::Client(std::shared_ptr<EQ::Net::EQStream> eqs) :
|
||||||
|
AccountGrabUpdateTimer(60000, true, std::bind(&Client::AccountUpdate, this)) {
|
||||||
|
|
||||||
ClientStream = eqs;
|
ClientStream = eqs;
|
||||||
|
|
||||||
@ -509,7 +504,6 @@ Client::Client(std::shared_ptr<EQStream> eqs) {
|
|||||||
AttemptedMessages = 0;
|
AttemptedMessages = 0;
|
||||||
ForceDisconnect = false;
|
ForceDisconnect = false;
|
||||||
|
|
||||||
AccountGrabUpdateTimer = new Timer(60000); //check every minute
|
|
||||||
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
||||||
|
|
||||||
TypeOfConnection = ConnectionTypeUnknown;
|
TypeOfConnection = ConnectionTypeUnknown;
|
||||||
@ -523,12 +517,6 @@ Client::~Client() {
|
|||||||
|
|
||||||
LeaveAllChannels(false);
|
LeaveAllChannels(false);
|
||||||
|
|
||||||
if(AccountGrabUpdateTimer)
|
|
||||||
{
|
|
||||||
delete AccountGrabUpdateTimer;
|
|
||||||
AccountGrabUpdateTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(GlobalChatLimiterTimer)
|
if(GlobalChatLimiterTimer)
|
||||||
{
|
{
|
||||||
delete GlobalChatLimiterTimer;
|
delete GlobalChatLimiterTimer;
|
||||||
@ -537,166 +525,96 @@ Client::~Client() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::CloseConnection() {
|
void Client::CloseConnection() {
|
||||||
|
|
||||||
ClientStream->RemoveData();
|
|
||||||
|
|
||||||
ClientStream->Close();
|
ClientStream->Close();
|
||||||
|
|
||||||
ClientStream->ReleaseFromUse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clientlist::CheckForStaleConnections(Client *c) {
|
void Clientlist::CheckForStaleConnections(Client *c) {
|
||||||
|
|
||||||
if(!c) return;
|
if(!c)
|
||||||
|
return;
|
||||||
|
|
||||||
std::list<Client*>::iterator Iterator;
|
for(auto Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
||||||
|
|
||||||
for(Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
if(((*Iterator).get() != c) && ((c->GetName() == (*Iterator)->GetName())
|
||||||
|
|
||||||
if(((*Iterator) != c) && ((c->GetName() == (*Iterator)->GetName())
|
|
||||||
&& (c->GetConnectionType() == (*Iterator)->GetConnectionType()))) {
|
&& (c->GetConnectionType() == (*Iterator)->GetConnectionType()))) {
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "Removing old connection for %s", c->GetName().c_str());
|
Log.Out(Logs::Detail, Logs::UCS_Server, "Removing old connection for %s", c->GetName().c_str());
|
||||||
|
|
||||||
struct in_addr in;
|
Log.Out(Logs::Detail, Logs::UCS_Server, "Client connection from %s:%d closed.", (*Iterator)->ClientStream->RemoteEndpoint().c_str(),
|
||||||
|
(*Iterator)->ClientStream->RemotePort());
|
||||||
in.s_addr = (*Iterator)->ClientStream->GetRemoteIP();
|
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "Client connection from %s:%d closed.", inet_ntoa(in),
|
|
||||||
ntohs((*Iterator)->ClientStream->GetRemotePort()));
|
|
||||||
|
|
||||||
safe_delete((*Iterator));
|
|
||||||
|
|
||||||
Iterator = ClientChatConnections.erase(Iterator);
|
Iterator = ClientChatConnections.erase(Iterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clientlist::Process()
|
void Clientlist::Process(Client *c, const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
std::shared_ptr<EQStream> eqs;
|
EmuOpcode opcode = app->GetOpcode();
|
||||||
|
|
||||||
while ((eqs = chatsf->Pop())) {
|
switch (opcode) {
|
||||||
struct in_addr in;
|
case OP_MailLogin: {
|
||||||
in.s_addr = eqs->GetRemoteIP();
|
char *PacketBuffer = (char *)app->pBuffer + 1;
|
||||||
|
char MailBox[64];
|
||||||
|
char Key[64];
|
||||||
|
char ConnectionTypeIndicator;
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "New Client UDP connection from %s:%d", inet_ntoa(in),
|
VARSTRUCT_DECODE_STRING(MailBox, PacketBuffer);
|
||||||
ntohs(eqs->GetRemotePort()));
|
|
||||||
|
|
||||||
eqs->SetOpcodeManager(&ChatOpMgr);
|
if (strlen(PacketBuffer) != 9) {
|
||||||
|
Log.Out(Logs::Detail, Logs::UCS_Server,
|
||||||
|
"Mail key is the wrong size. Version of world incompatible with UCS.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ConnectionTypeIndicator = VARSTRUCT_DECODE_TYPE(char, PacketBuffer);
|
||||||
|
|
||||||
auto c = new Client(eqs);
|
c->SetConnectionType(ConnectionTypeIndicator);
|
||||||
ClientChatConnections.push_back(c);
|
|
||||||
|
VARSTRUCT_DECODE_STRING(Key, PacketBuffer);
|
||||||
|
|
||||||
|
std::string MailBoxString = MailBox, CharacterName;
|
||||||
|
|
||||||
|
// Strip off the SOE.EQ.<shortname>.
|
||||||
|
//
|
||||||
|
std::string::size_type LastPeriod = MailBoxString.find_last_of(".");
|
||||||
|
|
||||||
|
if (LastPeriod == std::string::npos)
|
||||||
|
CharacterName = MailBoxString;
|
||||||
|
else
|
||||||
|
CharacterName = MailBoxString.substr(LastPeriod + 1);
|
||||||
|
|
||||||
|
Log.Out(Logs::Detail, Logs::UCS_Server, "Received login for user %s with key %s",
|
||||||
|
MailBox, Key);
|
||||||
|
|
||||||
|
if (!database.VerifyMailKey(CharacterName, inet_addr(c->ClientStream->RemoteEndpoint().c_str()), Key)) {
|
||||||
|
Log.Out(Logs::Detail, Logs::UCS_Server,
|
||||||
|
"Chat Key for %s does not match, closing connection.", MailBox);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->SetAccountID(database.FindAccount(CharacterName.c_str(), c));
|
||||||
|
|
||||||
|
database.GetAccountStatus(c);
|
||||||
|
|
||||||
|
if (c->GetConnectionType() == ConnectionTypeCombined)
|
||||||
|
c->SendFriends();
|
||||||
|
|
||||||
|
c->SendMailBoxes();
|
||||||
|
|
||||||
|
CheckForStaleConnections(c);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = ClientChatConnections.begin();
|
case OP_Mail: {
|
||||||
while (it != ClientChatConnections.end()) {
|
std::string CommandString = (const char *)app->pBuffer + 1;
|
||||||
(*it)->AccountUpdate();
|
ProcessOPMailCommand(c, CommandString);
|
||||||
if ((*it)->ClientStream->CheckClosed()) {
|
break;
|
||||||
struct in_addr in;
|
}
|
||||||
in.s_addr = (*it)->ClientStream->GetRemoteIP();
|
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "Client connection from %s:%d closed.", inet_ntoa(in),
|
default: {
|
||||||
ntohs((*it)->ClientStream->GetRemotePort()));
|
Log.Out(Logs::Detail, Logs::UCS_Server, "Unhandled chat opcode %8X", opcode);
|
||||||
|
break;
|
||||||
safe_delete((*it));
|
}
|
||||||
|
|
||||||
it = ClientChatConnections.erase(it);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
EQApplicationPacket *app = nullptr;
|
|
||||||
|
|
||||||
bool KeyValid = true;
|
|
||||||
|
|
||||||
while (KeyValid && !(*it)->GetForceDisconnect() && (app = (*it)->ClientStream->PopPacket())) {
|
|
||||||
EmuOpcode opcode = app->GetOpcode();
|
|
||||||
|
|
||||||
switch (opcode) {
|
|
||||||
case OP_MailLogin: {
|
|
||||||
char *PacketBuffer = (char *)app->pBuffer;
|
|
||||||
char MailBox[64];
|
|
||||||
char Key[64];
|
|
||||||
char ConnectionTypeIndicator;
|
|
||||||
|
|
||||||
VARSTRUCT_DECODE_STRING(MailBox, PacketBuffer);
|
|
||||||
|
|
||||||
if (strlen(PacketBuffer) != 9) {
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server,
|
|
||||||
"Mail key is the wrong size. Version of world incompatible with UCS.");
|
|
||||||
KeyValid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ConnectionTypeIndicator = VARSTRUCT_DECODE_TYPE(char, PacketBuffer);
|
|
||||||
|
|
||||||
(*it)->SetConnectionType(ConnectionTypeIndicator);
|
|
||||||
|
|
||||||
VARSTRUCT_DECODE_STRING(Key, PacketBuffer);
|
|
||||||
|
|
||||||
std::string MailBoxString = MailBox, CharacterName;
|
|
||||||
|
|
||||||
// Strip off the SOE.EQ.<shortname>.
|
|
||||||
//
|
|
||||||
std::string::size_type LastPeriod = MailBoxString.find_last_of(".");
|
|
||||||
|
|
||||||
if (LastPeriod == std::string::npos)
|
|
||||||
CharacterName = MailBoxString;
|
|
||||||
else
|
|
||||||
CharacterName = MailBoxString.substr(LastPeriod + 1);
|
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "Received login for user %s with key %s",
|
|
||||||
MailBox, Key);
|
|
||||||
|
|
||||||
if (!database.VerifyMailKey(CharacterName, (*it)->ClientStream->GetRemoteIP(), Key)) {
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server,
|
|
||||||
"Chat Key for %s does not match, closing connection.", MailBox);
|
|
||||||
KeyValid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*it)->SetAccountID(database.FindAccount(CharacterName.c_str(), (*it)));
|
|
||||||
|
|
||||||
database.GetAccountStatus((*it));
|
|
||||||
|
|
||||||
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
|
|
||||||
(*it)->SendFriends();
|
|
||||||
|
|
||||||
(*it)->SendMailBoxes();
|
|
||||||
|
|
||||||
CheckForStaleConnections((*it));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_Mail: {
|
|
||||||
std::string CommandString = (const char *)app->pBuffer;
|
|
||||||
ProcessOPMailCommand((*it), CommandString);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "Unhandled chat opcode %8X", opcode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
safe_delete(app);
|
|
||||||
}
|
|
||||||
if (!KeyValid || (*it)->GetForceDisconnect()) {
|
|
||||||
struct in_addr in;
|
|
||||||
in.s_addr = (*it)->ClientStream->GetRemoteIP();
|
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server,
|
|
||||||
"Force disconnecting client: %s:%d, KeyValid=%i, GetForceDisconnect()=%i",
|
|
||||||
inet_ntoa(in), ntohs((*it)->ClientStream->GetRemotePort()), KeyValid,
|
|
||||||
(*it)->GetForceDisconnect());
|
|
||||||
|
|
||||||
(*it)->ClientStream->Close();
|
|
||||||
|
|
||||||
safe_delete((*it));
|
|
||||||
|
|
||||||
it = ClientChatConnections.erase(it);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,10 +775,7 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
|
|||||||
|
|
||||||
void Clientlist::CloseAllConnections() {
|
void Clientlist::CloseAllConnections() {
|
||||||
|
|
||||||
|
for(auto Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
||||||
std::list<Client*>::iterator Iterator;
|
|
||||||
|
|
||||||
for(Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
|
||||||
|
|
||||||
Log.Out(Logs::Detail, Logs::UCS_Server, "Removing client %s", (*Iterator)->GetName().c_str());
|
Log.Out(Logs::Detail, Logs::UCS_Server, "Removing client %s", (*Iterator)->GetName().c_str());
|
||||||
|
|
||||||
@ -916,13 +831,10 @@ void Client::SendMailBoxes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Client *Clientlist::FindCharacter(std::string CharacterName) {
|
Client *Clientlist::FindCharacter(std::string CharacterName) {
|
||||||
|
for(auto Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
||||||
std::list<Client*>::iterator Iterator;
|
|
||||||
|
|
||||||
for(Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
|
||||||
|
|
||||||
if((*Iterator)->GetName() == CharacterName)
|
if((*Iterator)->GetName() == CharacterName)
|
||||||
return ((*Iterator));
|
return ((*Iterator).get());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,7 +1110,10 @@ void Client::ProcessChannelList(std::string Input) {
|
|||||||
GeneralChannelMessage("Channel " + Input + " not found.");
|
GeneralChannelMessage("Channel " + Input + " not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::AccountUpdate()
|
||||||
|
{
|
||||||
|
database.GetAccountStatus(this);
|
||||||
|
}
|
||||||
|
|
||||||
void Client::SendChannelList() {
|
void Client::SendChannelList() {
|
||||||
|
|
||||||
@ -2133,18 +2048,6 @@ void Client::SendHelp() {
|
|||||||
GeneralChannelMessage(";setowner, ;toggleinvites");
|
GeneralChannelMessage(";setowner, ;toggleinvites");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::AccountUpdate()
|
|
||||||
{
|
|
||||||
if(AccountGrabUpdateTimer)
|
|
||||||
{
|
|
||||||
if(AccountGrabUpdateTimer->Check(false))
|
|
||||||
{
|
|
||||||
AccountGrabUpdateTimer->Start(60000);
|
|
||||||
database.GetAccountStatus(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::SetConnectionType(char c) {
|
void Client::SetConnectionType(char c) {
|
||||||
|
|
||||||
switch(c)
|
switch(c)
|
||||||
@ -2191,9 +2094,8 @@ Client *Clientlist::IsCharacterOnline(std::string CharacterName) {
|
|||||||
// i.e. for the character they are logged in as, or for the character whose mailbox they have selected in the
|
// i.e. for the character they are logged in as, or for the character whose mailbox they have selected in the
|
||||||
// mail window.
|
// mail window.
|
||||||
//
|
//
|
||||||
std::list<Client*>::iterator Iterator;
|
|
||||||
|
|
||||||
for(Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
for(auto Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) {
|
||||||
|
|
||||||
if(!(*Iterator)->IsMailConnection())
|
if(!(*Iterator)->IsMailConnection())
|
||||||
continue;
|
continue;
|
||||||
@ -2203,13 +2105,50 @@ Client *Clientlist::IsCharacterOnline(std::string CharacterName) {
|
|||||||
// If the mail is destined for the primary mailbox for this character, or the one they have selected
|
// If the mail is destined for the primary mailbox for this character, or the one they have selected
|
||||||
//
|
//
|
||||||
if((MailBoxNumber == 0) || (MailBoxNumber == (*Iterator)->GetMailBoxNumber()))
|
if((MailBoxNumber == 0) || (MailBoxNumber == (*Iterator)->GetMailBoxNumber()))
|
||||||
return (*Iterator);
|
return (*Iterator).get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clientlist::HandleNewConnection(std::shared_ptr<EQ::Net::EQStream> connection)
|
||||||
|
{
|
||||||
|
Log.OutF(Logs::Detail, Logs::UCS_Server, "New Client UDP connection from {0}:{1}", connection->RemoteEndpoint(), connection->RemotePort());
|
||||||
|
Client *c = new Client(connection);
|
||||||
|
ClientChatConnections.push_back(std::unique_ptr<Client>(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clientlist::HandleConnectionChange(std::shared_ptr<EQ::Net::EQStream> connection, EQ::Net::DbProtocolStatus old_status, EQ::Net::DbProtocolStatus new_status)
|
||||||
|
{
|
||||||
|
if (new_status == EQ::Net::DbProtocolStatus::StatusDisconnected) {
|
||||||
|
Log.OutF(Logs::Detail, Logs::UCS_Server, "Client connection from {0}:{1} closed.", connection->RemoteEndpoint(), connection->RemotePort());
|
||||||
|
auto iter = ClientChatConnections.begin();
|
||||||
|
while (iter != ClientChatConnections.end()) {
|
||||||
|
if ((*iter)->ClientStream == connection) {
|
||||||
|
ClientChatConnections.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clientlist::HandlePacket(std::shared_ptr<EQ::Net::EQStream> connection, EmuOpcode opcode, EQ::Net::Packet &p)
|
||||||
|
{
|
||||||
|
auto iter = ClientChatConnections.begin();
|
||||||
|
while (iter != ClientChatConnections.end()) {
|
||||||
|
if ((*iter)->ClientStream == connection) {
|
||||||
|
Log.OutF(Logs::General, Logs::UCS_Server, "{0}", p.ToString());
|
||||||
|
EQApplicationPacket app(opcode, (unsigned char*)p.Data(), (uint32)p.Length());
|
||||||
|
Process((*iter).get(), &app);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Client::GetMailBoxNumber(std::string CharacterName) {
|
int Client::GetMailBoxNumber(std::string CharacterName) {
|
||||||
|
|
||||||
for(unsigned int i = 0; i < Characters.size(); i++)
|
for(unsigned int i = 0; i < Characters.size(); i++)
|
||||||
|
|||||||
@ -20,13 +20,14 @@
|
|||||||
#ifndef CHATSERVER_CLIENTLIST_H
|
#ifndef CHATSERVER_CLIENTLIST_H
|
||||||
#define CHATSERVER_CLIENTLIST_H
|
#define CHATSERVER_CLIENTLIST_H
|
||||||
|
|
||||||
#include "../common/opcodemgr.h"
|
#include <net/eqstream.h>
|
||||||
#include "../common/eq_stream_type.h"
|
#include <rulesys.h>
|
||||||
#include "../common/eq_stream_factory.h"
|
#include <patch/chat.h>
|
||||||
#include "../common/rulesys.h"
|
#include <event/timer.h>
|
||||||
#include "chatchannel.h"
|
#include "chatchannel.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#define MAX_JOINED_CHANNELS 10
|
#define MAX_JOINED_CHANNELS 10
|
||||||
|
|
||||||
@ -84,14 +85,14 @@ struct CharacterEntry {
|
|||||||
class Client {
|
class Client {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Client(std::shared_ptr<EQStream> eqs);
|
Client(std::shared_ptr<EQ::Net::EQStream> eqs);
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
std::shared_ptr<EQStream> ClientStream;
|
std::shared_ptr<EQ::Net::EQStream> ClientStream;
|
||||||
void AddCharacter(int CharID, const char *CharacterName, int Level);
|
void AddCharacter(int CharID, const char *CharacterName, int Level);
|
||||||
void ClearCharacters() { Characters.clear(); }
|
void ClearCharacters() { Characters.clear(); }
|
||||||
void SendMailBoxes();
|
void SendMailBoxes();
|
||||||
inline void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) { ClientStream->QueuePacket(p, ack_req); }
|
inline void QueuePacket(const EQApplicationPacket *p) { ClientStream->QueuePacket(p); }
|
||||||
std::string GetName() { if(Characters.size()) return Characters[0].Name; else return ""; }
|
std::string GetName() { if(Characters.size()) return Characters[0].Name; else return ""; }
|
||||||
void JoinChannels(std::string ChannelList);
|
void JoinChannels(std::string ChannelList);
|
||||||
void LeaveChannels(std::string ChannelList);
|
void LeaveChannels(std::string ChannelList);
|
||||||
@ -162,10 +163,10 @@ private:
|
|||||||
bool Revoked;
|
bool Revoked;
|
||||||
|
|
||||||
//Anti Spam Stuff
|
//Anti Spam Stuff
|
||||||
Timer *AccountGrabUpdateTimer;
|
|
||||||
uint32 TotalKarma;
|
uint32 TotalKarma;
|
||||||
|
|
||||||
Timer *GlobalChatLimiterTimer; //60 seconds
|
Timer *GlobalChatLimiterTimer; //60 seconds
|
||||||
|
EQ::Timer AccountGrabUpdateTimer;
|
||||||
int AttemptedMessages;
|
int AttemptedMessages;
|
||||||
bool ForceDisconnect;
|
bool ForceDisconnect;
|
||||||
ConnectionType TypeOfConnection;
|
ConnectionType TypeOfConnection;
|
||||||
@ -176,7 +177,7 @@ class Clientlist {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Clientlist(int MailPort);
|
Clientlist(int MailPort);
|
||||||
void Process();
|
void Process(Client *c, const EQApplicationPacket *app);
|
||||||
void CloseAllConnections();
|
void CloseAllConnections();
|
||||||
Client *FindCharacter(std::string CharacterName);
|
Client *FindCharacter(std::string CharacterName);
|
||||||
void CheckForStaleConnections(Client *c);
|
void CheckForStaleConnections(Client *c);
|
||||||
@ -184,12 +185,13 @@ public:
|
|||||||
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void HandleNewConnection(std::shared_ptr<EQ::Net::EQStream> connection);
|
||||||
|
void HandleConnectionChange(std::shared_ptr<EQ::Net::EQStream> connection, EQ::Net::DbProtocolStatus old_status, EQ::Net::DbProtocolStatus new_status);
|
||||||
|
void HandlePacket(std::shared_ptr<EQ::Net::EQStream> connection, EmuOpcode opcode, EQ::Net::Packet &p);
|
||||||
|
|
||||||
EQStreamFactory *chatsf;
|
std::unique_ptr<EQ::Net::EQStreamManager> chatsf;
|
||||||
|
std::unique_ptr<EQ::Patches::BasePatch> chat_patch;
|
||||||
std::list<Client*> ClientChatConnections;
|
std::list<std::unique_ptr<Client>> ClientChatConnections;
|
||||||
|
|
||||||
OpcodeManager *ChatOpMgr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
23
ucs/ucs.cpp
23
ucs/ucs.cpp
@ -17,15 +17,15 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../common/eqemu_logsys.h"
|
#include <eqemu_logsys.h>
|
||||||
#include "../common/global_define.h"
|
#include <global_define.h>
|
||||||
|
#include <timeoutmgr.h>
|
||||||
#include "clientlist.h"
|
#include "clientlist.h"
|
||||||
#include "../common/opcodemgr.h"
|
#include <rulesys.h>
|
||||||
#include "../common/eq_stream_factory.h"
|
#include <servertalk.h>
|
||||||
#include "../common/rulesys.h"
|
#include <platform.h>
|
||||||
#include "../common/servertalk.h"
|
#include <crash.h>
|
||||||
#include "../common/platform.h"
|
#include <event/event_loop.h>
|
||||||
#include "../common/crash.h"
|
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "ucsconfig.h"
|
#include "ucsconfig.h"
|
||||||
#include "chatchannel.h"
|
#include "chatchannel.h"
|
||||||
@ -143,12 +143,11 @@ int main() {
|
|||||||
|
|
||||||
worldserver->Connect();
|
worldserver->Connect();
|
||||||
|
|
||||||
|
auto &loop = EQ::EventLoop::Get();
|
||||||
while(RunLoops) {
|
while(RunLoops) {
|
||||||
|
|
||||||
Timer::SetCurrentTime();
|
Timer::SetCurrentTime();
|
||||||
|
|
||||||
g_Clientlist->Process();
|
|
||||||
|
|
||||||
if(ChannelListProcessTimer.Check())
|
if(ChannelListProcessTimer.Check())
|
||||||
ChannelList->Process();
|
ChannelList->Process();
|
||||||
|
|
||||||
@ -160,7 +159,9 @@ int main() {
|
|||||||
|
|
||||||
timeout_manager.CheckTimeouts();
|
timeout_manager.CheckTimeouts();
|
||||||
|
|
||||||
Sleep(100);
|
loop.Process();
|
||||||
|
|
||||||
|
Sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelList->RemoveAllChannels();
|
ChannelList->RemoveAllChannels();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user