RelatedA0 and RelatedB0 have been superceded by RelatedA and RelatedB, respectively, with slots 0-3 for each; SlottedMetaAck has been removed and tests have been changed

This commit is contained in:
FateJH 2018-03-12 23:16:49 -04:00
parent adb7738268
commit 68e3377d2e
10 changed files with 211 additions and 131 deletions

View file

@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet
import net.psforever.packet.control.SlottedMetaPacket
import net.psforever.packet.control.{RelatedA, RelatedB, SlottedMetaPacket}
import scodec.bits.BitVector
import scodec.{Attempt, Codec, DecodeResult, Err}
import scodec.codecs._
@ -74,15 +74,15 @@ object ControlPacketOpcode extends Enumeration {
// OPCODES 0x10-1e
case 0x10 => SlottedMetaPacket.decodeWithOpcode(SlottedMetaPacket7)
case 0x11 => control.RelatedA0.decode
case 0x12 => noDecoder(RelatedA1)
case 0x13 => noDecoder(RelatedA2)
case 0x14 => noDecoder(RelatedA3)
case 0x15 => control.RelatedB0.decode
case 0x16 => noDecoder(RelatedB1)
case 0x17 => noDecoder(RelatedB2)
case 0x11 => RelatedA.decodeWithOpcode(RelatedA0)
case 0x12 => RelatedA.decodeWithOpcode(RelatedA1)
case 0x13 => RelatedA.decodeWithOpcode(RelatedA2)
case 0x14 => RelatedA.decodeWithOpcode(RelatedA3)
case 0x15 => RelatedB.decodeWithOpcode(RelatedB0)
case 0x16 => RelatedB.decodeWithOpcode(RelatedB1)
case 0x17 => RelatedB.decodeWithOpcode(RelatedB2)
// 0x18
case 0x18 => noDecoder(RelatedB3)
case 0x18 => RelatedB.decodeWithOpcode(RelatedB3)
case 0x19 => control.MultiPacketEx.decode
case 0x1a => noDecoder(Unknown26)
case 0x1b => noDecoder(Unknown27)

View file

@ -0,0 +1,38 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet.control
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
import scodec.Codec
import scodec.bits.BitVector
import scodec.codecs._
/**
* Dispatched from the client in regards to errors trying to process prior `ControlPackets`.
* Explains which packet was in error by sending back its `subslot` number.
* @param slot the type of `ResultA` packet;
* valid types are integers 0-3
* @param subslot identification of a control packet
*/
final case class RelatedA(slot : Int, subslot : Int) extends PlanetSideControlPacket {
type Packet = RelatedA
if(slot < 0 || slot > 3) {
throw new IllegalArgumentException(s"slot number is out of range - $slot")
}
def opcode = {
val base = ControlPacketOpcode.RelatedA0.id
ControlPacketOpcode(base + slot)
}
def encode = RelatedA.encode(this).map(vect => vect.drop(8))
}
object RelatedA extends Marshallable[RelatedA] {
implicit val codec : Codec[RelatedA] = (
("slot" | uint8L.xmap[Int](a => a - ControlPacketOpcode.RelatedA0.id, a=>a) ) ::
("subslot" | uint16) // the slot is big endian. see 0x00A42F76
).as[RelatedA]
def decodeWithOpcode(slot : ControlPacketOpcode.Value)(bits : BitVector) = {
decode(ControlPacketOpcode.codec.encode(slot).require ++ bits)
}
}

View file

@ -1,22 +0,0 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet.control
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
import scodec.Codec
import scodec.codecs._
/**
* Dispatched from the client in regards to errors trying to process prior `ControlPackets`.
* Explains which packet was in error by sending back its `subslot` number.
* @param subslot identification of a control packet
*/
final case class RelatedA0(subslot : Int)
extends PlanetSideControlPacket {
type Packet = RelatedA0
def opcode = ControlPacketOpcode.RelatedA0
def encode = RelatedA0.encode(this)
}
object RelatedA0 extends Marshallable[RelatedA0] {
implicit val codec : Codec[RelatedA0] = ("subslot" | uint16).as[RelatedA0]
}

View file

@ -0,0 +1,39 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet.control
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
import scodec.Codec
import scodec.bits.BitVector
import scodec.codecs._
/**
* Dispatched to coordinate information regarding `ControlPacket` packets between the client and server.
* When dispatched by the client, it relates the current (or last received) `SlottedMetaPacket` `subslot` number back to the server.
* When dispatched by the server, it relates ???
* @param slot the type of `ResultB` packet;
* valid types are integers 0-3
* @param subslot identification of a control packet
*/
final case class RelatedB(slot : Int, subslot : Int) extends PlanetSideControlPacket {
type Packet = RelatedB
if(slot < 0 || slot > 3) {
throw new IllegalArgumentException(s"slot number is out of range - $slot")
}
def opcode = {
val base = ControlPacketOpcode.RelatedB0.id
ControlPacketOpcode(base + slot)
}
def encode = RelatedB.encode(this).map(vect => vect.drop(8))
}
object RelatedB extends Marshallable[RelatedB] {
implicit val codec : Codec[RelatedB] = (
("slot" | uint8L.xmap[Int](a => a - ControlPacketOpcode.RelatedB0.id, a=>a) ) ::
("subslot" | uint16) // the slot is big endian. see 0x00A42F76
).as[RelatedB]
def decodeWithOpcode(slot : ControlPacketOpcode.Value)(bits : BitVector) = {
decode(ControlPacketOpcode.codec.encode(slot).require ++ bits)
}
}

View file

@ -1,23 +0,0 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet.control
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
import scodec.Codec
import scodec.codecs._
/**
* Dispatched to coordinate information regarding `ControlPacket` packets between the client and server.
* When dispatched by the client, it relates the current (or last received) `SlottedMetaPacket` `subslot` number back to the server.
* When dispatched by the server, it relates ???
* @param subslot identification of a control packet
*/
final case class RelatedB0(subslot : Int)
extends PlanetSideControlPacket {
type Packet = RelatedB0
def opcode = ControlPacketOpcode.RelatedB0
def encode = RelatedB0.encode(this)
}
object RelatedB0 extends Marshallable[RelatedB0] {
implicit val codec : Codec[RelatedB0] = ("subslot" | uint16).as[RelatedB0]
}

View file

@ -1,35 +0,0 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet.control
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
import scodec.Codec
import scodec.bits.BitVector
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") //TODO 7 types of SlottedMeta, 4 types of ResultB?
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

@ -3,24 +3,80 @@ package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import net.psforever.packet.control.RelatedA
import scodec.bits._
class RelatedATest extends Specification {
val string0 = hex"00 11 01 04"
val string1 = hex"00 12 01 04"
val string2 = hex"00 13 01 04"
val string3 = hex"00 14 01 04"
"decode (0)" in {
PacketCoding.DecodePacket(string0).require match {
case RelatedA0(slot) =>
slot mustEqual 260
case RelatedA(slot, subslot) =>
slot mustEqual 0
subslot mustEqual 260
case _ =>
ko
}
}
"decode (1)" in {
PacketCoding.DecodePacket(string1).require match {
case RelatedA(slot, subslot) =>
slot mustEqual 1
subslot mustEqual 260
case _ =>
ko
}
}
"decode (2)" in {
PacketCoding.DecodePacket(string2).require match {
case RelatedA(slot, subslot) =>
slot mustEqual 2
subslot mustEqual 260
case _ =>
ko
}
}
"decode (3)" in {
PacketCoding.DecodePacket(string3).require match {
case RelatedA(slot, subslot) =>
slot mustEqual 3
subslot mustEqual 260
case _ =>
ko
}
}
"encode (0)" in {
val pkt = RelatedA0(260)
val pkt = RelatedA(0, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string0
}
"encode (1)" in {
val pkt = RelatedA(1, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string1
}
"encode (2)" in {
val pkt = RelatedA(2, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string2
}
"encode (3)" in {
val pkt = RelatedA(3, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string3
}
"encode (n)" in {
RelatedA(4, 260) must throwA[IllegalArgumentException]
}
}

View file

@ -3,24 +3,80 @@ package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import net.psforever.packet.control.RelatedB
import scodec.bits._
class RelatedBTest extends Specification {
val string0 = hex"00 15 01 04"
val string1 = hex"00 16 01 04"
val string2 = hex"00 17 01 04"
val string3 = hex"00 18 01 04"
"decode (0)" in {
PacketCoding.DecodePacket(string0).require match {
case RelatedB0(slot) =>
slot mustEqual 260
case RelatedB(slot, subslot) =>
slot mustEqual 0
subslot mustEqual 260
case _ =>
ko
}
}
"decode (1)" in {
PacketCoding.DecodePacket(string1).require match {
case RelatedB(slot, subslot) =>
slot mustEqual 1
subslot mustEqual 260
case _ =>
ko
}
}
"decode (2)" in {
PacketCoding.DecodePacket(string2).require match {
case RelatedB(slot, subslot) =>
slot mustEqual 2
subslot mustEqual 260
case _ =>
ko
}
}
"decode (3)" in {
PacketCoding.DecodePacket(string3).require match {
case RelatedB(slot, subslot) =>
slot mustEqual 3
subslot mustEqual 260
case _ =>
ko
}
}
"encode (0)" in {
val pkt = RelatedB0(260)
val pkt = RelatedB(0, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string0
}
"encode (1)" in {
val pkt = RelatedB(1, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string1
}
"encode (2)" in {
val pkt = RelatedB(2, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string2
}
"encode (3)" in {
val pkt = RelatedB(3, 260)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string3
}
"encode (n)" in {
RelatedB(4, 260) must throwA[IllegalArgumentException]
}
}

View file

@ -1,29 +0,0 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class SlottedMetaAckTest extends Specification {
val string = hex"00150da4"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case SlottedMetaAck(_, _) =>
ko
case RelatedB0(subslot) => //important!
subslot mustEqual 3492
case _ =>
ko
}
}
"encode" in {
val pkt = SlottedMetaAck(0, 3492)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string
}
}

View file

@ -241,7 +241,7 @@ class PacketCodingActor extends Actor with MDCContextAware {
packet match {
case SlottedMetaPacket(slot, subslot, innerPacket) =>
subslotInbound = subslot
self.tell(PacketCoding.CreateControlPacket(SlottedMetaAck(slot, subslot)), rightRef) //will go towards network
self.tell(PacketCoding.CreateControlPacket(RelatedB(slot, subslot)), rightRef) //will go to the network
UnmarshalInnerPacket(innerPacket, "the inner packet of a SlottedMetaPacket")
case MultiPacket(packets) =>
@ -250,11 +250,11 @@ class PacketCodingActor extends Actor with MDCContextAware {
case MultiPacketEx(packets) =>
packets.foreach { UnmarshalInnerPacket(_, "the inner packet of a MultiPacketEx") }
case RelatedA0(subslot) =>
log.error(s"bad subslot data - $subslot; potential disarray")
case RelatedA(slot, subslot) =>
log.error(s"result $slot: subslot $subslot was in error")
case RelatedB0(subslot) =>
log.trace(s"good control packet received - subslot data $subslot")
case RelatedB(slot, subslot) =>
log.trace(s"result $slot: subslot $subslot accepted")
case _ =>
sendResponseRight(container)