diff --git a/CMakeLists.txt b/CMakeLists.txt index a055a8010..f85a589cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,16 +292,17 @@ ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL) #Find everything we need FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(MySQL REQUIRED) +FIND_PACKAGE(Protobuf REQUIRED) IF(EQEMU_BUILD_PERL) FIND_PACKAGE(PerlLibs REQUIRED) 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 recast_navigation) +SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} protobuf::libprotoc protobuf::libprotobuf libuv fmt recast_navigation) FIND_PACKAGE(Sodium REQUIRED) IF(SODIUM_FOUND) - OPTION(EQEMU_ENABLE_SECURITY "Use Encryption For TCP Connections" ON) + OPTION(EQEMU_ENABLE_SECURITY "Use Secure Loginserver Hashes" ON) IF(EQEMU_ENABLE_SECURITY) INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_INCLUDE_DIRS}") ADD_DEFINITIONS(-DENABLE_SECURITY) @@ -340,6 +341,7 @@ ENDIF(EQEMU_BUILD_LUA) INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}") INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}") +INCLUDE_DIRECTORIES(SYSTEM "${Protobuf_INCLUDE_DIRS}") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common/glm") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" ) @@ -347,6 +349,13 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/src") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/format") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/detour/include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/recast/include") +INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/common") + +IF(VCPKG_TARGET_TRIPLET) + MESSAGE(STATUS "Vcpkg Detected") + MESSAGE(STATUS "Setting protobuf import dir: ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include") + SET(Protobuf_IMPORT_DIRS "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include") +ENDIF() IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) ADD_SUBDIRECTORY(common) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 85ddf2c31..ba28f10f4 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -383,7 +383,12 @@ SOURCE_GROUP(Util FILES INCLUDE_DIRECTORIES(Patches SocketLib StackWalker TinyXML) -ADD_LIBRARY(common ${common_sources} ${common_headers}) +protobuf_generate_cpp(PROTO_TASK_SRCS PROTO_TASK_HDRS "${CMAKE_CURRENT_SOURCE_DIR}/proto/task.proto") + +ADD_LIBRARY(common + ${common_sources} ${common_headers} + ${PROTO_TASK_SRCS} ${PROTO_TASK_HDRS} +) IF(UNIX) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) diff --git a/common/net/packet.cpp b/common/net/packet.cpp index 63040a438..ffcdb7088 100644 --- a/common/net/packet.cpp +++ b/common/net/packet.cpp @@ -2,6 +2,7 @@ #include "endian.h" #include #include +#include void EQ::Net::Packet::PutInt8(size_t offset, int8_t value) { @@ -167,6 +168,23 @@ void EQ::Net::Packet::PutData(size_t offset, void *data, size_t length) memcpy(((char*)Data() + offset), data, length); } +void EQ::Net::Packet::PutProtobuf(size_t offset, const google::protobuf::Message *msg) +{ + auto length = msg->ByteSizeLong(); + + if (length == 0) { + return; + } + + if (Length() < offset + length) { + if (!Resize(offset + length)) { + throw std::out_of_range("Packet::PutProtobuf(), could not resize packet and would of written past the end."); + } + } + + msg->SerializeToArray((void*)((char*)Data() + offset), (int)length); +} + int8_t EQ::Net::Packet::GetInt8(size_t offset) const { if (Length() < offset + 1) { diff --git a/common/net/packet.h b/common/net/packet.h index 3dbf8effa..c3e3437ee 100644 --- a/common/net/packet.h +++ b/common/net/packet.h @@ -8,6 +8,14 @@ #include #include +namespace google +{ + namespace protobuf + { + class Message; + } +} + namespace EQ { namespace Net { class StaticPacket; @@ -65,6 +73,7 @@ namespace EQ { void PutCString(size_t offset, const char *str); void PutPacket(size_t offset, const Packet &p); void PutData(size_t offset, void *data, size_t length); + void PutProtobuf(size_t offset, const google::protobuf::Message *msg); int8_t GetInt8(size_t offset) const; int16_t GetInt16(size_t offset) const; @@ -79,6 +88,7 @@ namespace EQ { std::string GetString(size_t offset, size_t length) const; std::string GetCString(size_t offset) const; StaticPacket GetPacket(size_t offset, size_t length) const; + google::protobuf::Message* GetProtobuf(size_t offset); std::string ToString() const; std::string ToString(size_t line_length) const; diff --git a/common/net/servertalk_client_connection.cpp b/common/net/servertalk_client_connection.cpp index 230bb3700..29a15b6a4 100644 --- a/common/net/servertalk_client_connection.cpp +++ b/common/net/servertalk_client_connection.cpp @@ -22,43 +22,9 @@ EQ::Net::ServertalkClient::~ServertalkClient() void EQ::Net::ServertalkClient::Send(uint16_t opcode, const EQ::Net::Packet &p) { EQ::Net::DynamicPacket out; -#ifdef ENABLE_SECURITY - if (m_encrypted) { - auto idx = 0; - if (p.Length() == 0) { - DynamicPacket p; - p.PutInt8(0, 0); - - out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES); - out.PutUInt16(4, opcode); - - std::unique_ptr cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]); - - crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); - (*(uint64_t*)&m_nonce_ours[0])++; - out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES); - } - else { - out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES); - out.PutUInt16(4, opcode); - - std::unique_ptr cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]); - - crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); - (*(uint64_t*)&m_nonce_ours[0])++; - out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES); - } - } - else { - out.PutUInt32(0, p.Length()); - out.PutUInt16(4, opcode); - out.PutPacket(6, p); - } -#else out.PutUInt32(0, p.Length()); out.PutUInt16(4, opcode); out.PutPacket(6, p); -#endif InternalSend(ServertalkMessage, out); } @@ -200,51 +166,6 @@ void EQ::Net::ServertalkClient::ProcessReadBuffer() 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); - memset(m_shared_key, 0, crypto_box_BEFORENMBYTES); - 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(); - - if (m_on_connect_cb) { - m_on_connect_cb(this); - } - } - else { - LogF(Logs::General, Logs::Error, "Could not process hello, size != {0}", 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); - } - } - else { - SendHandshake(); - - if (m_on_connect_cb) { - m_on_connect_cb(this); - } - } - } - catch (std::exception &ex) { - LogF(Logs::General, Logs::Error, "Error parsing hello from server: {0}", ex.what()); - m_connection->Disconnect(); - - if (m_on_connect_cb) { - m_on_connect_cb(nullptr); - } - } -#else try { bool enc = p.GetInt8(0) == 1 ? true : false; @@ -271,7 +192,6 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p) m_on_connect_cb(nullptr); } } -#endif } void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p) @@ -281,45 +201,6 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p) auto opcode = p.GetUInt16(4); if (length > 0) { auto data = p.GetString(6, length); -#ifdef ENABLE_SECURITY - if (m_encrypted) { - size_t message_len = length - crypto_secretbox_MACBYTES; - std::unique_ptr decrypted_text(new unsigned char[message_len]); - if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key)) - { - LogF(Logs::General, Logs::Error, "Error decrypting message from server"); - (*(uint64_t*)&m_nonce_theirs[0])++; - return; - } - - EQ::Net::StaticPacket decrypted_packet(&decrypted_text[0], message_len); - - (*(uint64_t*)&m_nonce_theirs[0])++; - - auto cb = m_message_callbacks.find(opcode); - if (cb != m_message_callbacks.end()) { - cb->second(opcode, decrypted_packet); - } - - if (m_message_callback) { - m_message_callback(opcode, decrypted_packet); - } - } - else { - size_t message_len = length; - EQ::Net::StaticPacket packet(&data[0], message_len); - - auto cb = m_message_callbacks.find(opcode); - if (cb != m_message_callbacks.end()) { - cb->second(opcode, packet); - } - - if (m_message_callback) { - m_message_callback(opcode, packet); - } - } - -#else size_t message_len = length; EQ::Net::StaticPacket packet(&data[0], message_len); @@ -331,7 +212,6 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p) if (m_message_callback) { m_message_callback(opcode, packet); } -#endif } } catch (std::exception &ex) { @@ -342,46 +222,9 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p) void EQ::Net::ServertalkClient::SendHandshake(bool downgrade) { EQ::Net::DynamicPacket 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); - - 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); - - 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; - - std::unique_ptr signed_buffer(new unsigned char[cipher_length]); - std::unique_ptr data_buffer(new unsigned char[data_length]); - - memset(&data_buffer[0], 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[0], &data_buffer[0], data_length, m_nonce_ours, m_shared_key); - - (*(uint64_t*)&m_nonce_ours[0])++; - - handshake.PutData(crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, &signed_buffer[0], cipher_length); - } - else { - handshake.PutString(0, m_identifier); - handshake.PutString(m_identifier.length() + 1, m_credentials); - handshake.PutUInt8(m_identifier.length() + 1 + m_credentials.length(), 0); - } -#else handshake.PutString(0, m_identifier); handshake.PutString(m_identifier.length() + 1, m_credentials); handshake.PutUInt8(m_identifier.length() + 1 + m_credentials.length(), 0); -#endif if (downgrade) { InternalSend(ServertalkClientDowngradeSecurityHandshake, handshake); diff --git a/common/net/servertalk_client_connection.h b/common/net/servertalk_client_connection.h index ae2fbb58a..58260c938 100644 --- a/common/net/servertalk_client_connection.h +++ b/common/net/servertalk_client_connection.h @@ -4,9 +4,6 @@ #include "../event/timer.h" #include "servertalk_common.h" #include "packet.h" -#ifdef ENABLE_SECURITY -#include -#endif namespace EQ { @@ -53,17 +50,6 @@ namespace EQ std::unordered_map> m_message_callbacks; std::function m_message_callback; std::function m_on_connect_cb; - -#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_server.h b/common/net/servertalk_server.h index 67d64ef93..4d6bb6a7a 100644 --- a/common/net/servertalk_server.h +++ b/common/net/servertalk_server.h @@ -5,10 +5,6 @@ #include #include -#ifdef ENABLE_SECURITY -#include -#endif - namespace EQ { namespace Net @@ -22,13 +18,8 @@ namespace EQ std::string credentials; ServertalkServerOptions() { -#ifdef ENABLE_SECURITY - encrypted = true; - allow_downgrade = true; -#else encrypted = false; allow_downgrade = true; -#endif ipv6 = false; } }; diff --git a/common/net/servertalk_server_connection.cpp b/common/net/servertalk_server_connection.cpp index 0be34e5c7..991e2fd5f 100644 --- a/common/net/servertalk_server_connection.cpp +++ b/common/net/servertalk_server_connection.cpp @@ -22,40 +22,9 @@ EQ::Net::ServertalkServerConnection::~ServertalkServerConnection() void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, const EQ::Net::Packet & p) { EQ::Net::DynamicPacket out; -#ifdef ENABLE_SECURITY - if (m_encrypted) { - if (p.Length() == 0) { - DynamicPacket p; - p.PutUInt8(0, 0); - - out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES); - out.PutUInt16(4, opcode); - - std::unique_ptr cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]); - crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); - (*(uint64_t*)&m_nonce_ours[0])++; - out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES); - } - else { - out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES); - out.PutUInt16(4, opcode); - - std::unique_ptr cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]); - crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); - (*(uint64_t*)&m_nonce_ours[0])++; - out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES); - } - } - else { - out.PutUInt32(0, p.Length()); - out.PutUInt16(4, opcode); - out.PutPacket(6, p); - } -#else out.PutUInt32(0, p.Length()); out.PutUInt16(4, opcode); out.PutPacket(6, p); -#endif InternalSend(ServertalkMessage, out); } @@ -165,29 +134,7 @@ void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c) void EQ::Net::ServertalkServerConnection::SendHello() { EQ::Net::DynamicPacket 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); } @@ -209,69 +156,6 @@ void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, bool downgrade_security) { -#ifdef ENABLE_SECURITY - if (downgrade_security && m_allow_downgrade && m_encrypted) { - LogF(Logs::General, Logs::TCP_Connection, "Downgraded encrypted connection to plaintext because otherside didn't support encryption {0}:{1}", - m_connection->RemoteIP(), m_connection->RemotePort()); - m_encrypted = false; - } - - 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; - std::unique_ptr decrypted_text(new unsigned char[message_len]); - - if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)p.Data() + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, cipher_len, m_nonce_theirs, m_shared_key)) - { - LogF(Logs::General, Logs::Error, "Error decrypting handshake from client, dropping connection."); - m_connection->Disconnect(); - return; - } - - m_identifier = (const char*)&decrypted_text[0]; - std::string credentials = (const char*)&decrypted_text[0] + (m_identifier.length() + 1); - - if (!m_parent->CheckCredentials(credentials)) { - LogF(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])++; - } - } - catch (std::exception &ex) { - LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what()); - m_connection->Disconnect(); - } - } - else { - try { - m_identifier = p.GetCString(0); - auto credentials = p.GetCString(m_identifier.length() + 1); - - if (!m_parent->CheckCredentials(credentials)) { - LogF(Logs::General, Logs::Error, "Got incoming connection with invalid credentials during handshake, dropping connection."); - m_connection->Disconnect(); - return; - } - - m_parent->ConnectionIdentified(this); - } - catch (std::exception &ex) { - LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what()); - m_connection->Disconnect(); - } - } -#else try { m_identifier = p.GetCString(0); auto credentials = p.GetCString(m_identifier.length() + 1); @@ -288,7 +172,6 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what()); m_connection->Disconnect(); } -#endif } void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p) @@ -298,46 +181,6 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p) auto opcode = p.GetUInt16(4); if (length > 0) { auto data = p.GetString(6, length); -#ifdef ENABLE_SECURITY - if (m_encrypted) { - size_t message_len = length - crypto_secretbox_MACBYTES; - std::unique_ptr decrypted_text(new unsigned char[message_len]); - - if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key)) - { - LogF(Logs::General, Logs::Error, "Error decrypting message from client"); - (*(uint64_t*)&m_nonce_theirs[0])++; - return; - } - - EQ::Net::StaticPacket decrypted_packet(&decrypted_text[0], message_len); - - (*(uint64_t*)&m_nonce_theirs[0])++; - - auto cb = m_message_callbacks.find(opcode); - if (cb != m_message_callbacks.end()) { - cb->second(opcode, decrypted_packet); - } - - if (m_message_callback) { - m_message_callback(opcode, decrypted_packet); - } - } - else { - size_t message_len = length; - EQ::Net::StaticPacket packet(&data[0], message_len); - - auto cb = m_message_callbacks.find(opcode); - if (cb != m_message_callbacks.end()) { - cb->second(opcode, packet); - } - - if (m_message_callback) { - m_message_callback(opcode, packet); - } - } - -#else size_t message_len = length; EQ::Net::StaticPacket packet(&data[0], message_len); @@ -349,7 +192,6 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p) if (m_message_callback) { m_message_callback(opcode, packet); } -#endif } } catch (std::exception &ex) { diff --git a/common/net/servertalk_server_connection.h b/common/net/servertalk_server_connection.h index a637f0946..3907a4328 100644 --- a/common/net/servertalk_server_connection.h +++ b/common/net/servertalk_server_connection.h @@ -4,9 +4,6 @@ #include "servertalk_common.h" #include "packet.h" #include -#ifdef ENABLE_SECURITY -#include -#endif namespace EQ { @@ -48,16 +45,6 @@ namespace EQ bool m_encrypted; bool m_allow_downgrade; -#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/proto/task.proto b/common/proto/task.proto new file mode 100644 index 000000000..e4bb26720 --- /dev/null +++ b/common/proto/task.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +import "google/protobuf/any.proto"; + +package EQ.Proto; + +message TaskMessage { + int32 message = 1; + google.protobuf.Any details = 2; +} + +message ClientTaskStateRequest { + int32 client_id = 1; +} + +message ClientTaskStateResponse { + int32 client_id = 1; +} + diff --git a/common/servertalk.h b/common/servertalk.h index 884c9d114..f1e3a282c 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -1341,42 +1341,15 @@ struct ServerSharedTaskMember_Struct { // used for various things we just need t #define TASKJOINOOZ_LEVEL 3 #define TASKJOINOOZ_TIMER 4 -#pragma pack() - /* * Routing */ struct RouteToMessage { - std::string filter; - std::string identifier; - std::string id; - size_t payload_size; - - template - void serialize(Archive &ar) - { - ar(filter, identifier, id, payload_size); - } + char filter[32]; + char identifier[32]; + char id[32]; }; -/* - * Tasks - */ - -enum TaskMessageTypes -{ - TaskGetClientTaskState = 1 -}; - -struct GetClientTaskStateRequest -{ - uint32 client_id; - - template - void serialize(Archive &ar) - { - ar(client_id); - } -}; +#pragma pack() diff --git a/common/service.cpp b/common/service.cpp index 16d3e3a6f..e4c22758f 100644 --- a/common/service.cpp +++ b/common/service.cpp @@ -49,6 +49,7 @@ void EQ::Service::Run() auto now = std::chrono::steady_clock::now(); auto time_since = std::chrono::duration_cast>(now - _impl->last_time); OnHeartbeat(time_since.count()); + _impl->last_time = now; })); auto &loop = EQ::EventLoop::Get(); diff --git a/common/world_connection.cpp b/common/world_connection.cpp index 1197bfc0e..61c5a5301 100644 --- a/common/world_connection.cpp +++ b/common/world_connection.cpp @@ -45,15 +45,15 @@ void EQ::WorldConnection::RouteMessage(const std::string &filter, const std::str auto identifier = m_connection->GetIdentifier(); RouteToMessage msg; - msg.filter = filter; - msg.identifier = identifier; - msg.id = id; - msg.payload_size = payload.Length(); + strn0cpy(msg.filter, filter.c_str(), 32); + strn0cpy(msg.identifier, identifier.c_str(), 32); + strn0cpy(msg.id, id.c_str(), 32); EQ::Net::DynamicPacket out; - out.PutSerialize(0, msg); - out.PutPacket(out.Length(), payload); - + out.Reserve(sizeof(RouteToMessage) + payload.Length()); + out.PutData(0, &msg, sizeof(RouteToMessage)); + out.PutPacket(sizeof(RouteToMessage), payload); + m_connection->Send(ServerOP_RouteTo, out); } @@ -67,10 +67,9 @@ void EQ::WorldConnection::_HandleMessage(uint16 opcode, const EQ::Net::Packet &p void EQ::WorldConnection::_HandleRoutedMessage(uint16 opcode, const EQ::Net::Packet &p) { if (m_on_routed_message) { - auto msg = p.GetSerialize(0); - auto payload_offset = p.Length() - msg.payload_size; - auto payload = p.GetPacket(payload_offset, msg.payload_size); + auto msg = (RouteToMessage*)p.Data(); + auto payload = p.GetPacket(sizeof(RouteToMessage), p.Length() - sizeof(RouteToMessage)); - m_on_routed_message(msg.filter, msg.identifier, msg.id, payload); + m_on_routed_message(msg->filter, msg->identifier, msg->id, payload); } } diff --git a/services/tasks/tasks_service.cpp b/services/tasks/tasks_service.cpp index 3ca180707..fcf6c4572 100644 --- a/services/tasks/tasks_service.cpp +++ b/services/tasks/tasks_service.cpp @@ -50,19 +50,21 @@ void EQ::TasksService::OnHeartbeat(double time_since_last) { void EQ::TasksService::OnRoutedMessage(const std::string& filter, const std::string& identifier, const std::string& id, const EQ::Net::Packet& payload) { - auto msg_type = payload.GetInt32(0); + LogF(Logs::General, Logs::Status, "On routed message with payload size {0}", payload.Length()); - switch (msg_type) { - case TaskGetClientTaskState: - { - Log(Logs::General, Logs::Status, "Task state request"); - auto req = payload.GetSerialize(4); - //Get the task state request - break; - } - default: - break; - } + //auto msg_type = payload.GetInt32(0); + // + //switch (msg_type) { + //case TaskGetClientTaskState: + //{ + // Log(Logs::General, Logs::Status, "Task state request"); + // auto req = payload.GetSerialize(4); + // //Get the task state request + // break; + //} + //default: + // break; + //} } EQRegisterService(EQ::TasksService); diff --git a/services/test1/CMakeLists.txt b/services/test1/CMakeLists.txt new file mode 100644 index 000000000..7369cb2c6 --- /dev/null +++ b/services/test1/CMakeLists.txt @@ -0,0 +1,17 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(service_sources + test1_service.cpp +) + +SET(service_headers + test1_service.h +) + +ADD_EXECUTABLE(test1_service ${service_sources} ${service_headers}) + +INSTALL(TARGETS test1_service RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + +TARGET_LINK_LIBRARIES(test1_service ${SERVER_LIBS}) + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/services/test1/test1_service.cpp b/services/test1/test1_service.cpp new file mode 100644 index 000000000..38f3c9331 --- /dev/null +++ b/services/test1/test1_service.cpp @@ -0,0 +1,61 @@ +#include "test1_service.h" +#include "../../common/eqemu_logsys.h" +#include "../../common/eqemu_config.h" + +EQ::Test1Service::Test1Service() + : EQ::Service("Test1", 1, 1) +{ + +} + +struct TestPacket +{ + int64_t f1; + int64_t f2; + int64_t f3; + int64_t f4; + int64_t f5; + int64_t f6; + int64_t f7; + char f8[4092]; + + template + void serialize(Archive &ar) + { + ar(f1, f2, f3, f4, f5, f6, f7, f8); + } +}; + +EQ::Test1Service::~Test1Service() { + +} + +void EQ::Test1Service::OnStart() { + +} + +void EQ::Test1Service::OnStop() { +} + +void EQ::Test1Service::OnHeartbeat(double time_since_last) { + TestPacket p; + p.f1 = 33; + p.f2 = 43; + p.f3 = 56; + p.f4 = 90; + + EQ::Net::DynamicPacket out; + out.PutInt32(0, 1234); + out.PutSerialize(4, p); + + for (int i = 0; i < 250; ++i) { + RouteMessage("Test2", "", out); + } +} + +void EQ::Test1Service::OnRoutedMessage(const std::string& filter, const std::string& identifier, const std::string& id, const EQ::Net::Packet& payload) +{ + +} + +EQRegisterService(EQ::Test1Service); diff --git a/services/test1/test1_service.h b/services/test1/test1_service.h new file mode 100644 index 000000000..15d98e5b1 --- /dev/null +++ b/services/test1/test1_service.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../../common/service.h" + +namespace EQ +{ + class Test1Service : public EQ::Service + { + public: + Test1Service(); + virtual ~Test1Service(); + + protected: + virtual void OnStart(); + virtual void OnStop(); + virtual void OnHeartbeat(double time_since_last); + virtual void OnRoutedMessage(const std::string& filter, const std::string& identifier, const std::string& id, const EQ::Net::Packet& payload); + }; +} diff --git a/services/test2/CMakeLists.txt b/services/test2/CMakeLists.txt new file mode 100644 index 000000000..8c8773998 --- /dev/null +++ b/services/test2/CMakeLists.txt @@ -0,0 +1,17 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(service_sources + test2_service.cpp +) + +SET(service_headers + test2_service.h +) + +ADD_EXECUTABLE(test2_service ${service_sources} ${service_headers}) + +INSTALL(TARGETS test2_service RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + +TARGET_LINK_LIBRARIES(test2_service ${SERVER_LIBS}) + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/services/test2/test2_service.cpp b/services/test2/test2_service.cpp new file mode 100644 index 000000000..f50e5a2a3 --- /dev/null +++ b/services/test2/test2_service.cpp @@ -0,0 +1,40 @@ +#include "test2_service.h" +#include "../../common/eqemu_logsys.h" +#include "../../common/eqemu_config.h" + +EQ::Test2Service::Test2Service() + : EQ::Service("Test2", 3000, 1) +{ + +} + +EQ::Test2Service::~Test2Service() { + +} + +void EQ::Test2Service::OnStart() { + bytes = 0; + packets = 0; +} + +void EQ::Test2Service::OnStop() { +} + +void EQ::Test2Service::OnHeartbeat(double time_since_last) { + + auto bytes_per_sec = bytes / time_since_last; + auto packets_per_sec = packets / time_since_last; + printf("Transfer rate %.2f KB/sec %.2f Packets/sec\n", bytes_per_sec / 1000.0, packets_per_sec); + + bytes = 0; + packets = 0; +} + +void EQ::Test2Service::OnRoutedMessage(const std::string& filter, const std::string& identifier, const std::string& id, const EQ::Net::Packet& payload) +{ + bytes += sizeof(RouteToMessage); + bytes += payload.Length(); + packets++; +} + +EQRegisterService(EQ::Test2Service); diff --git a/services/test2/test2_service.h b/services/test2/test2_service.h new file mode 100644 index 000000000..4a358c7ad --- /dev/null +++ b/services/test2/test2_service.h @@ -0,0 +1,23 @@ +#pragma once + +#include "../../common/service.h" + +namespace EQ +{ + class Test2Service : public EQ::Service + { + public: + Test2Service(); + virtual ~Test2Service(); + + protected: + virtual void OnStart(); + virtual void OnStop(); + virtual void OnHeartbeat(double time_since_last); + virtual void OnRoutedMessage(const std::string& filter, const std::string& identifier, const std::string& id, const EQ::Net::Packet& payload); + + private: + size_t bytes; + size_t packets; + }; +} diff --git a/world/router.cpp b/world/router.cpp index 1f9d77eb0..8840d5578 100644 --- a/world/router.cpp +++ b/world/router.cpp @@ -1,5 +1,5 @@ #include "router.h" -#include +#include "../common/string_util.h" Router::Router() { @@ -30,55 +30,44 @@ void Router::RemoveConnection(std::shared_ptr connection, uint16 opcode, const EQ::Net::Packet &p) { - auto msg = p.GetSerialize(0); - auto payload_offset = p.Length() - msg.payload_size; - auto payload = p.GetPacket(payload_offset, msg.payload_size); + auto msg = (RouteToMessage*)p.Data(); + char to_id[32]; + strn0cpy(to_id, msg->id, 32); - auto out_msg = msg; - out_msg.identifier = connection->GetIdentifier(); - out_msg.id = connection->GetUUID(); + strn0cpy(msg->id, connection->GetUUID().c_str(), 32); - EQ::Net::DynamicPacket out; - out.PutSerialize(0, out_msg); - out.PutPacket(out.Length(), payload); - - if (!msg.id.empty() && !msg.filter.empty()) { - auto id_regex = std::regex(msg.id); - auto filter_regex = std::regex(msg.filter); + if (to_id[0] != '\0' && msg->filter[0] != '\0') { for (auto &connection : m_connections) { auto id = connection->GetUUID(); auto identifier = connection->GetIdentifier(); - if (std::regex_match(id, id_regex)) { - connection->Send(ServerOP_RouteTo, out); + if (strcmp(to_id, id.c_str()) == 0) { + connection->Send(ServerOP_RouteTo, p); } - else if (std::regex_match(identifier, filter_regex)) { - connection->Send(ServerOP_RouteTo, out); + else if (strcmp(msg->filter, identifier.c_str()) == 0) { + connection->Send(ServerOP_RouteTo, p); } } } - else if (!msg.id.empty()) { - auto id_regex = std::regex(msg.id); - - for (auto &connection : m_connections) { - auto id = connection->GetUUID(); - if (std::regex_match(id, id_regex)) { - connection->Send(ServerOP_RouteTo, out); - } - } - } else if (!msg.filter.empty()) { - auto filter_regex = std::regex(msg.filter); - + else if (msg->filter[0] != '\0') { for (auto &connection : m_connections) { auto identifier = connection->GetIdentifier(); - if (std::regex_match(identifier, filter_regex)) { - connection->Send(ServerOP_RouteTo, out); + if (strcmp(msg->filter, identifier.c_str()) == 0) { + connection->Send(ServerOP_RouteTo, p); + } + } + } + else if (to_id[0] != '\0') { + for (auto &connection : m_connections) { + auto id = connection->GetUUID(); + if (strcmp(to_id, id.c_str()) == 0) { + connection->Send(ServerOP_RouteTo, p); } } } else { for (auto &connection : m_connections) { - connection->Send(ServerOP_RouteTo, out); + connection->Send(ServerOP_RouteTo, p); } } } diff --git a/zone/command.cpp b/zone/command.cpp index c4b819633..ed72624bb 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -39,6 +39,8 @@ #include #include +#include + #ifdef _WINDOWS #define strcasecmp _stricmp #endif @@ -2831,9 +2833,12 @@ void command_spawn(Client *c, const Seperator *sep) void command_test(Client *c, const Seperator *sep) { + EQ::Proto::ClientTaskStateRequest req; + req.set_client_id(123); + EQ::Net::DynamicPacket p; - p.PutInt32(0, 1234); - p.PutCString(p.Length(), "TestPacket"); + p.PutProtobuf(0, &req); + worldserver.RouteMessage("Tasks", "", p); //c->Message(15, "Triggering test command"); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index a92d7151c..6ddf4f7d8 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -471,14 +471,14 @@ bool TaskManager::SaveClientState(Client *c, ClientTaskState *state) } void Client::LoadClientTaskState() { - GetClientTaskStateRequest req; - req.client_id = CharacterID(); - - EQ::Net::DynamicPacket p; - p.PutInt32(0, TaskGetClientTaskState); - p.PutSerialize(4, req); - - worldserver.RouteMessage("Tasks", "", p); + //GetClientTaskStateRequest req; + //req.client_id = CharacterID(); + // + //EQ::Net::DynamicPacket p; + //p.PutInt32(0, TaskGetClientTaskState); + //p.PutSerialize(4, req); + // + //worldserver.RouteMessage("Tasks", "", p); } void Client::RemoveClientTaskState() {