From d5fe1cc5133cb3aba7bd8dc013db2f05e300c607 Mon Sep 17 00:00:00 2001 From: dongresource Date: Fri, 5 Mar 2021 18:21:40 +0100 Subject: [PATCH] Work around not being able to reach the shard from a local connection In certain circumstances, like when running a private server through Hamachi, the shard IP will be set to an address the local machine can't reach itself from, preventing only the local player from getting past character selection. This workaround detects local connections and sends a loopback address for the shard instead of the configured one. This makes those use cases feasible. --- src/CNLoginServer.cpp | 23 ++++++++++++++++------- src/CNProtocol.cpp | 4 ++-- src/CNProtocol.hpp | 3 ++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/CNLoginServer.cpp b/src/CNLoginServer.cpp index 3e1ed31..d67860e 100644 --- a/src/CNLoginServer.cpp +++ b/src/CNLoginServer.cpp @@ -458,13 +458,22 @@ void CNLoginServer::characterSelect(CNSocket* sock, CNPacketData* data) { std::cout << "Login Server: Selected character [" << selection->iPC_UID << "]" << std::endl; std::cout << "Connecting to shard server" << std::endl; ) - - // copy IP to resp (this struct uses ASCII encoding so we don't have to goof around converting encodings) - const char* SHARD_IP = settings::SHARDSERVERIP.c_str(); - memcpy(resp.g_FE_ServerIP, SHARD_IP, strlen(SHARD_IP)); - resp.g_FE_ServerIP[strlen(SHARD_IP)] = '\0'; + + const char* shard_ip = settings::SHARDSERVERIP.c_str(); + + /* + * Work around the issue of not being able to connect to a local server if + * the shard IP has been configured to an address the local machine can't + * reach itself from. + */ + if (sock->sockaddr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) + shard_ip = "127.0.0.1"; + + memcpy(resp.g_FE_ServerIP, shard_ip, strlen(shard_ip)); + + resp.g_FE_ServerIP[strlen(shard_ip)] = '\0'; resp.g_FE_ServerPort = settings::SHARDPORT; - + // pass player to CNSharedData Player passPlayer = {}; Database::getPlayer(&passPlayer, selection->iPC_UID); @@ -477,7 +486,7 @@ void CNLoginServer::characterSelect(CNSocket* sock, CNPacketData* data) { CNSharedData::setPlayer(resp.iEnterSerialKey, passPlayer); sock->sendPacket((void*)&resp, P_LS2CL_REP_SHARD_SELECT_SUCC, sizeof(sP_LS2CL_REP_SHARD_SELECT_SUCC)); - + // update current slot in DB Database::updateSelected(loginSessions[sock].userID, passPlayer.slot); } diff --git a/src/CNProtocol.cpp b/src/CNProtocol.cpp index 53c2ee5..3b7e124 100644 --- a/src/CNProtocol.cpp +++ b/src/CNProtocol.cpp @@ -63,7 +63,7 @@ CNPacketData::CNPacketData(void* b, uint32_t t, int l): buf(b), size(l), type(t) // ========================================================[[ CNSocket ]]======================================================== -CNSocket::CNSocket(SOCKET s, PacketHandler ph): sock(s), pHandler(ph) { +CNSocket::CNSocket(SOCKET s, struct sockaddr_in &addr, PacketHandler ph): sock(s), sockaddr(addr), pHandler(ph) { EKey = (uint64_t)(*(uint64_t*)&CNSocketEncryption::defaultKey[0]); } @@ -390,7 +390,7 @@ void CNServer::start() { addPollFD(newConnectionSocket); // add connection to list! - CNSocket* tmp = new CNSocket(newConnectionSocket, pHandler); + CNSocket* tmp = new CNSocket(newConnectionSocket, address, pHandler); connections[newConnectionSocket] = tmp; newConnection(tmp); diff --git a/src/CNProtocol.hpp b/src/CNProtocol.hpp index a91454e..fe52d0b 100644 --- a/src/CNProtocol.hpp +++ b/src/CNProtocol.hpp @@ -166,9 +166,10 @@ private: public: SOCKET sock; + sockaddr_in sockaddr; PacketHandler pHandler; - CNSocket(SOCKET s, PacketHandler ph); + CNSocket(SOCKET s, struct sockaddr_in &addr, PacketHandler ph); void setEKey(uint64_t k); void setFEKey(uint64_t k);