mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-01 09:12:25 +00:00
Integrating protobuffers
This commit is contained in:
parent
0b26c80d8f
commit
b9b2bf0477
@ -292,16 +292,17 @@ ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
|
|||||||
#Find everything we need
|
#Find everything we need
|
||||||
FIND_PACKAGE(ZLIB REQUIRED)
|
FIND_PACKAGE(ZLIB REQUIRED)
|
||||||
FIND_PACKAGE(MySQL REQUIRED)
|
FIND_PACKAGE(MySQL REQUIRED)
|
||||||
|
FIND_PACKAGE(Protobuf REQUIRED)
|
||||||
IF(EQEMU_BUILD_PERL)
|
IF(EQEMU_BUILD_PERL)
|
||||||
FIND_PACKAGE(PerlLibs REQUIRED)
|
FIND_PACKAGE(PerlLibs REQUIRED)
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||||
ENDIF(EQEMU_BUILD_PERL)
|
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)
|
FIND_PACKAGE(Sodium REQUIRED)
|
||||||
IF(SODIUM_FOUND)
|
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)
|
IF(EQEMU_ENABLE_SECURITY)
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_INCLUDE_DIRS}")
|
INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_INCLUDE_DIRS}")
|
||||||
ADD_DEFINITIONS(-DENABLE_SECURITY)
|
ADD_DEFINITIONS(-DENABLE_SECURITY)
|
||||||
@ -340,6 +341,7 @@ ENDIF(EQEMU_BUILD_LUA)
|
|||||||
|
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
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}/common/glm")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
|
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" )
|
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/format")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/detour/include")
|
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_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)
|
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||||
ADD_SUBDIRECTORY(common)
|
ADD_SUBDIRECTORY(common)
|
||||||
|
|||||||
@ -383,7 +383,12 @@ SOURCE_GROUP(Util FILES
|
|||||||
|
|
||||||
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker TinyXML)
|
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)
|
IF(UNIX)
|
||||||
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
|
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "endian.h"
|
#include "endian.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
|
||||||
void EQ::Net::Packet::PutInt8(size_t offset, int8_t value)
|
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);
|
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
|
int8_t EQ::Net::Packet::GetInt8(size_t offset) const
|
||||||
{
|
{
|
||||||
if (Length() < offset + 1) {
|
if (Length() < offset + 1) {
|
||||||
|
|||||||
@ -8,6 +8,14 @@
|
|||||||
#include <cereal/cereal.hpp>
|
#include <cereal/cereal.hpp>
|
||||||
#include <cereal/archives/binary.hpp>
|
#include <cereal/archives/binary.hpp>
|
||||||
|
|
||||||
|
namespace google
|
||||||
|
{
|
||||||
|
namespace protobuf
|
||||||
|
{
|
||||||
|
class Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace EQ {
|
namespace EQ {
|
||||||
namespace Net {
|
namespace Net {
|
||||||
class StaticPacket;
|
class StaticPacket;
|
||||||
@ -65,6 +73,7 @@ namespace EQ {
|
|||||||
void PutCString(size_t offset, const char *str);
|
void PutCString(size_t offset, const char *str);
|
||||||
void PutPacket(size_t offset, const Packet &p);
|
void PutPacket(size_t offset, const Packet &p);
|
||||||
void PutData(size_t offset, void *data, size_t length);
|
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;
|
int8_t GetInt8(size_t offset) const;
|
||||||
int16_t GetInt16(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 GetString(size_t offset, size_t length) const;
|
||||||
std::string GetCString(size_t offset) const;
|
std::string GetCString(size_t offset) const;
|
||||||
StaticPacket GetPacket(size_t offset, size_t length) const;
|
StaticPacket GetPacket(size_t offset, size_t length) const;
|
||||||
|
google::protobuf::Message* GetProtobuf(size_t offset);
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
std::string ToString(size_t line_length) const;
|
std::string ToString(size_t line_length) const;
|
||||||
|
|||||||
@ -22,43 +22,9 @@ EQ::Net::ServertalkClient::~ServertalkClient()
|
|||||||
void EQ::Net::ServertalkClient::Send(uint16_t opcode, const EQ::Net::Packet &p)
|
void EQ::Net::ServertalkClient::Send(uint16_t opcode, const EQ::Net::Packet &p)
|
||||||
{
|
{
|
||||||
EQ::Net::DynamicPacket out;
|
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<unsigned char[]> 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<unsigned char[]> 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.PutUInt32(0, p.Length());
|
||||||
out.PutUInt16(4, opcode);
|
out.PutUInt16(4, opcode);
|
||||||
out.PutPacket(6, p);
|
out.PutPacket(6, p);
|
||||||
#endif
|
|
||||||
InternalSend(ServertalkMessage, out);
|
InternalSend(ServertalkMessage, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,51 +166,6 @@ void EQ::Net::ServertalkClient::ProcessReadBuffer()
|
|||||||
|
|
||||||
void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
|
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 {
|
try {
|
||||||
bool enc = p.GetInt8(0) == 1 ? true : false;
|
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);
|
m_on_connect_cb(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
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);
|
auto opcode = p.GetUInt16(4);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
auto data = p.GetString(6, length);
|
auto data = p.GetString(6, length);
|
||||||
#ifdef ENABLE_SECURITY
|
|
||||||
if (m_encrypted) {
|
|
||||||
size_t message_len = length - crypto_secretbox_MACBYTES;
|
|
||||||
std::unique_ptr<unsigned char[]> 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;
|
size_t message_len = length;
|
||||||
EQ::Net::StaticPacket packet(&data[0], message_len);
|
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) {
|
if (m_message_callback) {
|
||||||
m_message_callback(opcode, packet);
|
m_message_callback(opcode, packet);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
@ -342,46 +222,9 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
|||||||
void EQ::Net::ServertalkClient::SendHandshake(bool downgrade)
|
void EQ::Net::ServertalkClient::SendHandshake(bool downgrade)
|
||||||
{
|
{
|
||||||
EQ::Net::DynamicPacket handshake;
|
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<unsigned char[]> signed_buffer(new unsigned char[cipher_length]);
|
|
||||||
std::unique_ptr<unsigned char[]> 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(0, m_identifier);
|
||||||
handshake.PutString(m_identifier.length() + 1, m_credentials);
|
handshake.PutString(m_identifier.length() + 1, m_credentials);
|
||||||
handshake.PutUInt8(m_identifier.length() + 1 + m_credentials.length(), 0);
|
handshake.PutUInt8(m_identifier.length() + 1 + m_credentials.length(), 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (downgrade) {
|
if (downgrade) {
|
||||||
InternalSend(ServertalkClientDowngradeSecurityHandshake, handshake);
|
InternalSend(ServertalkClientDowngradeSecurityHandshake, handshake);
|
||||||
|
|||||||
@ -4,9 +4,6 @@
|
|||||||
#include "../event/timer.h"
|
#include "../event/timer.h"
|
||||||
#include "servertalk_common.h"
|
#include "servertalk_common.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#ifdef ENABLE_SECURITY
|
|
||||||
#include <sodium.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
{
|
{
|
||||||
@ -53,17 +50,6 @@ namespace EQ
|
|||||||
std::unordered_map<uint16_t, std::function<void(uint16_t, EQ::Net::Packet&)>> m_message_callbacks;
|
std::unordered_map<uint16_t, std::function<void(uint16_t, EQ::Net::Packet&)>> m_message_callbacks;
|
||||||
std::function<void(uint16_t, EQ::Net::Packet&)> m_message_callback;
|
std::function<void(uint16_t, EQ::Net::Packet&)> m_message_callback;
|
||||||
std::function<void(ServertalkClient*)> m_on_connect_cb;
|
std::function<void(ServertalkClient*)> 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
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#ifdef ENABLE_SECURITY
|
|
||||||
#include <sodium.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
{
|
{
|
||||||
namespace Net
|
namespace Net
|
||||||
@ -22,13 +18,8 @@ namespace EQ
|
|||||||
std::string credentials;
|
std::string credentials;
|
||||||
|
|
||||||
ServertalkServerOptions() {
|
ServertalkServerOptions() {
|
||||||
#ifdef ENABLE_SECURITY
|
|
||||||
encrypted = true;
|
|
||||||
allow_downgrade = true;
|
|
||||||
#else
|
|
||||||
encrypted = false;
|
encrypted = false;
|
||||||
allow_downgrade = true;
|
allow_downgrade = true;
|
||||||
#endif
|
|
||||||
ipv6 = false;
|
ipv6 = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,40 +22,9 @@ EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
|
|||||||
void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, const EQ::Net::Packet & p)
|
void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, const EQ::Net::Packet & p)
|
||||||
{
|
{
|
||||||
EQ::Net::DynamicPacket out;
|
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<unsigned char[]> 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<unsigned char[]> 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.PutUInt32(0, p.Length());
|
||||||
out.PutUInt16(4, opcode);
|
out.PutUInt16(4, opcode);
|
||||||
out.PutPacket(6, p);
|
out.PutPacket(6, p);
|
||||||
#endif
|
|
||||||
InternalSend(ServertalkMessage, out);
|
InternalSend(ServertalkMessage, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,29 +134,7 @@ void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c)
|
|||||||
void EQ::Net::ServertalkServerConnection::SendHello()
|
void EQ::Net::ServertalkServerConnection::SendHello()
|
||||||
{
|
{
|
||||||
EQ::Net::DynamicPacket hello;
|
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);
|
hello.PutInt8(0, 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
InternalSend(ServertalkServerHello, hello);
|
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)
|
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<unsigned char[]> 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 {
|
try {
|
||||||
m_identifier = p.GetCString(0);
|
m_identifier = p.GetCString(0);
|
||||||
auto credentials = p.GetCString(m_identifier.length() + 1);
|
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());
|
LogF(Logs::General, Logs::Error, "Error parsing handshake from client: {0}", ex.what());
|
||||||
m_connection->Disconnect();
|
m_connection->Disconnect();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
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);
|
auto opcode = p.GetUInt16(4);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
auto data = p.GetString(6, length);
|
auto data = p.GetString(6, length);
|
||||||
#ifdef ENABLE_SECURITY
|
|
||||||
if (m_encrypted) {
|
|
||||||
size_t message_len = length - crypto_secretbox_MACBYTES;
|
|
||||||
std::unique_ptr<unsigned char[]> 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;
|
size_t message_len = length;
|
||||||
EQ::Net::StaticPacket packet(&data[0], message_len);
|
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) {
|
if (m_message_callback) {
|
||||||
m_message_callback(opcode, packet);
|
m_message_callback(opcode, packet);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
|
|||||||
@ -4,9 +4,6 @@
|
|||||||
#include "servertalk_common.h"
|
#include "servertalk_common.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#ifdef ENABLE_SECURITY
|
|
||||||
#include <sodium.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
{
|
{
|
||||||
@ -48,16 +45,6 @@ namespace EQ
|
|||||||
|
|
||||||
bool m_encrypted;
|
bool m_encrypted;
|
||||||
bool m_allow_downgrade;
|
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
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
common/proto/task.proto
Normal file
18
common/proto/task.proto
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1341,42 +1341,15 @@ struct ServerSharedTaskMember_Struct { // used for various things we just need t
|
|||||||
#define TASKJOINOOZ_LEVEL 3
|
#define TASKJOINOOZ_LEVEL 3
|
||||||
#define TASKJOINOOZ_TIMER 4
|
#define TASKJOINOOZ_TIMER 4
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routing
|
* Routing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct RouteToMessage
|
struct RouteToMessage
|
||||||
{
|
{
|
||||||
std::string filter;
|
char filter[32];
|
||||||
std::string identifier;
|
char identifier[32];
|
||||||
std::string id;
|
char id[32];
|
||||||
size_t payload_size;
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(filter, identifier, id, payload_size);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
#pragma pack()
|
||||||
* Tasks
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum TaskMessageTypes
|
|
||||||
{
|
|
||||||
TaskGetClientTaskState = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GetClientTaskStateRequest
|
|
||||||
{
|
|
||||||
uint32 client_id;
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
void serialize(Archive &ar)
|
|
||||||
{
|
|
||||||
ar(client_id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@ -49,6 +49,7 @@ void EQ::Service::Run()
|
|||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
auto time_since = std::chrono::duration_cast<std::chrono::duration<double>>(now - _impl->last_time);
|
auto time_since = std::chrono::duration_cast<std::chrono::duration<double>>(now - _impl->last_time);
|
||||||
OnHeartbeat(time_since.count());
|
OnHeartbeat(time_since.count());
|
||||||
|
_impl->last_time = now;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
auto &loop = EQ::EventLoop::Get();
|
auto &loop = EQ::EventLoop::Get();
|
||||||
|
|||||||
@ -45,15 +45,15 @@ void EQ::WorldConnection::RouteMessage(const std::string &filter, const std::str
|
|||||||
auto identifier = m_connection->GetIdentifier();
|
auto identifier = m_connection->GetIdentifier();
|
||||||
|
|
||||||
RouteToMessage msg;
|
RouteToMessage msg;
|
||||||
msg.filter = filter;
|
strn0cpy(msg.filter, filter.c_str(), 32);
|
||||||
msg.identifier = identifier;
|
strn0cpy(msg.identifier, identifier.c_str(), 32);
|
||||||
msg.id = id;
|
strn0cpy(msg.id, id.c_str(), 32);
|
||||||
msg.payload_size = payload.Length();
|
|
||||||
|
|
||||||
EQ::Net::DynamicPacket out;
|
EQ::Net::DynamicPacket out;
|
||||||
out.PutSerialize(0, msg);
|
out.Reserve(sizeof(RouteToMessage) + payload.Length());
|
||||||
out.PutPacket(out.Length(), payload);
|
out.PutData(0, &msg, sizeof(RouteToMessage));
|
||||||
|
out.PutPacket(sizeof(RouteToMessage), payload);
|
||||||
|
|
||||||
m_connection->Send(ServerOP_RouteTo, out);
|
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)
|
void EQ::WorldConnection::_HandleRoutedMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||||
{
|
{
|
||||||
if (m_on_routed_message) {
|
if (m_on_routed_message) {
|
||||||
auto msg = p.GetSerialize<RouteToMessage>(0);
|
auto msg = (RouteToMessage*)p.Data();
|
||||||
auto payload_offset = p.Length() - msg.payload_size;
|
auto payload = p.GetPacket(sizeof(RouteToMessage), p.Length() - sizeof(RouteToMessage));
|
||||||
auto payload = p.GetPacket(payload_offset, msg.payload_size);
|
|
||||||
|
|
||||||
m_on_routed_message(msg.filter, msg.identifier, msg.id, payload);
|
m_on_routed_message(msg->filter, msg->identifier, msg->id, payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
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) {
|
//auto msg_type = payload.GetInt32(0);
|
||||||
case TaskGetClientTaskState:
|
//
|
||||||
{
|
//switch (msg_type) {
|
||||||
Log(Logs::General, Logs::Status, "Task state request");
|
//case TaskGetClientTaskState:
|
||||||
auto req = payload.GetSerialize<GetClientTaskStateRequest>(4);
|
//{
|
||||||
//Get the task state request
|
// Log(Logs::General, Logs::Status, "Task state request");
|
||||||
break;
|
// auto req = payload.GetSerialize<GetClientTaskStateRequest>(4);
|
||||||
}
|
// //Get the task state request
|
||||||
default:
|
// break;
|
||||||
break;
|
//}
|
||||||
}
|
//default:
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQRegisterService(EQ::TasksService);
|
EQRegisterService(EQ::TasksService);
|
||||||
|
|||||||
17
services/test1/CMakeLists.txt
Normal file
17
services/test1/CMakeLists.txt
Normal file
@ -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)
|
||||||
61
services/test1/test1_service.cpp
Normal file
61
services/test1/test1_service.cpp
Normal file
@ -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 <class Archive>
|
||||||
|
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);
|
||||||
19
services/test1/test1_service.h
Normal file
19
services/test1/test1_service.h
Normal file
@ -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);
|
||||||
|
};
|
||||||
|
}
|
||||||
17
services/test2/CMakeLists.txt
Normal file
17
services/test2/CMakeLists.txt
Normal file
@ -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)
|
||||||
40
services/test2/test2_service.cpp
Normal file
40
services/test2/test2_service.cpp
Normal file
@ -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);
|
||||||
23
services/test2/test2_service.h
Normal file
23
services/test2/test2_service.h
Normal file
@ -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;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#include "router.h"
|
#include "router.h"
|
||||||
#include <regex>
|
#include "../common/string_util.h"
|
||||||
|
|
||||||
Router::Router()
|
Router::Router()
|
||||||
{
|
{
|
||||||
@ -30,55 +30,44 @@ void Router::RemoveConnection(std::shared_ptr<EQ::Net::ServertalkServerConnectio
|
|||||||
|
|
||||||
void Router::OnRouterMessage(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, uint16 opcode, const EQ::Net::Packet &p)
|
void Router::OnRouterMessage(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, uint16 opcode, const EQ::Net::Packet &p)
|
||||||
{
|
{
|
||||||
auto msg = p.GetSerialize<RouteToMessage>(0);
|
auto msg = (RouteToMessage*)p.Data();
|
||||||
auto payload_offset = p.Length() - msg.payload_size;
|
char to_id[32];
|
||||||
auto payload = p.GetPacket(payload_offset, msg.payload_size);
|
strn0cpy(to_id, msg->id, 32);
|
||||||
|
|
||||||
auto out_msg = msg;
|
strn0cpy(msg->id, connection->GetUUID().c_str(), 32);
|
||||||
out_msg.identifier = connection->GetIdentifier();
|
|
||||||
out_msg.id = connection->GetUUID();
|
|
||||||
|
|
||||||
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) {
|
for (auto &connection : m_connections) {
|
||||||
auto id = connection->GetUUID();
|
auto id = connection->GetUUID();
|
||||||
auto identifier = connection->GetIdentifier();
|
auto identifier = connection->GetIdentifier();
|
||||||
if (std::regex_match(id, id_regex)) {
|
if (strcmp(to_id, id.c_str()) == 0) {
|
||||||
connection->Send(ServerOP_RouteTo, out);
|
connection->Send(ServerOP_RouteTo, p);
|
||||||
}
|
}
|
||||||
else if (std::regex_match(identifier, filter_regex)) {
|
else if (strcmp(msg->filter, identifier.c_str()) == 0) {
|
||||||
connection->Send(ServerOP_RouteTo, out);
|
connection->Send(ServerOP_RouteTo, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!msg.id.empty()) {
|
else if (msg->filter[0] != '\0') {
|
||||||
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);
|
|
||||||
|
|
||||||
for (auto &connection : m_connections) {
|
for (auto &connection : m_connections) {
|
||||||
auto identifier = connection->GetIdentifier();
|
auto identifier = connection->GetIdentifier();
|
||||||
if (std::regex_match(identifier, filter_regex)) {
|
if (strcmp(msg->filter, identifier.c_str()) == 0) {
|
||||||
connection->Send(ServerOP_RouteTo, out);
|
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 {
|
else {
|
||||||
for (auto &connection : m_connections) {
|
for (auto &connection : m_connections) {
|
||||||
connection->Send(ServerOP_RouteTo, out);
|
connection->Send(ServerOP_RouteTo, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,8 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include <task.pb.h>
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
#endif
|
#endif
|
||||||
@ -2831,9 +2833,12 @@ void command_spawn(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
void command_test(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;
|
EQ::Net::DynamicPacket p;
|
||||||
p.PutInt32(0, 1234);
|
p.PutProtobuf(0, &req);
|
||||||
p.PutCString(p.Length(), "TestPacket");
|
|
||||||
worldserver.RouteMessage("Tasks", "", p);
|
worldserver.RouteMessage("Tasks", "", p);
|
||||||
|
|
||||||
//c->Message(15, "Triggering test command");
|
//c->Message(15, "Triggering test command");
|
||||||
|
|||||||
@ -471,14 +471,14 @@ bool TaskManager::SaveClientState(Client *c, ClientTaskState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::LoadClientTaskState() {
|
void Client::LoadClientTaskState() {
|
||||||
GetClientTaskStateRequest req;
|
//GetClientTaskStateRequest req;
|
||||||
req.client_id = CharacterID();
|
//req.client_id = CharacterID();
|
||||||
|
//
|
||||||
EQ::Net::DynamicPacket p;
|
//EQ::Net::DynamicPacket p;
|
||||||
p.PutInt32(0, TaskGetClientTaskState);
|
//p.PutInt32(0, TaskGetClientTaskState);
|
||||||
p.PutSerialize(4, req);
|
//p.PutSerialize(4, req);
|
||||||
|
//
|
||||||
worldserver.RouteMessage("Tasks", "", p);
|
//worldserver.RouteMessage("Tasks", "", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::RemoveClientTaskState() {
|
void Client::RemoveClientTaskState() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user