summaryrefslogtreecommitdiff
path: root/src/main/kotlin/NinePConnection.kt
blob: 86056eb47f775cfd1b9b68d6c36bcdb780448140 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import java.io.IOException
import java.math.BigInteger

/**
 * This class represents a 9P connection. It provides a practical implementation with networking to the 9P methods
 * described in [NinePTranslator]. Details about methods related to 9P can be found in [NinePTranslator]. Remember to
 * disconnect using [disconnect] after use.
 *
 * Details about network-related topics can be found in [NetworkPacketTransporter] and the implementation of choice.
 *
 * Details about 9P messages and methods can be found in [NinePTranslator].
 *
 * @param netPackTrans The networking API backend of choice.
 *
 * @throws UnresolvableHostException if the host resolution made by [netPackTrans] failed.
 */
class NinePConnection(netPackTrans: NetworkPacketTransporter) : NinePTranslator {
    /**
     * Networking API.
     */
    val npt: NetworkPacketTransporter = netPackTrans

    /**
     * Has the 9P connection been initialized yet?
     */
    private var hasBeenInitialized = false

    /**
     * Disconnect from the remote host,
     *
     * @throws IOException if an I/O error occurred while closing the socket.
     */
    fun disconnect() {
        this.npt.close()
    }

    /**
     * Read an [nBytes]-long unsigned integer number from the connection.
     *
     * In 9P, binary numbers (non-textual) are specified in little-endian order (least significant byte first).
     *
     * @param nBytes The length of the integer number in bytes. It only works with unsigned numbers strictly greater
     *               than zero (zero is excluded).
     * @return The number's value.
     * @throws IllegalArgumentException if [nBytes] is zero or negative.
     */
    private fun readInteger(nBytes: Int): BigInteger {
        require(nBytes > 0)
        val bytes = this.npt.receiveFixed(nBytes.toULong())
        var number: BigInteger = BigInteger.valueOf(0)
        for (i in 0..<bytes.size) {
            number += bytes[i].toInt().toBigInteger().shl(i)
        }

        return number
    }

    /**
     * Read a string from 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.
     *
     * @return The string.
     */
    private fun readString(): String {
        val length = readInteger(2).toInt()
        return String(this.npt.receiveFixed(length.toULong()).toByteArray())
    }

    /**
     * Read the message size and type.
     *
     * @return A pair in which the first element is the message size in bytes and the second is the message type as a
     * [NinePMessageType] constant.
     */
    private fun readMessageSizeType(): Pair<UInt, NinePMessageType> {
        return Pair(
            readInteger(4).toInt().toUInt(),
            NinePMessageType.fromByte(readInteger(1).toByte())
        )
    }

    override fun version() {
        TODO("Not yet implemented")
    }

    override fun auth() {
        TODO("Not yet implemented")
    }

    override fun flush() {
        TODO("Not yet implemented")
    }

    override fun attach() {
        TODO("Not yet implemented")
    }

    override fun walk(path: String) {
        TODO("Not yet implemented")
    }

    override fun open(path: String) {
        TODO("Not yet implemented")
    }

    override fun create(path: String) {
        TODO("Not yet implemented")
    }

    override fun read(path: String) {
        TODO("Not yet implemented")
    }

    override fun write(path: String) {
        TODO("Not yet implemented")
    }

    override fun clunk(path: String) {
        TODO("Not yet implemented")
    }

    override fun remove(path: String) {
        TODO("Not yet implemented")
    }

    override fun stat(path: String) {
        TODO("Not yet implemented")
    }

    override fun wstat(path: String) {
        TODO("Not yet implemented")
    }

    // TODO: implement methods from NinePTranslator
}