diff options
Diffstat (limited to 'src/main/kotlin/Connection.kt')
-rw-r--r-- | src/main/kotlin/Connection.kt | 321 |
1 files changed, 0 insertions, 321 deletions
diff --git a/src/main/kotlin/Connection.kt b/src/main/kotlin/Connection.kt deleted file mode 100644 index f2cdd15..0000000 --- a/src/main/kotlin/Connection.kt +++ /dev/null @@ -1,321 +0,0 @@ -import except.MsizeValueTooBigException -import except.RErrorException -import except.UnaccessibleFileException -import except.UnknownVersionException -import net.InMessage -import net.OutMessage -import net.TransportLayer -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 [net.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 except.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 - - // 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() - } - - /** - * Handy function to create an [net.InMessage] instance and check for errors. After successfully using this - * function, it is guaranteed that both no error occurred while reading the incoming message and the message is not - * of type R-error. - * - * It uses [tl] and [maxSize] for instancing the [net.InMessage] class. - * - * @return A pair of: (1) a nullable string (which can be: `null` if no error occurred, empty if an error occurred - * with no message, or non-empty with the error message) and (2) the optional [net.InMessage] instance (null if an - * error occurred). - * @throws except.InvalidMessageException if the received message is invalid. - * @throws except.RErrorException if the received message is an R-error message. - */ - private fun checkedInMessage(reqTag: UShort): InMessage { - val imsg = InMessage(this.tl, this.maxSize, reqTag) - if (imsg.type == NinePMessageType.RERROR) { - imsg.applyField(InMessage.Field("ename", InMessage.Field.Type.STRING, 0u)) - throw RErrorException(imsg.fieldsStr["ename"]) - } - return imsg - } - - override fun version(msize: UInt, version: String) { - val omsg = OutMessage(NinePMessageType.TVERSION, this.NOTAG, listOf("msize", "version"), - mapOf( - "msize" to Pair(BigInteger(msize.toString()), 4u) - ), - mapOf( - "version" to version - ), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - 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) { - throw MsizeValueTooBigException(msize, remoteMaxSize) - } - this.maxSize = remoteMaxSize - if (!imsg.fieldsStr["version"]!!.startsWith("9P2000")) { - throw UnknownVersionException(imsg.fieldsStr["version"]!!) - } - } - - 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(oldtag: UShort) { - val omsg = OutMessage(NinePMessageType.TFLUSH, this.tagGen.generate(), listOf("oldtag"), - mapOf( - "oldtag" to Pair(BigInteger(oldtag.toString()), 2u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - } - - override fun attach(fid: UInt, afid: UInt, uname: String, aname: String): QID { - val omsg = OutMessage(NinePMessageType.TATTACH, this.tagGen.generate(), listOf("fid", "afid", "uname", "aname"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u), - "afid" to Pair(BigInteger(afid.toString()), 4u) - ), - mapOf( - "uname" to uname, - "aname" to aname - ), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - - imsg.applyField(InMessage.Field("qid", InMessage.Field.Type.RAW, 13u)) - val qid = QID(imsg.fieldsRaw["qid"]!!.toList()) - return qid - } - - override fun walk(fid: UInt, newfid: UInt, wname: List<String>): List<QID> { - val nwname = wname.size - val omsg = OutMessage(NinePMessageType.TWALK, this.tagGen.generate(), listOf("fid", "newfid", "nwname"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u), - "newfid" to Pair(BigInteger(newfid.toString()), 4u), - "nwname" to Pair(BigInteger(nwname.toString()), 2u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - for (wn in wname) { // write wname elements - this.tl.transmit(OutMessage.convStringToBytes(wn)) - } - val imsg = checkedInMessage(omsg.tag) - - imsg.applyField(InMessage.Field("nwqid", InMessage.Field.Type.INTEGER, 2u)) - val nwqid = imsg.fieldsInt["nwqid"]!!.toInt() - if (nwqid < nwname) { - throw UnaccessibleFileException(wname.slice(0..nwqid)) - } - imsg.applyField(InMessage.Field("qids", InMessage.Field.Type.RAW, (nwqid * 13).toUInt())) - val rawQids = imsg.fieldsRaw["qids"]!! - val qids: MutableList<QID> = mutableListOf() - for (i in 0..<nwqid/13) { - val start = i * 13 - val end = ((i+1) * 13) - 1 - val rawQid = rawQids.slice(start..end) - qids += QID(rawQid) - } - return qids.toList() - } - - override fun open(fid: UInt, mode: FileMode): Pair<QID, UInt> { - val omsg = OutMessage(NinePMessageType.TOPEN, this.tagGen.generate(), listOf("fid", "mode"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u), - "mode" to Pair(BigInteger(mode.toModeByte().toString()), 1u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - imsg.applySchema(listOf( - InMessage.Field("qid", InMessage.Field.Type.RAW, 13u), - InMessage.Field("iounit", InMessage.Field.Type.INTEGER, 4u) - )) - val qid = QID(imsg.fieldsRaw["qid"]!!.toList()) - val iounit = imsg.fieldsInt["iounit"]!!.toInt().toUInt() - return Pair(qid, iounit) - } - - override fun create(fid: UInt, name: String, perm: FilePermissions, mode: FileMode): Pair<QID, UInt> { - val omsg = OutMessage(NinePMessageType.TCREATE, this.tagGen.generate(), listOf("fid", "name", "perm", "mode"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u), - "perm" to Pair(BigInteger(perm.toPermissionInt().toString()), 4u), - "mode" to Pair(BigInteger(mode.toModeByte().toString()), 1u) - ), - mapOf( - "name" to name - ), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - imsg.applySchema(listOf( - InMessage.Field("qid", InMessage.Field.Type.RAW, 13u), - InMessage.Field("iounit", InMessage.Field.Type.INTEGER, 4u) - )) - val qid = QID(imsg.fieldsRaw["qid"]!!.toList()) - val iounit = imsg.fieldsInt["iounit"]!!.toInt().toUInt() - return Pair(qid, iounit) - } - - override fun read(fid: UInt, offset: ULong, count: UInt): Array<UByte> { - val omsg = OutMessage(NinePMessageType.TREAD, this.tagGen.generate(), listOf("fid", "offset", "count"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u), - "offset" to Pair(BigInteger(offset.toString()), 8u), - "count" to Pair(BigInteger(count.toString()), 4u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - imsg.applyField(InMessage.Field("count", InMessage.Field.Type.INTEGER, 4u)) - val count = imsg.fieldsInt["count"]!!.toInt().toUInt() - imsg.applyField(InMessage.Field("data", InMessage.Field.Type.RAW, count)) - - return imsg.fieldsRaw["data"]!! - } - - override fun write(fid: UInt, offset: ULong, count: UInt, data: Iterable<UByte>): UInt { - val data = data.take(count.toInt()).toTypedArray() - val omsg = OutMessage(NinePMessageType.TWRITE, this.tagGen.generate(), listOf("offset", "count", "data"), - mapOf( - "offset" to Pair(BigInteger(offset.toString()), 8u), - "count" to Pair(BigInteger(count.toString()), 4u) - ), - emptyMap(), - mapOf( - "data" to data.toList() - ), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - imsg.applyField(InMessage.Field("count", InMessage.Field.Type.INTEGER, 4u)) - val count = imsg.fieldsInt["count"]!! - - return count.toInt().toUInt() - } - - override fun clunk(fid: UInt) { - val omsg = OutMessage(NinePMessageType.TCLUNK, this.tagGen.generate(), listOf("fid"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - } - - override fun remove(fid: UInt) { - val omsg = OutMessage(NinePMessageType.TREMOVE, this.tagGen.generate(), listOf("fid"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - } - - override fun stat(fid: UInt): Stat { - val omsg = OutMessage(NinePMessageType.TSTAT, this.tagGen.generate(), listOf("fid"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u) - ), - emptyMap(), - emptyMap(), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - imsg.applyField(InMessage.Field("nstat", InMessage.Field.Type.INTEGER, 2u)) - val nstat = imsg.fieldsInt["nstat"]!!.toInt().toUInt() - imsg.applyField(InMessage.Field("stat", InMessage.Field.Type.RAW, nstat)) - val rawStat = imsg.fieldsRaw["stat"]!!.toList() - return Stat(fid, rawStat) - } - - override fun wstat(fid: UInt, stat: Stat) { - val omsg = OutMessage(NinePMessageType.TWSTAT, this.tagGen.generate(), listOf("fid", "stat"), - mapOf( - "fid" to Pair(BigInteger(fid.toString()), 4u) - ), - emptyMap(), - mapOf( - "stat" to stat.toRaw() - ), - this.maxSize - ) - omsg.write(this.tl) - val imsg = checkedInMessage(omsg.tag) - } -}
\ No newline at end of file |