Refactor package naming scheme and line endings (CRLF)

This commit is contained in:
Chord 2016-05-03 03:58:58 -04:00
parent 14e48d47ae
commit df1d222df8
31 changed files with 404 additions and 385 deletions

View file

@ -1,5 +1,5 @@
lazy val commonSettings = Seq( lazy val commonSettings = Seq(
organization := "net.psforever", organization := "net.net.psforever",
version := "1.0", version := "1.0",
scalaVersion := "2.11.7", scalaVersion := "2.11.7",
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"), scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever package net.psforever
class ObjectFinalizedException(msg : String) extends Exception(msg) class ObjectFinalizedException(msg : String) extends Exception(msg)

View file

@ -1,7 +1,7 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.crypto package net.psforever.crypto
import psforever.IFinalizable import net.psforever.IFinalizable
import sna.Library import sna.Library
import com.sun.jna.Pointer import com.sun.jna.Pointer
import scodec.bits.ByteVector import scodec.bits.ByteVector
@ -63,6 +63,7 @@ object CryptoInterface {
/** /**
* Checks if two MAC values are the same in constant time, preventing a timing attack for MAC forgery * Checks if two MAC values are the same in constant time, preventing a timing attack for MAC forgery
*
* @param mac1 * @param mac1
* @param mac2 * @param mac2
*/ */
@ -218,6 +219,7 @@ object CryptoInterface {
val encryptionMACKey : ByteVector) extends CryptoState(decryptionKey, encryptionKey) { val encryptionMACKey : ByteVector) extends CryptoState(decryptionKey, encryptionKey) {
/** /**
* Performs a MAC operation over the message. Used when encrypting packets * Performs a MAC operation over the message. Used when encrypting packets
*
* @param message * @param message
* @return ByteVector * @return ByteVector
*/ */
@ -227,6 +229,7 @@ object CryptoInterface {
/** /**
* Performs a MAC operation over the message. Used when verifying decrypted packets * Performs a MAC operation over the message. Used when verifying decrypted packets
*
* @param message * @param message
* @return ByteVector * @return ByteVector
*/ */
@ -237,6 +240,7 @@ object CryptoInterface {
/** /**
* MACs the plaintext message, encrypts it, and then returns the encrypted message with the * MACs the plaintext message, encrypts it, and then returns the encrypted message with the
* MAC appended to the end. * MAC appended to the end.
*
* @param message Arbitrary set of bytes * @param message Arbitrary set of bytes
* @return ByteVector * @return ByteVector
*/ */

View file

@ -1,36 +1,36 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class ClientChallengeXchg(time : Long, challenge : ByteVector, p : ByteVector, g : ByteVector) final case class ClientChallengeXchg(time : Long, challenge : ByteVector, p : ByteVector, g : ByteVector)
extends PlanetSideCryptoPacket { extends PlanetSideCryptoPacket {
def opcode = CryptoPacketOpcode.ClientChallengeXchg def opcode = CryptoPacketOpcode.ClientChallengeXchg
def encode = ClientChallengeXchg.encode(this) def encode = ClientChallengeXchg.encode(this)
} }
object ClientChallengeXchg extends Marshallable[ClientChallengeXchg] { object ClientChallengeXchg extends Marshallable[ClientChallengeXchg] {
implicit val codec: Codec[ClientChallengeXchg] = ( implicit val codec: Codec[ClientChallengeXchg] = (
("unknown" | constant(1)) :: ("unknown" | constant(1)) ::
("unknown" | constant(1)) :: ("unknown" | constant(1)) ::
("client_time" | uint32L) :: ("client_time" | uint32L) ::
("challenge" | bytes(12)) :: ("challenge" | bytes(12)) ::
("end_chal?" | constant(0)) :: ("end_chal?" | constant(0)) ::
("objects?" | constant(1)) :: ("objects?" | constant(1)) ::
("object_type?" | constant(hex"0002".bits)) :: ("object_type?" | constant(hex"0002".bits)) ::
("unknown" | constant(hex"ff240000".bits)) :: ("unknown" | constant(hex"ff240000".bits)) ::
("P_len" | constant(hex"1000".bits)) :: ("P_len" | constant(hex"1000".bits)) ::
("P" | bytes(16)) :: ("P" | bytes(16)) ::
("G_len" | constant(hex"1000".bits)) :: ("G_len" | constant(hex"1000".bits)) ::
("G" | bytes(16)) :: ("G" | bytes(16)) ::
("end?" | constant(0)) :: ("end?" | constant(0)) ::
("end?" | constant(0)) :: ("end?" | constant(0)) ::
("objects?" | constant(1)) :: ("objects?" | constant(1)) ::
("unknown" | constant(hex"03070000".bits)) :: ("unknown" | constant(hex"03070000".bits)) ::
("end?" | constant(0)) ("end?" | constant(0))
).as[ClientChallengeXchg] ).as[ClientChallengeXchg]
} }

View file

@ -1,24 +1,24 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class ClientFinished(pubKey : ByteVector, challengeResult: ByteVector) final case class ClientFinished(pubKey : ByteVector, challengeResult: ByteVector)
extends PlanetSideCryptoPacket { extends PlanetSideCryptoPacket {
type Packet = ClientFinished type Packet = ClientFinished
def opcode = CryptoPacketOpcode.ClientFinished def opcode = CryptoPacketOpcode.ClientFinished
def encode = ClientFinished.encode(this) def encode = ClientFinished.encode(this)
} }
object ClientFinished extends Marshallable[ClientFinished] { object ClientFinished extends Marshallable[ClientFinished] {
implicit val codec : Codec[ClientFinished] = ( implicit val codec : Codec[ClientFinished] = (
("obj_type?" | constant(hex"10".bits)) :: ("obj_type?" | constant(hex"10".bits)) ::
("pub_key_len" | constant(hex"1000")) :: ("pub_key_len" | constant(hex"1000")) ::
("pub_key" | bytes(16)) :: ("pub_key" | bytes(16)) ::
("unknown" | constant(hex"0114".bits)) :: ("unknown" | constant(hex"0114".bits)) ::
("challenge_result" | bytes(0xc)) ("challenge_result" | bytes(0xc))
).as[ClientFinished] ).as[ClientFinished]
} }

View file

@ -1,21 +1,21 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class ClientStart(clientNonce : Long) final case class ClientStart(clientNonce : Long)
extends PlanetSideControlPacket { extends PlanetSideControlPacket {
type Packet = ClientStart type Packet = ClientStart
def opcode = ControlPacketOpcode.ClientStart def opcode = ControlPacketOpcode.ClientStart
def encode = ClientStart.encode(this) def encode = ClientStart.encode(this)
} }
object ClientStart extends Marshallable[ClientStart] { object ClientStart extends Marshallable[ClientStart] {
implicit val codec : Codec[ClientStart] = ( implicit val codec : Codec[ClientStart] = (
("unknown" | constant(hex"00000002".bits)) :: ("unknown" | constant(hex"00000002".bits)) ::
("client_nonce" | uint32L) :: ("client_nonce" | uint32L) ::
("unknown" | constant(hex"000001f0".bits)) ("unknown" | constant(hex"000001f0".bits))
).as[ClientStart] ).as[ClientStart]
} }

View file

@ -1,16 +1,16 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
final case class ConnectToWorldMessage(world : String) final case class ConnectToWorldMessage(world : String)
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
type Packet = ConnectToWorldMessage type Packet = ConnectToWorldMessage
def opcode = GamePacketOpcode.ConnectToWorldMessage def opcode = GamePacketOpcode.ConnectToWorldMessage
def encode = ConnectToWorldMessage.encode(this) def encode = ConnectToWorldMessage.encode(this)
} }
object ConnectToWorldMessage extends Marshallable[ConnectToWorldMessage] { object ConnectToWorldMessage extends Marshallable[ConnectToWorldMessage] {
implicit val codec : Codec[ConnectToWorldMessage] = ascii.as[ConnectToWorldMessage] implicit val codec : Codec[ConnectToWorldMessage] = ascii.as[ConnectToWorldMessage]
} }

View file

@ -1,15 +1,15 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.Codec import scodec.Codec
final case class ConnectionClose() final case class ConnectionClose()
extends PlanetSideControlPacket { extends PlanetSideControlPacket {
type Packet = ConnectionClose type Packet = ConnectionClose
def opcode = ControlPacketOpcode.ConnectionClose def opcode = ControlPacketOpcode.ConnectionClose
def encode = ConnectionClose.encode(this) def encode = ConnectionClose.encode(this)
} }
object ConnectionClose extends Marshallable[ConnectionClose] { object ConnectionClose extends Marshallable[ConnectionClose] {
implicit val codec: Codec[ConnectionClose] = PacketHelpers.emptyCodec(ConnectionClose()) implicit val codec: Codec[ConnectionClose] = PacketHelpers.emptyCodec(ConnectionClose())
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.BitVector import scodec.bits.BitVector
import scodec.{Err, DecodeResult, Attempt, Codec} import scodec.{Err, DecodeResult, Attempt, Codec}
@ -50,14 +50,18 @@ object ControlPacketOpcode extends Enumeration {
Unknown30 Unknown30
= Value = Value
def getPacketDecoder(opcode : ControlPacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideControlPacket]] = opcode match { def getPacketDecoder(opcode : ControlPacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideControlPacket]] = {
case HandleGamePacket => psforever.net.HandleGamePacket.decode import net.psforever
case ServerStart => psforever.net.ServerStart.decode
case ClientStart => psforever.net.ClientStart.decode opcode match {
case MultiPacket => psforever.net.MultiPacket.decode case HandleGamePacket => psforever.packet.HandleGamePacket.decode
case SlottedMetaPacket0 => psforever.net.SlottedMetaPacket.decode case ServerStart => psforever.packet.ServerStart.decode
case ConnectionClose => psforever.net.ConnectionClose.decode case ClientStart => psforever.packet.ClientStart.decode
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for control packet ${opcode}")) case MultiPacket => psforever.packet.MultiPacket.decode
case SlottedMetaPacket0 => psforever.packet.SlottedMetaPacket.decode
case ConnectionClose => psforever.packet.ConnectionClose.decode
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for control packet ${opcode}"))
}
} }
implicit val codec: Codec[this.Value] = PacketHelpers.createEnumerationCodec(this, uint8L) implicit val codec: Codec[this.Value] = PacketHelpers.createEnumerationCodec(this, uint8L)

View file

@ -0,0 +1,25 @@
// Copyright (c) 2016 PSForever.net to present
package net.psforever.packet
import scodec.bits.BitVector
import scodec.{Err, DecodeResult, Attempt}
// this isnt actually used as an opcode (i.e not serialized)
object CryptoPacketOpcode extends Enumeration {
type Type = Value
val Ignore, ClientChallengeXchg, ServerChallengeXchg,
ClientFinished, ServerFinished = Value
def getPacketDecoder(opcode : CryptoPacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideCryptoPacket]] = {
import net.psforever
opcode match {
case ClientChallengeXchg => psforever.packet.ClientChallengeXchg.decode
case ServerChallengeXchg => psforever.packet.ServerChallengeXchg.decode
case ServerFinished => psforever.packet.ServerFinished.decode
case ClientFinished => psforever.packet.ClientFinished.decode
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for crypto packet ${opcode}")
.pushContext("get_marshaller"))
}
}
}

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.{Err, DecodeResult, Attempt, Codec} import scodec.{Err, DecodeResult, Attempt, Codec}
import scodec.bits.BitVector import scodec.bits.BitVector
@ -31,11 +31,15 @@ object GamePacketOpcode extends Enumeration {
DismountVehicleMsg DismountVehicleMsg
= Value = Value
def getPacketDecoder(opcode : GamePacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideGamePacket]] = opcode match { def getPacketDecoder(opcode : GamePacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideGamePacket]] = {
case LoginMessage => psforever.net.LoginMessage.decode import net.psforever
case LoginRespMessage => psforever.net.LoginRespMessage.decode
case VNLWorldStatusMessage => psforever.net.VNLWorldStatusMessage.decode opcode match {
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for game packet ${opcode}")) case LoginMessage => psforever.packet.LoginMessage.decode
case LoginRespMessage => psforever.packet.LoginRespMessage.decode
case VNLWorldStatusMessage => psforever.packet.VNLWorldStatusMessage.decode
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for game packet ${opcode}"))
}
} }
implicit val codec: Codec[this.Value] = PacketHelpers.createEnumerationCodec(this, uint8L) implicit val codec: Codec[this.Value] = PacketHelpers.createEnumerationCodec(this, uint8L)

View file

@ -1,16 +1,16 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
final case class HandleGamePacket(packet : ByteVector) final case class HandleGamePacket(packet : ByteVector)
extends PlanetSideControlPacket { extends PlanetSideControlPacket {
def opcode = ControlPacketOpcode.HandleGamePacket def opcode = ControlPacketOpcode.HandleGamePacket
def encode = throw new Exception("This packet type should never be encoded") def encode = throw new Exception("This packet type should never be encoded")
} }
object HandleGamePacket extends Marshallable[HandleGamePacket] { object HandleGamePacket extends Marshallable[HandleGamePacket] {
implicit val codec : Codec[HandleGamePacket] = bytes.as[HandleGamePacket].decodeOnly implicit val codec : Codec[HandleGamePacket] = bytes.as[HandleGamePacket].decodeOnly
} }

View file

@ -1,72 +1,72 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
import shapeless._ import shapeless._
final case class LoginMessage(majorVersion : Long, final case class LoginMessage(majorVersion : Long,
minorVersion : Long, minorVersion : Long,
buildDate : String, buildDate : String,
username : String, username : String,
password : Option[String], password : Option[String],
token : Option[String], token : Option[String],
revision : Long) extends PlanetSideGamePacket { revision : Long) extends PlanetSideGamePacket {
require(majorVersion >= 0) require(majorVersion >= 0)
require(minorVersion >= 0) require(minorVersion >= 0)
require(revision >= 0) require(revision >= 0)
require(password.isDefined ^ token.isDefined, "Either 'username' or 'token' must be set, but not both") require(password.isDefined ^ token.isDefined, "Either 'username' or 'token' must be set, but not both")
def opcode = GamePacketOpcode.LoginMessage def opcode = GamePacketOpcode.LoginMessage
def encode = LoginMessage.encode(this) def encode = LoginMessage.encode(this)
} }
object LoginMessage extends Marshallable[LoginMessage] { object LoginMessage extends Marshallable[LoginMessage] {
private def username = PacketHelpers.encodedStringAligned(7) private def username = PacketHelpers.encodedStringAligned(7)
private def password = PacketHelpers.encodedString private def password = PacketHelpers.encodedString
private def tokenPath = fixedSizeBytes(32, ascii) :: username private def tokenPath = fixedSizeBytes(32, ascii) :: username
private def passwordPath = username :: password private def passwordPath = username :: password
type Struct = String :: Option[String] :: Option[String] :: HNil type Struct = String :: Option[String] :: Option[String] :: HNil
/* Okay, okay, here's what's happening here: /* Okay, okay, here's what's happening here:
PlanetSide's *wonderful* packet design reuses packets for different encodings. PlanetSide's *wonderful* packet design reuses packets for different encodings.
What we have here is that depending on a boolean in the LoginPacket, we will either What we have here is that depending on a boolean in the LoginPacket, we will either
be decoding a username & password OR a token & username. Yeah...so this doesn't be decoding a username & password OR a token & username. Yeah...so this doesn't
really fit in to a fixed packet decoding scheme. really fit in to a fixed packet decoding scheme.
The below code abstracts away from this by using pattern matching. The below code abstracts away from this by using pattern matching.
The scodec specific part is the either(...) Codec, which decodes one bit and chooses The scodec specific part is the either(...) Codec, which decodes one bit and chooses
Left or Right depending on it. Left or Right depending on it.
*/ */
implicit val credentialChoice : Codec[Struct] = { implicit val credentialChoice : Codec[Struct] = {
type InStruct = Either[String :: String :: HNil, String :: String :: HNil] type InStruct = Either[String :: String :: HNil, String :: String :: HNil]
def from(a : InStruct) : Struct = a match { def from(a : InStruct) : Struct = a match {
case Left(username :: password :: HNil) => username :: Some(password) :: None :: HNil case Left(username :: password :: HNil) => username :: Some(password) :: None :: HNil
case Right(token :: username :: HNil) => username :: None :: Some(token) :: HNil case Right(token :: username :: HNil) => username :: None :: Some(token) :: HNil
} }
// serialization can fail if the user did not specify a token or password (or both) // serialization can fail if the user did not specify a token or password (or both)
def to(a : Struct) : InStruct = a match { def to(a : Struct) : InStruct = a match {
case username :: Some(password) :: None :: HNil => Left(username :: password :: HNil) case username :: Some(password) :: None :: HNil => Left(username :: password :: HNil)
case username :: None :: Some(token) :: HNil => Right(token :: username :: HNil) case username :: None :: Some(token) :: HNil => Right(token :: username :: HNil)
} }
either(bool, passwordPath, tokenPath).xmap[Struct](from, to) either(bool, passwordPath, tokenPath).xmap[Struct](from, to)
} }
implicit val codec : Codec[LoginMessage] = ( implicit val codec : Codec[LoginMessage] = (
("major_version" | uint32L) :: ("major_version" | uint32L) ::
("minor_version" | uint32L) :: ("minor_version" | uint32L) ::
("build_date" | PacketHelpers.encodedString) :: ("build_date" | PacketHelpers.encodedString) ::
( (
// The :+ operator (and the parens) are required because we are adding an HList to an HList, // The :+ operator (and the parens) are required because we are adding an HList to an HList,
// not merely a value (like bool). Weird shit, but hey this works. // not merely a value (like bool). Weird shit, but hey this works.
("credential_choice" | credentialChoice) :+ ("credential_choice" | credentialChoice) :+
("revision" | uint32L) ("revision" | uint32L)
) )
).as[LoginMessage] ).as[LoginMessage]
} }

View file

@ -1,34 +1,34 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class LoginRespMessage(token : String, // printable ascii for 16 final case class LoginRespMessage(token : String, // printable ascii for 16
unknown : ByteVector, // hex"00000000 18FABE0C 00000000 00000000" unknown : ByteVector, // hex"00000000 18FABE0C 00000000 00000000"
error : Long, // 0 error : Long, // 0
stationError : Long, // 1 stationError : Long, // 1
subscriptionStatus : Long, // 2 or 5 subscriptionStatus : Long, // 2 or 5
someToken : Long, // 685276011 someToken : Long, // 685276011
username : String, // the user username : String, // the user
unk5 : Long, // 0 and unset bool unk5 : Long, // 0 and unset bool
someBit : Boolean) extends PlanetSideGamePacket { someBit : Boolean) extends PlanetSideGamePacket {
def opcode = GamePacketOpcode.LoginRespMessage def opcode = GamePacketOpcode.LoginRespMessage
def encode = LoginRespMessage.encode(this) def encode = LoginRespMessage.encode(this)
} }
object LoginRespMessage extends Marshallable[LoginRespMessage] { object LoginRespMessage extends Marshallable[LoginRespMessage] {
implicit val codec : Codec[LoginRespMessage] = ( implicit val codec : Codec[LoginRespMessage] = (
("token" | fixedSizeBytes(16, ascii)) :: ("token" | fixedSizeBytes(16, ascii)) ::
("unknown" | bytes(16)) :: ("unknown" | bytes(16)) ::
("error" | uint32L) :: ("error" | uint32L) ::
("station_error" | uint32L) :: ("station_error" | uint32L) ::
("subscription_status" | uint32L) :: ("subscription_status" | uint32L) ::
("unknown" | uint32L) :: ("unknown" | uint32L) ::
("username" | PacketHelpers.encodedString) :: ("username" | PacketHelpers.encodedString) ::
("unknown" | uint32L) :: ("unknown" | uint32L) ::
("unknown" | byteAligned(bool)) ("unknown" | byteAligned(bool))
).as[LoginRespMessage] ).as[LoginRespMessage]
} }

View file

@ -1,18 +1,18 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class MultiPacket(packets : Vector[ByteVector]) final case class MultiPacket(packets : Vector[ByteVector])
extends PlanetSideControlPacket { extends PlanetSideControlPacket {
type Packet = MultiPacket type Packet = MultiPacket
def opcode = ControlPacketOpcode.MultiPacket def opcode = ControlPacketOpcode.MultiPacket
def encode = MultiPacket.encode(this) def encode = MultiPacket.encode(this)
} }
object MultiPacket extends Marshallable[MultiPacket] { object MultiPacket extends Marshallable[MultiPacket] {
implicit val codec : Codec[MultiPacket] = ("packets" | vector(variableSizeBytes(uint8L, bytes))).as[MultiPacket] implicit val codec : Codec[MultiPacket] = ("packets" | vector(variableSizeBytes(uint8L, bytes))).as[MultiPacket]
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import java.nio.charset.Charset import java.nio.charset.Charset

View file

@ -1,8 +1,8 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import psforever.crypto.CryptoInterface import net.psforever.crypto.CryptoInterface
import psforever.crypto.CryptoInterface._ import net.psforever.crypto.CryptoInterface._
import scodec.Attempt.{Successful, Failure} import scodec.Attempt.{Successful, Failure}
import scodec.bits._ import scodec.bits._
import scodec.{DecodeResult, Err, Attempt, Codec} import scodec.{DecodeResult, Err, Attempt, Codec}
@ -38,6 +38,7 @@ object PacketCoding {
* decode it given an optional header and required payload. This function does all of the * decode it given an optional header and required payload. This function does all of the
* hard work of making decisions along the way in order to decode a planetside packet to * hard work of making decisions along the way in order to decode a planetside packet to
* completion. * completion.
*
* @param msg the raw packet * @param msg the raw packet
* @param cryptoState the current state of the connection's crypto. This is only used when decoding * @param cryptoState the current state of the connection's crypto. This is only used when decoding
* crypto packets as they do not have opcodes * crypto packets as they do not have opcodes
@ -60,6 +61,7 @@ object PacketCoding {
/** /**
* Helper function to decode a packet without specifying a crypto packet state. * Helper function to decode a packet without specifying a crypto packet state.
* Mostly used when there is no crypto state available, such as tests. * Mostly used when there is no crypto state available, such as tests.
*
* @param msg packet data bytes * @param msg packet data bytes
* @return PlanetSidePacketContainer * @return PlanetSidePacketContainer
*/ */
@ -70,6 +72,7 @@ object PacketCoding {
/** /**
* Similar to UnmarshalPacket, but does not process any packet header and does not support * Similar to UnmarshalPacket, but does not process any packet header and does not support
* decoding of crypto packets. Mostly used in tests. * decoding of crypto packets. Mostly used in tests.
*
* @param msg raw, unencrypted packet * @param msg raw, unencrypted packet
* @return PlanetSidePacket * @return PlanetSidePacket
*/ */

View file

@ -1,32 +1,32 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class ServerChallengeXchg(time : Long, challenge : ByteVector, pubKey : ByteVector) final case class ServerChallengeXchg(time : Long, challenge : ByteVector, pubKey : ByteVector)
extends PlanetSideCryptoPacket { extends PlanetSideCryptoPacket {
type Packet = ServerChallengeXchg type Packet = ServerChallengeXchg
def opcode = CryptoPacketOpcode.ServerChallengeXchg def opcode = CryptoPacketOpcode.ServerChallengeXchg
def encode = ServerChallengeXchg.encode(this) def encode = ServerChallengeXchg.encode(this)
} }
object ServerChallengeXchg extends Marshallable[ServerChallengeXchg] { object ServerChallengeXchg extends Marshallable[ServerChallengeXchg] {
def getCompleteChallenge(time : Long, rest : ByteVector): ByteVector = def getCompleteChallenge(time : Long, rest : ByteVector): ByteVector =
uint32L.encode(time).require.toByteVector ++ rest uint32L.encode(time).require.toByteVector ++ rest
implicit val codec: Codec[ServerChallengeXchg] = ( implicit val codec: Codec[ServerChallengeXchg] = (
("unknown" | constant(2)) :: ("unknown" | constant(2)) ::
("unknown" | constant(1)) :: ("unknown" | constant(1)) ::
("server_time" | uint32L) :: ("server_time" | uint32L) ::
("challenge" | bytes(0xC)) :: ("challenge" | bytes(0xC)) ::
("end?" | constant(0)) :: ("end?" | constant(0)) ::
("objects" | constant(1)) :: ("objects" | constant(1)) ::
("unknown" | constant(hex"03070000000c00".bits)) :: ("unknown" | constant(hex"03070000000c00".bits)) ::
("pub_key_len" | constant(hex"1000")) :: ("pub_key_len" | constant(hex"1000")) ::
("pub_key" | bytes(16)) :: ("pub_key" | bytes(16)) ::
("unknown" | constant(0x0e)) ("unknown" | constant(0x0e))
).as[ServerChallengeXchg] ).as[ServerChallengeXchg]
} }

View file

@ -1,21 +1,21 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class ServerFinished(challengeResult : ByteVector) final case class ServerFinished(challengeResult : ByteVector)
extends PlanetSideCryptoPacket { extends PlanetSideCryptoPacket {
type Packet = ServerFinished type Packet = ServerFinished
def opcode = CryptoPacketOpcode.ServerFinished def opcode = CryptoPacketOpcode.ServerFinished
def encode = ServerFinished.encode(this) def encode = ServerFinished.encode(this)
} }
object ServerFinished extends Marshallable[ServerFinished] { object ServerFinished extends Marshallable[ServerFinished] {
implicit val codec : Codec[ServerFinished] = ( implicit val codec : Codec[ServerFinished] = (
("unknown" | constant(hex"0114".bits)) :: ("unknown" | constant(hex"0114".bits)) ::
("challenge_result" | bytes(0xc)) ("challenge_result" | bytes(0xc))
).as[ServerFinished] ).as[ServerFinished]
} }

View file

@ -1,21 +1,21 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
import scodec.bits._ import scodec.bits._
final case class ServerStart(clientNonce : Long, serverNonce : Long) final case class ServerStart(clientNonce : Long, serverNonce : Long)
extends PlanetSideControlPacket { extends PlanetSideControlPacket {
type Packet = ServerStart type Packet = ServerStart
def opcode = ControlPacketOpcode.ServerStart def opcode = ControlPacketOpcode.ServerStart
def encode = ServerStart.encode(this) def encode = ServerStart.encode(this)
} }
object ServerStart extends Marshallable[ServerStart] { object ServerStart extends Marshallable[ServerStart] {
implicit val codec : Codec[ServerStart] = ( implicit val codec : Codec[ServerStart] = (
("client_nonce" | uint32L) :: ("client_nonce" | uint32L) ::
("server_nonce" | uint32L) :: ("server_nonce" | uint32L) ::
("unknown" | constant(hex"000000000001d300000002".bits)) ("unknown" | constant(hex"000000000001d300000002".bits))
).as[ServerStart] ).as[ServerStart]
} }

View file

@ -1,28 +1,28 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
final case class SlottedMetaPacket(/*slot : Int,*/ packet : ByteVector) final case class SlottedMetaPacket(/*slot : Int,*/ packet : ByteVector)
extends PlanetSideControlPacket { extends PlanetSideControlPacket {
type Packet = SlottedMetaPacket type Packet = SlottedMetaPacket
//assert(slot >= 0 && slot <= 7, "Slot number is out of range") //assert(slot >= 0 && slot <= 7, "Slot number is out of range")
def opcode = { def opcode = {
val base = ControlPacketOpcode.SlottedMetaPacket0.id val base = ControlPacketOpcode.SlottedMetaPacket0.id
ControlPacketOpcode(base/* + slot*/) ControlPacketOpcode(base/* + slot*/)
} }
def encode = SlottedMetaPacket.encode(this) def encode = SlottedMetaPacket.encode(this)
} }
object SlottedMetaPacket extends Marshallable[SlottedMetaPacket] { object SlottedMetaPacket extends Marshallable[SlottedMetaPacket] {
implicit val codec : Codec[SlottedMetaPacket] = ( implicit val codec : Codec[SlottedMetaPacket] = (
("unknown" | constant(0)) :: ("unknown" | constant(0)) ::
("unknown" | constant(0)) :: ("unknown" | constant(0)) ::
("rest" | bytes) ("rest" | bytes)
).as[SlottedMetaPacket] ).as[SlottedMetaPacket]
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.net package net.psforever.packet
import java.net.{InetAddress, InetSocketAddress} import java.net.{InetAddress, InetSocketAddress}

View file

@ -1,21 +0,0 @@
// Copyright (c) 2016 PSForever.net to present
package psforever.net
import scodec.bits.BitVector
import scodec.{Err, DecodeResult, Attempt}
// this isnt actually used as an opcode (i.e not serialized)
object CryptoPacketOpcode extends Enumeration {
type Type = Value
val Ignore, ClientChallengeXchg, ServerChallengeXchg,
ClientFinished, ServerFinished = Value
def getPacketDecoder(opcode : CryptoPacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideCryptoPacket]] = opcode match {
case ClientChallengeXchg => psforever.net.ClientChallengeXchg.decode
case ServerChallengeXchg => psforever.net.ServerChallengeXchg.decode
case ServerFinished => psforever.net.ServerFinished.decode
case ClientFinished => psforever.net.ClientFinished.decode
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for crypto packet ${opcode}")
.pushContext("get_marshaller"))
}
}

View file

@ -1,8 +1,8 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
import org.specs2.mutable._ import org.specs2.mutable._
import psforever.crypto.CryptoInterface import net.psforever.crypto.CryptoInterface
import psforever.crypto.CryptoInterface.CryptoDHState import net.psforever.crypto.CryptoInterface.CryptoDHState
import scodec.bits._ import scodec.bits._
class CryptoInterfaceTest extends Specification { class CryptoInterfaceTest extends Specification {

View file

@ -1,6 +1,6 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
import org.specs2.mutable._ import org.specs2.mutable._
import psforever.net._ import net.psforever.packet._
import scodec.Codec import scodec.Codec
import scodec.bits._ import scodec.bits._

View file

@ -2,7 +2,7 @@
import java.net.{InetAddress, InetSocketAddress} import java.net.{InetAddress, InetSocketAddress}
import org.specs2.mutable._ import org.specs2.mutable._
import psforever.net._ import net.psforever.packet._
import scodec.bits._ import scodec.bits._
class GamePacketTest extends Specification { class GamePacketTest extends Specification {

View file

@ -1,6 +1,6 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
import org.specs2.mutable._ import org.specs2.mutable._
import psforever.net._ import net.psforever.packet._
import scodec.bits._ import scodec.bits._
class PacketCodingTest extends Specification { class PacketCodingTest extends Specification {

View file

@ -2,9 +2,9 @@
import java.net.{InetAddress, InetSocketAddress} import java.net.{InetAddress, InetSocketAddress}
import akka.actor.{Actor, ActorLogging, ActorRef, DiagnosticActorLogging, Identify, MDCContextAware} import akka.actor.{Actor, ActorLogging, ActorRef, DiagnosticActorLogging, Identify, MDCContextAware}
import psforever.crypto.CryptoInterface.{CryptoState, CryptoStateWithMAC} import net.psforever.crypto.CryptoInterface.{CryptoState, CryptoStateWithMAC}
import psforever.crypto.CryptoInterface import net.psforever.crypto.CryptoInterface
import psforever.net._ import net.psforever.packet._
import scodec.Attempt.{Failure, Successful} import scodec.Attempt.{Failure, Successful}
import scodec.bits._ import scodec.bits._
import scodec.{Attempt, Codec, Err} import scodec.{Attempt, Codec, Err}

View file

@ -2,7 +2,7 @@
import java.net.{InetAddress, InetSocketAddress} import java.net.{InetAddress, InetSocketAddress}
import akka.actor.{Actor, ActorLogging, ActorRef, Identify, MDCContextAware} import akka.actor.{Actor, ActorLogging, ActorRef, Identify, MDCContextAware}
import psforever.net._ import net.psforever.packet._
import scodec.Attempt.{Failure, Successful} import scodec.Attempt.{Failure, Successful}
import scodec.bits._ import scodec.bits._

View file

@ -4,7 +4,7 @@ import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.core.status._ import ch.qos.logback.core.status._
import ch.qos.logback.core.util.StatusPrinter import ch.qos.logback.core.util.StatusPrinter
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import psforever.crypto.CryptoInterface import net.psforever.crypto.CryptoInterface
import org.slf4j import org.slf4j
import org.fusesource.jansi.Ansi._ import org.fusesource.jansi.Ansi._
import org.fusesource.jansi.Ansi.Color._ import org.fusesource.jansi.Ansi.Color._

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present // Copyright (c) 2016 PSForever.net to present
package psforever.crypto package net.psforever.crypto
import akka.actor.{Actor, ActorLogging, FSM} import akka.actor.{Actor, ActorLogging, FSM}
import akka.util.ByteString import akka.util.ByteString
@ -22,7 +22,7 @@ class CryptoStateManager extends Actor with ActorLogging with FSM[CryptoState, C
when(ClientStart()) { when(ClientStart()) {
/*case Event(RawPacket(msg), _) => { /*case Event(RawPacket(msg), _) => {
val decoded = Codec.decode[psforever.net.ClientStart](msg.bits) val decoded = Codec.decode[net.psforever.net.ClientStart](msg.bits)
try { try {
val packet = decoded.require.value val packet = decoded.require.value
println("Got cNonce: " + packet.clientNonce) println("Got cNonce: " + packet.clientNonce)