diff --git a/build.sbt b/build.sbt index 7e21530b..574d91af 100644 --- a/build.sbt +++ b/build.sbt @@ -5,12 +5,15 @@ lazy val commonSettings = Seq( scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"), resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", libraryDependencies := Seq( - "com.typesafe.akka" %% "akka-actor" % "2.3.11", + "com.typesafe.akka" %% "akka-actor" % "2.3.11", "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0", - "org.specs2" %% "specs2-core" % "2.3.11" % "test", - "org.scodec" %% "scodec-core" % "1.8.3", - "org.scodec" %% "scodec-akka" % "0.1.0-SNAPSHOT", - "net.java.dev.jna" % "jna" % "4.2.1" + "org.specs2" %% "specs2-core" % "2.3.11" % "test", + "org.scodec" %% "scodec-core" % "1.8.3", + "org.scodec" %% "scodec-akka" % "0.1.0-SNAPSHOT", + "net.java.dev.jna" % "jna" % "4.2.1", + "ch.qos.logback" % "logback-classic" % "1.1.7", + "org.log4s" %% "log4s" % "1.3.0", + "org.fusesource.jansi" % "jansi" % "1.12" ) ) diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 2cde4e69..e70bda61 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -59,7 +59,7 @@ class GamePacketTest extends Specification { val pkt = PacketCoding.EncodePacket(msg).require.toByteVector - println(pkt) + //println(pkt) true mustEqual true } diff --git a/pslogin/src/main/scala/CryptoSessionActor.scala b/pslogin/src/main/scala/CryptoSessionActor.scala index ea5d9de5..ea4e0020 100644 --- a/pslogin/src/main/scala/CryptoSessionActor.scala +++ b/pslogin/src/main/scala/CryptoSessionActor.scala @@ -1,7 +1,7 @@ // Copyright (c) 2016 PSForever.net to present import java.net.{InetAddress, InetSocketAddress} -import akka.actor.{ActorRef, Identify, Actor, ActorLogging} +import akka.actor.{ActorRef, Identify, Actor} import psforever.crypto.CryptoInterface.{CryptoStateWithMAC, CryptoState} import psforever.crypto.CryptoInterface import psforever.net._ @@ -14,7 +14,9 @@ import java.security.SecureRandom /** * Actor that stores crypto state for a connection and filters away any packet metadata. */ -class CryptoSessionActor extends Actor with ActorLogging { +class CryptoSessionActor extends Actor { + private[this] val logger = org.log4s.getLogger + var leftRef : ActorRef = ActorRef.noSender var rightRef : ActorRef = ActorRef.noSender @@ -43,7 +45,7 @@ class CryptoSessionActor extends Actor with ActorLogging { context.become(NewClient) case _ => - log.error("Unknown message") + logger.error("Unknown message") context.stop(self) } @@ -51,7 +53,7 @@ class CryptoSessionActor extends Actor with ActorLogging { case RawPacket(msg) => // PacketCoding.DecodePacket PacketCoding.UnmarshalPacket(msg) match { - case Failure(e) => log.error("Could not decode packet: " + e) + case Failure(e) => logger.error("Could not decode packet: " + e) case Successful(p) => //println("RECV: " + p) @@ -61,16 +63,16 @@ class CryptoSessionActor extends Actor with ActorLogging { context.become(CryptoExchange) case default => - log.error("Unexpected packet type " + p) + logger.error("Unexpected packet type " + p) } } - case default => log.error(s"Invalid message received ${default}") + case default => logger.error(s"Invalid message received ${default}") } def CryptoExchange : Receive = { case RawPacket(msg) => PacketCoding.UnmarshalPacket(msg, CryptoPacketOpcode.ClientChallengeXchg) match { - case Failure(e) => log.error("Could not decode packet: " + e) + case Failure(e) => logger.error("Could not decode packet: " + e) case Successful(p) => //println("RECV: " + p) @@ -100,16 +102,16 @@ class CryptoSessionActor extends Actor with ActorLogging { serverMACBuffer ++= sentPacket.drop(3) context.become(CryptoSetupFinishing) - case default => log.error("Unexpected packet type " + p) + case default => logger.error("Unexpected packet type " + p) } } - case default => log.error(s"Invalid message received ${default}") + case default => logger.error(s"Invalid message received ${default}") } def CryptoSetupFinishing : Receive = { case RawPacket(msg) => PacketCoding.UnmarshalPacket(msg, CryptoPacketOpcode.ClientFinished) match { - case Failure(e) => log.error("Could not decode packet: " + e) + case Failure(e) => logger.error("Could not decode packet: " + e) case Successful(p) => //println("RECV: " + p) @@ -203,12 +205,12 @@ class CryptoSessionActor extends Actor with ActorLogging { self ! packet case Failure(e) => - println("Failed to decode encrypted packet: " + e) + logger.error("Failed to decode encrypted packet: " + e) } case default => failWithError("Unexpected packet type " + default) } - case Failure(e) => println("Could not decode raw packet: " + e) + case Failure(e) => logger.error("Could not decode raw packet: " + e) } case ctrl @ ControlPacket(_, _) => val from = sender() @@ -222,7 +224,7 @@ class CryptoSessionActor extends Actor with ActorLogging { } def failWithError(error : String) = { - log.error(error) + logger.error(error) } def resetState() : Unit = { @@ -253,7 +255,7 @@ class CryptoSessionActor extends Actor with ActorLogging { val packet = PacketCoding.encryptPacket(cryptoState.get, cont).require sendResponse(packet) } else { - log.error("Invalid sender") + logger.error("Invalid sender") } } diff --git a/pslogin/src/main/scala/LoginSessionActor.scala b/pslogin/src/main/scala/LoginSessionActor.scala index 4eb1009e..fcc58334 100644 --- a/pslogin/src/main/scala/LoginSessionActor.scala +++ b/pslogin/src/main/scala/LoginSessionActor.scala @@ -6,7 +6,9 @@ import psforever.net._ import scodec.Attempt.{Failure, Successful} import scodec.bits._ -class LoginSessionActor extends Actor with ActorLogging { +class LoginSessionActor extends Actor { + private[this] val logger = org.log4s.getLogger + var leftRef : ActorRef = ActorRef.noSender var rightRef : ActorRef = ActorRef.noSender @@ -19,7 +21,7 @@ class LoginSessionActor extends Actor with ActorLogging { context.become(Started) case _ => - log.error("Unknown message") + logger.error("Unknown message") context.stop(self) } @@ -36,7 +38,7 @@ class LoginSessionActor extends Actor with ActorLogging { case SlottedMetaPacket(innerPacket) => PacketCoding.DecodePacket(innerPacket) match { case Successful(p) => - println("RECV[INNER]: " + p) + logger.trace("RECV[INNER]: " + p) val packet = LoginRespMessage("AAAABBBBCCCCDDDD", hex"00000000 18FABE0C 00000000 00000000", @@ -53,7 +55,7 @@ class LoginSessionActor extends Actor with ActorLogging { )) sendResponse(PacketCoding.CreateGamePacket(0, msg)) - case Failure(e) => println("Failed to decode inner packet " + e) + case Failure(e) => logger.error("Failed to decode inner packet " + e) } } } @@ -63,12 +65,12 @@ class LoginSessionActor extends Actor with ActorLogging { } def failWithError(error : String) = { - log.error(error) + logger.error(error) sendResponse(PacketCoding.CreateControlPacket(ConnectionClose())) } def sendResponse(cont : PlanetSidePacketContainer) = { - println("LOGIN SEND: " + cont) + logger.trace("LOGIN SEND: " + cont) rightRef ! cont } } diff --git a/pslogin/src/main/scala/PsLogin.scala b/pslogin/src/main/scala/PsLogin.scala index 8477651d..77a2f14d 100644 --- a/pslogin/src/main/scala/PsLogin.scala +++ b/pslogin/src/main/scala/PsLogin.scala @@ -1,25 +1,52 @@ // Copyright (c) 2016 PSForever.net to present -import akka.actor.{Props, ActorSystem} +import akka.actor.{ActorSystem, Props} +import ch.qos.logback.classic.LoggerContext +import ch.qos.logback.core.util.StatusPrinter import psforever.crypto.CryptoInterface +import org.log4s._ +import org.slf4j +import org.slf4j.LoggerFactory + +import org.fusesource.jansi.Ansi._ +import org.fusesource.jansi.Ansi.Color._ object PsLogin { + private val logger = org.log4s.getLogger + + def banner = { + println(ansi().fgBright(BLUE).a(""" ___ ________""")) + println(ansi().fgBright(BLUE).a(""" / _ \/ __/ __/__ _______ _ _____ ____""")) + println(ansi().fgBright(MAGENTA).a(""" / ___/\ \/ _// _ \/ __/ -_) |/ / -_) __/""")) + println(ansi().fgBright(RED).a("""/_/ /___/_/ \___/_/ \__/|___/\__/_/""").reset()) + println(""" Login Server - PSForever Project""") + println + } + def main(args : Array[String]) : Unit = { - println("PsLogin v0.1") + banner + + // assume SLF4J is bound to logback in the current environment + val lc = slf4j.LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext] + + // print logback's internal status + StatusPrinter.printInCaseOfErrorsOrWarnings(lc) try { CryptoInterface.initialize() - println("Crypto initialized") + logger.info("PSCrypto initialized") } catch { case e : UnsatisfiedLinkError => - println("Unable to initialize " + CryptoInterface.libName) - println("Reason: " + e.getMessage) - e.getStackTrace.foreach(println) + logger.error(e)("Unable to initialize " + CryptoInterface.libName) sys.exit(1) } + logger.info("Starting actor subsystems...") + val system = ActorSystem("PsLogin") val session = system.actorOf(Props[SessionRouter], "session-router") val listener = system.actorOf(Props(new UdpListener(session)), "udp-listener") + + system.awaitTermination() } } diff --git a/pslogin/src/main/scala/SessionRouter.scala b/pslogin/src/main/scala/SessionRouter.scala index d596e357..8eadcab5 100644 --- a/pslogin/src/main/scala/SessionRouter.scala +++ b/pslogin/src/main/scala/SessionRouter.scala @@ -13,7 +13,9 @@ case class SessionState(id : Long, address : InetSocketAddress, pipeline : List[ def inject(pkt : RawPacket) = pipeline.head ! pkt } -class SessionRouter extends Actor with ActorLogging { +class SessionRouter extends Actor { + private[this] val logger = org.log4s.getLogger + val idBySocket = mutable.Map[InetSocketAddress, Long]() val sessionById = mutable.Map[Long, SessionState]() val sessionByActor = mutable.Map[ActorRef, SessionState]() @@ -43,7 +45,7 @@ class SessionRouter extends Actor with ActorLogging { inputRef = sender() context.become(started) case _ => - log.error("Unknown message") + logger.error("Unknown message") context.stop(self) } @@ -52,7 +54,7 @@ class SessionRouter extends Actor with ActorLogging { if(idBySocket.contains(from)) { sessionById{idBySocket{from}}.inject(RawPacket(msg)) } else { - log.info("New session from " + from.toString) + logger.info("New session from " + from.toString) val session = createNewSession(from) idBySocket{from} = session.id @@ -66,7 +68,7 @@ class SessionRouter extends Actor with ActorLogging { val session = sessionByActor{sender()} inputRef ! SendPacket(msg, session.address) - case _ => log.error("Unknown message") + case _ => logger.error("Unknown message") } def createNewSession(address : InetSocketAddress) = { diff --git a/pslogin/src/main/scala/UdpListener.scala b/pslogin/src/main/scala/UdpListener.scala index 7d888281..1bd3bf64 100644 --- a/pslogin/src/main/scala/UdpListener.scala +++ b/pslogin/src/main/scala/UdpListener.scala @@ -11,7 +11,9 @@ final case class SendPacket(msg : ByteVector, to : InetSocketAddress) final case class Hello() final case class HelloFriend(next: ActorRef) -class UdpListener(nextActor: ActorRef) extends Actor with ActorLogging { +class UdpListener(nextActor: ActorRef) extends Actor { + private val logger = org.log4s.getLogger + import context.system IO(Udp) ! Udp.Bind(self, new InetSocketAddress("127.0.0.1", 51000)) @@ -20,7 +22,7 @@ class UdpListener(nextActor: ActorRef) extends Actor with ActorLogging { def receive = { case Udp.Bound(local) => - println("UDP bound: " + local) + logger.info(s"Now listening on UDP:$local") nextActor ! Hello() context.become(ready(sender())) @@ -35,6 +37,6 @@ class UdpListener(nextActor: ActorRef) extends Actor with ActorLogging { nextActor ! ReceivedPacket(data.toByteVector, remote) case Udp.Unbind => socket ! Udp.Unbind case Udp.Unbound => context.stop(self) - case x : Any => log.error("Unhandled message: " + x.toString) + case x : Any => logger.error("Unhandled message: " + x.toString) } } \ No newline at end of file