-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WiP: txtfile packet dumper + start of tests
- Loading branch information
Showing
2 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
packetdumper/src/main/kotlin/com/jasonernst/packetdumper/filedumper/TextFilePacketDumper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package com.jasonernst.packetdumper.filedumper | ||
|
||
import com.jasonernst.packetdumper.EtherType | ||
import com.jasonernst.packetdumper.stringdumper.StringPacketDumper | ||
import org.slf4j.LoggerFactory | ||
import java.io.BufferedWriter | ||
import java.io.File | ||
import java.io.IOException | ||
import java.nio.ByteBuffer | ||
import java.time.LocalDateTime | ||
import java.util.concurrent.atomic.AtomicBoolean | ||
|
||
/** | ||
* Dumps buffers into hexdump text files that can be imported by wireshark. The format is as follows: | ||
* | ||
* offset(hex) up to 16 bytes of data per line, separated by a space, ending in a newline | ||
* offset(hex) up to 16 bytes of data per line, separated by a space, ending in a newline | ||
* | ||
* offset(hex) up to 16 bytes of data per line, separated by a space, ending in a newline | ||
* offset(hex) up to 16 bytes of data per line, separated by a space, ending in a newline | ||
* | ||
* Each block of offsets is separated by a blank newline, and represents a new packet / dump. When | ||
* the new dump starts, the offset can restart at 0. | ||
*/ | ||
class TextFilePacketDumper(private val path: String, private val name: String) : AbstractFilePacketDumper() { | ||
private val logger = LoggerFactory.getLogger(javaClass) | ||
private val stringDumper = StringPacketDumper() | ||
|
||
private val isOpen = AtomicBoolean(false) | ||
override lateinit var filename: String | ||
private lateinit var file: File | ||
private lateinit var bufferedWriter: BufferedWriter | ||
private var loggedError = false | ||
|
||
override fun open() { | ||
if (isOpen.get()) { | ||
logger.error("Trying to open a file that is already open") | ||
return | ||
} | ||
filename = "$path/${name}_${LocalDateTime.now()}.dump" | ||
file = File(filename) | ||
bufferedWriter = file.bufferedWriter() | ||
logger.debug("TextFilePacketDumper opened file $filename") | ||
isOpen.set(true) | ||
} | ||
|
||
override fun close() { | ||
if (!isOpen.get()) { | ||
logger.error("Trying to close a file that is already closed") | ||
return | ||
} | ||
try { | ||
bufferedWriter.flush() | ||
} catch (e: Exception) { | ||
logger.error("Error flushing dump file", e) | ||
} | ||
try { | ||
bufferedWriter.close() | ||
} catch (e: Exception) { | ||
logger.error("Error closing dump file", e) | ||
} | ||
isOpen.set(false) | ||
} | ||
|
||
override fun dumpBuffer( | ||
buffer: ByteBuffer, | ||
offset: Int, | ||
length: Int, | ||
addresses: Boolean, | ||
etherType: EtherType?, | ||
) { | ||
if (!isOpen.get()) { | ||
if (!loggedError) { | ||
logger.error("Trying to dump to a file that is not open") | ||
loggedError = true | ||
} | ||
return | ||
} | ||
val output = stringDumper.dumpBufferToString(buffer, offset, length, addresses, etherType) | ||
logger.debug("Intermediary output: $output") | ||
try { | ||
bufferedWriter.write(output) | ||
bufferedWriter.write("\n") | ||
bufferedWriter.flush() | ||
} catch (e: IOException) { | ||
if (!loggedError) { | ||
logger.error("Error writing to dump file", e) | ||
loggedError = true | ||
} | ||
} | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
...dumper/src/test/kotlin/com/jasonernst/packetdumper/filedumper/TestTextFilePacketDumper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package com.jasonernst.packetdumper.filedumper | ||
|
||
import com.jasonernst.packetdumper.EtherType | ||
import com.jasonernst.packetdumper.stringdumper.StringPacketDumper | ||
import org.junit.jupiter.api.AfterEach | ||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Disabled | ||
import org.junit.jupiter.api.Test | ||
import org.slf4j.LoggerFactory | ||
import java.io.File | ||
import java.nio.ByteBuffer | ||
|
||
class TestTextFilePacketDumper { | ||
private val logger = LoggerFactory.getLogger(javaClass) | ||
private val dumper = TextFilePacketDumper("/tmp", "test") | ||
|
||
/** | ||
* Dumps a buffer to a file using the dumper, closes the file. Opens it back up and reads the | ||
* buffer back and returns it. | ||
* | ||
* If the addresses flag is true, strip the addresses before returning the buffer. | ||
* If the etherType is not null, strip the dummy ethernet header before returning the buffer. | ||
* | ||
* If either of those two things are present during the write, but not present during the read, | ||
* throw an Exception. | ||
*/ | ||
private fun writeReadBuffer( | ||
buffer: ByteBuffer, | ||
addresses: Boolean = false, | ||
etherType: EtherType? = null, | ||
): ByteBuffer { | ||
dumper.dumpBuffer(buffer, 0, buffer.limit(), addresses, etherType) | ||
dumper.close() | ||
|
||
// re-open the file | ||
val file = File(dumper.filename) | ||
val fileLines = file.readLines() | ||
val readBuffer = ByteBuffer.wrap(fileLines.joinToString().toByteArray()) | ||
|
||
if (etherType != null) { | ||
TODO() // need to strip the dummy ethernet header | ||
} | ||
|
||
if (addresses) { | ||
TODO() // need to strip them | ||
} | ||
|
||
return readBuffer | ||
} | ||
|
||
@AfterEach fun tearDown() { | ||
// just in case a test fails, we want to make sure the file is closed | ||
dumper.close() | ||
|
||
// delete the file created for the test to cleanup | ||
try { | ||
// File(dumper.filename).delete() | ||
logger.debug("Deleted file ${dumper.filename}") | ||
} catch (e: Exception) { | ||
// ignore | ||
} | ||
} | ||
|
||
@Test fun testOpenClose() { | ||
dumper.open() | ||
dumper.close() | ||
} | ||
|
||
@Disabled("This is broken atm") | ||
@Test fun testDumpBuffer() { | ||
dumper.open() | ||
val stringDumper = StringPacketDumper() | ||
val buffer = ByteBuffer.wrap("Hello, World!".toByteArray()) | ||
logger.debug("write buffer: ${stringDumper.dumpBufferToString(buffer, 0, buffer.limit())}") | ||
val readBuffer = writeReadBuffer(buffer) | ||
logger.debug("read buffer: ${stringDumper.dumpBufferToString(readBuffer, 0, readBuffer.limit())}") | ||
assertEquals(buffer, readBuffer) | ||
} | ||
} |