diff --git a/CMakeLists.txt b/CMakeLists.txt index 4732ca8d0..1d3adcc25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,6 +312,7 @@ IF(EQEMU_BUILD_SERVER) ADD_SUBDIRECTORY(zone) ADD_SUBDIRECTORY(ucs) ADD_SUBDIRECTORY(queryserv) + ADD_SUBDIRECTORY(socket_server) ADD_SUBDIRECTORY(eqlaunch) ENDIF(EQEMU_BUILD_SERVER) IF(EQEMU_BUILD_LOGIN) diff --git a/common/EmuTCPConnection.cpp b/common/EmuTCPConnection.cpp index 465d16c1e..39c297ccf 100644 --- a/common/EmuTCPConnection.cpp +++ b/common/EmuTCPConnection.cpp @@ -366,7 +366,22 @@ bool EmuTCPConnection::LineOutQueuePush(char* line) { safe_delete_array(line); return(true); } - + if (strcmp(line, "**PACKETMODESS**") == 0) { + MSendQueue.lock(); + safe_delete_array(sendbuf); + if (TCPMode == modeConsole) + Send((const uchar*) "\0**PACKETMODESS**\r", 18); + TCPMode = modePacket; + PacketMode = packetModeSocket_Server; + EmuTCPNetPacket_Struct* tnps = 0; + while ((tnps = InModeQueue.pop())) { + SendPacket(tnps); + safe_delete_array(tnps); + } + MSendQueue.unlock(); + safe_delete_array(line); + return(true); + } } return(TCPConnection::LineOutQueuePush(line)); @@ -419,7 +434,15 @@ bool EmuTCPConnection::ConnectIP(uint32 irIP, uint16 irPort, char* errbuf) { sendbuf_used = sendbuf_size; sendbuf = new uchar[sendbuf_size]; memcpy(sendbuf, "\0**PACKETMODEQS**\r", sendbuf_size); - } else { + } + else if (PacketMode == packetModeSocket_Server) { + safe_delete_array(sendbuf); + sendbuf_size = 18; + sendbuf_used = sendbuf_size; + sendbuf = new uchar[sendbuf_size]; + memcpy(sendbuf, "\0**PACKETMODESS**\r", sendbuf_size); + } + else { //default: packetModeZone safe_delete_array(sendbuf); sendbuf_size = 20; diff --git a/common/EmuTCPConnection.h b/common/EmuTCPConnection.h index ff7dd8995..947ee9480 100644 --- a/common/EmuTCPConnection.h +++ b/common/EmuTCPConnection.h @@ -30,7 +30,7 @@ class EmuTCPServer; class EmuTCPConnection : public TCPConnection { public: enum eTCPMode { modeConsole, modeTransition, modePacket }; - enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ }; + enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ, packetModeSocket_Server }; EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, SOCKET iSock, uint32 irIP, uint16 irPort, bool iOldFormat = false); EmuTCPConnection(bool iOldFormat = false, EmuTCPServer* iRelayServer = 0, eTCPMode iMode = modePacket); // for outgoing connections diff --git a/common/logtypes.h b/common/logtypes.h index cadfbf71a..1776c9518 100644 --- a/common/logtypes.h +++ b/common/logtypes.h @@ -65,6 +65,13 @@ LOG_TYPE( QUERYSERV, CLIENT, DISABLED ) LOG_TYPE( QUERYSERV, TRACE, DISABLED ) LOG_TYPE( QUERYSERV, PACKETS, DISABLED) +LOG_CATEGORY(SOCKET_SERVER) +LOG_TYPE(SOCKET_SERVER, INIT, ENABLED) +LOG_TYPE(SOCKET_SERVER, ERROR, ENABLED) +LOG_TYPE(SOCKET_SERVER, CLIENT, DISABLED) +LOG_TYPE(SOCKET_SERVER, TRACE, DISABLED) +LOG_TYPE(SOCKET_SERVER, PACKETS, DISABLED) + LOG_CATEGORY( SPAWNS ) LOG_TYPE( SPAWNS, MAIN, DISABLED ) LOG_TYPE( SPAWNS, CONDITIONS, DISABLED ) diff --git a/common/platform.h b/common/platform.h index efb176ec4..7eaae045b 100644 --- a/common/platform.h +++ b/common/platform.h @@ -8,6 +8,7 @@ enum EQEmuExePlatform ExePlatformWorld, ExePlatformLogin, ExePlatformQueryServ, + ExePlatformSocket_Server, ExePlatformUCS, ExePlatformLaunch, ExePlatformSharedMemory, diff --git a/socket_server/CMakeLists.txt b/socket_server/CMakeLists.txt new file mode 100644 index 000000000..f647863d9 --- /dev/null +++ b/socket_server/CMakeLists.txt @@ -0,0 +1,44 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(socket_server_sources + database.cpp + socket_server.cpp + socket_server_config.cpp + worldserver.cpp +) + +SET(socket_server_headers + database.h + socket_server_config.h + worldserver.h +) + +ADD_EXECUTABLE(socket_server ${socket_server_sources} ${socket_server_headers}) + +INSTALL(TARGETS socket_server RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) + +ADD_DEFINITIONS(-DQSERV) + +TARGET_LINK_LIBRARIES(socket_server Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) + +IF(MSVC) + SET_TARGET_PROPERTIES(socket_server PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") + TARGET_LINK_LIBRARIES(socket_server "Ws2_32.lib") +ENDIF(MSVC) + +IF(MINGW) + TARGET_LINK_LIBRARIES(socket_server "WS2_32") +ENDIF(MINGW) + +IF(UNIX) + TARGET_LINK_LIBRARIES(socket_server "${CMAKE_DL_LIBS}") + TARGET_LINK_LIBRARIES(socket_server "z") + TARGET_LINK_LIBRARIES(socket_server "m") + IF(NOT DARWIN) + TARGET_LINK_LIBRARIES(socket_server "rt") + ENDIF(NOT DARWIN) + TARGET_LINK_LIBRARIES(socket_server "pthread") + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/socket_server/database.cpp b/socket_server/database.cpp new file mode 100644 index 000000000..a2c04bbb4 --- /dev/null +++ b/socket_server/database.cpp @@ -0,0 +1,131 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +#include "../common/debug.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Disgrace: for windows compile +#ifdef _WINDOWS +#include +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#else +#include "../common/unix.h" +#include +#endif + +#include "database.h" +#include "../common/eq_packet_structs.h" +#include "../common/StringUtil.h" +#include "../common/servertalk.h" + +Database::Database () +{ + DBInitVars(); +} + +/* +Establish a connection to a mysql database with the supplied parameters +*/ + +Database::Database(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +{ + DBInitVars(); + Connect(host, user, passwd, database, port); +} + +bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +{ + uint32 errnum= 0; + char errbuf[MYSQL_ERRMSG_SIZE]; + if (!Open(host, user, passwd, database, port, &errnum, errbuf)) + { + LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf); + HandleMysqlError(errnum); + + return false; + } + else + { + LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port); + return true; + } +} + +void Database::DBInitVars() { + +} + + + +void Database::HandleMysqlError(uint32 errnum) { +} + +/* + +Close the connection to the database +*/ +Database::~Database() +{ +} + +bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_len) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (!RunQuery(query,MakeAnyLenString(&query, "select `value` from `variables` where `varname`='%s'", varname), errbuf, &result)) { + + _log(UCS__ERROR, "Unable to get message count from database. %s %s", query, errbuf); + + safe_delete_array(query); + + return false; + } + + safe_delete_array(query); + + if (mysql_num_rows(result) != 1) { + + mysql_free_result(result); + + return false; + } + + row = mysql_fetch_row(result); + + snprintf(varvalue, varvalue_len, "%s", row[0]); + + mysql_free_result(result); + + return true; +} \ No newline at end of file diff --git a/socket_server/database.h b/socket_server/database.h new file mode 100644 index 000000000..6500ffad6 --- /dev/null +++ b/socket_server/database.h @@ -0,0 +1,54 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef CHATSERVER_DATABASE_H +#define CHATSERVER_DATABASE_H + +#define AUTHENTICATION_TIMEOUT 60 +#define INVALID_ID 0xFFFFFFFF + +#include "../common/debug.h" +#include "../common/types.h" +#include "../common/dbcore.h" +#include "../common/linked_list.h" +#include "../common/servertalk.h" +#include +#include +#include + +//atoi is not uint32 or uint32 safe!!!! +#define atoul(str) strtoul(str, nullptr, 10) + +class Database : public DBcore { +public: + Database(); + Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); + bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); + ~Database(); + + bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len); +protected: + void HandleMysqlError(uint32 errnum); +private: + void DBInitVars(); + +}; + +#endif + diff --git a/socket_server/socket_server.cpp b/socket_server/socket_server.cpp new file mode 100644 index 000000000..eed4751d1 --- /dev/null +++ b/socket_server/socket_server.cpp @@ -0,0 +1,115 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "../common/debug.h" +#include "../common/opcodemgr.h" +#include "../common/EQStreamFactory.h" +#include "../common/rulesys.h" +#include "../common/servertalk.h" +#include "../common/platform.h" +#include "../common/crash.h" +#include "database.h" +#include "socket_server_config.h" +#include "worldserver.h" +#include + +#include +volatile bool RunLoops = true; +TimeoutManager timeout_manager; +Database database; +std::string WorldShortName; + +const socket_server_config *Config; +WorldServer *worldserver = 0; + +void CatchSignal(int sig_num) { + RunLoops = false; + if(worldserver) + worldserver->Disconnect(); +} + +int main() { + RegisterExecutablePlatform(ExePlatformSocket_Server); + set_exception_handler(); + Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect + _log(SOCKET_SERVER__INIT, "Starting EQEmu Socket Server."); + if (!socket_server_config::LoadConfig()) { + _log(SOCKET_SERVER__INIT, "Loading server configuration failed."); + return 1; + } + + Config = socket_server_config::get(); + + if(!load_log_settings(Config->LogSettingsFile.c_str())) + _log(SOCKET_SERVER__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str()); + else + _log(SOCKET_SERVER__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str()); + + WorldShortName = Config->ShortName; + + /* + _log(SOCKET_SERVER__INIT, "Connecting to MySQL..."); + + if (!database.Connect( + Config->QSDatabaseHost.c_str(), + Config->QSDatabaseUsername.c_str(), + Config->QSDatabasePassword.c_str(), + Config->QSDatabaseDB.c_str(), + Config->QSDatabasePort)) { + _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); + return 1; + } + */ + + if (signal(SIGINT, CatchSignal) == SIG_ERR) { + _log(SOCKET_SERVER__ERROR, "Could not set signal handler"); + return 1; + } + if (signal(SIGTERM, CatchSignal) == SIG_ERR) { + _log(SOCKET_SERVER__ERROR, "Could not set signal handler"); + return 1; + } + + worldserver = new WorldServer; + worldserver->Connect(); + + while(RunLoops) { + Timer::SetCurrentTime(); + if (InterserverTimer.Check()) { + if (worldserver->TryReconnect() && (!worldserver->Connected())) + worldserver->AsyncConnect(); + } + worldserver->Process(); + timeout_manager.CheckTimeouts(); + Sleep(100); + } +} + +void UpdateWindowTitle(char* iNewTitle) { +#ifdef _WINDOWS + char tmp[500]; + if (iNewTitle) { + snprintf(tmp, sizeof(tmp), "SOCKET_SERVER: %s", iNewTitle); + } + else { + snprintf(tmp, sizeof(tmp), "SOCKET_SERVER"); + } + SetConsoleTitle(tmp); +#endif +} diff --git a/socket_server/socket_server_config.cpp b/socket_server/socket_server_config.cpp new file mode 100644 index 000000000..8f08eba9d --- /dev/null +++ b/socket_server/socket_server_config.cpp @@ -0,0 +1,28 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "../common/debug.h" +#include "socket_server_config.h" + +socket_server_config *socket_server_config::_chat_config = nullptr; + +std::string socket_server_config::GetByName(const std::string &var_name) const { + return(EQEmuConfig::GetByName(var_name)); +} + diff --git a/socket_server/socket_server_config.h b/socket_server/socket_server_config.h new file mode 100644 index 000000000..bc86107d3 --- /dev/null +++ b/socket_server/socket_server_config.h @@ -0,0 +1,55 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef __socket_server_config_H +#define __socket_server_config_H + +#include "../common/EQEmuConfig.h" + +class socket_server_config : public EQEmuConfig { +public: + virtual std::string GetByName(const std::string &var_name) const; + +private: + + static socket_server_config *_chat_config; + +public: + + // Produce a const singleton + static const socket_server_config *get() { + if (_chat_config == nullptr) + LoadConfig(); + return(_chat_config); + } + + // Load the config + static bool LoadConfig() { + if (_chat_config != nullptr) + delete _chat_config; + _chat_config=new socket_server_config; + _config=_chat_config; + + return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); + } + +}; + +#endif + diff --git a/socket_server/worldserver.cpp b/socket_server/worldserver.cpp new file mode 100644 index 000000000..f4e7cdf76 --- /dev/null +++ b/socket_server/worldserver.cpp @@ -0,0 +1,69 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include +#include +#include +#include +#include +#include +#include + +#include "../common/servertalk.h" +#include "worldserver.h" +#include "socket_server_config.h" +#include "database.h" +#include "lfguild.h" +#include "../common/packet_functions.h" +#include "../common/md5.h" +#include "../common/packet_dump.h" + +extern WorldServer worldserver; +extern const socket_server_config *Config; +extern Database database; + +WorldServer::WorldServer() +: WorldConnection(EmuTCPConnection::packetModeSocket_Server, Config->SharedKey.c_str()){ + pTryReconnect = true; +} + +WorldServer::~WorldServer(){ +} + +void WorldServer::OnConnected(){ + _log(SOCKET_SERVER__INIT, "Connected to World."); + WorldConnection::OnConnected(); +} + +void WorldServer::Process(){ + WorldConnection::Process(); + if (!Connected()) + return; + + ServerPacket *pack = 0; + while((pack = tcpc.PopPacket())){ + _log(SOCKET_SERVER__TRACE, "Received Opcode: %4X", pack->opcode); + switch(pack->opcode) { + case 0: { break; } + case ServerOP_KeepAlive: { break; } + } + } + + safe_delete(pack); + return; +} \ No newline at end of file diff --git a/socket_server/worldserver.h b/socket_server/worldserver.h new file mode 100644 index 000000000..167342248 --- /dev/null +++ b/socket_server/worldserver.h @@ -0,0 +1,35 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef WORLDSERVER_H +#define WORLDSERVER_H + +#include "../common/worldconn.h" +#include "../common/eq_packet_structs.h" + +class WorldServer : public WorldConnection +{ + public: + WorldServer(); + virtual ~WorldServer(); + virtual void Process(); + + private: + virtual void OnConnected(); +}; +#endif + diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 3ac008267..594f77bc1 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -23,6 +23,7 @@ SET(world_sources perl_EQW.cpp perl_HTTPRequest.cpp queryserv.cpp + socket_server.cpp ucs.cpp wguild_mgr.cpp world_logsys.cpp @@ -53,6 +54,7 @@ SET(world_headers LoginServerList.h net.h queryserv.h + socket_server.h SoFCharCreateData.h ucs.h wguild_mgr.h diff --git a/world/console.cpp b/world/console.cpp index 57161487d..5a9ee60f5 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -46,6 +46,7 @@ #include "LauncherList.h" #include "ucs.h" #include "queryserv.h" +#include "socket_server.h" #ifdef _WINDOWS #define snprintf _snprintf @@ -60,6 +61,7 @@ extern ClientList client_list; extern LauncherList launcher_list; extern UCSConnection UCSLink; extern QueryServConnection QSLink; +extern Socket_Server_Connection SSLink; extern volatile bool RunLoops; ConsoleList console_list; @@ -250,18 +252,26 @@ bool Console::Process() { _log(WORLD__CONSOLE,"New launcher from %s:%d", inet_ntoa(in), GetPort()); launcher_list.Add(tcpc); tcpc = 0; - } else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) + } + else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) { _log(WORLD__CONSOLE,"New UCS Connection from %s:%d", inet_ntoa(in), GetPort()); UCSLink.SetConnection(tcpc); tcpc = 0; } - else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ) + else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ) { _log(WORLD__CONSOLE,"New QS Connection from %s:%d", inet_ntoa(in), GetPort()); QSLink.SetConnection(tcpc); tcpc = 0; - } else { + } + else if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeSocket_Server) + { + _log(WORLD__CONSOLE, "New Socket Server Connection from %s:%d", inet_ntoa(in), GetPort()); + SSLink.SetConnection(tcpc); + tcpc = 0; + } + else { _log(WORLD__CONSOLE,"Unsupported packet mode from %s:%d", inet_ntoa(in), GetPort()); } return false; diff --git a/world/net.cpp b/world/net.cpp index d7179bffe..f8d3410c0 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -86,6 +86,7 @@ #include "AdventureManager.h" #include "ucs.h" #include "queryserv.h" +#include "socket_server.h" TimeoutManager timeout_manager; EQStreamFactory eqsf(WorldStream,9000); @@ -97,6 +98,7 @@ LoginServerList loginserverlist; EQWHTTPServer http_server; UCSConnection UCSLink; QueryServConnection QSLink; +Socket_Server_Connection SSLink; LauncherList launcher_list; AdventureManager adventure_manager; DBAsync *dbasync = nullptr; @@ -454,6 +456,8 @@ int main(int argc, char** argv) { QSLink.Process(); + SSLink.Process(); + LFPGroupList.Process(); adventure_manager.Process(); diff --git a/world/socket_server.cpp b/world/socket_server.cpp new file mode 100644 index 000000000..826a95620 --- /dev/null +++ b/world/socket_server.cpp @@ -0,0 +1,127 @@ +#include "../common/debug.h" +#include "Socket_Server.h" +#include "WorldConfig.h" +#include "clientlist.h" +#include "zonelist.h" +#include "../common/logsys.h" +#include "../common/logtypes.h" +#include "../common/md5.h" +#include "../common/EmuTCPConnection.h" +#include "../common/packet_dump.h" + +extern ClientList client_list; +extern ZSList zoneserver_list; + +Socket_Server_Connection::Socket_Server_Connection() +{ + Stream = 0; + authenticated = false; +} + +void Socket_Server_Connection::SetConnection(EmuTCPConnection *inStream) +{ + if(Stream) + { + _log(SOCKET_SERVER__ERROR, "Incoming Socket_Server Connection while we were already connected to a Socket_Server."); + Stream->Disconnect(); + } + + Stream = inStream; + + authenticated = false; +} + +bool Socket_Server_Connection::Process() +{ + if (!Stream || !Stream->Connected()) + return false; + + ServerPacket *pack = 0; + + while((pack = Stream->PopPacket())) + { + if (!authenticated) + { + if (WorldConfig::get()->SharedKey.length() > 0) + { + if (pack->opcode == ServerOP_ZAAuth && pack->size == 16) + { + uint8 tmppass[16]; + + MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass); + + if (memcmp(pack->pBuffer, tmppass, 16) == 0) + authenticated = true; + else + { + struct in_addr in; + in.s_addr = GetIP(); + _log(SOCKET_SERVER__ERROR, "Socket_Server authorization failed."); + ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed); + SendPacket(pack); + delete pack; + Disconnect(); + return false; + } + } + else + { + struct in_addr in; + in.s_addr = GetIP(); + _log(SOCKET_SERVER__ERROR, "Socket_Server_ authorization failed."); + ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed); + SendPacket(pack); + delete pack; + Disconnect(); + return false; + } + } + else + { + _log(SOCKET_SERVER__ERROR,"**WARNING** You have not configured a world shared key in your config file. You should add a STRING element to your element to prevent unauthorized zone access."); + authenticated = true; + } + delete pack; + continue; + } + switch(pack->opcode) + { + case 0: + break; + + case ServerOP_KeepAlive: + { + // ignore this + break; + } + case ServerOP_ZAAuth: + { + _log(SOCKET_SERVER__ERROR, "Got authentication from Socket_Server_ when they are already authenticated."); + break; + } + case ServerOP_LFGuildUpdate: + { + zoneserver_list.SendPacket(pack); + break; + } + default: + { + _log(SOCKET_SERVER__ERROR, "Unknown ServerOPcode from Socket_Server_ 0x%04x, size %d", pack->opcode, pack->size); + DumpPacket(pack->pBuffer, pack->size); + break; + } + } + + delete pack; + } + return(true); +} + +bool Socket_Server_Connection::SendPacket(ServerPacket* pack) +{ + if(!Stream) + return false; + + return Stream->SendPacket(pack); +} + diff --git a/world/socket_server.h b/world/socket_server.h new file mode 100644 index 000000000..7cb39c2d6 --- /dev/null +++ b/world/socket_server.h @@ -0,0 +1,23 @@ +#ifndef Socket_Server__H +#define Socket_Server__H + +#include "../common/types.h" +#include "../common/EmuTCPConnection.h" +#include "../common/servertalk.h" + +class Socket_Server_Connection +{ +public: + Socket_Server_Connection(); + void SetConnection(EmuTCPConnection *inStream); + bool Process(); + bool SendPacket(ServerPacket* pack); + void Disconnect() { if(Stream) Stream->Disconnect(); } + void SendMessage(const char *From, const char *Message); +private: + inline uint32 GetIP() const { return Stream ? Stream->GetrIP() : 0; } + EmuTCPConnection *Stream; + bool authenticated; +}; + +#endif /*Socket_Server__H_*/