Handle meta packet and return ack. server scroller

The scroller isn't usable in production as the client will deselect the
server listing each time the list is updated. This prevents you from
selecting a server.
This commit is contained in:
Chord 2016-05-04 23:03:30 -04:00
parent c7f70e3543
commit cdf240cf66
3 changed files with 131 additions and 29 deletions

View file

@ -0,0 +1,35 @@
// Copyright (c) 2016 PSForever.net to present
package net.psforever.packet.control
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
import scodec.Codec
import scodec.bits.{BitVector, ByteOrdering, ByteVector}
import scodec.codecs._
final case class SlottedMetaAck(slot : Int, subslot : Int)
extends PlanetSideControlPacket {
type Packet = SlottedMetaAck
assert(slot >= 0 && slot <= 7, s"Slot number ($slot) is out of range")
def opcode = {
val base = ControlPacketOpcode.RelatedB0.id
ControlPacketOpcode(base + slot % 4)
}
// XXX: a nasty hack to ignore the "slot" field
// There is so much wrong with this it's not even funny. Why scodec, whyyyy...
// I've never had a library make me feel so stupid and smart at the same time
def encode = SlottedMetaAck.encode(this).map(vect => vect.drop(8))
}
object SlottedMetaAck extends Marshallable[SlottedMetaAck] {
implicit val codec : Codec[SlottedMetaAck] = (
("slot" | uint8L.xmap[Int](a => a - ControlPacketOpcode.RelatedB0.id, a=>a) ) ::
("subslot" | uint16)
).as[SlottedMetaAck]
def decodeWithOpcode(slot : ControlPacketOpcode.Value)(bits : BitVector) = {
decode(ControlPacketOpcode.codec.encode(slot).require ++ bits)
}
}

View file

@ -255,7 +255,8 @@ class CryptoSessionActor extends Actor with MDCContextAware {
def handleEstablishedPacket(from : ActorRef, cont : PlanetSidePacketContainer) = {
// we are processing a packet we decrypted
if(from == self) {
rightRef ! cont
import MDCContextAware.Implicits._
rightRef !> cont
} else if(from == rightRef) { // processing a completed packet from the right. encrypt
val packet = PacketCoding.encryptPacket(cryptoState.get, cont).require
sendResponse(packet)

View file

@ -2,15 +2,19 @@
import java.net.{InetAddress, InetSocketAddress}
import akka.actor.{Actor, ActorRef, MDCContextAware}
import net.psforever.packet._
import net.psforever.packet.{PlanetSideGamePacket, _}
import net.psforever.packet.control._
import net.psforever.packet.game._
import scodec.Attempt.{Failure, Successful}
import scodec.bits._
import scala.util.Random
class LoginSessionActor extends Actor with MDCContextAware {
private[this] val log = org.log4s.getLogger
private case class UpdateServerList()
var leftRef : ActorRef = ActorRef.noSender
var rightRef : ActorRef = ActorRef.noSender
@ -28,27 +32,108 @@ class LoginSessionActor extends Actor with MDCContextAware {
}
def Started : Receive = {
case UpdateServerList() =>
updateServerList
case ctrl @ ControlPacket(_, _) =>
handlePkt(ctrl)
handlePktContainer(ctrl)
case game @ GamePacket(_, _, _) =>
handlePkt(game)
handlePktContainer(game)
case default => failWithError(s"Invalid packet class received: $default")
}
def handlePkt(pkt : PlanetSidePacketContainer) : Unit = pkt match {
def handlePkt(pkt : PlanetSidePacket) : Unit = pkt match {
case ctrl : PlanetSideControlPacket =>
handleControlPkt(ctrl)
case game : PlanetSideGamePacket =>
handleGamePkt(game)
case default => failWithError(s"Invalid packet class received: $default")
}
def handlePktContainer(pkt : PlanetSidePacketContainer) : Unit = pkt match {
case ctrl @ ControlPacket(opcode, ctrlPkt) =>
handleControlPkt(ctrlPkt)
case game @ GamePacket(opcode, seq, gamePkt) =>
handleGamePkt(gamePkt)
case default => failWithError(s"Invalid packet class received: $default")
case default => failWithError(s"Invalid packet container class received: $default")
}
def handleControlPkt(pkt : PlanetSideControlPacket) = {
pkt match {
case meta @ SlottedMetaPacket(slot, subslot, innerPacket) =>
case SlottedMetaPacket(slot, subslot, innerPacket) =>
sendResponse(PacketCoding.CreateControlPacket(SlottedMetaAck(slot, subslot)))
PacketCoding.DecodePacket(innerPacket) match {
case Successful(p) =>
log.trace("RECV[INNER]: " + p)
case Failure(e) =>
log.error(s"Failed to decode inner packet of SlottedMetaPacket: $e")
case Successful(v) =>
handlePkt(v)
}
case MultiPacket(packets) =>
packets.foreach { pkt =>
PacketCoding.DecodePacket(pkt) match {
case Failure(e) =>
log.error(s"Failed to decode inner packet of MultiPacket: $e")
case Successful(v) =>
handlePkt(v)
}
}
case default =>
log.debug(s"Unhandled ControlPacket $default")
}
}
def handleGamePkt(pkt : PlanetSideGamePacket) = pkt match {
case LoginMessage(majorVersion, minorVersion, buildDate, username,
password, token, revision) =>
val clientVersion = s"Client Version: ${majorVersion}.${minorVersion}.${revision}, ${buildDate}"
if(token.isDefined)
log.info(s"New login UN:$username Token:${token.get}. ${clientVersion}")
else
log.info(s"New login UN:$username PW:$password. ${clientVersion}")
val newToken = token.getOrElse("THISISMYTOKENYES")
val response = LoginRespMessage(newToken, hex"00000000 18FABE0C 00000000 00000000",
0, 1, 2, 685276011, username, 0, false)
sendResponse(PacketCoding.CreateGamePacket(0, response))
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
context.system.scheduler.schedule(0 seconds, 250 milliseconds, self, UpdateServerList())
case default => log.debug(s"Unhandled GamePacket ${pkt}")
}
val scrollerWindow = 20
val scrollerText = "PSForever_The_next_generation_of_PlanetSide_Hey_what_a_neat_scroller!"
var scrollerOffset = 0
def updateServerList = {
val start = scrollerOffset % scrollerText.length
var end = (scrollerOffset+scrollerWindow) % scrollerText.length
var finalName = ""
if(end < start)
finalName = scrollerText.substring(start, scrollerText.length) + ";" + scrollerText.substring(0, end)
else
finalName = scrollerText.substring(start, end)
scrollerOffset += 1
//println(finalName)
val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ",
Vector(
WorldInformation(finalName, WorldStatus.Up, ServerType.Development,
Vector(WorldConnectionInfo(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 51000))), EmpireNeed.TR)
))
sendResponse(PacketCoding.CreateGamePacket(0, msg))
}
/*
val packet = LoginRespMessage("AAAABBBBCCCCDDDD",
hex"00000000 18FABE0C 00000000 00000000",
@ -65,26 +150,7 @@ class LoginSessionActor extends Actor with MDCContextAware {
))
sendResponse(PacketCoding.CreateGamePacket(0, msg))
case Failure(e) => log.error("Failed to decode inner packet " + e)
}
case MultiPacket(packets) =>
packets.foreach { pkt =>
PacketCoding.UnmarshalPacket(pkt) match {
case Failure(e) =>
log.error(s"Failed to decode inner packet of MultiPacket: $e")
case Successful(v) =>
handlePkt(v) // dont send a message to ourselves as then packets will be processed in the wrong order
}
}
case default =>
log.debug(s"Unhandled ControlPacket $default")
}
}
def handleGamePkt(pkt : PlanetSideGamePacket) = {
log.debug(s"Unhandled GamePacket ${pkt}")
}
*/
def failWithError(error : String) = {
log.error(error)
//sendResponse(PacketCoding.CreateControlPacket(ConnectionClose()))