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.
This commit is contained in:
dongresource 2021-03-05 18:21:40 +01:00
parent da8dde9818
commit d5fe1cc513
3 changed files with 20 additions and 10 deletions

View File

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

View File

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

View File

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