[Packet] VNLWorldStatus message - added IP port

Found out that the hidden fields were an array of IP and ports
This commit is contained in:
Chord 2016-03-04 14:47:38 -05:00
parent cc87c15b21
commit f762aa8e1f
3 changed files with 54 additions and 9 deletions

View file

@ -1,5 +1,8 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package psforever.net
import java.net.{InetAddress, InetSocketAddress}
import scodec._ import scodec._
import scodec.bits._ import scodec.bits._
import scodec.codecs._ import scodec.codecs._
@ -24,8 +27,12 @@ object EmpireNeed extends Enumeration {
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint2L) implicit val codec = PacketHelpers.createEnumerationCodec(this, uint2L)
} }
final case class WorldConnectionInfo(address : InetSocketAddress)
final case class WorldInformation(name : String, status : WorldStatus.Value, final case class WorldInformation(name : String, status : WorldStatus.Value,
serverType : ServerType.Value, empireNeed : EmpireNeed.Value) serverType : ServerType.Value,
connections : Vector[WorldConnectionInfo],
empireNeed : EmpireNeed.Value)
final case class VNLWorldStatusMessage(welcomeMessage : String, worlds : Vector[WorldInformation]) final case class VNLWorldStatusMessage(welcomeMessage : String, worlds : Vector[WorldInformation])
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
@ -74,6 +81,28 @@ object VNLWorldStatusMessage extends Marshallable[VNLWorldStatusMessage] {
("status1" | uint8L)).xmap(to, from) ("status1" | uint8L)).xmap(to, from)
} }
implicit val connectionCodec : Codec[WorldConnectionInfo] = {
type DecodeStruct = ByteVector :: Int :: HNil
type EncodeStruct = InetSocketAddress :: HNil
def decode(a : DecodeStruct) : EncodeStruct = a match {
case ipBytes :: port :: HNil =>
val addr = new InetSocketAddress(InetAddress.getByAddress(ipBytes.reverse.toArray), port)
addr :: HNil
}
def encode(a : EncodeStruct) : DecodeStruct = a match {
case addr :: HNil =>
val ip = addr.getAddress.getAddress
val port = addr.getPort
ByteVector(ip).reverse :: port :: HNil
}
(bytes(4) :: uint16L).xmap(decode, encode).as[WorldConnectionInfo]
}
implicit val codec : Codec[VNLWorldStatusMessage] = ( implicit val codec : Codec[VNLWorldStatusMessage] = (
("welcome_message" | PacketHelpers.encodedWideString) :: ("welcome_message" | PacketHelpers.encodedWideString) ::
("worlds" | vectorOfN(uint8L, ( ("worlds" | vectorOfN(uint8L, (
@ -81,7 +110,8 @@ object VNLWorldStatusMessage extends Marshallable[VNLWorldStatusMessage] {
// XXX: this needs to be byte aligned, but not sure how to do this // XXX: this needs to be byte aligned, but not sure how to do this
("world_name" | PacketHelpers.encodedString) :: ( ("world_name" | PacketHelpers.encodedString) :: (
("status_and_type" | statusCodec) :+ ("status_and_type" | statusCodec) :+
("unknown" | constant(hex"01459e25403775")) :+ // TODO: limit the size of this vector to 11 as the client will fail on any more
("connections" | vectorOfN(uint8L, connectionCodec)) :+
("empire_need" | EmpireNeed.codec) ("empire_need" | EmpireNeed.codec)
) )
).as[WorldInformation] ).as[WorldInformation]

View file

@ -1,4 +1,6 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
import java.net.{InetAddress, InetSocketAddress}
import org.specs2.mutable._ import org.specs2.mutable._
import psforever.net._ import psforever.net._
import scodec.bits._ import scodec.bits._
@ -17,9 +19,15 @@ class GamePacketTest extends Specification {
case VNLWorldStatusMessage(message, worlds) => case VNLWorldStatusMessage(message, worlds) =>
worlds.length mustEqual 1 worlds.length mustEqual 1
message mustEqual "Welcome to PlanetSide! " message mustEqual "Welcome to PlanetSide! "
worlds{0}.name mustEqual "gemini" val world = worlds{0}
worlds{0}.empireNeed mustEqual EmpireNeed.NC
worlds{0}.status mustEqual WorldStatus.Up world.name mustEqual "gemini"
world.empireNeed mustEqual EmpireNeed.NC
world.status mustEqual WorldStatus.Up
world.connections.length mustEqual 1
world.connections{0}.address.getPort mustEqual 30007
world.connections{0}.address.getAddress.toString mustEqual "/64.37.158.69"
case default => case default =>
true mustEqual false true mustEqual false
} }
@ -27,7 +35,14 @@ class GamePacketTest extends Specification {
"encode" in { "encode" in {
val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ",
Vector(WorldInformation("gemini", WorldStatus.Up, ServerType.Beta, EmpireNeed.NC))) Vector(
WorldInformation("gemini", WorldStatus.Up, ServerType.Beta,
Vector(
WorldConnectionInfo(new InetSocketAddress(InetAddress.getByName("64.37.158.69"), 30007))
), EmpireNeed.NC
)
)
)
//0100 04 00 01459e2540377540 //0100 04 00 01459e2540377540
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
@ -38,8 +53,8 @@ class GamePacketTest extends Specification {
"encode and decode multiple worlds" in { "encode and decode multiple worlds" in {
val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ",
Vector( Vector(
WorldInformation("PSForever1", WorldStatus.Up, ServerType.Released, EmpireNeed.NC), WorldInformation("PSForever1", WorldStatus.Up, ServerType.Released, Vector(), EmpireNeed.NC),
WorldInformation("PSForever2", WorldStatus.Down, ServerType.Beta, EmpireNeed.TR) WorldInformation("PSForever2", WorldStatus.Down, ServerType.Beta, Vector(), EmpireNeed.TR)
)) ))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector

View file

@ -209,7 +209,7 @@ class LoginSessionActor(session : LoginSession) extends Actor with ActorLogging
val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ",
Vector( Vector(
WorldInformation("gemini", WorldStatus.Up, ServerType.Released, EmpireNeed.NC) WorldInformation("gemini", WorldStatus.Up, ServerType.Released, Vector(), EmpireNeed.NC)
)) ))
sendResponse(PacketCoding.encryptPacket(cryptoState.get, PacketCoding.CreateGamePacket(4, sendResponse(PacketCoding.encryptPacket(cryptoState.get, PacketCoding.CreateGamePacket(4,