Restructure repository

* Move /common/src to /src
* Move services to net.psforever package
* Move /pslogin to /server
This commit is contained in:
Jakob Gillich 2020-08-23 03:26:06 +02:00
parent 89a30ae6f6
commit f4fd78fc5d
958 changed files with 527 additions and 725 deletions

View file

@ -0,0 +1,27 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class ClientStartTest extends Specification {
val string = hex"0001 00000002 00261e27 000001f0"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case ClientStart(nonce) =>
nonce mustEqual 656287232
case _ =>
ko
}
}
"encode" in {
val msg = ClientStart(656287232)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class ConnectionCloseTest extends Specification {
val string = hex"001D"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case ConnectionClose() =>
ok
case _ =>
ko
}
}
"encode" in {
val msg = ConnectionClose()
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -0,0 +1,32 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class ControlSyncRespTest extends Specification {
val string = hex"0008 5268 21392D92 0000000000000276 0000000000000275 0000000000000275 0000000000000276"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case ControlSyncResp(a, b, c, d, e, f) =>
a mustEqual 21096
b mustEqual 0x21392d92
c mustEqual 0x276
d mustEqual 0x275
e mustEqual 0x275
f mustEqual 0x276
case _ =>
ko
}
}
"encode" in {
val encoded = PacketCoding.EncodePacket(ControlSyncResp(21096, 0x21392d92, 0x276, 0x275, 0x275, 0x276)).require
encoded.toByteVector mustEqual string
}
}

View file

@ -0,0 +1,32 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class ControlSyncTest extends Specification {
val string = hex"0007 5268 0000004D 00000052 0000004D 0000007C 0000004D 0000000000000276 0000000000000275"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case ControlSync(a, b, c, d, e, f, g, h) =>
a mustEqual 21096
b mustEqual 0x4d
c mustEqual 0x52
d mustEqual 0x4d
e mustEqual 0x7c
f mustEqual 0x4d
g mustEqual 0x276
h mustEqual 0x275
case _ =>
ko
}
}
"encode" in {
val encoded = PacketCoding.EncodePacket(ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275)).require
encoded.toByteVector mustEqual string
}
}

View file

@ -0,0 +1,31 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class HandleGamePacketTest extends Specification {
//this is the first from a series of SlottedMetaPacket4s; the length field was modified from 12 DC to pass the test
val base =
hex"18 D5 96 00 00 BC 8E 00 03 A2 16 5D A4 5F B0 80 00 04 30 40 00 08 30 46 00 4A 00 48 00 02 02 F0 62 1E 80 80 00 00 00 00 00 3F FF CC 0D 40 00 20 00 03 00 27 C3 01 C8 00 00 03 08 00 00 03 FF FF FF FC A4 04 00 00 62 00 18 02 00 50 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 C8 00 00 01 00 7E C8 00 C8 00 00 00 5D B0 81 40 00 00 00 00 00 00 00 00 00 00 00 00 02 C0 00 40 83 85 46 86 C7 07 8A 4A 80 70 0C 00 01 98 00 00 01 24 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 30 90 78 70 65 5F 6A 6F 69 6E 5F 70 6C 61 74 6F 6F 6E 92 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 34 8F 78 70 65 5F 6A 6F 69 6E 5F 6F 75 74 66 69 74 92 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 31 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 39 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 38 92 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 33 93 78 70 65 5F 77 61 72 70 5F 67 61 74 65 5F 75 73 61 67 65 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 32 92 78 70 65 5F 69 6E 73 74 61 6E 74 5F 61 63 74 69 6F 6E 8E 78 70 65 5F 66 6F 72 6D 5F 73 71 75 61 64 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 36 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 37 8E 78 70 65 5F 6A 6F 69 6E 5F 73 71 75 61 64 8C 78 70 65 5F 62 69 6E 64 5F 61 6D 73 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 35 91 78 70 65 5F 62 69 6E 64 5F 66 61 63 69 6C 69 74"
val string = hex"00 00 01 CB" ++ base
"decode" in {
PacketCoding.DecodePacket(string).require match {
case HandleGamePacket(len, data, extra) =>
len mustEqual 459
data mustEqual base
extra mustEqual BitVector.empty
case _ =>
ko
}
}
"encode" in {
val pkt = HandleGamePacket(base)
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
msg mustEqual string
}
}

View file

@ -0,0 +1,199 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet.control.{ControlSync, MultiPacketBundle, MultiPacketCollector}
import net.psforever.packet.crypto.{ClientFinished, ServerFinished}
import net.psforever.packet.game.ObjectDeleteMessage
import net.psforever.types.PlanetSideGUID
class MultiPacketCollectorTest extends Specification {
val packet1 = ObjectDeleteMessage(PlanetSideGUID(1103), 2)
"MultiPacketBundle" should {
import scodec.bits._
val packet2 = ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275)
"construct" in {
MultiPacketBundle(List(packet1))
ok
}
"fail to construct if not initialized with PlanetSidePackets" in {
MultiPacketBundle(Nil) must throwA[IllegalArgumentException]
}
"concatenate bundles into a new bundle" in {
val obj1 = MultiPacketBundle(List(packet1))
val obj2 = MultiPacketBundle(List(packet2))
val obj3 = obj1 + obj2
obj3 match {
case MultiPacketBundle(list) =>
list.size mustEqual 2
list.head mustEqual packet1
list(1) mustEqual packet2
case _ =>
ko
}
}
"accept PlanetSideGamePackets and PlanetSideControlPackets" in {
MultiPacketBundle(List(packet2, packet1)) match {
case MultiPacketBundle(list) =>
list.size mustEqual 2
list.head mustEqual packet2
list(1) mustEqual packet1
case _ =>
ko
}
}
"ignore other types of PlanetSideContainerPackets" in {
val param = List(packet2, ClientFinished(hex"", hex""), packet1, ServerFinished(hex""))
MultiPacketBundle(param) match { //warning message will display in log
case MultiPacketBundle(list) =>
list.size mustEqual 2
list.head mustEqual param.head
list(1) mustEqual param(2)
case _ =>
ko
}
}
}
"MultiPacketCollector" should {
val packet2 = ObjectDeleteMessage(PlanetSideGUID(1105), 2)
val packet3 = ObjectDeleteMessage(PlanetSideGUID(1107), 2)
"construct" in {
new MultiPacketCollector()
ok
}
"construct with initial packets" in {
MultiPacketCollector(List(packet1, packet2))
ok
}
"can retrieve a bundle packets" in {
val obj = MultiPacketCollector(List(packet1, packet2))
obj.Bundle match {
case Some(MultiPacketBundle(list)) =>
list.size mustEqual 2
list.head mustEqual packet1
list(1) mustEqual packet2
case _ =>
ko
}
}
"can retrieve a bundle of potential packets" in {
val obj1 = new MultiPacketCollector()
obj1.Bundle match {
case Some(_) =>
ko
case _ => ;
}
val obj2 = MultiPacketCollector(List(packet1, packet2))
obj2.Bundle match {
case None =>
ko
case Some(MultiPacketBundle(list)) =>
list.size mustEqual 2
list.head mustEqual packet1
list(1) mustEqual packet2
}
}
"clear packets after being asked to bundle" in {
val list = List(packet1, packet2)
val obj = MultiPacketCollector(list)
obj.Bundle match {
case Some(MultiPacketBundle(bundle)) =>
bundle mustEqual list
case _ =>
ko
}
obj.Bundle match {
case Some(MultiPacketBundle(_)) =>
ko
case _ =>
ok
}
}
"add a packet" in {
val obj = new MultiPacketCollector()
obj.Add(packet1)
obj.Bundle match {
case Some(MultiPacketBundle(list)) =>
list.size mustEqual 1
list.head mustEqual packet1
case _ =>
ko
}
}
"add packets" in {
val obj = new MultiPacketCollector()
obj.Add(List(packet1, packet2))
obj.Bundle match {
case Some(MultiPacketBundle(list)) =>
list.size mustEqual 2
list.head mustEqual packet1
list(1) mustEqual packet2
case _ =>
ko
}
}
"concatenate bundles (1)" in {
val obj1 = new MultiPacketCollector()
obj1.Add(List(packet1, packet2))
obj1.Bundle match {
case Some(MultiPacketBundle(bundle1)) =>
val obj2 = MultiPacketCollector(bundle1)
obj2.Add(packet3)
obj2.Bundle match {
case Some(MultiPacketBundle(list)) =>
list.size mustEqual 3
list.head mustEqual packet1
list(1) mustEqual packet2
list(2) mustEqual packet3
case _ =>
ko
}
case _ =>
ko
}
}
"concatenate bundles (2)" in {
val obj1 = new MultiPacketCollector()
obj1.Add(List(packet1, packet2))
obj1.Bundle match {
case Some(MultiPacketBundle(bundle1)) =>
val obj2 = new MultiPacketCollector()
obj2.Add(packet3)
obj2.Add(bundle1)
obj2.Bundle match {
case Some(MultiPacketBundle(list)) =>
list.size mustEqual 3
list.head mustEqual packet3
list(1) mustEqual packet1
list(2) mustEqual packet2
case _ =>
ko
}
case _ =>
ko
}
}
}
}

View file

@ -0,0 +1,47 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet.control._
import org.specs2.specification.core.Fragment
import scodec.bits._
class MultiPacketExTest extends Specification {
val strings = Vector(
hex"00",
hex"01 41",
hex"01 41" ++ hex"02 4142",
hex"fe" ++ ByteVector.fill(0xfe)(0x41),
hex"ffff00" ++ ByteVector.fill(0xff)(0x41),
hex"ff0001" ++ ByteVector.fill(0x100)(0x41),
hex"ff ffff ffff 0000" ++ ByteVector.fill(0x0000ffff)(0x41),
hex"ff ffff 0000 0100" ++ ByteVector.fill(0x00010000)(0x41)
)
val packets = Vector(
MultiPacketEx(Vector(ByteVector.empty)),
MultiPacketEx(Vector(hex"41")),
MultiPacketEx(Vector(hex"41", hex"4142")),
MultiPacketEx(Vector(ByteVector.fill(0xfe)(0x41))),
MultiPacketEx(Vector(ByteVector.fill(0xff)(0x41))),
MultiPacketEx(Vector(ByteVector.fill(0x100)(0x41))),
MultiPacketEx(Vector(ByteVector.fill(0x0000ffff)(0x41))),
MultiPacketEx(Vector(ByteVector.fill(0x00010000)(0x41)))
)
"decode" in {
Fragment.foreach(strings.indices) { i =>
"test " + i ! { MultiPacketEx.decode(strings { i }.bits).require.value mustEqual packets { i } }
}
}
"encode" in {
Fragment.foreach(packets.indices) { i =>
"test " + i ! { MultiPacketEx.encode(packets { i }).require.toByteVector mustEqual strings { i } }
}
}
"sizeCodec description" in {
MultiPacketEx.sizeCodec.toString mustEqual "variable-bit unsigned integer"
}
}

View file

@ -0,0 +1,41 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class MultiPacketTest extends Specification {
val string =
hex"00 03 04 00 15 13 23 3A 00 09 03 E3 00 19 16 6D 56 05 68 05 40 A0 EF 45 00 15 0E 44 00 A0 A2 41 00 00 0F 88 00 06 E4 C0 60 00 00 00 15 E4 32 40 74 72 61 69 6E 69 6E 67 5F 77 65 61 70 6F 6E 73 30 31 13 BD 68 05 53 F6 EF 90 D1 6E 03 14 FE 78 8C 20 1C C0 00 00 1F 00 09 03 E4 6D 56 05 68 05 40 A0 EF 45 00 15 0E 44 30 89 A1 41 00 00 0F 8A 01 00 04 18 EF 80"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case MultiPacket(data) =>
data.size mustEqual 4
data(0) mustEqual hex"00151323"
data(
1
) mustEqual hex"000903e30019166d5605680540a0ef4500150e4400a0a24100000f880006e4c06000000015e43240747261696e696e675f776561706f6e733031"
data(2) mustEqual hex"bd680553f6ef90d16e0314fe788c201cc00000"
data(3) mustEqual hex"000903e46d5605680540a0ef4500150e443089a14100000f8a01000418ef80"
case _ =>
ko
}
}
"encode" in {
val msg = MultiPacket(
Vector(
hex"00151323",
hex"000903e30019166d5605680540a0ef4500150e4400a0a24100000f880006e4c06000000015e43240747261696e696e675f776561706f6e733031",
hex"bd680553f6ef90d16e0314fe788c201cc00000",
hex"000903e46d5605680540a0ef4500150e443089a14100000f8a01000418ef80"
)
)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -0,0 +1,82 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
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 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 = 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

@ -0,0 +1,82 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
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 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 = 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

@ -0,0 +1,79 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import org.specs2.specification.core.Fragment
import scodec.bits._
import scodec.codecs.uint16
class SlottedMetaPacketTest extends Specification {
val string = hex"00 09 00 00 00194302484C36563130433F" ++
hex"4C6835316369774A0000000018FABE0C" ++
hex"00000000000000000000000001000000" ++
hex"020000006B7BD8288C6469666671756F" ++
hex"7469656E740000000000440597570065" ++
hex"006C0063006F006D006500200074006F" ++
hex"00200050006C0061006E006500740053" ++
hex"0069006400650021002000018667656D" ++
hex"696E690100040001459E2540377540"
def createMetaPacket(slot: Int, subslot: Int, rest: ByteVector) =
hex"00" ++
ControlPacketOpcode.codec
.encode(
ControlPacketOpcode(ControlPacketOpcode.SlottedMetaPacket0.id + slot)
)
.require
.toByteVector ++ uint16.encode(subslot).require.toByteVector ++ rest
"decode as the base slot and subslot" in {
PacketCoding.DecodePacket(string).require match {
case SlottedMetaPacket(slot, subslot, rest) =>
slot mustEqual 0
subslot mustEqual 0
rest mustEqual string.drop(4)
case _ =>
ko
}
}
"decode as an arbitrary slot and subslot" in {
val maxSlots = ControlPacketOpcode.SlottedMetaPacket7.id - ControlPacketOpcode.SlottedMetaPacket0.id
// create all possible SlottedMetaPackets
Fragment.foreach(0 to maxSlots) { i =>
"slot " + i ! {
val subslot = 12323
val pkt = createMetaPacket(i, subslot, ByteVector.empty)
PacketCoding.DecodePacket(pkt).require match {
case SlottedMetaPacket(slot, subslotDecoded, rest) =>
// XXX: there isn't a simple solution to Slot0 and Slot4 be aliases of each other structurally
// This is probably best left to higher layers
//slot mustEqual i % 4 // this is seen at 0x00A3FBFA
slot mustEqual i
subslotDecoded mustEqual subslot
rest mustEqual ByteVector.empty // empty in this case
case _ =>
ko
}
}
}
}
"encode" in {
val encoded = PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x1000, ByteVector.empty)).require
val encoded2 = PacketCoding.EncodePacket(SlottedMetaPacket(3, 0xffff, hex"414243")).require
val encoded3 = PacketCoding.EncodePacket(SlottedMetaPacket(7, 0, hex"00")).require
encoded.toByteVector mustEqual createMetaPacket(0, 0x1000, ByteVector.empty)
encoded2.toByteVector mustEqual createMetaPacket(3, 0xffff, hex"414243")
encoded3.toByteVector mustEqual createMetaPacket(7, 0, hex"00")
PacketCoding.EncodePacket(SlottedMetaPacket(8, 0, hex"00")).require must throwA[AssertionError]
PacketCoding.EncodePacket(SlottedMetaPacket(-1, 0, hex"00")).require must throwA[AssertionError]
PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x10000, hex"00")).require must throwA[IllegalArgumentException]
}
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2017 PSForever
package control
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.control._
import scodec.bits._
class TeardownConnectionTest extends Specification {
val string = hex"00 05 02 4F 57 17 00 06"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case TeardownConnection(nonce) =>
nonce mustEqual 391597826
case _ =>
ko
}
}
"encode" in {
val encoded = PacketCoding.EncodePacket(TeardownConnection(391597826)).require
encoded.toByteVector mustEqual string
}
}