Add environment printing and fix comments

This commit is contained in:
Chord 2016-07-19 02:20:36 -04:00
parent b32a6c0263
commit 8b14015582
2 changed files with 84 additions and 23 deletions

View file

@ -12,11 +12,13 @@ import org.fusesource.jansi.Ansi._
import org.fusesource.jansi.Ansi.Color._
import scala.collection.JavaConverters._
import scala.concurrent.Await
import scala.concurrent.duration._
object PsLogin {
private val logger = org.log4s.getLogger
def banner = {
def banner() : Unit = {
println(ansi().fgBright(BLUE).a(""" ___ ________"""))
println(ansi().fgBright(BLUE).a(""" / _ \/ __/ __/__ _______ _ _____ ____"""))
println(ansi().fgBright(MAGENTA).a(""" / ___/\ \/ _// _ \/ __/ -_) |/ / -_) __/"""))
@ -25,6 +27,30 @@ object PsLogin {
println
}
/** Grabs the most essential system information and returns it as a preformatted string */
def systemInformation : String = {
s"""|~~~ System Information ~~~
|${System.getProperty("os.name")} (v. ${System.getProperty("os.version")}, ${System.getProperty("os.arch")})
|${System.getProperty("java.vm.name")} (build ${System.getProperty("java.version")}), ${System.getProperty("java.vendor")} - ${System.getProperty("java.vendor.url")}
""".stripMargin
}
/** Used to enumerate all of the Java properties. Used in testing only */
def enumerateAllProperties() : Unit = {
val props = System.getProperties
val enums = props.propertyNames()
while(enums.hasMoreElements) {
val key = enums.nextElement.toString
System.out.println(key + " : " + props.getProperty(key))
}
}
/**
* Checks the current logger context
* @param context SLF4J logger context
* @return Boolean return true if context has errors
*/
def loggerHasErrors(context : LoggerContext) = {
val statusUtil = new StatusUtil(context)
@ -32,7 +58,8 @@ object PsLogin {
}
def main(args : Array[String]) : Unit = {
banner
banner()
println(systemInformation)
// assume SLF4J is bound to logback in the current environment
val lc = slf4j.LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
@ -42,6 +69,12 @@ object PsLogin {
sys.exit(1)
}
/** Initialize the PSCrypto native library
*
* PSCrypto provides PlanetSide specific crypto that is required to communicate with it.
* It has to be distributed as a native library because there is no Scala version of the required
* cryptographic primitives (MD5MAC). See https://github.com/psforever/PSCrypto for more information.
*/
try {
CryptoInterface.initialize()
logger.info("PSCrypto initialized")
@ -49,30 +82,58 @@ object PsLogin {
catch {
case e : UnsatisfiedLinkError =>
logger.error(e)("Unable to initialize " + CryptoInterface.libName)
CryptoInterface.printEnvironment()
sys.exit(1)
}
// TODO: pluralize "processors"
logger.info(s"Detected ${Runtime.getRuntime.availableProcessors()} available logical processors")
logger.info("Starting actor subsystems...")
/** Make sure we capture Akka messages (but only INFO and above)
*
* This same config can be specified in a configuration file, but that's more work at this point.
* In the future we will have a unified configuration file specific to this server
*/
val config = Map(
"akka.loggers" -> List("akka.event.slf4j.Slf4jLogger").asJava,
"akka.loglevel" -> "INFO",
"akka.logging-filter" -> "akka.event.slf4j.Slf4jLoggingFilter"
).asJava
//val system = ActorSystem("PsLogin", Some(ConfigFactory.parseMap(config)), None, Some(MDCPropagatingExecutionContextWrapper(ExecutionContext.Implicits.global)))
/** Start up the main actor system. This "system" is the home for all actors running on this server */
val system = ActorSystem("PsLogin", ConfigFactory.parseMap(config))
val loginTemplate = List(SessionPipeline("crypto-session-", Props[CryptoSessionActor]),
SessionPipeline("login-session-", Props[LoginSessionActor]))
val worldTemplate = List(SessionPipeline("crypto-session-", Props[CryptoSessionActor]),
SessionPipeline("world-session-", Props[WorldSessionActor]))
/** Create pipelines for the login and world servers
*
* The first node in the pipe is an Actor that handles the crypto for protecting packets.
* After any crypto operations have been applied or unapplied, the packets are passed on to the next
* actor in the chain. For an incoming packet, this is a player session handler. For an outgoing packet
* this is the session router, which returns the packet to the sending host.
*
* See SessionRouter.scala for a diagram
*/
val loginTemplate = List(
SessionPipeline("crypto-session-", Props[CryptoSessionActor]),
SessionPipeline("login-session-", Props[LoginSessionActor])
)
val worldTemplate = List(
SessionPipeline("crypto-session-", Props[CryptoSessionActor]),
SessionPipeline("world-session-", Props[WorldSessionActor])
)
val loginServerPort = 51000
val worldServerPort = 51001
/** Create two actors for handling the login and world server endpoints */
val listener = system.actorOf(Props(new UdpListener(Props(new SessionRouter(loginTemplate)), "login-session-router",
InetAddress.getLocalHost, 51000)), "login-udp-endpoint")
InetAddress.getLocalHost, loginServerPort)), "login-udp-endpoint")
val worldListener = system.actorOf(Props(new UdpListener(Props(new SessionRouter(worldTemplate)), "world-session-router",
InetAddress.getLocalHost, 51001)), "world-udp-endpoint")
InetAddress.getLocalHost, worldServerPort)), "world-udp-endpoint")
logger.info(s"NOTE: Set client.ini to point to ${InetAddress.getLocalHost.getHostAddress}:$loginServerPort")
// Wait forever until the actor system shuts down
Await.result(system.whenTerminated, Duration.Inf)
}
}

View file

@ -36,19 +36,19 @@ class SessionRouter(pipeline : List[SessionPipeline]) extends Actor with MDCCont
log.info("SessionRouter started...ready for PlanetSide sessions")
}
/*
Login sessions are divided between two actors. the crypto session actor transparently handles all of the cryptographic
setup of the connection. Once a correct crypto session has been established, all packets, after being decrypted
will be passed on to the login session actor. This actor has important state that is used to maintain the login
session.
> PlanetSide Session Pipeline <
read() route decrypt
UDP Socket -----> [Session Router] -----> [Crypto Actor] -----> [Session Actor]
^ | ^ | ^ |
| write() | | encrypt | | response |
+--------------+ +-----------+ +-----------------+
/**
* Login sessions are divided between two actors. The crypto session actor transparently handles all of the cryptographic
* setup of the connection. Once a correct crypto session has been established, all packets, after being decrypted
* will be passed on to the login session actor. This actor has important state that is used to maintain the login
* session.
*
* > PlanetSide Session Pipeline <
*
* read() route decrypt
* UDP Socket -----> [Session Router] -----> [Crypto Actor] -----> [Session Actor]
* ^ | ^ | ^ |
* | write() | | encrypt | | response |
* +--------------+ +-----------+ +-----------------+
*/
def receive = initializing