World <-> Login connection reworked

This commit is contained in:
KimLS
2016-10-28 19:02:03 -07:00
parent fab8765c2f
commit 0b8b41d91f
32 changed files with 729 additions and 701 deletions
+1
View File
@@ -41,6 +41,7 @@ public:
virtual void Close() = 0;
virtual void ReleaseFromUse() = 0;
virtual void RemoveData() = 0;
virtual std::string GetRemoteAddr() const = 0;
virtual uint32 GetRemoteIP() const = 0;
virtual uint16 GetRemotePort() const = 0;
virtual bool CheckState(EQStreamState state) = 0;
+4
View File
@@ -63,6 +63,10 @@ void EQStreamProxy::Close() {
m_stream->Close();
}
std::string EQStreamProxy::GetRemoteAddr() const {
return(m_stream->GetRemoteAddr());
}
uint32 EQStreamProxy::GetRemoteIP() const {
return(m_stream->GetRemoteIP());
}
+1
View File
@@ -21,6 +21,7 @@ public:
virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true);
virtual EQApplicationPacket *PopPacket();
virtual void Close();
virtual std::string GetRemoteAddr() const;
virtual uint32 GetRemoteIP() const;
virtual uint16 GetRemotePort() const;
virtual void ReleaseFromUse();
+5
View File
@@ -132,6 +132,11 @@ void EQ::Net::EQStream::Close() {
m_connection->Close();
}
std::string EQ::Net::EQStream::GetRemoteAddr() const
{
return RemoteEndpoint();
}
uint32 EQ::Net::EQStream::GetRemoteIP() const {
return inet_addr(RemoteEndpoint().c_str());
}
+1
View File
@@ -75,6 +75,7 @@ namespace EQ
virtual void Close();
virtual void ReleaseFromUse() { };
virtual void RemoveData() { };
virtual std::string GetRemoteAddr() const;
virtual uint32 GetRemoteIP() const;
virtual uint16 GetRemotePort() const { return m_connection->RemotePort(); }
virtual bool CheckState(EQStreamState state);
+139 -17
View File
@@ -19,6 +19,45 @@ EQ::Net::ServertalkClient::~ServertalkClient()
{
}
void EQ::Net::ServertalkClient::Send(uint16_t opcode, EQ::Net::Packet & p)
{
EQ::Net::WritablePacket out;
#ifdef ENABLE_SECURITY
if (m_encrypted) {
out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES);
out.PutUInt16(4, opcode);
unsigned char *cipher = new unsigned char[p.Length() + crypto_secretbox_MACBYTES];
crypto_box_easy_afternm(cipher, (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key);
(*(uint64_t*)&m_nonce_ours[0])++;
out.PutData(6, cipher, p.Length() + crypto_secretbox_MACBYTES);
delete[] cipher;
}
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);
}
void EQ::Net::ServertalkClient::SendPacket(ServerPacket *p)
{
EQ::Net::ReadOnlyPacket pout(p->pBuffer, p->size);
Send(p->opcode, pout);
}
void EQ::Net::ServertalkClient::OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb)
{
m_message_callbacks.insert(std::make_pair(opcode, cb));
}
void EQ::Net::ServertalkClient::Connect()
{
if (m_addr.length() == 0 || m_port == 0 || m_connection || m_connecting) {
@@ -37,8 +76,8 @@ void EQ::Net::ServertalkClient::Connect()
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.reset();
});
m_connection->OnRead(std::bind(&EQ::Net::ServertalkClient::ProcessData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
@@ -98,7 +137,7 @@ void EQ::Net::ServertalkClient::ProcessReadBuffer()
length = *(uint32_t*)&m_buffer[current];
type = *(uint8_t*)&m_buffer[current + 4];
if (current + 5 + length < total) {
if (current + 5 + length > total) {
break;
}
@@ -144,6 +183,7 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
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 {
@@ -156,6 +196,10 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
m_encrypted = true;
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
else {
Log.OutF(Logs::General, Logs::Error, "Could not process hello, size != {0}", 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
@@ -163,37 +207,104 @@ void EQ::Net::ServertalkClient::ProcessHello(EQ::Net::Packet &p)
}
else {
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
}
catch (std::exception &ex) {
Log.OutF(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;
if (enc) {
Log.OutF(Logs::General, Logs::Error, "Server requested encryption but we do not support encryption.");
m_connection->Disconnect();
return;
SendHandshake(true);
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
else {
SendHandshake();
if (m_on_connect_cb) {
m_on_connect_cb(this);
}
}
}
catch (std::exception &ex) {
Log.OutF(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);
}
}
#endif
}
void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
{
try {
auto length = p.GetUInt32(0);
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<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))
{
Log.OutF(Logs::General, Logs::Error, "Error decrypting message from server");
(*(uint64_t*)&m_nonce_theirs[0])++;
return;
}
EQ::Net::ReadOnlyPacket 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);
}
}
else {
size_t message_len = length;
EQ::Net::ReadOnlyPacket packet(&data[0], message_len);
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
}
}
#else
size_t message_len = length;
EQ::Net::ReadOnlyPacket packet(&data[0], message_len);
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
}
#endif
}
}
catch (std::exception &ex) {
Log.OutF(Logs::General, Logs::Error, "Error parsing message from server: {0}", ex.what());
}
}
void EQ::Net::ServertalkClient::SendHandshake()
void EQ::Net::ServertalkClient::SendHandshake(bool downgrade)
{
EQ::Net::WritablePacket handshake;
#ifdef ENABLE_SECURITY
@@ -206,30 +317,41 @@ void EQ::Net::ServertalkClient::SendHandshake()
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;
unsigned char *signed_buffer = new unsigned char[cipher_length];
unsigned char *data_buffer = new unsigned char[data_length];
memset(data_buffer, 0, data_length);
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, data_buffer, data_length, m_nonce_ours, m_shared_key);
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, cipher_length);
Log.OutF(Logs::General, Logs::Debug, "Sending {1} bytes handshake:\n{0}", handshake.ToString(), handshake.Length());
delete[] signed_buffer;
delete[] data_buffer;
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
InternalSend(ServertalkClientHandshake, handshake);
if (downgrade) {
InternalSend(ServertalkClientDowngradeSecurityHandshake, handshake);
}
else {
InternalSend(ServertalkClientHandshake, handshake);
}
}
+13 -1
View File
@@ -4,7 +4,9 @@
#include "../event/timer.h"
#include "servertalk_common.h"
#include "packet.h"
#ifdef ENABLE_SECURITY
#include <sodium.h>
#endif
namespace EQ
{
@@ -16,6 +18,13 @@ namespace EQ
ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials);
~ServertalkClient();
void Send(uint16_t opcode, EQ::Net::Packet &p);
void SendPacket(ServerPacket *p);
void OnConnect(std::function<void(ServertalkClient*)> cb) { m_on_connect_cb = cb; }
void OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb);
bool Connected() const { return m_connecting != true; }
std::shared_ptr<EQ::Net::TCPConnection> Handle() { return m_connection; }
private:
void Connect();
void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length);
@@ -24,7 +33,8 @@ namespace EQ
void ProcessReadBuffer();
void ProcessHello(EQ::Net::Packet &p);
void ProcessMessage(EQ::Net::Packet &p);
void SendHandshake();
void SendHandshake() { SendHandshake(false); }
void SendHandshake(bool downgrade);
std::unique_ptr<EQ::Timer> m_timer;
@@ -37,6 +47,8 @@ namespace EQ
bool m_encrypted;
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
std::vector<char> m_buffer;
std::unordered_map<uint16_t, std::function<void(uint16_t, EQ::Net::Packet&)>> m_message_callbacks;
std::function<void(ServertalkClient*)> m_on_connect_cb;
#ifdef ENABLE_SECURITY
unsigned char m_public_key_ours[crypto_box_PUBLICKEYBYTES];
+3
View File
@@ -1,5 +1,7 @@
#pragma once
#include "../servertalk.h"
namespace EQ
{
namespace Net
@@ -9,6 +11,7 @@ namespace EQ
ServertalkClientHello = 1,
ServertalkServerHello,
ServertalkClientHandshake,
ServertalkClientDowngradeSecurityHandshake,
ServertalkMessage,
};
}
+2 -1
View File
@@ -12,9 +12,10 @@ void EQ::Net::ServertalkServer::Listen(const ServertalkServerOptions& opts)
{
m_encrypted = opts.encrypted;
m_credentials = opts.credentials;
m_allow_downgrade = opts.allow_downgrade;
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));
m_unident_connections.push_back(std::make_shared<ServertalkServerConnection>(connection, this, m_encrypted, m_allow_downgrade));
});
}
+6
View File
@@ -18,11 +18,16 @@ namespace EQ
int port;
bool ipv6;
bool encrypted;
bool allow_downgrade;
std::string credentials;
ServertalkServerOptions() {
#ifdef ENABLE_SECURITY
encrypted = true;
allow_downgrade = true;
#else
encrypted = false;
allow_downgrade = true;
#endif
ipv6 = false;
}
@@ -50,6 +55,7 @@ namespace EQ
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;
bool m_allow_downgrade;
std::string m_credentials;
friend class ServertalkServerConnection;
+135 -10
View File
@@ -2,11 +2,12 @@
#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)
EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, EQ::Net::ServertalkServer *parent, bool encrypted, bool allow_downgrade)
{
m_connection = c;
m_parent = parent;
m_encrypted = encrypted;
m_allow_downgrade = allow_downgrade;
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();
@@ -16,6 +17,43 @@ EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
{
}
void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet & p)
{
EQ::Net::WritablePacket out;
#ifdef ENABLE_SECURITY
if (m_encrypted) {
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.PutUInt16(4, opcode);
out.PutPacket(6, p);
#endif
InternalSend(ServertalkMessage, out);
}
void EQ::Net::ServertalkServerConnection::SendPacket(ServerPacket * p)
{
EQ::Net::ReadOnlyPacket pout(p->pBuffer, p->size);
Send(p->opcode, pout);
}
void EQ::Net::ServertalkServerConnection::OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb)
{
m_message_callbacks.insert(std::make_pair(opcode, cb));
}
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);
@@ -44,7 +82,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
length = *(uint32_t*)&m_buffer[current];
type = *(uint8_t*)&m_buffer[current + 4];
if (current + 5 + length < total) {
if (current + 5 + length > total) {
break;
}
@@ -75,6 +113,9 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
case ServertalkClientHandshake:
ProcessHandshake(p);
break;
case ServertalkClientDowngradeSecurityHandshake:
ProcessHandshake(p, true);
break;
case ServertalkMessage:
ProcessMessage(p);
break;
@@ -142,9 +183,15 @@ void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type
m_connection->Write((const char*)out.Data(), out.Length());
}
void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p)
void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, bool downgrade_security)
{
#ifdef ENABLE_SECURITY
if (downgrade_security && m_allow_downgrade && m_encrypted) {
Log.OutF(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)) {
@@ -155,16 +202,16 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p)
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))
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))
{
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);
m_identifier = (const char*)&decrypted_text[0];
std::string credentials = (const char*)&decrypted_text[0] + (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.");
@@ -175,7 +222,6 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p)
m_parent->ConnectionIdentified(this);
(*(uint64_t*)&m_nonce_theirs[0])++;
delete[] decrypted_text;
}
}
catch (std::exception &ex) {
@@ -184,13 +230,92 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p)
}
}
else {
m_identifier.assign((char*)p.Data(), p.Length());
try {
m_identifier = p.GetCString(0);
auto credentials = p.GetCString(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);
}
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());
try {
m_identifier = p.GetCString(0);
auto credentials = p.GetCString(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);
}
catch (std::exception &ex) {
Log.OutF(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)
{
try {
auto length = p.GetUInt32(0);
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<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))
{
Log.OutF(Logs::General, Logs::Error, "Error decrypting message from client");
(*(uint64_t*)&m_nonce_theirs[0])++;
return;
}
EQ::Net::ReadOnlyPacket 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);
}
}
else {
size_t message_len = length;
EQ::Net::ReadOnlyPacket packet(&data[0], message_len);
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
}
}
#else
size_t message_len = length;
EQ::Net::ReadOnlyPacket packet(&data[0], message_len);
auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet);
}
#endif
}
}
catch (std::exception &ex) {
Log.OutF(Logs::General, Logs::Error, "Error parsing message from client: {0}", ex.what());
}
}
+13 -5
View File
@@ -4,7 +4,9 @@
#include "servertalk_common.h"
#include "packet.h"
#include <vector>
#ifdef ENABLE_SECURITY
#include <sodium.h>
#endif
namespace EQ
{
@@ -14,28 +16,34 @@ namespace EQ
class ServertalkServerConnection
{
public:
ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, ServertalkServer *parent, bool encrypted);
ServertalkServerConnection(std::shared_ptr<EQ::Net::TCPConnection> c, ServertalkServer *parent, bool encrypted, bool allow_downgrade);
~ServertalkServerConnection();
std::string GetIdentifier() const {
return m_identifier;
}
void Send(uint16_t opcode, EQ::Net::Packet &p);
void SendPacket(ServerPacket *p);
void OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb);
std::string GetIdentifier() const { return m_identifier; }
std::shared_ptr<EQ::Net::TCPConnection> Handle() { return m_connection; }
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 ProcessHandshake(EQ::Net::Packet &p) { ProcessHandshake(p, false); }
void ProcessHandshake(EQ::Net::Packet &p, bool security_downgrade);
void ProcessMessage(EQ::Net::Packet &p);
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
ServertalkServer *m_parent;
std::vector<char> m_buffer;
std::unordered_map<uint16_t, std::function<void(uint16_t, EQ::Net::Packet&)>> m_message_callbacks;
std::string m_identifier;
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];
+36
View File
@@ -151,6 +151,42 @@ void EQ::Net::TCPConnection::Write(const char *data, size_t count)
});
}
std::string EQ::Net::TCPConnection::LocalIP() const
{
sockaddr_storage addr;
int addr_len = sizeof(addr);
uv_tcp_getsockname(m_socket, (sockaddr*)&addr, &addr_len);
char endpoint[64] = { 0 };
if (addr.ss_family == AF_INET) {
uv_ip4_name((const sockaddr_in*)&addr, endpoint, 64);
}
else if (addr.ss_family == AF_INET6) {
uv_ip6_name((const sockaddr_in6*)&addr, endpoint, 64);
}
return endpoint;
}
int EQ::Net::TCPConnection::LocalPort() const
{
sockaddr_storage addr;
int addr_len = sizeof(addr);
uv_tcp_getsockname(m_socket, (sockaddr*)&addr, &addr_len);
char endpoint[64] = { 0 };
if (addr.ss_family == AF_INET) {
sockaddr_in *s = (sockaddr_in*)&addr;
return ntohs(s->sin_port);
}
else if (addr.ss_family == AF_INET6) {
sockaddr_in6 *s = (sockaddr_in6*)&addr;
return ntohs(s->sin6_port);
}
return 0;
}
std::string EQ::Net::TCPConnection::RemoteIP() const
{
sockaddr_storage addr;
+3
View File
@@ -23,6 +23,9 @@ namespace EQ
void Disconnect();
void Read(const char *data, size_t count);
void Write(const char *data, size_t count);
std::string LocalIP() const;
int LocalPort() const;
std::string RemoteIP() const;
int RemotePort() const;
private:
+1 -1
View File
@@ -530,7 +530,7 @@ struct ClientAuth_Struct {
char key[30]; // the Key the client will present
uint8 lsadmin; // login server admin level
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint32 ip;
char ip[64];
uint8 local; // 1 if the client is from the local network
};