summaryrefslogtreecommitdiff
path: root/src/main/kotlin/Message.kt
diff options
context:
space:
mode:
authorEdoardo La Greca2025-08-05 15:35:14 +0200
committerEdoardo La Greca2025-08-05 15:35:14 +0200
commit88064541ca9c1ab8710974d599db49591f161b24 (patch)
tree2b3c458a619a2e9f8f3f169e57edf839165c40e7 /src/main/kotlin/Message.kt
parentea8f822d198780baa2d00b4ced5dde9b1540b997 (diff)
change Message class to OutMessage
Diffstat (limited to 'src/main/kotlin/Message.kt')
-rw-r--r--src/main/kotlin/Message.kt104
1 files changed, 0 insertions, 104 deletions
diff --git a/src/main/kotlin/Message.kt b/src/main/kotlin/Message.kt
deleted file mode 100644
index 5007c26..0000000
--- a/src/main/kotlin/Message.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-import java.math.BigInteger
-import kotlin.math.pow
-
-/**
- * A 9P message with the given type, tag, and fields. The message size is calculated automatically.
- *
- * Important note: the field names in [fieldValuesInt] and [fieldValuesStr] (i.e. the keys of their maps) must be
- * mutually exclusive and the union of these two maps' keys must result in a subset of (or a set equal to)
- * [fieldNames]. Calling [write] when these conditions are not met throws an exception.
- *
- * @param type The 9P message type.
- * @param tag The tag given to the message.
- * @param fieldNames The names of the message fields, in the same order they are expected to be sent.
- * @param fieldValuesInt A map of each field name into its value. This map only stores integer values.
- * @param fieldValuesStr A map of each field name into its value. This map only stores string values.
- */
-class Message(val type: NinePMessageType, val tag: UShort, val fieldNames: List<String>, val fieldValuesInt: Map<String, BigInteger>, val fieldValuesStr: Map<String, String>, val maxSize: UInt) {
- /**
- * Intersection between [fieldNames] and [fieldValuesInt]. In other words: the amount of integer fields that are
- * going to be used when writing the message.
- */
- private val insecInts = fieldNames.intersect(fieldValuesInt.keys)
- /**
- * Intersection between [fieldNames] and [fieldValuesStr]. In other words: the amount of string fields that are
- * going to be used when writing the message.
- */
- private val insecStrs = fieldNames.intersect(fieldValuesStr.keys)
-
- /**
- * Send the message using the given networking API.
- *
- * @param tl The networking API.
- * @throws IllegalArgumentException if [fieldNames], [fieldValuesInt], and [fieldValuesStr] are incoherent or the
- * final size of the message exceeds the negotiated value.
- */
- fun write(tl: TransportLayer) {
- // check that names in fieldNames exist as keys in either fieldValuesInt or fieldValuesStr but not both
- require(insecInts.size == fieldNames.size - insecStrs.size)
-
- val totalSize = size()
- if (totalSize > this.maxSize) {
- throw IllegalArgumentException("Message size exceeded.")
- }
- writeMessageSizeType(tl, totalSize, type)
- writeInteger(tl, tag.toInt().toBigInteger())
- for (field in fieldNames) {
- if (field in insecInts) {
- writeInteger(tl, fieldValuesInt[field]!!)
- } else {
- writeString(tl, fieldValuesStr[field]!!)
- }
- }
- }
-
- // TODO: Add size that the value is required to fit in
- /**
- * Write an integer number to the connection.
- *
- * In 9P, binary numbers (non-textual) are specified in little-endian order (least significant byte first).
- *
- * @param tl The networking API.
- * @param value The number's value.
- */
- private fun writeInteger(tl: TransportLayer, value: BigInteger) {
- val bytes = value.toByteArray()
- tl.transmit(Array(bytes.size) { i -> bytes[i].toUByte() })
- }
-
- /**
- * Write a string to the connection.
- *
- * In 9P, strings are represented as a 2-byte integer (the string's size) followed by the actual UTF-8 string. The
- * null terminator is forbidden in 9P messages.
- *
- * @param tl The networking API.
- * @param value The string.
- * @throws IllegalArgumentException if the value of the string's size does not fit into 2 bytes.
- */
- private fun writeString(tl: TransportLayer, value: String) {
- require(value.length <= 2.0.pow(16.0) - 1)
- writeInteger(tl, value.length.toBigInteger())
- val bytes = value.toByteArray()
- tl.transmit(Array(bytes.size) { i -> bytes[i].toUByte() })
- }
-
- /**
- * Write the message size and type.
- *
- * @param tl The networking API.
- * @param size The total message size, including the 4 bytes of this parameter and the type's byte.
- * @param type The 9P message type as a [NinePMessageType] constant.
- */
- private fun writeMessageSizeType(tl: TransportLayer, size: UInt, type: NinePMessageType) {
- writeInteger(tl, size.toInt().toBigInteger())
- writeInteger(tl, type.value.toInt().toBigInteger())
- }
-
- /**
- * Calculate the expected size of the message.
- */
- fun size(): UInt {
- return 4u + 1u + 2u + this.insecInts.sumOf { this.fieldValuesInt[it]!!.bitLength().toUInt() } + this.insecStrs.sumOf { 2u + this.fieldValuesStr[it]!!.length.toUInt() }
- }
-} \ No newline at end of file