mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 15:34:42 +00:00
New SLF4J logger log4s. ANSI colors
Used jANSI for Windows console color support. Log4s for a Scala logging facade (which uses SLF4J). Using logback as the logging driver.
This commit is contained in:
parent
36d9f5134c
commit
1318ebd751
7 changed files with 77 additions and 39 deletions
13
build.sbt
13
build.sbt
|
|
@ -5,12 +5,15 @@ lazy val commonSettings = Seq(
|
||||||
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),
|
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),
|
||||||
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
|
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
|
||||||
libraryDependencies := Seq(
|
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",
|
"com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
|
||||||
"org.specs2" %% "specs2-core" % "2.3.11" % "test",
|
"org.specs2" %% "specs2-core" % "2.3.11" % "test",
|
||||||
"org.scodec" %% "scodec-core" % "1.8.3",
|
"org.scodec" %% "scodec-core" % "1.8.3",
|
||||||
"org.scodec" %% "scodec-akka" % "0.1.0-SNAPSHOT",
|
"org.scodec" %% "scodec-akka" % "0.1.0-SNAPSHOT",
|
||||||
"net.java.dev.jna" % "jna" % "4.2.1"
|
"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"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class GamePacketTest extends Specification {
|
||||||
|
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
println(pkt)
|
//println(pkt)
|
||||||
|
|
||||||
true mustEqual true
|
true mustEqual true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2016 PSForever.net to present
|
// Copyright (c) 2016 PSForever.net to present
|
||||||
import java.net.{InetAddress, InetSocketAddress}
|
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.{CryptoStateWithMAC, CryptoState}
|
||||||
import psforever.crypto.CryptoInterface
|
import psforever.crypto.CryptoInterface
|
||||||
import psforever.net._
|
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.
|
* 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 leftRef : ActorRef = ActorRef.noSender
|
||||||
var rightRef : ActorRef = ActorRef.noSender
|
var rightRef : ActorRef = ActorRef.noSender
|
||||||
|
|
||||||
|
|
@ -43,7 +45,7 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
|
|
||||||
context.become(NewClient)
|
context.become(NewClient)
|
||||||
case _ =>
|
case _ =>
|
||||||
log.error("Unknown message")
|
logger.error("Unknown message")
|
||||||
context.stop(self)
|
context.stop(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +53,7 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
case RawPacket(msg) =>
|
case RawPacket(msg) =>
|
||||||
// PacketCoding.DecodePacket
|
// PacketCoding.DecodePacket
|
||||||
PacketCoding.UnmarshalPacket(msg) match {
|
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) =>
|
case Successful(p) =>
|
||||||
//println("RECV: " + p)
|
//println("RECV: " + p)
|
||||||
|
|
||||||
|
|
@ -61,16 +63,16 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
|
|
||||||
context.become(CryptoExchange)
|
context.become(CryptoExchange)
|
||||||
case default =>
|
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 = {
|
def CryptoExchange : Receive = {
|
||||||
case RawPacket(msg) =>
|
case RawPacket(msg) =>
|
||||||
PacketCoding.UnmarshalPacket(msg, CryptoPacketOpcode.ClientChallengeXchg) match {
|
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) =>
|
case Successful(p) =>
|
||||||
//println("RECV: " + p)
|
//println("RECV: " + p)
|
||||||
|
|
||||||
|
|
@ -100,16 +102,16 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
serverMACBuffer ++= sentPacket.drop(3)
|
serverMACBuffer ++= sentPacket.drop(3)
|
||||||
|
|
||||||
context.become(CryptoSetupFinishing)
|
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 = {
|
def CryptoSetupFinishing : Receive = {
|
||||||
case RawPacket(msg) =>
|
case RawPacket(msg) =>
|
||||||
PacketCoding.UnmarshalPacket(msg, CryptoPacketOpcode.ClientFinished) match {
|
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) =>
|
case Successful(p) =>
|
||||||
//println("RECV: " + p)
|
//println("RECV: " + p)
|
||||||
|
|
||||||
|
|
@ -203,12 +205,12 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
|
|
||||||
self ! packet
|
self ! packet
|
||||||
case Failure(e) =>
|
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 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(_, _) =>
|
case ctrl @ ControlPacket(_, _) =>
|
||||||
val from = sender()
|
val from = sender()
|
||||||
|
|
@ -222,7 +224,7 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
}
|
}
|
||||||
|
|
||||||
def failWithError(error : String) = {
|
def failWithError(error : String) = {
|
||||||
log.error(error)
|
logger.error(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
def resetState() : Unit = {
|
def resetState() : Unit = {
|
||||||
|
|
@ -253,7 +255,7 @@ class CryptoSessionActor extends Actor with ActorLogging {
|
||||||
val packet = PacketCoding.encryptPacket(cryptoState.get, cont).require
|
val packet = PacketCoding.encryptPacket(cryptoState.get, cont).require
|
||||||
sendResponse(packet)
|
sendResponse(packet)
|
||||||
} else {
|
} else {
|
||||||
log.error("Invalid sender")
|
logger.error("Invalid sender")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import psforever.net._
|
||||||
import scodec.Attempt.{Failure, Successful}
|
import scodec.Attempt.{Failure, Successful}
|
||||||
import scodec.bits._
|
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 leftRef : ActorRef = ActorRef.noSender
|
||||||
var rightRef : ActorRef = ActorRef.noSender
|
var rightRef : ActorRef = ActorRef.noSender
|
||||||
|
|
||||||
|
|
@ -19,7 +21,7 @@ class LoginSessionActor extends Actor with ActorLogging {
|
||||||
|
|
||||||
context.become(Started)
|
context.become(Started)
|
||||||
case _ =>
|
case _ =>
|
||||||
log.error("Unknown message")
|
logger.error("Unknown message")
|
||||||
context.stop(self)
|
context.stop(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +38,7 @@ class LoginSessionActor extends Actor with ActorLogging {
|
||||||
case SlottedMetaPacket(innerPacket) =>
|
case SlottedMetaPacket(innerPacket) =>
|
||||||
PacketCoding.DecodePacket(innerPacket) match {
|
PacketCoding.DecodePacket(innerPacket) match {
|
||||||
case Successful(p) =>
|
case Successful(p) =>
|
||||||
println("RECV[INNER]: " + p)
|
logger.trace("RECV[INNER]: " + p)
|
||||||
|
|
||||||
val packet = LoginRespMessage("AAAABBBBCCCCDDDD",
|
val packet = LoginRespMessage("AAAABBBBCCCCDDDD",
|
||||||
hex"00000000 18FABE0C 00000000 00000000",
|
hex"00000000 18FABE0C 00000000 00000000",
|
||||||
|
|
@ -53,7 +55,7 @@ class LoginSessionActor extends Actor with ActorLogging {
|
||||||
))
|
))
|
||||||
|
|
||||||
sendResponse(PacketCoding.CreateGamePacket(0, msg))
|
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) = {
|
def failWithError(error : String) = {
|
||||||
log.error(error)
|
logger.error(error)
|
||||||
sendResponse(PacketCoding.CreateControlPacket(ConnectionClose()))
|
sendResponse(PacketCoding.CreateControlPacket(ConnectionClose()))
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendResponse(cont : PlanetSidePacketContainer) = {
|
def sendResponse(cont : PlanetSidePacketContainer) = {
|
||||||
println("LOGIN SEND: " + cont)
|
logger.trace("LOGIN SEND: " + cont)
|
||||||
rightRef ! cont
|
rightRef ! cont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,52 @@
|
||||||
// Copyright (c) 2016 PSForever.net to present
|
// 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 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 {
|
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 = {
|
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 {
|
try {
|
||||||
CryptoInterface.initialize()
|
CryptoInterface.initialize()
|
||||||
println("Crypto initialized")
|
logger.info("PSCrypto initialized")
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
case e : UnsatisfiedLinkError =>
|
case e : UnsatisfiedLinkError =>
|
||||||
println("Unable to initialize " + CryptoInterface.libName)
|
logger.error(e)("Unable to initialize " + CryptoInterface.libName)
|
||||||
println("Reason: " + e.getMessage)
|
|
||||||
e.getStackTrace.foreach(println)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info("Starting actor subsystems...")
|
||||||
|
|
||||||
val system = ActorSystem("PsLogin")
|
val system = ActorSystem("PsLogin")
|
||||||
val session = system.actorOf(Props[SessionRouter], "session-router")
|
val session = system.actorOf(Props[SessionRouter], "session-router")
|
||||||
val listener = system.actorOf(Props(new UdpListener(session)), "udp-listener")
|
val listener = system.actorOf(Props(new UdpListener(session)), "udp-listener")
|
||||||
|
|
||||||
|
system.awaitTermination()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ case class SessionState(id : Long, address : InetSocketAddress, pipeline : List[
|
||||||
def inject(pkt : RawPacket) = pipeline.head ! pkt
|
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 idBySocket = mutable.Map[InetSocketAddress, Long]()
|
||||||
val sessionById = mutable.Map[Long, SessionState]()
|
val sessionById = mutable.Map[Long, SessionState]()
|
||||||
val sessionByActor = mutable.Map[ActorRef, SessionState]()
|
val sessionByActor = mutable.Map[ActorRef, SessionState]()
|
||||||
|
|
@ -43,7 +45,7 @@ class SessionRouter extends Actor with ActorLogging {
|
||||||
inputRef = sender()
|
inputRef = sender()
|
||||||
context.become(started)
|
context.become(started)
|
||||||
case _ =>
|
case _ =>
|
||||||
log.error("Unknown message")
|
logger.error("Unknown message")
|
||||||
context.stop(self)
|
context.stop(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,7 +54,7 @@ class SessionRouter extends Actor with ActorLogging {
|
||||||
if(idBySocket.contains(from)) {
|
if(idBySocket.contains(from)) {
|
||||||
sessionById{idBySocket{from}}.inject(RawPacket(msg))
|
sessionById{idBySocket{from}}.inject(RawPacket(msg))
|
||||||
} else {
|
} else {
|
||||||
log.info("New session from " + from.toString)
|
logger.info("New session from " + from.toString)
|
||||||
|
|
||||||
val session = createNewSession(from)
|
val session = createNewSession(from)
|
||||||
idBySocket{from} = session.id
|
idBySocket{from} = session.id
|
||||||
|
|
@ -66,7 +68,7 @@ class SessionRouter extends Actor with ActorLogging {
|
||||||
val session = sessionByActor{sender()}
|
val session = sessionByActor{sender()}
|
||||||
|
|
||||||
inputRef ! SendPacket(msg, session.address)
|
inputRef ! SendPacket(msg, session.address)
|
||||||
case _ => log.error("Unknown message")
|
case _ => logger.error("Unknown message")
|
||||||
}
|
}
|
||||||
|
|
||||||
def createNewSession(address : InetSocketAddress) = {
|
def createNewSession(address : InetSocketAddress) = {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,9 @@ final case class SendPacket(msg : ByteVector, to : InetSocketAddress)
|
||||||
final case class Hello()
|
final case class Hello()
|
||||||
final case class HelloFriend(next: ActorRef)
|
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
|
import context.system
|
||||||
IO(Udp) ! Udp.Bind(self, new InetSocketAddress("127.0.0.1", 51000))
|
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 = {
|
def receive = {
|
||||||
case Udp.Bound(local) =>
|
case Udp.Bound(local) =>
|
||||||
println("UDP bound: " + local)
|
logger.info(s"Now listening on UDP:$local")
|
||||||
|
|
||||||
nextActor ! Hello()
|
nextActor ! Hello()
|
||||||
context.become(ready(sender()))
|
context.become(ready(sender()))
|
||||||
|
|
@ -35,6 +37,6 @@ class UdpListener(nextActor: ActorRef) extends Actor with ActorLogging {
|
||||||
nextActor ! ReceivedPacket(data.toByteVector, remote)
|
nextActor ! ReceivedPacket(data.toByteVector, remote)
|
||||||
case Udp.Unbind => socket ! Udp.Unbind
|
case Udp.Unbind => socket ! Udp.Unbind
|
||||||
case Udp.Unbound => context.stop(self)
|
case Udp.Unbound => context.stop(self)
|
||||||
case x : Any => log.error("Unhandled message: " + x.toString)
|
case x : Any => logger.error("Unhandled message: " + x.toString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue