summaryrefslogtreecommitdiff
path: root/src/main/kotlin/Connection.kt
blob: 62334070d1d1ae8834d5f5e88ccb91b872762e26 (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
138
139
140
141
142
143
144
145
146
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 [ProtocolTranslator]. Details about methods related to 9P can be found in [ProtocolTranslator]. Remember
 * to disconnect using [disconnect] after use.
 *
 * Details about network-related topics can be found in [TransportLayer] and the implementation of choice.
 *
 * Details about 9P messages and methods can be found in [ProtocolTranslator].
 *
 * @param transLay The networking API backend of choice.
 *
 * @throws UnresolvableHostException if the host resolution made by [transLay] failed.
 */
class Connection(transLay: TransportLayer) : ProtocolTranslator {
    /**
     * Networking API.
     */
    private val tl: TransportLayer = transLay

    /**
     * Tag generator.
     */
    private val tagGen = TagGenerator(TagGenerator.TagGenerationMethod.INCREMENTAL, 1u)

    /**
     * Maximum size for messages negotiated between the client and the server.
     */
    private var maxSize: UInt = 0u

    /**
     * Each FID associated with each file.
     */
    val fids: Map<UInt, String> = emptyMap()

    // 9P constants.
    val DEFAULT_VERSION = "9P2000"
    val NOTAG = 0.toUShort().inv()
    val NOFID = 0.toUInt().inv()


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

    override fun version(msize: UInt, version: String): String? {
        val omsg = OutMessage(NinePMessageType.TVERSION, this.NOTAG, listOf("msize", "version"),
            mapOf(
                "msize" to BigInteger(msize.toString())
            ),
            mapOf(
                "version" to version
            ),
            this.maxSize
        )
        val imsg: InMessage
        try {
            imsg = InMessage(this.tl, msize, omsg.tag)
        } catch (ime: InvalidMessageException) {
            return ime.message
        }
        imsg.applySchema(listOf(
            InMessage.Field("msize", InMessage.Field.Type.INTEGER, 4u),
            InMessage.Field("version", InMessage.Field.Type.STRING, 0u)
        ))
        val remoteMaxSize = imsg.fieldsInt["msize"]!!.toInt().toUInt()
        if (remoteMaxSize > this.maxSize) {
            return "Invalid remote msize value (too big)."
        }
        this.maxSize = remoteMaxSize
        if (imsg.fieldsStr["version"] == "unknown") {
            return "Unknown version."
        }
        return null
    }

    override fun auth(afid: UInt, uname: String, aname: String) {
        // TODO: Leave this unimplemented until p9any and TLS are implemented
        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(fid: UInt, offset: ULong, count: UInt): String? {
        val msg = Message(NinePMessageType.TREAD, tagGen.generate(), listOf("fid", "offset", "count"),
            mapOf(
                "fid" to BigInteger(fid.toString()),
                "offset" to BigInteger(offset.toString()),
                "count" to BigInteger(count.toString())
            ),
            emptyMap(),
            this.maxSize
        )
        val error = responseError(msg)
        if (error != null) {
            return error
        }

        return null
    }

    override fun write(fid: UInt, offset: ULong, count: UInt, data: Iterable<UByte>): String? {

    }

    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")
    }
}