X-Git-Url: https://git.distorted.org.uk/~mdw/tripe-android/blobdiff_plain/a5ec891a1f3cbe4ae9aad5d2252f39b483ed543e..3bb2303d42adb3f37420f168b009ecfe64f888cd:/sys.scala diff --git a/sys.scala b/sys.scala index 6931431..402bf1d 100644 --- a/sys.scala +++ b/sys.scala @@ -28,7 +28,7 @@ package uk.org.distorted.tripe; package object sys { /*----- Imports -----------------------------------------------------------*/ import scala.collection.convert.decorateAsJava._; -import scala.collection.mutable.HashSet; +import scala.collection.mutable.{HashMap, HashSet}; import java.io.{BufferedReader, BufferedWriter, Closeable, File, FileDescriptor, FileInputStream, FileOutputStream, @@ -124,7 +124,7 @@ import StringImplicits._; /*----- Main code ---------------------------------------------------------*/ /* Import the native code library. */ -System.loadLibrary("toy"); +System.loadLibrary("tripe"); /* Native types. * @@ -810,15 +810,15 @@ private final val maxTriggers = 2; private var nTriggers = 0; private var triggers: List[Wrapper] = Nil; -@native protected def makeTrigger(): Wrapper; -@native protected def destroyTrigger(trig: Wrapper); -@native protected def resetTrigger(trig: Wrapper); +@native protected def make_trigger(): Wrapper; +@native protected def destroy_trigger(trig: Wrapper); +@native protected def reset_trigger(trig: Wrapper); @native protected def trigger(trig: Wrapper); private def getTrigger(): Wrapper = { triggerLock synchronized { if (nTriggers == 0) - makeTrigger() + make_trigger() else { val trig = triggers.head; triggers = triggers.tail; @@ -829,10 +829,10 @@ private def getTrigger(): Wrapper = { } private def putTrigger(trig: Wrapper) { - resetTrigger(trig); + reset_trigger(trig); triggerLock synchronized { if (nTriggers >= maxTriggers) - destroyTrigger(trig); + destroy_trigger(trig); else { triggers ::= trig; nTriggers += 1; @@ -859,59 +859,69 @@ def interruptWithTrigger[T](body: Wrapper => T): T = { }; } -/*----- Connecting to a server --------------------------------------------*/ +/*----- Glue for the VPN server -------------------------------------------*/ -/* Primitive operations. */ -final val CF_CLOSERD = 1; -final val CF_CLOSEWR = 2; -final val CF_CLOSEMASK = CF_CLOSERD | CF_CLOSEWR; -@native protected def connect(path: CString, trig: Wrapper): Wrapper; -@native protected def send(conn: Wrapper, buf: CString, - start: Int, len: Int, trig: Wrapper); -@native protected def recv(conn: Wrapper, buf: CString, - start: Int, len: Int, trig: Wrapper): Int; -@native def closeconn(conn: Wrapper, how: Int); - -class Connection(path: String) extends Closeable { - - /* The underlying primitive connection. */ - private[this] val conn = interruptWithTrigger { trig => - connect(path.toCString, trig); - }; - - /* Alternative constructors. */ - def this(file: File) { this(file.getPath); } +/* The lock class. This is only a class because they're much easier to find + * than loose objects through JNI. + */ +private class ServerLock; - /* Cleanup.*/ - override def close() { closeconn(conn, CF_CLOSEMASK); } - override protected def finalize() { super.finalize(); close(); } +/* Exceptions. */ +class NameResolutionException(msg: String) extends Exception(msg); +class InitializationException(msg: String) extends Exception(msg); - class Input private[Connection] extends InputStream { - /* An input stream which reads from the connection. */ +/* Primitive operations. */ +@native protected def open_tun(): Int; +@native protected def base_init(); +@native protected def setup_resolver(); +@native def load_keys(priv: CString, pub: CString, tag: CString); +@native def unload_keys(); +@native def bind(host: CString, svc: CString); +@native def unbind(); +@native def mark(seq: Int); +@native def run(); +@native protected def send(buf: CString, start: Int, len: Int, + trig: Wrapper); +@native protected def recv(buf: CString, start: Int, len: Int, + trig: Wrapper): Int; + +base_init(); +setup_resolver(); + +/* Tunnel descriptor plumbing. */ +val pending = HashMap[String, Int](); + +def getTunnelFd(peer: CString): Int = + pending synchronized { pending(peer.toJString) }; +def storeTunnelFd(peer: String, fd: Int) + { pending synchronized { pending(peer) = fd; } } +def withdrawTunnelFd(peer: String) + { pending synchronized { pending -= peer; } } +def withTunnelFd[T](peer: String, fd: Int)(body: => T): T = { + storeTunnelFd(peer, fd); + try { body } finally { withdrawTunnelFd(peer); } +} - override def read(): Int = { - val buf = new Array[Byte](1); - val n = read(buf, 0, 1); - if (n < 0) -1 else buf(0)&0xff; - } - override def read(buf: Array[Byte]): Int = - read(buf, 0, buf.length); - override def read(buf: Array[Byte], start: Int, len: Int) = - interruptWithTrigger { trig => recv(conn, buf, start, len, trig); }; - override def close() { closeconn(conn, CF_CLOSERD); } +/* Server I/O. */ +lazy val serverInput: InputStream = new InputStream { + override def read(): Int = { + val buf = new Array[Byte](1); + val n = read(buf, 0, 1); + if (n < 0) -1 else buf(0)&0xff; } - lazy val input = new Input; - - class Output private[Connection] extends OutputStream { - /* An output stream which writes to the connection. */ + override def read(buf: Array[Byte]): Int = + read(buf, 0, buf.length); + override def read(buf: Array[Byte], start: Int, len: Int) = + interruptWithTrigger { trig => recv(buf, start, len, trig); }; + override def close() { } +} - override def write(b: Int) { write(Array[Byte](b.toByte), 0, 1); } - override def write(buf: Array[Byte]) { write(buf, 0, buf.length); } - override def write(buf: Array[Byte], start: Int, len: Int) - { interruptWithTrigger { trig => send(conn, buf, start, len, trig); } } - override def close() { closeconn(conn, CF_CLOSEWR); } - } - lazy val output = new Output; +lazy val serverOutput: OutputStream = new OutputStream { + override def write(b: Int) { write(Array[Byte](b.toByte), 0, 1); } + override def write(buf: Array[Byte]) { write(buf, 0, buf.length); } + override def write(buf: Array[Byte], start: Int, len: Int) + { interruptWithTrigger { trig => send(buf, start, len, trig); } } + override def close() { } } /*----- Crypto-library hacks ----------------------------------------------*/