From 1d1df3bf7adc3c25a612d626a0f25502d758ae93 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 23 Oct 2016 17:55:19 -0700 Subject: [PATCH] Servertalk implementation wip, added optional support for pub-key authenticated encryption (via libsodium), not backwards compatible. --- CMakeLists.txt | 36 +++ client_files/export/CMakeLists.txt | 22 +- client_files/import/CMakeLists.txt | 22 +- cmake/FindSodium.cmake | 30 +++ common/CMakeLists.txt | 23 +- common/net/relay.cpp | 0 common/net/relay.h | 0 common/net/relay_link.cpp | 236 -------------------- common/net/relay_link.h | 51 ----- common/net/servertalk_client_connection.cpp | 235 +++++++++++++++++++ common/net/servertalk_client_connection.h | 53 +++++ common/net/servertalk_common.h | 15 ++ common/net/servertalk_server.cpp | 96 ++++++++ common/net/servertalk_server.h | 58 +++++ common/net/servertalk_server_connection.cpp | 196 ++++++++++++++++ common/net/servertalk_server_connection.h | 51 +++++ common/net/tcp_connection.cpp | 15 +- eqlaunch/CMakeLists.txt | 22 +- queryserv/CMakeLists.txt | 17 +- shared_memory/CMakeLists.txt | 22 +- ucs/CMakeLists.txt | 17 +- ucs/ucs.cpp | 17 ++ world/CMakeLists.txt | 19 +- zone/CMakeLists.txt | 17 +- zone/net.cpp | 1 - 25 files changed, 822 insertions(+), 449 deletions(-) create mode 100644 cmake/FindSodium.cmake delete mode 100644 common/net/relay.cpp delete mode 100644 common/net/relay.h delete mode 100644 common/net/relay_link.cpp delete mode 100644 common/net/relay_link.h create mode 100644 common/net/servertalk_client_connection.cpp create mode 100644 common/net/servertalk_client_connection.h create mode 100644 common/net/servertalk_common.h create mode 100644 common/net/servertalk_server.cpp create mode 100644 common/net/servertalk_server.h create mode 100644 common/net/servertalk_server_connection.cpp create mode 100644 common/net/servertalk_server_connection.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f1ad45d70..a4cf4e529 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,10 +64,26 @@ IF(MSVC) SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64") SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64") SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64") + SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include") + IF(MSVC_VERSION GREATER 1800) + SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic") + ELSEIF(MSVC_VERSION EQUAL 1800) + SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic") + ELSE() + SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic") + ENDIF() ELSE(CMAKE_CL_64) SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86") SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86") SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86") + SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include") + IF(MSVC_VERSION GREATER 1800) + SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic") + ELSEIF(MSVC_VERSION EQUAL 1800) + SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic") + ELSE() + SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic") + ENDIF() ENDIF(CMAKE_CL_64) #disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere @@ -315,6 +331,26 @@ IF(EQEMU_BUILD_PERL) INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}") ENDIF(EQEMU_BUILD_PERL) +SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt) + +FIND_PACKAGE(Sodium REQUIRED) +IF(SODIUM_FOUND) + INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_INCLUDE_DIRS}") + ADD_DEFINITIONS(-DENABLE_SECURITY) + SET(SERVER_LIBS ${SERVER_LIBS} ${SODIUM_LIBRARIES}) +ENDIF() + +IF(WIN32) + SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv") +ENDIF() + +IF(UNIX) + SET(SERVER_LIBS ${SERVER_LIBS} ${CMAKE_DL_LIBS} "z" "m" "pthread") + IF(NOT DARWIN) + SET(SERVER_LIBS ${SERVER_LIBS} "rt") + ENDIF() +ENDIF() + IF(EQEMU_BUILD_LUA) FIND_PACKAGE(EQLua51 REQUIRED) SET(Boost_USE_STATIC_LIBS OFF) diff --git a/client_files/export/CMakeLists.txt b/client_files/export/CMakeLists.txt index bb171b0b4..c24a01865 100644 --- a/client_files/export/CMakeLists.txt +++ b/client_files/export/CMakeLists.txt @@ -11,26 +11,6 @@ ADD_EXECUTABLE(export_client_files ${export_sources} ${export_headers}) INSTALL(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(export_client_files common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) - -IF(MSVC) - SET_TARGET_PROPERTIES(export_client_files PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(export_client_files "Ws2_32.lib") -ENDIF(MSVC) - -IF(MINGW) - TARGET_LINK_LIBRARIES(export_client_files "WS2_32") -ENDIF(MINGW) - -IF(UNIX) - TARGET_LINK_LIBRARIES(export_client_files "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(export_client_files "z") - TARGET_LINK_LIBRARIES(export_client_files "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(export_client_files "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(export_client_files "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +TARGET_LINK_LIBRARIES(export_client_files ${SERVER_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/client_files/import/CMakeLists.txt b/client_files/import/CMakeLists.txt index 4c27adbe4..0f779497c 100644 --- a/client_files/import/CMakeLists.txt +++ b/client_files/import/CMakeLists.txt @@ -11,26 +11,6 @@ ADD_EXECUTABLE(import_client_files ${import_sources} ${import_headers}) INSTALL(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(import_client_files common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) - -IF(MSVC) - SET_TARGET_PROPERTIES(import_client_files PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(import_client_files "Ws2_32.lib") -ENDIF(MSVC) - -IF(MINGW) - TARGET_LINK_LIBRARIES(import_client_files "WS2_32") -ENDIF(MINGW) - -IF(UNIX) - TARGET_LINK_LIBRARIES(import_client_files "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(import_client_files "z") - TARGET_LINK_LIBRARIES(import_client_files "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(import_client_files "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(import_client_files "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +TARGET_LINK_LIBRARIES(import_client_files ${SERVER_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/cmake/FindSodium.cmake b/cmake/FindSodium.cmake new file mode 100644 index 000000000..3c5ae3467 --- /dev/null +++ b/cmake/FindSodium.cmake @@ -0,0 +1,30 @@ +if (NOT MSVC) +include(FindPkgConfig) +pkg_check_modules(PC_SODIUM "libsodium") +if (NOT PC_SODIUM_FOUND) + pkg_check_modules(PC_SODIUM "sodium") +endif (NOT PC_SODIUM_FOUND) +if (PC_SODIUM_FOUND) + set(SODIUM_INCLUDE_HINTS ${PC_SODIUM_INCLUDE_DIRS} ${PC_SODIUM_INCLUDE_DIRS}/*) + set(SODIUM_LIBRARY_HINTS ${PC_SODIUM_LIBRARY_DIRS} ${PC_SODIUM_LIBRARY_DIRS}/*) +endif() +endif (NOT MSVC) + +# some libraries install the headers is a subdirectory of the include dir +# returned by pkg-config, so use a wildcard match to improve chances of finding +# headers and libraries. +find_path( + SODIUM_INCLUDE_DIRS + NAMES sodium.h + HINTS ${SODIUM_INCLUDE_HINTS} +) + +find_library( + SODIUM_LIBRARIES + NAMES libsodium sodium + HINTS ${SODIUM_LIBRARY_HINTS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SODIUM DEFAULT_MSG SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS) +mark_as_advanced(SODIUM_FOUND SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a538d18d0..56bf6c40a 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -76,8 +76,9 @@ SET(common_sources net/daybreak_connection.cpp net/eqstream.cpp net/packet.cpp - net/relay.cpp - net/relay_link.cpp + net/servertalk_client_connection.cpp + net/servertalk_server.cpp + net/servertalk_server_connection.cpp net/tcp_connection.cpp net/tcp_server.cpp patches/patches.cpp @@ -222,8 +223,10 @@ SET(common_headers net/endian.h net/eqstream.h net/packet.h - net/relay.h - net/relay_link.h + net/servertalk_client_connection.h + net/servertalk_common.h + net/servertalk_server.h + net/servertalk_server_connection.h net/tcp_connection.h net/tcp_server.h patches/patches.h @@ -301,10 +304,13 @@ SOURCE_GROUP(Net FILES net/eqstream.h net/packet.cpp net/packet.h - net/relay.cpp - net/relay.h - net/relay_link.cpp - net/relay_link.h + net/servertalk_client_connection.cpp + net/servertalk_client_connection.h + net/servertalk_common.h + net/servertalk_server.cpp + net/servertalk_server.h + net/servertalk_server_connection.cpp + net/servertalk_server_connection.h net/tcp_connection.cpp net/tcp_connection.h net/tcp_server.cpp @@ -414,7 +420,6 @@ INCLUDE_DIRECTORIES(Patches SocketLib StackWalker TinyXML) ADD_LIBRARY(common ${common_sources} ${common_headers}) IF(UNIX) - ADD_DEFINITIONS(-fPIC) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) ENDIF(UNIX) diff --git a/common/net/relay.cpp b/common/net/relay.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/common/net/relay.h b/common/net/relay.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/common/net/relay_link.cpp b/common/net/relay_link.cpp deleted file mode 100644 index 95083e3e7..000000000 --- a/common/net/relay_link.cpp +++ /dev/null @@ -1,236 +0,0 @@ -#include "relay_link.h" -#include "dns.h" -#include "../eqemu_logsys.h" -#include "../md5.h" -#include "../servertalk.h" - -EQ::Net::RelayLink::RelayLink(const std::string &addr, int port, const std::string &identifier, const std::string &password) - : m_timer(std::unique_ptr(new EQ::Timer(250, true, std::bind(&EQ::Net::RelayLink::Connect, this)))), - m_keepalive(std::unique_ptr(new EQ::Timer(5000, true, std::bind(&EQ::Net::RelayLink::SendKeepAlive, this)))) -{ - m_established = false; - m_connecting = false; - m_port = port; - m_identifier = identifier; - m_password = password; - DNSLookup(addr, port, false, [this](const std::string &address) { - m_addr = address; - }); - - m_opcode_dispatch.insert(std::make_pair(ServerOP_ZAAuthFailed, std::bind(&RelayLink::OnAuthFailed, this, std::placeholders::_1))); -} - -EQ::Net::RelayLink::~RelayLink() -{ -} - -void EQ::Net::RelayLink::OnMessageType(uint16 opcode, std::function cb) -{ - if (opcode != ServerOP_ZAAuthFailed) { - m_opcode_dispatch.insert(std::make_pair(opcode, cb)); - } -} - -void EQ::Net::RelayLink::SendPacket(uint16 opcode, const EQ::Net::Packet &p) -{ - EQ::Net::WritablePacket packet; - packet.PutUInt32(0, p.Length() + 7); - packet.PutInt8(4, 0); - packet.PutUInt16(5, opcode); - if(p.Length() > 0) - packet.PutPacket(7, p); - - if (m_connection) { - m_connection->Write((const char*)packet.Data(), packet.Length()); - } - else { - m_packet_queue.push(packet); - } -} - -void EQ::Net::RelayLink::Connect() -{ - if (m_addr.length() == 0 || m_port == 0 || m_connection || m_connecting) { - return; - } - - m_connecting = true; - EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr connection) { - if (connection == nullptr) { - Log.OutF(Logs::General, Logs::Debug, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port); - m_connecting = false; - return; - } - - Log.OutF(Logs::General, Logs::Debug, "Connected to {0}:{1}", m_addr, m_port); - m_connection = connection; - m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) { - Log.OutF(Logs::General, Logs::Debug, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port); - m_established = false; - m_connection.reset(); - }); - - m_connection->OnRead(std::bind(&EQ::Net::RelayLink::ProcessData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_connection->Start(); - - SendIdentifier(); - m_connecting = false; - }); -} - -void EQ::Net::RelayLink::ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length) -{ - EQ::Net::ReadOnlyPacket p((void*)data, length); - try { - Log.OutF(Logs::General, Logs::Debug, "Process data:\n{0}", p.ToString()); - - if (m_established) { - ProcessPacket(p); - } - else { - std::string msg; - if (m_identifier.compare("LOGIN") == 0) { - msg = fmt::format("**PACKETMODE**\r"); - } - else { - msg = fmt::format("**PACKETMODE{0}**\r", m_identifier); - } - - std::string cmp_msg; - if (p.GetInt8(0) == '*') { - cmp_msg = p.GetString(0, msg.length()); - } - else if (p.GetInt8(1) == '*') { - cmp_msg = p.GetString(1, msg.length()); - } - else { - return; - } - - if (cmp_msg.compare(msg) == 0) { - m_established = true; - Log.OutF(Logs::General, Logs::Debug, "Established connection of type {0}", m_identifier); - SendPassword(); - } - } - } - catch (std::exception &ex) { - Log.OutF(Logs::General, Logs::Debug, "Error parsing relay link packet: {0}", ex.what()); - } -} - -void EQ::Net::RelayLink::ProcessPacket(const EQ::Net::Packet &p) -{ - char *buffer = (char*)p.Data(); - m_data_buffer.insert(m_data_buffer.begin() + m_data_buffer.size(), buffer, buffer + p.Length()); - - ProcessBuffer(); -} - -void EQ::Net::RelayLink::ProcessBuffer() -{ - size_t size = 7; - size_t base = 0; - size_t used = m_data_buffer.size(); - while ((used - base) >= size) { - uint32 packet_size = *(uint32*)&m_data_buffer[base]; - uint8 packet_flags = *(uint8*)&m_data_buffer[base + 4]; - uint16 packet_opcode = *(uint16*)&m_data_buffer[base + 5]; - - if ((used - base) >= packet_size) { - EQ::Net::ReadOnlyPacket p(&m_data_buffer[base], packet_size); - - if (m_opcode_dispatch.count(packet_opcode) > 0) { - auto &cb = m_opcode_dispatch[(int)packet_opcode]; - cb(p); - } - else { - Log.OutF(Logs::General, Logs::Debug, "Unhandled packet of type {0:x}", packet_opcode); - } - - base += packet_size; - } - else { - EQ::Net::WritablePacket p; - - if (m_opcode_dispatch.count(packet_opcode) > 0) { - auto &cb = m_opcode_dispatch[(int)packet_opcode]; - cb(p); - } - else { - Log.OutF(Logs::General, Logs::Debug, "Unhandled packet of type {0:x}", packet_opcode); - } - } - } - - if (used == base) { - m_data_buffer.clear(); - } - else { - m_data_buffer.erase(m_data_buffer.begin(), m_data_buffer.begin() + base); - } -} - -void EQ::Net::RelayLink::ProcessQueue() -{ - if (!m_connection) - return; - - while (!m_packet_queue.empty()) { - auto &p = m_packet_queue.front(); - m_connection->Write((const char*)p.Data(), p.Length()); - m_packet_queue.pop(); - } -} - -void EQ::Net::RelayLink::SendIdentifier() -{ - std::string msg; - if (m_identifier.compare("LOGIN") == 0) { - msg = fmt::format("**PACKETMODE**\r"); - } - else { - msg = fmt::format("**PACKETMODE{0}**\r", m_identifier); - } - EQ::Net::WritablePacket packet; - packet.PutData(0, (void*)msg.c_str(), msg.length()); - SendInternal(packet); -} - -void EQ::Net::RelayLink::SendInternal(const EQ::Net::Packet &p) -{ - if (m_connection == nullptr) { - return; - } - - m_connection->Write((const char*)p.Data(), p.Length()); -} - -void EQ::Net::RelayLink::SendPassword() -{ - if (m_password.length() > 0) { - char hash[16] = { 0 }; - MD5::Generate((const uchar*)m_password.c_str(), m_password.length(), (uchar*)&hash[0]); - - EQ::Net::WritablePacket p; - p.PutData(0, &hash[0], 16); - SendPacket(ServerOP_ZAAuth, p); - } -} - -void EQ::Net::RelayLink::OnAuthFailed(const EQ::Net::Packet &p) -{ - if (m_connection) { - Log.OutF(Logs::General, Logs::Debug, "Authorization failed for server type {0}", m_identifier); - m_connection->Disconnect(); - } -} - -void EQ::Net::RelayLink::SendKeepAlive() -{ - if (!m_connection) - return; - - EQ::Net::WritablePacket p; - SendPacket(0, p); -} diff --git a/common/net/relay_link.h b/common/net/relay_link.h deleted file mode 100644 index 1add3b6ff..000000000 --- a/common/net/relay_link.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "tcp_server.h" -#include "packet.h" -#include "../types.h" -#include "../event/timer.h" -#include "../event/event_loop.h" -#include -#include - -namespace EQ -{ - namespace Net { - class RelayLink - { - public: - RelayLink(const std::string &addr, int port, const std::string &identifier, const std::string &password); - ~RelayLink(); - - void OnMessageType(uint16 opcode, std::function cb); - void SendPacket(uint16 opcode, const EQ::Net::Packet &p); - bool Connected() const { return m_connection != nullptr; } - std::string GetIP() const { return m_addr; } - uint16 GetPort() const { return m_port; } - private: - void Connect(); - void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length); - void ProcessPacket(const EQ::Net::Packet &p); - void ProcessBuffer(); - void ProcessQueue(); - void SendIdentifier(); - void SendInternal(const EQ::Net::Packet &p); - void SendPassword(); - void OnAuthFailed(const EQ::Net::Packet &p); - void SendKeepAlive(); - - std::unique_ptr m_timer; - std::unique_ptr m_keepalive; - std::string m_addr; - std::string m_identifier; - std::string m_password; - int m_port; - std::shared_ptr m_connection; - bool m_established; - bool m_connecting; - std::vector m_data_buffer; - std::map> m_opcode_dispatch; - std::queue m_packet_queue; - }; - } -} diff --git a/common/net/servertalk_client_connection.cpp b/common/net/servertalk_client_connection.cpp new file mode 100644 index 000000000..1c2117d55 --- /dev/null +++ b/common/net/servertalk_client_connection.cpp @@ -0,0 +1,235 @@ +#include "servertalk_client_connection.h" +#include "dns.h" +#include "../eqemu_logsys.h" + +EQ::Net::ServertalkClient::ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials) + : m_timer(std::unique_ptr(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkClient::Connect, this)))) +{ + m_port = port; + m_ipv6 = ipv6; + m_identifier = identifier.empty() ? "Unknown" : identifier; + m_credentials = credentials; + m_connecting = false; + DNSLookup(addr, port, false, [this](const std::string &address) { + m_addr = address; + }); +} + +EQ::Net::ServertalkClient::~ServertalkClient() +{ +} + +void EQ::Net::ServertalkClient::Connect() +{ + if (m_addr.length() == 0 || m_port == 0 || m_connection || m_connecting) { + return; + } + + m_connecting = true; + EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr connection) { + if (connection == nullptr) { + Log.OutF(Logs::General, Logs::TCP_Connection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port); + m_connecting = false; + return; + } + + Log.OutF(Logs::General, Logs::TCP_Connection, "Connected to {0}:{1}", m_addr, m_port); + m_connection = connection; + m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) { + Log.OutF(Logs::General, Logs::TCP_Connection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port); + m_connection.reset(); + m_encrypted = false; + }); + + m_connection->OnRead(std::bind(&EQ::Net::ServertalkClient::ProcessData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + m_connection->Start(); + + SendHello(); + m_connecting = false; + }); +} + +void EQ::Net::ServertalkClient::ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length) +{ + m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + length); + ProcessReadBuffer(); +} + +void EQ::Net::ServertalkClient::SendHello() +{ + EQ::Net::WritablePacket p; + InternalSend(ServertalkClientHello, p); +} + +void EQ::Net::ServertalkClient::InternalSend(ServertalkPacketType type, EQ::Net::Packet &p) +{ + if (!m_connection) + return; + + EQ::Net::WritablePacket out; + out.PutUInt32(0, (uint32_t)p.Length()); + out.PutUInt8(4, (uint8_t)type); + if (p.Length() > 0) { + out.PutPacket(5, p); + } + + m_connection->Write((const char*)out.Data(), out.Length()); +} + +void EQ::Net::ServertalkClient::ProcessReadBuffer() +{ + size_t current = 0; + size_t total = m_buffer.size(); + + while (current < total) { + auto left = total - current; + + /* + //header: + //uint32 length; + //uint8 type; + */ + size_t length = 0; + uint8_t type = 0; + if (left < 5) { + break; + } + + length = *(uint32_t*)&m_buffer[current]; + type = *(uint8_t*)&m_buffer[current + 4]; + + if (current + 5 + length < total) { + break; + } + + if (length == 0) { + EQ::Net::WritablePacket p; + switch (type) { + case ServertalkServerHello: + ProcessHello(p); + break; + case ServertalkMessage: + ProcessMessage(p); + break; + } + } + else { + EQ::Net::ReadOnlyPacket p(&m_buffer[current + 5], length); + switch (type) { + case ServertalkServerHello: + ProcessHello(p); + break; + case ServertalkMessage: + ProcessMessage(p); + break; + } + } + + current += length + 5; + } + + if (current == total) { + m_buffer.clear(); + } + else { + m_buffer.erase(m_buffer.begin(), m_buffer.begin() + current); + } +} + +void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p) +{ +#ifdef ENABLE_SECURITY + memset(m_public_key_ours, 0, crypto_box_PUBLICKEYBYTES); + memset(m_public_key_theirs, 0, crypto_box_PUBLICKEYBYTES); + memset(m_private_key_ours, 0, crypto_box_SECRETKEYBYTES); + memset(m_nonce_ours, 0, crypto_box_NONCEBYTES); + memset(m_nonce_theirs, 0, crypto_box_NONCEBYTES); + m_encrypted = false; + + try { + bool enc = p.GetInt8(0) == 1 ? true : false; + + if (enc) { + if (p.Length() == (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES)) { + memcpy(m_public_key_theirs, (char*)p.Data() + 1, crypto_box_PUBLICKEYBYTES); + memcpy(m_nonce_theirs, (char*)p.Data() + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES); + m_encrypted = true; + + SendHandshake(); + } + else { + Log.OutF(Logs::General, Logs::Error, "Could not process hello, size != {0}", 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); + } + } + else { + SendHandshake(); + } + } + catch (std::exception &ex) { + Log.OutF(Logs::General, Logs::Error, "Error parsing hello from server: {0}", ex.what()); + m_connection->Disconnect(); + } +#else + try { + bool enc = p.GetInt8(0) == 1 ? true : false; + + if (enc) { + Log.OutF(Logs::General, Logs::Error, "Server requested encryption but we do not support encryption."); + m_connection->Disconnect(); + return; + } + else { + SendHandshake(); + } +} + catch (std::exception &ex) { + Log.OutF(Logs::General, Logs::Error, "Error parsing hello from server: {0}", ex.what()); + m_connection->Disconnect(); + } +#endif +} + +void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p) +{ +} + +void EQ::Net::ServertalkClient::SendHandshake() +{ + EQ::Net::WritablePacket handshake; +#ifdef ENABLE_SECURITY + if (m_encrypted) { + crypto_box_keypair(m_public_key_ours, m_private_key_ours); + randombytes_buf(m_nonce_ours, crypto_box_NONCEBYTES); + + crypto_box_beforenm(m_shared_key, m_public_key_theirs, m_private_key_ours); + + handshake.PutData(0, m_public_key_ours, crypto_box_PUBLICKEYBYTES); + handshake.PutData(crypto_box_PUBLICKEYBYTES, m_nonce_ours, crypto_box_NONCEBYTES); + + size_t cipher_length = m_identifier.length() + 1 + m_credentials.length() + 1 + crypto_secretbox_MACBYTES; + size_t data_length = m_identifier.length() + 1 + m_credentials.length() + 1; + unsigned char *signed_buffer = new unsigned char[cipher_length]; + unsigned char *data_buffer = new unsigned char[data_length]; + memset(data_buffer, 0, data_length); + memcpy(&data_buffer[0], m_identifier.c_str(), m_identifier.length()); + memcpy(&data_buffer[1 + m_identifier.length()], m_credentials.c_str(), m_credentials.length()); + + crypto_box_easy_afternm(signed_buffer, data_buffer, data_length, m_nonce_ours, m_shared_key); + + (*(uint64_t*)&m_nonce_ours[0])++; + + handshake.PutData(crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, signed_buffer, cipher_length); + + Log.OutF(Logs::General, Logs::Debug, "Sending {1} bytes handshake:\n{0}", handshake.ToString(), handshake.Length()); + + delete[] signed_buffer; + delete[] data_buffer; + } + else { + handshake.PutString(0, m_identifier); + } +#else + handshake.PutString(0, m_identifier); +#endif + InternalSend(ServertalkClientHandshake, handshake); +} diff --git a/common/net/servertalk_client_connection.h b/common/net/servertalk_client_connection.h new file mode 100644 index 000000000..61513dada --- /dev/null +++ b/common/net/servertalk_client_connection.h @@ -0,0 +1,53 @@ +#pragma once + +#include "tcp_connection.h" +#include "../event/timer.h" +#include "servertalk_common.h" +#include "packet.h" +#include + +namespace EQ +{ + namespace Net + { + class ServertalkClient + { + public: + ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials); + ~ServertalkClient(); + + private: + void Connect(); + void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length); + void SendHello(); + void InternalSend(ServertalkPacketType type, EQ::Net::Packet &p); + void ProcessReadBuffer(); + void ProcessHello(EQ::Net::Packet &p); + void ProcessMessage(EQ::Net::Packet &p); + void SendHandshake(); + + std::unique_ptr m_timer; + + std::string m_addr; + std::string m_identifier; + std::string m_credentials; + bool m_connecting; + int m_port; + bool m_ipv6; + bool m_encrypted; + std::shared_ptr m_connection; + std::vector m_buffer; + +#ifdef ENABLE_SECURITY + unsigned char m_public_key_ours[crypto_box_PUBLICKEYBYTES]; + unsigned char m_private_key_ours[crypto_box_SECRETKEYBYTES]; + unsigned char m_nonce_ours[crypto_box_NONCEBYTES]; + + unsigned char m_public_key_theirs[crypto_box_PUBLICKEYBYTES]; + unsigned char m_nonce_theirs[crypto_box_NONCEBYTES]; + + unsigned char m_shared_key[crypto_box_BEFORENMBYTES]; +#endif + }; + } +} diff --git a/common/net/servertalk_common.h b/common/net/servertalk_common.h new file mode 100644 index 000000000..2accfa0af --- /dev/null +++ b/common/net/servertalk_common.h @@ -0,0 +1,15 @@ +#pragma once + +namespace EQ +{ + namespace Net + { + enum ServertalkPacketType + { + ServertalkClientHello = 1, + ServertalkServerHello, + ServertalkClientHandshake, + ServertalkMessage, + }; + } +} \ No newline at end of file diff --git a/common/net/servertalk_server.cpp b/common/net/servertalk_server.cpp new file mode 100644 index 000000000..1fe2f6d26 --- /dev/null +++ b/common/net/servertalk_server.cpp @@ -0,0 +1,96 @@ +#include "servertalk_server.h" + +EQ::Net::ServertalkServer::ServertalkServer() +{ +} + +EQ::Net::ServertalkServer::~ServertalkServer() +{ +} + +void EQ::Net::ServertalkServer::Listen(const ServertalkServerOptions& opts) +{ + m_encrypted = opts.encrypted; + m_credentials = opts.credentials; + m_server.reset(new EQ::Net::TCPServer()); + m_server->Listen(opts.port, opts.ipv6, [this](std::shared_ptr connection) { + m_unident_connections.push_back(std::make_shared(connection, this, m_encrypted)); + }); +} + +void EQ::Net::ServertalkServer::OnConnectionIdentified(const std::string &type, std::function)> cb) +{ + m_on_ident.insert(std::make_pair(type, cb)); +} + +void EQ::Net::ServertalkServer::OnConnectionRemoved(const std::string &type, std::function)> cb) +{ + m_on_disc.insert(std::make_pair(type, cb)); +} + +void EQ::Net::ServertalkServer::ConnectionDisconnected(ServertalkServerConnection *conn) +{ + if (conn->GetIdentifier().empty()) { + auto iter = m_unident_connections.begin(); + while (iter != m_unident_connections.end()) { + if (conn == iter->get()) { + m_unident_connections.erase(iter); + return; + } + ++iter; + } + } + else { + auto type = m_ident_connections.find(conn->GetIdentifier()); + if (type != m_ident_connections.end()) { + auto iter = type->second.begin(); + while (iter != type->second.end()) { + if (conn == iter->get()) { + auto on_disc = m_on_disc.find(conn->GetIdentifier()); + if (on_disc != m_on_disc.end()) { + on_disc->second(*iter); + } + type->second.erase(iter); + return; + } + ++iter; + } + } + } +} + +void EQ::Net::ServertalkServer::ConnectionIdentified(ServertalkServerConnection *conn) +{ + auto iter = m_unident_connections.begin(); + while (iter != m_unident_connections.end()) { + if (conn == iter->get()) { + auto on_ident = m_on_ident.find(conn->GetIdentifier()); + if (on_ident != m_on_ident.end()) { + on_ident->second(*iter); + } + + if (m_ident_connections.count(conn->GetIdentifier()) > 0) { + auto &vec = m_ident_connections[conn->GetIdentifier()]; + vec.push_back(*iter); + } + else { + std::vector> vec; + vec.push_back(*iter); + m_ident_connections.insert(std::make_pair(conn->GetIdentifier(), vec)); + } + + m_unident_connections.erase(iter); + return; + } + ++iter; + } +} + +bool EQ::Net::ServertalkServer::CheckCredentials(const std::string &credentials) +{ + if (credentials.compare(m_credentials) == 0) { + return true; + } + + return false; +} diff --git a/common/net/servertalk_server.h b/common/net/servertalk_server.h new file mode 100644 index 000000000..262732322 --- /dev/null +++ b/common/net/servertalk_server.h @@ -0,0 +1,58 @@ +#pragma once + +#include "tcp_server.h" +#include "servertalk_server_connection.h" +#include +#include + +#ifdef ENABLE_SECURITY +#include +#endif + +namespace EQ +{ + namespace Net + { + struct ServertalkServerOptions + { + int port; + bool ipv6; + bool encrypted; + std::string credentials; + + ServertalkServerOptions() { +#ifdef ENABLE_SECURITY + encrypted = true; +#endif + ipv6 = false; + } + }; + + class ServertalkServer + { + public: + ServertalkServer(); + ~ServertalkServer(); + + void Listen(const ServertalkServerOptions& opts); + void OnConnectionIdentified(const std::string &type, std::function)> cb); + void OnConnectionRemoved(const std::string &type, std::function)> cb); + + private: + void ConnectionDisconnected(ServertalkServerConnection *conn); + void ConnectionIdentified(ServertalkServerConnection *conn); + bool CheckCredentials(const std::string &credentials); + + std::unique_ptr m_server; + std::vector> m_unident_connections; + std::map>> m_ident_connections; + + std::map)>> m_on_ident; + std::map)>> m_on_disc; + bool m_encrypted; + std::string m_credentials; + + friend class ServertalkServerConnection; + }; + } +} diff --git a/common/net/servertalk_server_connection.cpp b/common/net/servertalk_server_connection.cpp new file mode 100644 index 000000000..a8f999e07 --- /dev/null +++ b/common/net/servertalk_server_connection.cpp @@ -0,0 +1,196 @@ +#include "servertalk_server_connection.h" +#include "servertalk_server.h" +#include "../eqemu_logsys.h" + +EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr c, EQ::Net::ServertalkServer *parent, bool encrypted) +{ + m_connection = c; + m_parent = parent; + m_encrypted = encrypted; + m_connection->OnRead(std::bind(&ServertalkServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + m_connection->OnDisconnect(std::bind(&ServertalkServerConnection::OnDisconnect, this, std::placeholders::_1)); + m_connection->Start(); +} + +EQ::Net::ServertalkServerConnection::~ServertalkServerConnection() +{ +} + +void EQ::Net::ServertalkServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz) +{ + m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + sz); + ProcessReadBuffer(); +} + +void EQ::Net::ServertalkServerConnection::ProcessReadBuffer() +{ + size_t current = 0; + size_t total = m_buffer.size(); + + while (current < total) { + auto left = total - current; + + /* + //header: + //uint32 length; + //uint8 type; + */ + size_t length = 0; + uint8_t type = 0; + if (left < 5) { + break; + } + + length = *(uint32_t*)&m_buffer[current]; + type = *(uint8_t*)&m_buffer[current + 4]; + + if (current + 5 + length < total) { + break; + } + + if (length == 0) { + EQ::Net::WritablePacket p; + switch (type) { + case ServertalkClientHello: + { + SendHello(); + } + break; + case ServertalkClientHandshake: + ProcessHandshake(p); + break; + case ServertalkMessage: + ProcessMessage(p); + break; + } + } + else { + EQ::Net::ReadOnlyPacket p(&m_buffer[current + 5], length); + switch (type) { + case ServertalkClientHello: + { + SendHello(); + } + break; + case ServertalkClientHandshake: + ProcessHandshake(p); + break; + case ServertalkMessage: + ProcessMessage(p); + break; + } + } + + current += length + 5; + } + + if (current == total) { + m_buffer.clear(); + } + else { + m_buffer.erase(m_buffer.begin(), m_buffer.begin() + current); + } +} + +void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c) +{ + m_parent->ConnectionDisconnected(this); +} + +void EQ::Net::ServertalkServerConnection::SendHello() +{ + EQ::Net::WritablePacket hello; + +#ifdef ENABLE_SECURITY + memset(m_public_key_ours, 0, crypto_box_PUBLICKEYBYTES); + memset(m_public_key_theirs, 0, crypto_box_PUBLICKEYBYTES); + memset(m_private_key_ours, 0, crypto_box_SECRETKEYBYTES); + memset(m_nonce_ours, 0, crypto_box_NONCEBYTES); + memset(m_nonce_theirs, 0, crypto_box_NONCEBYTES); + + if (m_encrypted) { + hello.PutInt8(0, 1); + + crypto_box_keypair(m_public_key_ours, m_private_key_ours); + randombytes_buf(m_nonce_ours, crypto_box_NONCEBYTES); + + hello.PutData(1, m_public_key_ours, crypto_box_PUBLICKEYBYTES); + hello.PutData(1 + crypto_box_PUBLICKEYBYTES, m_nonce_ours, crypto_box_NONCEBYTES); + } + else { + hello.PutInt8(0, 0); + } +#else + hello.PutInt8(0, 0); +#endif + + InternalSend(ServertalkServerHello, hello); +} + +void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type, EQ::Net::Packet &p) +{ + if (!m_connection) + return; + + EQ::Net::WritablePacket out; + out.PutUInt32(0, (uint32_t)p.Length()); + out.PutUInt8(4, (uint8_t)type); + if (p.Length() > 0) { + out.PutPacket(5, p); + } + + m_connection->Write((const char*)out.Data(), out.Length()); +} + +void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p) +{ +#ifdef ENABLE_SECURITY + if (m_encrypted) { + try { + if (p.Length() > (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES)) { + memcpy(m_public_key_theirs, (char*)p.Data(), crypto_box_PUBLICKEYBYTES); + memcpy(m_nonce_theirs, (char*)p.Data() + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES); + + crypto_box_beforenm(m_shared_key, m_public_key_theirs, m_private_key_ours); + + size_t cipher_len = p.Length() - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES; + size_t message_len = cipher_len - crypto_secretbox_MACBYTES; + unsigned char *decrypted_text = new unsigned char[message_len]; + if (crypto_box_open_easy_afternm(decrypted_text, (unsigned char*)p.Data() + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, cipher_len, m_nonce_theirs, m_shared_key)) + { + Log.OutF(Logs::General, Logs::Error, "Error decrypting handshake from client, dropping connection."); + m_connection->Disconnect(); + return; + } + + m_identifier = (const char*)decrypted_text; + std::string credentials = (const char*)decrypted_text + (m_identifier.length() + 1); + + if (!m_parent->CheckCredentials(credentials)) { + Log.OutF(Logs::General, Logs::Error, "Got incoming connection with invalid credentials during handshake, dropping connection."); + m_connection->Disconnect(); + return; + } + + m_parent->ConnectionIdentified(this); + + (*(uint64_t*)&m_nonce_theirs[0])++; + delete[] decrypted_text; + } + } + catch (std::exception &ex) { + Log.OutF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what()); + m_connection->Disconnect(); + } + } + else { + m_identifier.assign((char*)p.Data(), p.Length()); + } +#else + m_identifier.assign((char*)p.Data(), p.Length()); +#endif +} + +void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p) +{ +} diff --git a/common/net/servertalk_server_connection.h b/common/net/servertalk_server_connection.h new file mode 100644 index 000000000..c1859b890 --- /dev/null +++ b/common/net/servertalk_server_connection.h @@ -0,0 +1,51 @@ +#pragma once + +#include "tcp_connection.h" +#include "servertalk_common.h" +#include "packet.h" +#include +#include + +namespace EQ +{ + namespace Net + { + class ServertalkServer; + class ServertalkServerConnection + { + public: + ServertalkServerConnection(std::shared_ptr c, ServertalkServer *parent, bool encrypted); + ~ServertalkServerConnection(); + + std::string GetIdentifier() const { + return m_identifier; + } + private: + void OnRead(TCPConnection* c, const unsigned char* data, size_t sz); + void ProcessReadBuffer(); + void OnDisconnect(TCPConnection* c); + void SendHello(); + void InternalSend(ServertalkPacketType type, EQ::Net::Packet &p); + void ProcessHandshake(EQ::Net::Packet &p); + void ProcessMessage(EQ::Net::Packet &p); + + std::shared_ptr m_connection; + ServertalkServer *m_parent; + + std::vector m_buffer; + std::string m_identifier; + + bool m_encrypted; +#ifdef ENABLE_SECURITY + unsigned char m_public_key_ours[crypto_box_PUBLICKEYBYTES]; + unsigned char m_private_key_ours[crypto_box_SECRETKEYBYTES]; + unsigned char m_nonce_ours[crypto_box_NONCEBYTES]; + + unsigned char m_public_key_theirs[crypto_box_PUBLICKEYBYTES]; + unsigned char m_nonce_theirs[crypto_box_NONCEBYTES]; + + unsigned char m_shared_key[crypto_box_BEFORENMBYTES]; +#endif + }; + } +} diff --git a/common/net/tcp_connection.cpp b/common/net/tcp_connection.cpp index 526e52a40..be5266104 100644 --- a/common/net/tcp_connection.cpp +++ b/common/net/tcp_connection.cpp @@ -107,12 +107,17 @@ void EQ::Net::TCPConnection::OnDisconnect(std::function cb void EQ::Net::TCPConnection::Disconnect() { if (m_socket) { - uv_close((uv_handle_t*)m_socket, on_close_handle); + m_socket->data = this; + uv_close((uv_handle_t*)m_socket, [](uv_handle_t* handle) { + TCPConnection *connection = (TCPConnection*)handle->data; + + if (connection->m_on_disconnect_cb) { + connection->m_on_disconnect_cb(connection); + } + + delete handle; + }); m_socket = nullptr; - - if (m_on_disconnect_cb) { - m_on_disconnect_cb(this); - } } } diff --git a/eqlaunch/CMakeLists.txt b/eqlaunch/CMakeLists.txt index dd14a58be..260a2b5bc 100644 --- a/eqlaunch/CMakeLists.txt +++ b/eqlaunch/CMakeLists.txt @@ -15,26 +15,6 @@ ADD_EXECUTABLE(eqlaunch ${eqlaunch_sources} ${eqlaunch_headers}) INSTALL(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(eqlaunch common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) - -IF(MSVC) - SET_TARGET_PROPERTIES(eqlaunch PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(eqlaunch "Ws2_32.lib") -ENDIF(MSVC) - -IF(MINGW) - TARGET_LINK_LIBRARIES(eqlaunch "WS2_32") -ENDIF(MINGW) - -IF(UNIX) - TARGET_LINK_LIBRARIES(eqlaunch "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(eqlaunch "z") - TARGET_LINK_LIBRARIES(eqlaunch "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(eqlaunch "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(eqlaunch "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +TARGET_LINK_LIBRARIES(eqlaunch ${SERVER_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index d652311d4..393747a91 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -21,21 +21,6 @@ INSTALL(TARGETS queryserv RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) ADD_DEFINITIONS(-DQSERV) -TARGET_LINK_LIBRARIES(queryserv common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt) - -IF(WIN32) - TARGET_LINK_LIBRARIES(queryserv "ws2_32" "psapi" "iphlpapi" "userenv") -ENDIF(WIN32) - -IF(UNIX) - TARGET_LINK_LIBRARIES(queryserv "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(queryserv "z") - TARGET_LINK_LIBRARIES(queryserv "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(queryserv "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(queryserv "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +TARGET_LINK_LIBRARIES(queryserv ${SERVER_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 0d8a7bc34..1844df758 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -23,26 +23,6 @@ ADD_EXECUTABLE(shared_memory ${shared_memory_sources} ${shared_memory_headers}) INSTALL(TARGETS shared_memory RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(shared_memory common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) - -IF(MSVC) - SET_TARGET_PROPERTIES(shared_memory PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(shared_memory "Ws2_32.lib") -ENDIF(MSVC) - -IF(MINGW) - TARGET_LINK_LIBRARIES(shared_memory "WS2_32") -ENDIF(MINGW) - -IF(UNIX) - TARGET_LINK_LIBRARIES(shared_memory "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(shared_memory "z") - TARGET_LINK_LIBRARIES(shared_memory "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(shared_memory "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(shared_memory "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +TARGET_LINK_LIBRARIES(shared_memory ${SERVER_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/ucs/CMakeLists.txt b/ucs/CMakeLists.txt index a1f785c4a..e09e12781 100644 --- a/ucs/CMakeLists.txt +++ b/ucs/CMakeLists.txt @@ -23,21 +23,6 @@ INSTALL(TARGETS ucs RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) ADD_DEFINITIONS(-DUCS) -TARGET_LINK_LIBRARIES(ucs common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt) - -IF(WIN32) - TARGET_LINK_LIBRARIES(ucs "ws2_32" "psapi" "iphlpapi" "userenv") -ENDIF(WIN32) - -IF(UNIX) - TARGET_LINK_LIBRARIES(ucs "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(ucs "z") - TARGET_LINK_LIBRARIES(ucs "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(ucs "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(ucs "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +TARGET_LINK_LIBRARIES(ucs ${SERVER_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 52cce5228..95e63d2ff 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -34,6 +34,8 @@ #include #include "../common/net/tcp_server.h" +#include "../common/net/servertalk_server.h" +#include "../common/net/servertalk_client_connection.h" ChatChannelList *ChannelList; Clientlist *g_Clientlist; @@ -144,6 +146,21 @@ int main() { worldserver->Connect(); + EQ::Net::ServertalkServer server; + EQ::Net::ServertalkServerOptions opts; + opts.port = 5999; + server.Listen(opts); + + server.OnConnectionIdentified("QueryServ", [](std::shared_ptr conn) { + Log.Out(Logs::General, Logs::Debug, "New QueryServ Connection...."); + }); + + server.OnConnectionRemoved("QueryServ", [](std::shared_ptr conn) { + Log.Out(Logs::General, Logs::Debug, "Lost QueryServ connection."); + }); + + EQ::Net::ServertalkClient client("127.0.0.1", 5999, false, "QueryServ", "User:Root;Password:1234567890"); + while(RunLoops) { Timer::SetCurrentTime(); diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 775648674..03b23df08 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -68,21 +68,10 @@ INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) ADD_DEFINITIONS(-DWORLD) -TARGET_LINK_LIBRARIES(world common ${PERL_LIBRARY} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt) +TARGET_LINK_LIBRARIES(world ${SERVER_LIBS}) -IF(WIN32) - TARGET_LINK_LIBRARIES(world "ws2_32" "psapi" "iphlpapi" "userenv") -ENDIF(WIN32) - -IF(UNIX) - TARGET_LINK_LIBRARIES(world "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(world "z") - TARGET_LINK_LIBRARIES(world "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(world "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(world "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +IF(EQEMU_BUILD_PERL) + TARGET_LINK_LIBRARIES(world ${PERL_LIBRARY}) +ENDIF(EQEMU_BUILD_PERL) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 019f9ab7f..53e6edcd0 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -231,11 +231,7 @@ INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) ADD_DEFINITIONS(-DZONE) -TARGET_LINK_LIBRARIES(zone common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt) - -IF(WIN32) - TARGET_LINK_LIBRARIES(zone "ws2_32" "psapi" "iphlpapi" "userenv") -ENDIF(WIN32) +TARGET_LINK_LIBRARIES(zone ${SERVER_LIBS}) IF(EQEMU_BUILD_PERL) TARGET_LINK_LIBRARIES(zone ${PERL_LIBRARY}) @@ -245,15 +241,4 @@ IF(EQEMU_BUILD_LUA) TARGET_LINK_LIBRARIES(zone luabind ${LUA_LIBRARY}) ENDIF(EQEMU_BUILD_LUA) -IF(UNIX) - TARGET_LINK_LIBRARIES(zone "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(zone "z") - TARGET_LINK_LIBRARIES(zone "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(zone "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(zone "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) - SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/zone/net.cpp b/zone/net.cpp index 492742de1..d08fd7975 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -66,7 +66,6 @@ #include "../common/event/event_loop.h" #include "../common/event/timer.h" #include "../common/net/eqstream.h" -#include "../common/net/relay_link.h" #include #include