src/Pure/System/system_channel.scala
changeset 79049 10b6add456d0
parent 79048 caddfe4949a8
child 79053 badb3da19ac6
--- a/src/Pure/System/system_channel.scala	Fri Nov 24 14:11:01 2023 +0100
+++ b/src/Pure/System/system_channel.scala	Fri Nov 24 15:58:24 2023 +0100
@@ -8,18 +8,40 @@
 
 
 import java.io.{InputStream, OutputStream}
-import java.net.{ServerSocket, InetAddress}
+import java.net.{InetAddress, InetSocketAddress, ProtocolFamily, ServerSocket, SocketAddress, StandardProtocolFamily, UnixDomainSocketAddress}
+import java.nio.channels.{ServerSocketChannel, Channels}
 
 
 object System_Channel {
-  def apply(): System_Channel = new System_Channel
+  def apply(unix_domain: Boolean = Platform.is_unix): System_Channel =
+    if (unix_domain) new Unix else new Inet
+
+  class Inet extends System_Channel(StandardProtocolFamily.INET) {
+    server.bind(new InetSocketAddress(Server.localhost, 0), 50)
+
+    override def address: String =
+      Server.print_address(server.getLocalAddress.asInstanceOf[InetSocketAddress].getPort)
+  }
+
+  class Unix extends System_Channel(StandardProtocolFamily.UNIX) {
+    private val socket_file = Isabelle_System.tmp_file("socket", initialized = false)
+    private val socket_file_name = socket_file.getPath
+
+    server.bind(UnixDomainSocketAddress.of(socket_file_name))
+
+    override def address: String = socket_file_name
+    override def shutdown(): Unit = {
+      super.shutdown()
+      socket_file.delete
+    }
+  }
 }
 
-class System_Channel private {
-  private val server = new ServerSocket(0, 50, Server.localhost)
+abstract class System_Channel private(protocol_family: ProtocolFamily) {
+  protected val server: ServerSocketChannel = ServerSocketChannel.open(protocol_family)
 
-  val address: String = Server.print_address(server.getLocalPort)
-  val password: String = UUID.random().toString
+  def address: String
+  lazy val password: String = UUID.random().toString
 
   override def toString: String = address
 
@@ -28,8 +50,8 @@
   def rendezvous(): (OutputStream, InputStream) = {
     val socket = server.accept
     try {
-      val out_stream = socket.getOutputStream
-      val in_stream = socket.getInputStream
+      val out_stream = Channels.newOutputStream(socket)
+      val in_stream = Channels.newInputStream(socket)
 
       Byte_Message.read_line(in_stream) match {
         case Some(bs) if bs.text == password => (out_stream, in_stream)