mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
encode and decode of only known packet of the ResetSequence type (#752)
This commit is contained in:
parent
41b3eb5f66
commit
b548260257
|
|
@ -1,7 +1,7 @@
|
|||
package net.psforever.actors.net
|
||||
|
||||
import akka.actor.Cancellable
|
||||
import akka.actor.typed.{ActorRef, ActorTags, Behavior, PostStop, Signal}
|
||||
import akka.actor.typed._
|
||||
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
|
||||
import akka.io.Udp
|
||||
import java.net.InetSocketAddress
|
||||
|
|
@ -19,8 +19,8 @@ import scodec.Attempt.{Failure, Successful}
|
|||
import scodec.bits.{BitVector, ByteVector, HexStringSyntax}
|
||||
import scodec.interop.akka.EnrichedByteVector
|
||||
import net.psforever.objects.Default
|
||||
import net.psforever.packet.{CryptoPacketOpcode, PacketCoding, PlanetSideControlPacket, PlanetSideCryptoPacket, PlanetSideGamePacket, PlanetSidePacket}
|
||||
import net.psforever.packet.control.{ClientStart, ConnectionClose, ControlSync, ControlSyncResp, HandleGamePacket, MultiPacket, MultiPacketEx, RelatedA, RelatedB, ServerStart, SlottedMetaPacket, TeardownConnection}
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import net.psforever.packet.crypto.{ClientChallengeXchg, ClientFinished, ServerChallengeXchg, ServerFinished}
|
||||
import net.psforever.packet.game.{ChangeFireModeMessage, CharacterInfoMessage, KeepAliveMessage, PingMsg}
|
||||
import net.psforever.packet.PacketCoding.CryptoCoding
|
||||
|
|
@ -522,8 +522,9 @@ class MiddlewareActor(
|
|||
log.error(s"Unexpected crypto packet '$packet'")
|
||||
Behaviors.same
|
||||
|
||||
case packet =>
|
||||
log.error(s"Unexpected type of packet '$packet'")
|
||||
case _: PlanetSideResetSequencePacket =>
|
||||
log.debug("Received sequence reset request from client; complying")
|
||||
outSequence = 0
|
||||
Behaviors.same
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ trait PlanetSideCryptoPacket extends PlanetSidePacket {
|
|||
}
|
||||
|
||||
/** PlanetSide ResetSequence packets: self-contained? */
|
||||
trait PlanetSideResetSequencePacket extends PlanetSidePacket { }
|
||||
trait PlanetSideResetSequencePacket extends PlanetSidePacket {
|
||||
def opcode: ResetSequenceOpcode.Type
|
||||
}
|
||||
|
||||
/** PlanetSide packet type. Used in more complicated packet headers
|
||||
*
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import java.security.{Key, Security}
|
|||
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.RC5ParameterSpec
|
||||
import net.psforever.packet.reset.ResetSequence
|
||||
import scodec.Attempt.{Failure, Successful}
|
||||
import scodec.bits._
|
||||
import scodec.{Attempt, Codec, DecodeResult, Err}
|
||||
|
|
@ -118,6 +119,13 @@ object PacketCoding {
|
|||
case Successful(opcode) => Successful(opcode ++ payload)
|
||||
case f @ Failure(_) => f
|
||||
}
|
||||
|
||||
case packet: PlanetSideResetSequencePacket =>
|
||||
ResetSequenceOpcode.codec.encode(packet.opcode) match {
|
||||
case Successful(opcode) => Successful(opcode)
|
||||
case f @ Failure(_) => f
|
||||
}
|
||||
|
||||
case _ =>
|
||||
Failure(Err("packet not supported"))
|
||||
}
|
||||
|
|
@ -208,8 +216,11 @@ object PacketCoding {
|
|||
case (PacketType.Normal, None) =>
|
||||
Failure(Err("Cannot unmarshal encrypted packet without a cipher"))
|
||||
case (PacketType.ResetSequence, Some(_crypto)) =>
|
||||
val test = _crypto.decrypt(payload.drop(1))
|
||||
Failure(Err(s"ResetSequence not completely supported, but: $flags, $sequence, and $payload; decrypt: $test"))
|
||||
_crypto.decrypt(payload.drop(1)) match {
|
||||
case Successful(p) if p == hex"01" => Successful((ResetSequence(), sequence))
|
||||
case Successful(p) => Failure(Err(s"ResetSequence decrypted to unsupported value - $p"))
|
||||
case _ => Failure(Err(s"ResetSequence did not decrypt properly"))
|
||||
}
|
||||
case (ptype, _) =>
|
||||
Failure(Err(s"Cannot unmarshal $ptype packet at all"))
|
||||
}
|
||||
|
|
@ -243,9 +254,12 @@ object PacketCoding {
|
|||
GamePacketOpcode.codec.decode(msg.bits) match {
|
||||
case Successful(opcode) =>
|
||||
GamePacketOpcode.getPacketDecoder(opcode.value)(opcode.remainder) match {
|
||||
case Failure(_) if opcode.value.id == 1 =>
|
||||
Successful(ResetSequence())
|
||||
case Failure(e) =>
|
||||
Failure(Err(f"Failed to parse game packet 0x${opcode.value.id}%02x: " + e.messageWithContext))
|
||||
case Successful(p) => Successful(p.value)
|
||||
case Successful(p) =>
|
||||
Successful(p.value)
|
||||
}
|
||||
case Failure(e) => Failure(Err("Failed to decode game packet's opcode: " + e.message))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package net.psforever.packet
|
||||
|
||||
import scodec.bits.BitVector
|
||||
import scodec.{Attempt, Codec, DecodeResult, Err}
|
||||
import scodec.codecs.uint8L
|
||||
|
||||
object ResetSequenceOpcode extends Enumeration(1) {
|
||||
type Type = Value
|
||||
val ResetSequence = Value
|
||||
|
||||
def getPacketDecoder(opcode: ResetSequenceOpcode.Type): BitVector => Attempt[DecodeResult[PlanetSideResetSequencePacket]] =
|
||||
opcode match {
|
||||
case ResetSequence => reset.ResetSequence.decode
|
||||
case _ =>
|
||||
(_: BitVector) =>
|
||||
Attempt.failure(
|
||||
Err(s"Could not find a marshaller for reset sequence packet $opcode")
|
||||
.pushContext("get_marshaller")
|
||||
)
|
||||
}
|
||||
|
||||
implicit val codec: Codec[this.Value] = PacketHelpers.createEnumerationCodec(this, uint8L)
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package net.psforever.packet.reset
|
||||
|
||||
import net.psforever.packet.{Marshallable, PacketHelpers, PlanetSideResetSequencePacket, ResetSequenceOpcode}
|
||||
import scodec.{Attempt, Codec}
|
||||
import scodec.bits.BitVector
|
||||
|
||||
final case class ResetSequence()
|
||||
extends PlanetSideResetSequencePacket {
|
||||
type Packet = ResetSequence
|
||||
def opcode: ResetSequenceOpcode.Type = ResetSequenceOpcode.ResetSequence
|
||||
def encode: Attempt[BitVector] = ResetSequence.encode(this)
|
||||
}
|
||||
|
||||
object ResetSequence extends Marshallable[ResetSequence] {
|
||||
implicit val codec: Codec[ResetSequence] = PacketHelpers.emptyCodec[ResetSequence](ResetSequence())
|
||||
}
|
||||
25
src/test/scala/reset/ResetSequenceTest.scala
Normal file
25
src/test/scala/reset/ResetSequenceTest.scala
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2021 PSForever
|
||||
package reset
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.reset.ResetSequence
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class ResetSequenceTest extends Specification {
|
||||
val string = hex"01"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.decodePacket(string).require match {
|
||||
case ResetSequence() => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ResetSequence()
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue