Skip to content

Commit 5553b8d

Browse files
Add an indirection in SocketHandler, to default to JNI on Windows (#4)
1 parent bb1789f commit 5553b8d

File tree

5 files changed

+97
-40
lines changed

5 files changed

+97
-40
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package libdaemonjvm.internal
2+
3+
object DefaultSocketHandler {
4+
def default: SocketHandler =
5+
JniSocketHandler
6+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package libdaemonjvm.internal
2+
3+
import java.nio.channels.{ServerSocketChannel, SocketChannel}
4+
import java.nio.file.Path
5+
6+
import org.scalasbt.ipcsocket.{UnixDomainServerSocket, UnixDomainSocket}
7+
import java.net.Socket
8+
import java.net.ServerSocket
9+
import java.io.IOException
10+
import org.scalasbt.ipcsocket.NativeErrorException
11+
import scala.util.Properties
12+
import org.scalasbt.ipcsocket.Win32NamedPipeSocket
13+
import org.scalasbt.ipcsocket.Win32NamedPipeServerSocket
14+
15+
import libdaemonjvm.errors._
16+
import libdaemonjvm.SocketPaths
17+
import java.util.Locale
18+
19+
object JniSocketHandler extends SocketHandler {
20+
21+
def supported(): Boolean =
22+
(Properties.isLinux || Properties.isWin || Properties.isMac) &&
23+
sys.props.get("os.arch").exists { arch =>
24+
val arch0 = arch.toLowerCase(Locale.ROOT)
25+
arch0 == "x86_64" || arch0 == "amd64"
26+
}
27+
28+
private val connectionRelatedCodes = Set(61, 111)
29+
private def exHandler: PartialFunction[Throwable, Nothing] = {
30+
case ex: IOException
31+
if Option(ex.getCause)
32+
.collect { case e: NativeErrorException => e }
33+
.exists(e => connectionRelatedCodes(e.returnCode)) =>
34+
throw new ConnectExceptionLike(ex)
35+
case ex: IOException if ex.getMessage.contains("error code 2") =>
36+
throw new SocketExceptionLike(ex)
37+
case ex: IOException if ex.getMessage.contains("Couldn't open pipe for") =>
38+
throw new SocketExceptionLike(ex)
39+
}
40+
41+
private def actualPath(paths: SocketPaths): String =
42+
if (usesWindowsPipe) paths.windowsPipeName
43+
else paths.path.toString
44+
45+
def usesWindowsPipe: Boolean =
46+
Properties.isWin
47+
48+
def client(paths: SocketPaths): Either[Socket, SocketChannel] = {
49+
val s =
50+
try SocketMaker.client(actualPath(paths))
51+
catch exHandler
52+
Left(s)
53+
}
54+
55+
def server(paths: SocketPaths): Either[ServerSocket, ServerSocketChannel] = {
56+
val s = SocketMaker.server(actualPath(paths))
57+
Left(s)
58+
}
59+
}

library/src/libdaemonjvm/internal/SocketHandler.scala

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,22 @@ package libdaemonjvm.internal
33
import java.nio.channels.{ServerSocketChannel, SocketChannel}
44
import java.nio.file.Path
55

6-
import org.scalasbt.ipcsocket.{UnixDomainServerSocket, UnixDomainSocket}
76
import java.net.Socket
87
import java.net.ServerSocket
9-
import java.io.IOException
10-
import org.scalasbt.ipcsocket.NativeErrorException
11-
import scala.util.Properties
12-
import org.scalasbt.ipcsocket.Win32NamedPipeSocket
13-
import org.scalasbt.ipcsocket.Win32NamedPipeServerSocket
148

15-
import libdaemonjvm.errors._
169
import libdaemonjvm.SocketPaths
1710

18-
object SocketHandler {
19-
private val connectionRelatedCodes = Set(61, 111)
20-
private def exHandler: PartialFunction[Throwable, Nothing] = {
21-
case ex: IOException
22-
if Option(ex.getCause)
23-
.collect { case e: NativeErrorException => e }
24-
.exists(e => connectionRelatedCodes(e.returnCode)) =>
25-
throw new ConnectExceptionLike(ex)
26-
case ex: IOException if ex.getMessage.contains("error code 2") =>
27-
throw new SocketExceptionLike(ex)
28-
case ex: IOException if ex.getMessage.contains("Couldn't open pipe for") =>
29-
throw new SocketExceptionLike(ex)
30-
}
31-
32-
private def actualPath(paths: SocketPaths): String =
33-
if (usesWindowsPipe) paths.windowsPipeName
34-
// val bt = "\\"
35-
// s"$bt$bt.${bt}pipe$bt" + f
36-
else paths.path.toString
11+
trait SocketHandler {
12+
def usesWindowsPipe: Boolean
13+
def client(paths: SocketPaths): Either[Socket, SocketChannel]
14+
def server(paths: SocketPaths): Either[ServerSocket, ServerSocketChannel]
15+
}
3716

17+
object SocketHandler {
3818
def usesWindowsPipe: Boolean =
39-
Properties.isWin
40-
41-
def client(paths: SocketPaths): Either[Socket, SocketChannel] = {
42-
val s =
43-
try SocketMaker.client(actualPath(paths))
44-
catch exHandler
45-
Left(s)
46-
}
47-
48-
def server(paths: SocketPaths): Either[ServerSocket, ServerSocketChannel] = {
49-
val s = SocketMaker.server(actualPath(paths))
50-
Left(s)
51-
}
19+
DefaultSocketHandler.default.usesWindowsPipe
20+
def client(paths: SocketPaths): Either[Socket, SocketChannel] =
21+
DefaultSocketHandler.default.client(paths)
22+
def server(paths: SocketPaths): Either[ServerSocket, ServerSocketChannel] =
23+
DefaultSocketHandler.default.server(paths)
5224
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package libdaemonjvm.internal
2+
3+
import scala.util.Properties
4+
5+
object DefaultSocketHandler {
6+
def default: SocketHandler =
7+
sys.props.get("libdaemonjvm.internal.DefaultSocketHandler") match {
8+
case Some("JniSocketHandler" | "jni") => JniSocketHandler
9+
case Some("Java16SocketHandler" | "java16") => Java16SocketHandler
10+
case _ =>
11+
// On Windows, default to JNI for now when we can, as the JNI and Java 16
12+
// support aren't compatible with each other, so that Java 8 and Java 17 processes
13+
// can talk to each other (via the JNI stuff).
14+
// In more detail, JNI support relies on Windows "named pipes", while the Java 16
15+
// one relies on proper Unix-like domain socket support (added at some point in Windows
16+
// 10). Hence the incompatibility.
17+
if (Properties.isWin && JniSocketHandler.supported()) JniSocketHandler
18+
else Java16SocketHandler
19+
}
20+
}

library16/src/libdaemonjvm/internal/SocketHandler.scala renamed to library16/src/libdaemonjvm/internal/Java16SocketHandler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import java.nio.file.Paths
1313

1414
import libdaemonjvm.SocketPaths
1515

16-
object SocketHandler {
16+
object Java16SocketHandler extends SocketHandler {
1717
def usesWindowsPipe: Boolean = false
1818

1919
def client(paths: SocketPaths): Either[Socket, SocketChannel] = {

0 commit comments

Comments
 (0)