NineKt: Teaching Kotlin to speak 9P =================================== NineKt (I don't really care about pronunciation, "nine-kay-tee" or "nine-Kate" or whatever you want) is a library written in Kotlin (and primarily targeting the JVM) that provides a client-side implementation to the [9P protocol](https://en.wikipedia.org/wiki/9P_(protocol)). It targets any JVM application, especially those that run on Android. The implementation of client-side 9P provided by NineKt and the expected server-side behavior are those described by the [section 5 in 9front's manual pages](https://man.9front.org/5/). All differences between this and the original Plan 9 from Bell Labs specification, or any other specification (provided by, e.g., forks of it), are therefore ignored. Rationale --------- There are a bunch of reasons why NineKt was born: 1. [All other JVM implementations](http://9p.cat-v.org/implementations) look dead. 2. There is no Kotlin implementation yet. 3. There seems to be no such thing for Android, but Android apps can create custom file systems in a bunch of ways. See the section named "A word on Android" below. 4. I thought it would be fun to make. Usage ----- The most important class, and also the fulcrum of the entire implementation, is `NinePConnection`. This class implements the 9P protocol on top of another unknown transport-layer protocol (although it's usually TCP) provided, and managed, by a subclass of the `NetworkPacketTransporter` abstract class. For this reason, the `NinePConnection`'s constructor requires an instance of another class that implements `NetworkPacketTransporter`. It doesn't need anything else. The `NetworkPacketTransporter` class provides abstraction over the specific networking methods. This makes the classes using `NetworkPacketTransporter` independent of both the specific networking API and the underlying transport-layer protocol of choice, therefore allowing swapping the API or protocol at any time and vastly improves portability. With all this considered, since Java's standard library provides a networking API already, I thought that an implementation based on that would be imperative, appreciated, and especially broadly used. ```kotlin // This example uses one of the dial(2) formats for the address and port. val npconn: NinePConnection try { npconn = NinePConnection(NetworkPacketTransporterJavaNet("net!9p.mydomain.com!564")) } catch (uhe: UnresolvableHostException) { // failed :( // what now? } ``` While `NetworkPacketTransporter`'s implementation of choice initializes the transport-layer connection as soon as it's instanced, this is not true for `NinePConnection` and the 9P connection it manages. The reason why this class behaves in such way lies in its purpose, which is to only expose methods that coincide 1:1 with 9P's protocol message types. Therefore, providing an automated way to initialize the protocol would mix two levels of abstraction in the same class. For this purpose, the `initNineP` utility function is a shorthand that can do exactly this for you, although it's possible to do so manually by using the 9P primitives. A word on Android ----------------- Android 11 introduces ([back](https://source.android.com/docs/core/storage/scoped#fuse-performance-tuning)) the support for [FUSE](https://en.wikipedia.org/wiki/Filesystem_in_Userspace) ([source](https://source.android.com/docs/core/storage/scoped#using-scoped-storage-with-fuse)), but this limits compatibility with certain versions of Android, and consequently certain devices. Android has also been supporting the [Storage Access Framework](https://developer.android.com/guide/topics/providers/document-provider) since version 4.4. [TODO] Notes ----- - Source files live in `src/main/kotlin`. - All manual page references (e.g. `dial(2)`) refer to [9front's manual](https://man.9front.org/). The number between parentheses is the section number. - The horizontal margin for code comments and documentation is 120 characters. However, it can be surpassed if it's really necessary License ------- The [Unlicense](https://unlicense.org/).