Skip to content

Commit

Permalink
pcapng - scalafmt and renaming
Browse files Browse the repository at this point in the history
  • Loading branch information
nikiforo committed Aug 23, 2022
1 parent bbb70f9 commit 8d55e61
Show file tree
Hide file tree
Showing 17 changed files with 93 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ import scodec.codecs._
import shapeless.ops.hlist.{Init, Last, Prepend}
import shapeless.{::, HList, HNil}

trait Block

object Block {
object BlockCodec {

// format: off
private def codec[A, L <: HList, LB <: HList](blockType: Codec[A])(f: Length => Codec[L])(
private def commonStructure[A, L <: HList, LB <: HList](blockType: Codec[A])(f: Length => Codec[L])(
implicit
prepend: Prepend.Aux[L, Unit :: HNil, LB],
init: Init.Aux[LB, L],
Expand All @@ -45,32 +43,35 @@ object Block {
("Block Total Length" | constant(length.bv) )}
// format: on

def codecByHex[L <: HList, LB <: HList](hexConstant: ByteVector)(f: Length => Codec[L])(
implicit
prepend: Prepend.Aux[L, Unit :: HNil, LB],
init: Init.Aux[LB, L],
last: Last.Aux[LB, Unit]
): Codec[Unit :: Length :: LB] = codec(constant(hexConstant))(f)
def unknownByteOrder[L <: HList, LB <: HList](hexConstant: ByteVector)(f: Length => Codec[L])(
implicit
prepend: Prepend.Aux[L, Unit :: HNil, LB],
init: Init.Aux[LB, L],
last: Last.Aux[LB, Unit]
): Codec[Unit :: Length :: LB] = commonStructure(constant(hexConstant))(f)

def codecByLength[L <: HList, LB <: HList](hexConstant: ByteVector, c: Codec[L])(
implicit
prepend: Prepend.Aux[L, Unit :: HNil, LB],
init: Init.Aux[LB, L],
last: Last.Aux[LB, Unit],
ord: ByteOrdering,
): Codec[Unit :: Length :: LB] = codecByHex(hexConstant)(length => fixedSizeBytes(length.toLong - 12, c))
def byBlockBytesCodec[L <: HList, LB <: HList](
hexConstant: ByteVector,
blockBytesCodec: Codec[L]
)(implicit
prepend: Prepend.Aux[L, Unit :: HNil, LB],
init: Init.Aux[LB, L],
last: Last.Aux[LB, Unit],
ord: ByteOrdering
): Codec[Unit :: Length :: LB] =
unknownByteOrder(hexConstant)(length => fixedSizeBytes(length.toLong - 12, blockBytesCodec))

def codecIgnored(
hexConstant: ByteVector
def ignored(
hexConstant: ByteVector
)(implicit ord: ByteOrdering): Codec[Length :: ByteVector :: HNil] =
codecByHex(hexConstant) { length =>
unknownByteOrder(hexConstant) { length =>
fixedSizeBytes(length.toLong - 12, bytes) :: Codec.deriveHNil
}.dropUnits

def codecUnrecognized(
implicit ord: ByteOrdering
def unrecognizedBlockType(implicit
ord: ByteOrdering
): Codec[ByteVector :: Length :: ByteVector :: HNil] =
codec(bytes(4)) { length =>
commonStructure(bytes(4)) { length =>
fixedSizeBytes(length.toLong - 12, bytes) :: Codec.deriveHNil
}.dropUnits
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ import scodec.Codec
import scodec.bits._
import scodec.codecs._

trait Block

object Block {
object BlockCodec {

// format: off
inline def codec[A, L <: Tuple](
private inline def commonStructure[A, L <: Tuple](
blockType: Codec[A]
)(f: Length => Codec[L]): Codec[Tuple.Concat[A *: Length *: L, Unit *: EmptyTuple]] =
("Block Type" | blockType ) ::
Expand All @@ -40,27 +38,27 @@ object Block {
("Block Total Length" | constant(length.bv) )}
// format: on

inline def codecByHex[L <: Tuple](
hexConstant: ByteVector
inline def unknownByteOrder[L <: Tuple](
hexConstant: ByteVector
)(f: Length => Codec[L]): Codec[Tuple.Concat[Unit *: Length *: L, Unit *: EmptyTuple]] =
codec(constant(hexConstant))(f)
commonStructure(constant(hexConstant))(f)

inline def codecByLength[L <: Tuple](hexConstant: ByteVector, c: Codec[L])(
implicit ord: ByteOrdering,
inline def byBlockBytesCodec[L <: Tuple](hexConstant: ByteVector, blockBytesCodec: Codec[L])(
implicit ord: ByteOrdering
): Codec[Tuple.Concat[Unit *: Length *: L, Unit *: EmptyTuple]] =
codecByHex(hexConstant)(length => fixedSizeBytes(length.toLong - 12, c))
unknownByteOrder(hexConstant)(length => fixedSizeBytes(length.toLong - 12, blockBytesCodec))

def codecIgnored(
hexConstant: ByteVector
def ignored(
hexConstant: ByteVector
)(implicit ord: ByteOrdering): Codec[Length *: ByteVector *: EmptyTuple] =
codecByHex(hexConstant) { length =>
unknownByteOrder(hexConstant) { length =>
fixedSizeBytes(length.toLong - 12, bytes).tuple
}.dropUnits

def codecUnrecognized(
implicit ord: ByteOrdering
def unrecognizedBlockType(implicit
ord: ByteOrdering
): Codec[ByteVector *: Length *: ByteVector *: EmptyTuple] =
codec(bytes(4)) { length =>
commonStructure(bytes(4)) { length =>
fixedSizeBytes(length.toLong - 12, bytes).tuple
}.dropUnits
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ object LinkType {
case class Unknown(value: Long) extends LinkType

def fromInt(l: Int): LinkType =
fromLong(l)
fromLong(l.toLong)

def toInt(lt: LinkType): Int = lt match {
case Null => 0
Expand All @@ -64,7 +64,7 @@ object LinkType {
case other => Unknown(other)
}

def toLong(lt: LinkType): Long = toInt(lt)
def toLong(lt: LinkType): Long = toInt(lt).toLong

implicit def codec(implicit bo: ByteOrdering): Codec[LinkType] =
guint32.xmap[LinkType](fromLong, toLong)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ package pcapng
import scodec.bits._
import scodec.Decoder

trait BodyBlock extends Block
trait BodyBlock

object BodyBlock {

Expand All @@ -36,6 +36,6 @@ object BodyBlock {
NameResolutionBlock.codec,
InterfaceStatisticsBlock.codec,
ProcessInformationBlock.codec,
UnrecognizedBlock.codec,
UnrecognizedBlock.codec
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ object CaptureFile {
): Pipe[F, Byte, TimeStamped[A]] = { bytes =>
def go(
idbs: Vector[InterfaceDescriptionBlock],
blocks: Stream[F, BodyBlock],
blocks: Stream[F, BodyBlock]
): Pull[F, TimeStamped[A], Unit] =
blocks.pull.uncons1.flatMap {
case Some((idb: InterfaceDescriptionBlock, tail)) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ object EnhancedPacketBlock {

// format: off
def codec(implicit ord: ByteOrdering): Codec[EnhancedPacketBlock] =
"EPB" | Block.codecByLength(hexConstant, epbCodec).dropUnits.as[EnhancedPacketBlock]
"EPB" | BlockCodec.byBlockBytesCodec(hexConstant, epbCodec).dropUnits.as[EnhancedPacketBlock]

private def epbCodec(implicit ord: ByteOrdering) =
("Interface ID" | guint32 ) ::
Expand All @@ -51,16 +51,16 @@ object EnhancedPacketBlock {
("Captured Packet Length" | guint32 ).flatPrepend { packetLength =>
("Original Packet Length" | guint32 ) ::
("Packet Data" | bytes(packetLength.toInt) ) ::
("Packet padding" | ignore(padTo32Bits(packetLength.toInt) * 8) ) ::
("Packet padding" | ignore(padTo32Bits(packetLength.toInt)) ) ::
("Options" | bytes )}
// format: on

private def hexConstant(implicit ord: ByteOrdering): ByteVector =
orderDependent(hex"00000006", hex"06000000")

private def padTo32Bits(length: Int) = {
private def padTo32Bits(length: Int): Long = {
val rem = length % 4
if (rem == 0) 0
else 4 - rem
val bytes = if (rem == 0) 0 else 4 - rem
bytes.toLong * 8
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object InterfaceDescriptionBlock {

// format: off
def codec(implicit ord: ByteOrdering): Codec[InterfaceDescriptionBlock] =
"IDB" | Block.codecByLength(hexConstant, idbCodec).dropUnits.as[InterfaceDescriptionBlock]
"IDB" | BlockCodec.byBlockBytesCodec(hexConstant, idbCodec).dropUnits.as[InterfaceDescriptionBlock]

private def idbCodec(implicit ord: ByteOrdering) =
("LinkType" | guint16.xmap[LinkType](LinkType.fromInt, LinkType.toInt) ) ::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ case class InterfaceStatisticsBlock(length: Length, bytes: ByteVector) extends B
object InterfaceStatisticsBlock {

def codec(implicit ord: ByteOrdering): Codec[InterfaceStatisticsBlock] =
"ISB" | Block.codecIgnored(hexConstant).as[InterfaceStatisticsBlock]
"ISB" | BlockCodec.ignored(hexConstant).as[InterfaceStatisticsBlock]

private def hexConstant(implicit ord: ByteOrdering) =
orderDependent(hex"00000005", hex"05000000")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,8 @@
package fs2.protocols
package pcapng

import scodec.Codec
import scodec.bits._
import scodec.codecs._
import scodec.bits.{ByteOrdering, ByteVector}

case class DummyBlock(
blockType: ByteVector,
totalLength: Length,
body: ByteVector
) extends BodyBlock

object DummyBlock {

// format: off
def codec(implicit ord: ByteOrdering): Codec[DummyBlock] = "Dummy" | {
("Block Type" | bytes(4) ) ::
("Block Total Length" | bytes(4).xmapc(Length)(_.bv) ).flatPrepend { length =>
("Block Body" | bytes(length.toLong.toInt - 12) ) ::
("Block Total Length" | constant(length.bv) )}
}.dropUnits.as[DummyBlock]
// format: on
case class Length(bv: ByteVector) extends AnyVal {
def toLong(implicit ord: ByteOrdering): Long = bv.toLong(signed = false, ord)
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ case class NameResolutionBlock(length: Length, bytes: ByteVector) extends BodyBl
object NameResolutionBlock {

def codec(implicit ord: ByteOrdering): Codec[NameResolutionBlock] =
"NRB" | Block.codecIgnored(hexConstant).as[NameResolutionBlock]
"NRB" | BlockCodec.ignored(hexConstant).as[NameResolutionBlock]

private def hexConstant(implicit ord: ByteOrdering) =
orderDependent(hex"00000004", hex"04000000")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ case class ProcessInformationBlock(length: Length, bytes: ByteVector) extends Bo
object ProcessInformationBlock {

def codec(implicit ord: ByteOrdering): Codec[ProcessInformationBlock] =
"PIB" | Block.codecIgnored(hexConstant).as[ProcessInformationBlock]
"PIB" | BlockCodec.ignored(hexConstant).as[ProcessInformationBlock]

private def hexConstant(implicit ord: ByteOrdering) =
orderDependent(hex"80000001", hex"01000080")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ case class SectionHeaderBlock(
majorVersion: Int,
minorVersion: Int,
bytes: ByteVector
) extends Block
)

object SectionHeaderBlock {

private val hexConstant = hex"0A0D0D0A"

// format: off
val codec: Codec[SectionHeaderBlock] =
"SHB" | Block.codecByHex(hexConstant) { length =>
("Byte-Order Magic" | ByteOrderMagic ).flatPrepend { implicit ord =>
"SHB" | BlockCodec.unknownByteOrder(hexConstant) { length =>
("Byte-Order Magic" | ByteOrderMagic ).flatPrepend { implicit byteOrder =>
("Major Version" | guint16 ) ::
("Minor Version" | guint16 ) ::
("Block Bytes" | bytes(length.toLong.toInt - 20) )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ case class SimplePacketBlock(length: Length, bytes: ByteVector) extends BodyBloc
object SimplePacketBlock {

def codec(implicit ord: ByteOrdering): Codec[ProcessInformationBlock] =
"SPB" | Block.codecIgnored(hexConstant).as[ProcessInformationBlock]
"SPB" | BlockCodec.ignored(hexConstant).as[ProcessInformationBlock]

private def hexConstant(implicit ord: ByteOrdering) =
orderDependent(hex"00000003", hex"03000000")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
package fs2.protocols.pcapng
/*
* Copyright (c) 2013 Functional Streams for Scala
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package fs2.protocols
package pcapng

import scodec.Codec
import scodec.bits._
import scodec.codecs._

case class UnrecognizedBlock(blockType: ByteVector, length: Length, bytes: ByteVector) extends BodyBlock
case class UnrecognizedBlock(blockType: ByteVector, length: Length, bytes: ByteVector)
extends BodyBlock

object UnrecognizedBlock {

def codec(implicit ord: ByteOrdering): Codec[UnrecognizedBlock] =
"UB" | Block.codecUnrecognized.as[UnrecognizedBlock]
"UB" | BlockCodec.unrecognizedBlockType.as[UnrecognizedBlock]
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ import scodec.bits.{ByteOrdering, ByteVector}

package object pcapng {

case class Length(bv: ByteVector) extends AnyVal {
def toLong(implicit ord: ByteOrdering): Long = bv.toLong(signed = false, ord)
}

def orderDependent[T](
big: ByteVector,
little: ByteVector
Expand Down
21 changes: 5 additions & 16 deletions protocols/shared/src/test/scala/fs2/protocols/PcapNgExample.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,19 @@ package fs2
package protocols

import cats.effect.{IO, IOApp}
import cats.syntax.all._
import cats.syntax.foldable._
import cats.syntax.option._
import fs2.io.file.{Files, Path}
import fs2.protocols.pcap.LinkType
import fs2.protocols.pcapng.{CaptureFile, DummyBlock}
import fs2.protocols.pcapng.CaptureFile

object PcapNgExample extends IOApp.Simple {

def run: IO[Unit] =
output.compile.toList.flatMap(x => IO.println(x.length)) // _.traverse_(IO.println)
output.compile.toList.flatMap(_.traverse_(IO.println))

private def byteStream: Stream[IO, Byte] =
Files[IO].readAll(Path("/Users/anikiforov/pcapng/many_interfaces.pcapng"))

private def revealFailed =
byteStream
.through(CaptureFile.streamDecoder.toPipeByte)
.flatMap {
case dummy: DummyBlock => Stream.emit(dummy)
case _ => Stream.empty
}
.debug()

private def decode =
byteStream.through(CaptureFile.streamDecoder.toPipeByte)
Files[IO].readAll(Path("/path/to/pcapng"))

private def output =
byteStream.through(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class BlockTest extends munit.FunSuite {
assertEquals(actual, fullyDecoded(Enhanced4.expected))
}

test("real-data dummy") {
val actual = DummyBlock.codec(LittleEndian).decode(RD.bytes.bits)
test("real-data UnrecognizedBlock") {
val actual = UnrecognizedBlock.codec(LittleEndian).decode(RD.bytes.bits)
assertEquals(actual, fullyDecoded(RD.expectedDummy))
}

Expand Down Expand Up @@ -203,6 +203,6 @@ private object BlockTest {
val bytes = header ++ length.bv ++ props ++ data ++ padding ++ opts ++ length.bv

val expectedEPB = EnhancedPacketBlock(length, 0, 381443, 399317124, 66, 66, data, opts)
val expectedDummy = DummyBlock(header, length, props ++ data ++ padding ++ opts)
val expectedDummy = UnrecognizedBlock(header, length, props ++ data ++ padding ++ opts)
}
}

0 comments on commit 8d55e61

Please sign in to comment.