From 3086fd5758951d6a9b823850e7726a66b6f6f2b8 Mon Sep 17 00:00:00 2001 From: Subsonic154 Date: Thu, 16 Apr 2026 07:29:28 -0400 Subject: [PATCH] Refactored code, cover more private IP address ranges --- src/main/resources/application.conf | 14 ++++++---- .../net/psforever/actors/net/LoginActor.scala | 28 +++++++++++++++---- .../scala/net/psforever/util/Config.scala | 1 + 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 76efc08f7..442ee8ab3 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -1,12 +1,14 @@ # The socket bind address for all net.psforever.services except admin. 127.0.0.1 is the -# default for local testing, for public servers use 0.0.0.0 instead. +# default for local testing, for LAN or public servers use 0.0.0.0 instead. bind = 127.0.0.1 -# The public host name or IP address. Used to forward clients from the login -# server to the world server. The default value will only allow local connections. -# If you encounter issues trying to connect to the world from other machines on the same network -# when this is not the default value and you have a router that lacks Hairpin NAT support, make sure -# the hosts file on this system has the host name of the system set to resolve to it's local IP address on the network. +# The private host name or IP address. Used to forward clients on the local network +# from the login server to the world server. The default value will only allow connections from the host machine, +# set this to the host machines private address on the local network to allow connections from other machines on it. +local = 127.0.0.1 + +# The public host name or IP address. Used to forward external clients from outside the local network +# from the login server to the world server. The default value will not allow external connections. public = 127.0.0.1 # Login server configuration diff --git a/src/main/scala/net/psforever/actors/net/LoginActor.scala b/src/main/scala/net/psforever/actors/net/LoginActor.scala index 4d0a0c0e8..fc7769d47 100644 --- a/src/main/scala/net/psforever/actors/net/LoginActor.scala +++ b/src/main/scala/net/psforever/actors/net/LoginActor.scala @@ -33,6 +33,10 @@ object LoginActor { final case class ReceptionistListing(listing: Receptionist.Listing) extends Command + private val gameTestServerAddressLocal = new InetSocketAddress(InetAddress.getByName(Config.app.local), Config.app.world.port) + private val gameTestServerAddressPublic = new InetSocketAddress(InetAddress.getByName(Config.app.public), Config.app.world.port) + private val localHostAddress = new InetSocketAddress("127.0.0.1", Config.app.world.port) + /** * What does a token do? * No one knows. @@ -78,6 +82,21 @@ object LoginActor { //remove color codes from the server name - look for '\\#' followed by six characters or numbers name.replaceAll("\\\\#[\\da-fA-F]{6}","") } + + /** + * Selects the appropriate host address for transfer to world server. + * This is a workaround for cases of local connections not working + * properly when using a router that lacks Hairpin NAT support. + * @param ipAddress the IP address of the connecting client in string form + * @return the appropriate host address + */ + private def selectHostAddress(ipAddress: String): InetSocketAddress = { + ipAddress.substring(0, ipAddress.indexOf(".")) match { + case "127" => localHostAddress + case "10" | "169" | "172" | "192" => gameTestServerAddressLocal + case _ => gameTestServerAddressPublic + } + } } class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], connectionId: String, sessionId: Long) @@ -96,8 +115,6 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne private var port: Int = 0 private val serverName: String = Config.app.world.serverName - private val gameTestServerAddress = new InetSocketAddress(InetAddress.getByName(Config.app.public), Config.app.world.port) - private val localHost: InetAddress = InetAddress.getLocalHost private val bcryptRounds = 12 @@ -153,8 +170,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne updateServerList() case SocketPane.NextPort(_, _, portNum) => - val address = if (ipAddress == "127.0.0.1") ipAddress else if (ipAddress.startsWith("192.168")) localHost.getHostAddress else gameTestServerAddress.getAddress.getHostAddress - log.info(s"Connecting to ${address.toLowerCase}: $portNum ...") + val address = LoginActor.selectHostAddress(ipAddress).getAddress.getHostAddress val response = ConnectToWorldMessage(serverName, address, portNum) context.become(idlingBehavior) middlewareActor ! MiddlewareActor.Send(response) @@ -166,7 +182,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne private def waitingForServerTransferBehavior: Receive = persistentSetupMixinBehavior.orElse { case SocketPane.NextPort(_, _, portNum) => - val address = if (ipAddress == "127.0.0.1") ipAddress else if (ipAddress.startsWith("192.168")) localHost.getHostAddress else gameTestServerAddress.getAddress.getHostAddress + val address = LoginActor.selectHostAddress(ipAddress).getAddress.getHostAddress log.info(s"Connecting to ${address.toLowerCase}: $portNum ...") val response = ConnectToWorldMessage(serverName, address, portNum) context.become(idlingBehavior) @@ -499,7 +515,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne serverName, WorldStatus.Up, Config.app.world.serverType, - Vector(WorldConnectionInfo(gameTestServerAddress)), //todo ideally, ask for info from SocketPane + Vector(WorldConnectionInfo(LoginActor.selectHostAddress(ipAddress))), //todo ideally, ask for info from SocketPane PlanetSideEmpire.VS ) ) diff --git a/src/main/scala/net/psforever/util/Config.scala b/src/main/scala/net/psforever/util/Config.scala index ef1314248..f4c487b2a 100644 --- a/src/main/scala/net/psforever/util/Config.scala +++ b/src/main/scala/net/psforever/util/Config.scala @@ -84,6 +84,7 @@ object Config { case class AppConfig( bind: String, + local: String, public: String, login: LoginConfig, world: WorldConfig,