mirror of https://github.com/sbt/sbt.git
72 lines
2.0 KiB
Scala
72 lines
2.0 KiB
Scala
/* sbt -- Simple Build Tool
|
|
* Copyright 2009 Mark Harrah
|
|
*/
|
|
package xsbt
|
|
|
|
import java.io.{BufferedReader, BufferedWriter, InputStream, InputStreamReader, OutputStreamWriter, OutputStream}
|
|
import java.net.{InetAddress, ServerSocket, Socket}
|
|
|
|
object IPC
|
|
{
|
|
private val portMin = 1025
|
|
private val portMax = 65536
|
|
private val loopback = InetAddress.getByName(null) // loopback
|
|
|
|
def client[T](port: Int)(f: IPC => T): T =
|
|
ipc(new Socket(loopback, port))(f)
|
|
|
|
def pullServer[T](f: Server => T): T =
|
|
{
|
|
val server = makeServer
|
|
try { f(new Server(server)) }
|
|
finally { server.close() }
|
|
}
|
|
def makeServer: ServerSocket =
|
|
{
|
|
val random = new java.util.Random
|
|
def nextPort = random.nextInt(portMax - portMin + 1) + portMin
|
|
def createServer(attempts: Int): ServerSocket =
|
|
if(attempts > 0)
|
|
try { new ServerSocket(nextPort, 1, loopback) }
|
|
catch { case _: Exception => createServer(attempts - 1) }
|
|
else
|
|
error("Could not connect to socket: maximum attempts exceeded")
|
|
createServer(10)
|
|
}
|
|
def server[T](f: IPC => Option[T]): T = serverImpl(makeServer, f)
|
|
def server[T](port: Int)(f: IPC => Option[T]): T =
|
|
serverImpl(new ServerSocket(port, 1, loopback), f)
|
|
private def serverImpl[T](server: ServerSocket, f: IPC => Option[T]): T =
|
|
{
|
|
def listen(): T =
|
|
{
|
|
ipc(server.accept())(f) match
|
|
{
|
|
case Some(done) => done
|
|
case None => listen()
|
|
}
|
|
}
|
|
|
|
try { listen() }
|
|
finally { server.close() }
|
|
}
|
|
private def ipc[T](s: Socket)(f: IPC => T): T =
|
|
try { f(new IPC(s)) }
|
|
finally { s.close() }
|
|
|
|
final class Server private[IPC](s: ServerSocket) extends NotNull
|
|
{
|
|
def port = s.getLocalPort
|
|
def close() = s.close()
|
|
def connection[T](f: IPC => T): T = IPC.ipc(s.accept())(f)
|
|
}
|
|
}
|
|
final class IPC private(s: Socket) extends NotNull
|
|
{
|
|
def port = s.getLocalPort
|
|
private val in = new BufferedReader(new InputStreamReader(s.getInputStream))
|
|
private val out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream))
|
|
|
|
def send(s: String) = { out.write(s); out.newLine(); out.flush() }
|
|
def receive: String = in.readLine()
|
|
} |