Servertalk implementation wip, added optional support for pub-key authenticated encryption (via libsodium), not backwards compatible.

This commit is contained in:
KimLS 2016-10-23 17:55:19 -07:00
parent e29ca88a76
commit 1d1df3bf7a
25 changed files with 822 additions and 449 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

30
cmake/FindSodium.cmake Normal file
View File

@ -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)

View File

@ -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)

View File

View File

View File

@ -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<EQ::Timer>(new EQ::Timer(250, true, std::bind(&EQ::Net::RelayLink::Connect, this)))),
m_keepalive(std::unique_ptr<EQ::Timer>(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<void(const EQ::Net::Packet&p)> 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<EQ::Net::TCPConnection> 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);
}

View File

@ -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 <map>
#include <queue>
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<void(const EQ::Net::Packet &p)> 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<EQ::Timer> m_timer;
std::unique_ptr<EQ::Timer> m_keepalive;
std::string m_addr;
std::string m_identifier;
std::string m_password;
int m_port;
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
bool m_established;
bool m_connecting;
std::vector<char> m_data_buffer;
std::map<uint16, std::function<void(const EQ::Net::Packet &p)>> m_opcode_dispatch;
std::queue<EQ::Net::WritablePacket> m_packet_queue;
};
}
}

View File

@ -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<EQ::Timer>(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<EQ::Net::TCPConnection> 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);
}

View File

@ -0,0 +1,53 @@
#pragma once
#include "tcp_connection.h"
#include "../event/timer.h"
#include "servertalk_common.h"
#include "packet.h"
#include <sodium.h>
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<EQ::Timer> 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<EQ::Net::TCPConnection> m_connection;
std::vector<char> 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
};
}
}

View File

@ -0,0 +1,15 @@
#pragma once
namespace EQ
{
namespace Net
{
enum ServertalkPacketType
{
ServertalkClientHello = 1,
ServertalkServerHello,
ServertalkClientHandshake,
ServertalkMessage,
};
}
}

View File

@ -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<EQ::Net::TCPConnection> connection) {
m_unident_connections.push_back(std::make_shared<ServertalkServerConnection>(connection, this, m_encrypted));
});
}
void EQ::Net::ServertalkServer::OnConnectionIdentified(const std::string &type, std::function<void(std::shared_ptr<ServertalkServerConnection>)> cb)
{
m_on_ident.insert(std::make_pair(type, cb));
}
void EQ::Net::ServertalkServer::OnConnectionRemoved(const std::string &type, std::function<void(std::shared_ptr<ServertalkServerConnection>)> 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<std::shared_ptr<EQ::Net::ServertalkServerConnection>> 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;
}

View File

@ -0,0 +1,58 @@
#pragma once
#include "tcp_server.h"
#include "servertalk_server_connection.h"
#include <vector>
#include <map>
#ifdef ENABLE_SECURITY
#include <sodium.h>
#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<void(std::shared_ptr<ServertalkServerConnection>)> cb);
void OnConnectionRemoved(const std::string &type, std::function<void(std::shared_ptr<ServertalkServerConnection>)> cb);
private:
void ConnectionDisconnected(ServertalkServerConnection *conn);
void ConnectionIdentified(ServertalkServerConnection *conn);
bool CheckCredentials(const std::string &credentials);
std::unique_ptr<EQ::Net::TCPServer> m_server;
std::vector<std::shared_ptr<ServertalkServerConnection>> m_unident_connections;
std::map<std::string, std::vector<std::shared_ptr<ServertalkServerConnection>>> m_ident_connections;
std::map<std::string, std::function<void(std::shared_ptr<ServertalkServerConnection>)>> m_on_ident;
std::map<std::string, std::function<void(std::shared_ptr<ServertalkServerConnection>)>> m_on_disc;
bool m_encrypted;
std::string m_credentials;
friend class ServertalkServerConnection;
};
}
}

View File

@ -0,0 +1,196 @@
#include "servertalk_server_connection.h"
#include "servertalk_server.h"
#include "../eqemu_logsys.h"
EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> 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)
{
}

View File

@ -0,0 +1,51 @@
#pragma once
#include "tcp_connection.h"
#include "servertalk_common.h"
#include "packet.h"
#include <vector>
#include <sodium.h>
namespace EQ
{
namespace Net
{
class ServertalkServer;
class ServertalkServerConnection
{
public:
ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> 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<EQ::Net::TCPConnection> m_connection;
ServertalkServer *m_parent;
std::vector<char> 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
};
}
}

View File

@ -107,12 +107,17 @@ void EQ::Net::TCPConnection::OnDisconnect(std::function<void(TCPConnection*)> cb
void EQ::Net::TCPConnection::Disconnect()
{
if (m_socket) {
uv_close((uv_handle_t*)m_socket, on_close_handle);
m_socket = nullptr;
m_socket->data = this;
uv_close((uv_handle_t*)m_socket, [](uv_handle_t* handle) {
TCPConnection *connection = (TCPConnection*)handle->data;
if (m_on_disconnect_cb) {
m_on_disconnect_cb(this);
}
if (connection->m_on_disconnect_cb) {
connection->m_on_disconnect_cb(connection);
}
delete handle;
});
m_socket = nullptr;
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -34,6 +34,8 @@
#include <signal.h>
#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<EQ::Net::ServertalkServerConnection> conn) {
Log.Out(Logs::General, Logs::Debug, "New QueryServ Connection....");
});
server.OnConnectionRemoved("QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> 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();

View File

@ -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)

View File

@ -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)

View File

@ -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 <iostream>
#include <string>