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(
organization := "net.psforever",
organization := "net.net.psforever",
version := "1.0",
scalaVersion := "2.11.7",
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),

View file

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

View file

@ -1,7 +1,7 @@
// 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 com.sun.jna.Pointer
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
*
* @param mac1
* @param mac2
*/
@ -218,6 +219,7 @@ object CryptoInterface {
val encryptionMACKey : ByteVector) extends CryptoState(decryptionKey, encryptionKey) {
/**
* Performs a MAC operation over the message. Used when encrypting packets
*
* @param message
* @return ByteVector
*/
@ -227,6 +229,7 @@ object CryptoInterface {
/**
* Performs a MAC operation over the message. Used when verifying decrypted packets
*
* @param message
* @return ByteVector
*/
@ -237,6 +240,7 @@ object CryptoInterface {
/**
* MACs the plaintext message, encrypts it, and then returns the encrypted message with the
* MAC appended to the end.
*
* @param message Arbitrary set of bytes
* @return ByteVector
*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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
package psforever.net
package net.psforever.packet
import scodec.{Err, DecodeResult, Attempt, Codec}
import scodec.bits.BitVector
@ -31,11 +31,15 @@ object GamePacketOpcode extends Enumeration {
DismountVehicleMsg
= Value
def getPacketDecoder(opcode : GamePacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideGamePacket]] = opcode match {
case LoginMessage => psforever.net.LoginMessage.decode
case LoginRespMessage => psforever.net.LoginRespMessage.decode
case VNLWorldStatusMessage => psforever.net.VNLWorldStatusMessage.decode
case default => (a : BitVector) => Attempt.failure(Err(s"Could not find a marshaller for game packet ${opcode}"))
def getPacketDecoder(opcode : GamePacketOpcode.Type) : (BitVector) => Attempt[DecodeResult[PlanetSideGamePacket]] = {
import net.psforever
opcode match {
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)

View file

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

View file

@ -1,72 +1,72 @@
// Copyright (c) 2016 PSForever.net to present
package psforever.net
import scodec.Codec
import scodec.codecs._
import scodec.bits._
import shapeless._
final case class LoginMessage(majorVersion : Long,
minorVersion : Long,
buildDate : String,
username : String,
password : Option[String],
token : Option[String],
revision : Long) extends PlanetSideGamePacket {
require(majorVersion >= 0)
require(minorVersion >= 0)
require(revision >= 0)
require(password.isDefined ^ token.isDefined, "Either 'username' or 'token' must be set, but not both")
def opcode = GamePacketOpcode.LoginMessage
def encode = LoginMessage.encode(this)
}
object LoginMessage extends Marshallable[LoginMessage] {
private def username = PacketHelpers.encodedStringAligned(7)
private def password = PacketHelpers.encodedString
private def tokenPath = fixedSizeBytes(32, ascii) :: username
private def passwordPath = username :: password
type Struct = String :: Option[String] :: Option[String] :: HNil
/* Okay, okay, here's what's happening here:
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
be decoding a username & password OR a token & username. Yeah...so this doesn't
really fit in to a fixed packet decoding scheme.
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
Left or Right depending on it.
*/
implicit val credentialChoice : Codec[Struct] = {
type InStruct = Either[String :: String :: HNil, String :: String :: HNil]
def from(a : InStruct) : Struct = a match {
case Left(username :: password :: HNil) => username :: Some(password) :: None :: 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)
def to(a : Struct) : InStruct = a match {
case username :: Some(password) :: None :: HNil => Left(username :: password :: HNil)
case username :: None :: Some(token) :: HNil => Right(token :: username :: HNil)
}
either(bool, passwordPath, tokenPath).xmap[Struct](from, to)
}
implicit val codec : Codec[LoginMessage] = (
("major_version" | uint32L) ::
("minor_version" | uint32L) ::
("build_date" | PacketHelpers.encodedString) ::
(
// 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.
("credential_choice" | credentialChoice) :+
("revision" | uint32L)
)
).as[LoginMessage]
package net.psforever.packet
import scodec.Codec
import scodec.codecs._
import scodec.bits._
import shapeless._
final case class LoginMessage(majorVersion : Long,
minorVersion : Long,
buildDate : String,
username : String,
password : Option[String],
token : Option[String],
revision : Long) extends PlanetSideGamePacket {
require(majorVersion >= 0)
require(minorVersion >= 0)
require(revision >= 0)
require(password.isDefined ^ token.isDefined, "Either 'username' or 'token' must be set, but not both")
def opcode = GamePacketOpcode.LoginMessage
def encode = LoginMessage.encode(this)
}
object LoginMessage extends Marshallable[LoginMessage] {
private def username = PacketHelpers.encodedStringAligned(7)
private def password = PacketHelpers.encodedString
private def tokenPath = fixedSizeBytes(32, ascii) :: username
private def passwordPath = username :: password
type Struct = String :: Option[String] :: Option[String] :: HNil
/* Okay, okay, here's what's happening here:
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
be decoding a username & password OR a token & username. Yeah...so this doesn't
really fit in to a fixed packet decoding scheme.
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
Left or Right depending on it.
*/
implicit val credentialChoice : Codec[Struct] = {
type InStruct = Either[String :: String :: HNil, String :: String :: HNil]
def from(a : InStruct) : Struct = a match {
case Left(username :: password :: HNil) => username :: Some(password) :: None :: 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)
def to(a : Struct) : InStruct = a match {
case username :: Some(password) :: None :: HNil => Left(username :: password :: HNil)
case username :: None :: Some(token) :: HNil => Right(token :: username :: HNil)
}
either(bool, passwordPath, tokenPath).xmap[Struct](from, to)
}
implicit val codec : Codec[LoginMessage] = (
("major_version" | uint32L) ::
("minor_version" | uint32L) ::
("build_date" | PacketHelpers.encodedString) ::
(
// 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.
("credential_choice" | credentialChoice) :+
("revision" | uint32L)
)
).as[LoginMessage]
}

View file

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

View file

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

View file

@ -1,8 +1,8 @@
// Copyright (c) 2016 PSForever.net to present
package psforever.net
package net.psforever.packet
import psforever.crypto.CryptoInterface
import psforever.crypto.CryptoInterface._
import net.psforever.crypto.CryptoInterface
import net.psforever.crypto.CryptoInterface._
import scodec.Attempt.{Successful, Failure}
import scodec.bits._
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
* hard work of making decisions along the way in order to decode a planetside packet to
* completion.
*
* @param msg the raw packet
* @param cryptoState the current state of the connection's crypto. This is only used when decoding
* 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.
* Mostly used when there is no crypto state available, such as tests.
*
* @param msg packet data bytes
* @return PlanetSidePacketContainer
*/
@ -70,6 +72,7 @@ object PacketCoding {
/**
* Similar to UnmarshalPacket, but does not process any packet header and does not support
* decoding of crypto packets. Mostly used in tests.
*
* @param msg raw, unencrypted packet
* @return PlanetSidePacket
*/

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 PSForever.net to present
package psforever.net
package net.psforever.packet
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
import org.specs2.mutable._
import psforever.crypto.CryptoInterface
import psforever.crypto.CryptoInterface.CryptoDHState
import net.psforever.crypto.CryptoInterface
import net.psforever.crypto.CryptoInterface.CryptoDHState
import scodec.bits._
class CryptoInterfaceTest extends Specification {

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
import java.net.{InetAddress, InetSocketAddress}
import akka.actor.{Actor, ActorLogging, ActorRef, Identify, MDCContextAware}
import psforever.net._
import net.psforever.packet._
import scodec.Attempt.{Failure, Successful}
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.util.StatusPrinter
import com.typesafe.config.ConfigFactory
import psforever.crypto.CryptoInterface
import net.psforever.crypto.CryptoInterface
import org.slf4j
import org.fusesource.jansi.Ansi._
import org.fusesource.jansi.Ansi.Color._

View file

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