> datagramChannelClass() {
+ return AFSYSTEMDatagramChannel.class;
+ }
+ });
+
+ private AFSYSTEMSelectorProvider() {
+ super();
+ }
+
+ /**
+ * Returns the singleton instance.
+ *
+ * @return The instance.
+ */
+ @SuppressFBWarnings("MS_EXPOSE_REP")
+ public static AFSYSTEMSelectorProvider getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Returns the singleton instance.
+ *
+ * @return The instance.
+ */
+ public static AFSYSTEMSelectorProvider provider() {
+ return getInstance();
+ }
+
+ /**
+ * Constructs a new socket pair from two sockets.
+ *
+ * @param s1 Some socket, the first one.
+ * @param s2 Some socket, the second one.
+ * @return The pair.
+ */
+ @Override
+ protected AFSocketPair
newSocketPair(P s1, P s2) {
+ return new AFSYSTEMSocketPair<>(s1, s2);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public AFSYSTEMSocketPair openSocketChannelPair() throws IOException {
+ return (AFSYSTEMSocketPair) super.openSocketChannelPair();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public AFSYSTEMSocketPair openDatagramChannelPair() throws IOException {
+ return (AFSYSTEMSocketPair) super.openDatagramChannelPair();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public AFSYSTEMSocketPair openDatagramChannelPair(AFSocketType type)
+ throws IOException {
+ return (AFSYSTEMSocketPair) super.openDatagramChannelPair(type);
+ }
+
+ @Override
+ protected AFSYSTEMSocket newSocket() throws IOException {
+ return AFSYSTEMSocket.newInstance();
+ }
+
+ @Override
+ public AFSYSTEMDatagramChannel openDatagramChannel() throws IOException {
+ return AFSYSTEMDatagramSocket.newInstance().getChannel();
+ }
+
+ @Override
+ public AFSYSTEMDatagramChannel openDatagramChannel(AFSocketType type) throws IOException {
+ return AFSYSTEMDatagramSocket.newInstance(type).getChannel();
+ }
+
+ @Override
+ public AFSYSTEMDatagramChannel openDatagramChannel(ProtocolFamily family) throws IOException {
+ return (AFSYSTEMDatagramChannel) super.openDatagramChannel(family);
+ }
+
+ @Override
+ public AFSYSTEMServerSocketChannel openServerSocketChannel() throws IOException {
+ return AFSYSTEMServerSocket.newInstance().getChannel();
+ }
+
+ @Override
+ public AFSYSTEMServerSocketChannel openServerSocketChannel(SocketAddress sa) throws IOException {
+ return AFSYSTEMServerSocket.bindOn(AFSYSTEMSocketAddress.unwrap(sa)).getChannel();
+ }
+
+ @Override
+ public AFSYSTEMSocketChannel openSocketChannel() throws IOException {
+ return (AFSYSTEMSocketChannel) super.openSocketChannel();
+ }
+
+ @Override
+ public AFSYSTEMSocketChannel openSocketChannel(SocketAddress sa) throws IOException {
+ return AFSYSTEMSocket.connectTo(AFSYSTEMSocketAddress.unwrap(sa)).getChannel();
+ }
+
+ @Override
+ protected ProtocolFamily protocolFamily() {
+ return AFSYSTEMProtocolFamily.SYSTEM;
+ }
+
+ @Override
+ protected AFAddressFamily<@NonNull AFSYSTEMSocketAddress> addressFamily() {
+ return AF_SYSTEM;
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMServerSocket.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMServerSocket.java
new file mode 100644
index 000000000..3e122b955
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMServerSocket.java
@@ -0,0 +1,124 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.SocketException;
+
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFServerSocket;
+import org.newsclub.net.unix.AFServerSocketChannel;
+import org.newsclub.net.unix.AFSocket;
+import org.newsclub.net.unix.AFSocketAddress;
+import org.newsclub.net.unix.AFSocketImpl;
+
+/**
+ * The server part of an {@code AF_SYSTEM} socket.
+ *
+ * @author Christian Kohlschütter
+ */
+public class AFSYSTEMServerSocket extends AFServerSocket {
+ AFSYSTEMServerSocket(FileDescriptor fdObj) throws IOException {
+ super(fdObj);
+ }
+
+ @Override
+ protected AFServerSocketChannel newChannel() {
+ return new AFSYSTEMServerSocketChannel(this);
+ }
+
+ @Override
+ public AFSYSTEMServerSocketChannel getChannel() {
+ return (AFSYSTEMServerSocketChannel) super.getChannel();
+ }
+
+ /**
+ * Returns a new, unbound AF_SYSTEM {@link ServerSocket}.
+ *
+ * @return The new, unbound {@link AFServerSocket}.
+ * @throws IOException if the operation fails.
+ */
+ public static AFSYSTEMServerSocket newInstance() throws IOException {
+ return (AFSYSTEMServerSocket) AFServerSocket.newInstance(AFSYSTEMServerSocket::new);
+ }
+
+ static AFSYSTEMServerSocket newInstance(FileDescriptor fdObj, int localPort, int remotePort)
+ throws IOException {
+ return (AFSYSTEMServerSocket) AFServerSocket.newInstance(AFSYSTEMServerSocket::new, fdObj,
+ localPort, remotePort);
+ }
+
+ /**
+ * Returns a new AF_SYSTEM {@link ServerSocket} that is bound to the given
+ * {@link AFSYSTEMSocketAddress}.
+ *
+ * @param addr The socket file to bind to.
+ * @return The new, bound {@link AFServerSocket}.
+ * @throws IOException if the operation fails.
+ */
+ public static AFSYSTEMServerSocket bindOn(final AFSYSTEMSocketAddress addr) throws IOException {
+ return (AFSYSTEMServerSocket) AFServerSocket.bindOn(AFSYSTEMServerSocket::new, addr);
+ }
+
+ /**
+ * Returns a new AF_SYSTEM {@link ServerSocket} that is bound to the given
+ * {@link AFSocketAddress}.
+ *
+ * @param addr The socket file to bind to.
+ * @param deleteOnClose If {@code true}, the socket file (if the address points to a file) will be
+ * deleted upon {@link #close}.
+ * @return The new, bound {@link AFServerSocket}.
+ * @throws IOException if the operation fails.
+ */
+ public static AFSYSTEMServerSocket bindOn(final AFSYSTEMSocketAddress addr, boolean deleteOnClose)
+ throws IOException {
+ return (AFSYSTEMServerSocket) AFServerSocket.bindOn(AFSYSTEMServerSocket::new, addr,
+ deleteOnClose);
+ }
+
+ /**
+ * Returns a new, unbound AF_SYSTEM {@link ServerSocket} that will always bind to the
+ * given address, regardless of any socket address used in a call to bind
.
+ *
+ * @param forceAddr The address to use.
+ * @return The new, yet unbound {@link AFServerSocket}.
+ * @throws IOException if an exception occurs.
+ */
+ public static AFSYSTEMServerSocket forceBindOn(final AFSYSTEMSocketAddress forceAddr)
+ throws IOException {
+ return (AFSYSTEMServerSocket) AFServerSocket.forceBindOn(AFSYSTEMServerSocket::new, forceAddr);
+ }
+
+ @Override
+ protected AFSocketImpl newImpl(FileDescriptor fdObj)
+ throws SocketException {
+ return new AFSYSTEMSocketImpl(fdObj);
+ }
+
+ @Override
+ protected AFSocket newSocketInstance() throws IOException {
+ return AFSYSTEMSocket.newInstance();
+ }
+
+ @Override
+ public AFSYSTEMSocket accept() throws IOException {
+ return (AFSYSTEMSocket) super.accept();
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMServerSocketChannel.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMServerSocketChannel.java
new file mode 100644
index 000000000..ddb25739d
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMServerSocketChannel.java
@@ -0,0 +1,45 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.io.IOException;
+
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFServerSocketChannel;
+
+/**
+ * A selectable channel for stream-oriented listening sockets.
+ *
+ * @author Christian Kohlschütter
+ */
+public final class AFSYSTEMServerSocketChannel extends
+ AFServerSocketChannel {
+ AFSYSTEMServerSocketChannel(AFSYSTEMServerSocket socket) {
+ super(socket, AFSYSTEMSelectorProvider.getInstance());
+ }
+
+ /**
+ * Opens a server-socket channel.
+ *
+ * @return The new channel
+ * @throws IOException on error.
+ */
+ public static AFSYSTEMServerSocketChannel open() throws IOException {
+ return AFSYSTEMServerSocket.newInstance().getChannel();
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocket.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocket.java
new file mode 100644
index 000000000..de5969b19
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocket.java
@@ -0,0 +1,138 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFSYSTEMSocketImplExtensions;
+import org.newsclub.net.unix.AFSocket;
+import org.newsclub.net.unix.AFSocketCapability;
+import org.newsclub.net.unix.AFSocketFactory;
+
+/**
+ * Implementation of an {@code AF_SYSTEM} socket.
+ *
+ * @author Christian Kohlschütter
+ */
+public final class AFSYSTEMSocket extends AFSocket implements
+ AFSYSTEMSocketExtensions {
+ private static AFSYSTEMSocketImplExtensions staticExtensions = null;
+
+ AFSYSTEMSocket(FileDescriptor fdObj, AFSocketFactory factory)
+ throws SocketException {
+ super(new AFSYSTEMSocketImpl(fdObj), factory);
+ }
+
+ @SuppressWarnings("unused")
+ private static synchronized AFSYSTEMSocketImplExtensions getStaticImplExtensions()
+ throws IOException {
+ if (staticExtensions == null) {
+ try (AFSYSTEMSocket socket = new AFSYSTEMSocket(null, null)) {
+ staticExtensions = (AFSYSTEMSocketImplExtensions) socket.getImplExtensions();
+ }
+ }
+ return staticExtensions;
+ }
+
+ /**
+ * Returns true
iff {@link AFSYSTEMSocket}s (sockets of type "AF_SYSTEM") are
+ * supported by the current Java VM and the kernel.
+ *
+ * To support {@link AFSYSTEMSocket}s, a custom JNI library must be loaded that is supplied with
+ * junixsocket , and the system must support AF_SYSTEM sockets.
+ *
+ * This call is equivalent to checking {@link AFSocket#isSupported()} and
+ * {@link AFSocket#supports(AFSocketCapability)} with
+ * {@link AFSocketCapability#CAPABILITY_DARWIN}.
+ *
+ * @return {@code true} iff supported.
+ */
+ public static boolean isSupported() {
+ return AFSocket.isSupported() && AFSocket.supports(AFSocketCapability.CAPABILITY_DARWIN);
+ }
+
+ @Override
+ protected AFSYSTEMSocketChannel newChannel() {
+ return new AFSYSTEMSocketChannel(this);
+ }
+
+ /**
+ * Creates a new, unbound {@link AFSocket}.
+ *
+ * This "default" implementation is a bit "lenient" with respect to the specification.
+ *
+ * In particular, we ignore calls to {@link Socket#getTcpNoDelay()} and
+ * {@link Socket#setTcpNoDelay(boolean)}.
+ *
+ * @return A new, unbound socket.
+ * @throws IOException if the operation fails.
+ */
+ public static AFSYSTEMSocket newInstance() throws IOException {
+ return (AFSYSTEMSocket) AFSocket.newInstance(AFSYSTEMSocket::new, (AFSYSTEMSocketFactory) null);
+ }
+
+ static AFSYSTEMSocket newInstance(AFSYSTEMSocketFactory factory) throws SocketException {
+ return (AFSYSTEMSocket) AFSocket.newInstance(AFSYSTEMSocket::new, factory);
+ }
+
+ /**
+ * Creates a new, unbound, "strict" {@link AFSocket}.
+ *
+ * This call uses an implementation that tries to be closer to the specification than
+ * {@link #newInstance()}, at least for some cases.
+ *
+ * @return A new, unbound socket.
+ * @throws IOException if the operation fails.
+ */
+ public static AFSYSTEMSocket newStrictInstance() throws IOException {
+ return (AFSYSTEMSocket) AFSocket.newInstance(AFSYSTEMSocket::new, (AFSYSTEMSocketFactory) null);
+ }
+
+ /**
+ * Creates a new {@link AFSocket} and connects it to the given {@link AFSYSTEMSocketAddress}.
+ *
+ * @param addr The address to connect to.
+ * @return A new, connected socket.
+ * @throws IOException if the operation fails.
+ */
+ public static AFSYSTEMSocket connectTo(AFSYSTEMSocketAddress addr) throws IOException {
+ return (AFSYSTEMSocket) AFSocket.connectTo(AFSYSTEMSocket::new, addr);
+ }
+
+ @Override
+ public AFSYSTEMSocketChannel getChannel() {
+ return (AFSYSTEMSocketChannel) super.getChannel();
+ }
+
+ /**
+ * Very basic self-test function.
+ *
+ * Prints "supported" and "capabilities" status to System.out.
+ *
+ * @param args ignored.
+ */
+ public static void main(String[] args) {
+ System.out.print(AFSYSTEMSocket.class.getName() + ".isSupported(): ");
+ System.out.flush();
+ System.out.println(AFSYSTEMSocket.isSupported());
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketChannel.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketChannel.java
new file mode 100644
index 000000000..95566ded1
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketChannel.java
@@ -0,0 +1,33 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFSocketChannel;
+
+/**
+ * A selectable channel for stream-oriented connecting sockets.
+ *
+ * @author Christian Kohlschütter
+ */
+public final class AFSYSTEMSocketChannel extends AFSocketChannel implements
+ AFSYSTEMSocketExtensions {
+ AFSYSTEMSocketChannel(AFSYSTEMSocket socket) {
+ super(socket, AFSYSTEMSelectorProvider.getInstance());
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketExtensions.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketExtensions.java
new file mode 100644
index 000000000..3d1b1a7c6
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketExtensions.java
@@ -0,0 +1,29 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import org.newsclub.net.unix.AFSocketExtensions;
+
+/**
+ * Defines certain methods that all junixsocket AF_SYSTEM socket implementations share and extend
+ * beyond the standard socket API.
+ *
+ * @author Christian Kohlschütter
+ */
+public interface AFSYSTEMSocketExtensions extends AFSocketExtensions {
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketFactory.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketFactory.java
new file mode 100644
index 000000000..0e62599a8
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketFactory.java
@@ -0,0 +1,58 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFSocketFactory;
+
+/**
+ * The base for a SocketFactory that connects to AF_SYSTEM sockets.
+ */
+public abstract class AFSYSTEMSocketFactory extends AFSocketFactory {
+ /**
+ * Creates a {@link AFSYSTEMSocketFactory}.
+ */
+ protected AFSYSTEMSocketFactory() {
+ super();
+ }
+
+ @Override
+ public final Socket createSocket() throws SocketException {
+ return configure(AFSYSTEMSocket.newInstance(this));
+ }
+
+ @Override
+ protected final AFSYSTEMSocket connectTo(AFSYSTEMSocketAddress addr) throws IOException {
+ return configure(AFSYSTEMSocket.connectTo(addr));
+ }
+
+ /**
+ * Performs some optional configuration on a newly created socket.
+ *
+ * @param sock The socket.
+ * @return The very socket.
+ * @throws SocketException on error.
+ */
+ protected AFSYSTEMSocket configure(AFSYSTEMSocket sock) throws SocketException {
+ return sock;
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketImpl.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketImpl.java
new file mode 100644
index 000000000..b7190b434
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketImpl.java
@@ -0,0 +1,40 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFSocketImpl;
+
+final class AFSYSTEMSocketImpl extends AFSocketImpl {
+ AFSYSTEMSocketImpl(FileDescriptor fdObj) {
+ super(AFSYSTEMSelectorProvider.AF_SYSTEM, fdObj);
+ }
+
+ @Override
+ public Object getOption(int optID) throws SocketException {
+ return getOptionLenient(optID);
+ }
+
+ @Override
+ public void setOption(int optID, Object value) throws SocketException {
+ setOptionLenient(optID, value);
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketOptions.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketOptions.java
new file mode 100644
index 000000000..bf230554e
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketOptions.java
@@ -0,0 +1,32 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * AF_SYSTEM-specific socket options.
+ *
+ * @author Christian Kohlschütter
+ */
+@NonNullByDefault
+public final class AFSYSTEMSocketOptions {
+ private AFSYSTEMSocketOptions() {
+ throw new IllegalStateException();
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketPair.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketPair.java
new file mode 100644
index 000000000..99b028dbb
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/AFSYSTEMSocketPair.java
@@ -0,0 +1,61 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.io.IOException;
+
+import org.newsclub.net.unix.AFSocketPair;
+import org.newsclub.net.unix.AFSomeSocket;
+
+/**
+ * A pair of sockets.
+ *
+ * @param The socket type.
+ * @author Christian Kohlschütter
+ */
+public final class AFSYSTEMSocketPair extends AFSocketPair {
+ /**
+ * Creates a new socket pair.
+ *
+ * @param socket1 The first socket.
+ * @param socket2 The second socket.
+ */
+ AFSYSTEMSocketPair(T socket1, T socket2) {
+ super(socket1, socket2);
+ }
+
+ /**
+ * Opens a socket pair of interconnected channels.
+ *
+ * @return The new channel pair.
+ * @throws IOException on error.
+ */
+ public static AFSYSTEMSocketPair open() throws IOException {
+ return AFSYSTEMSelectorProvider.provider().openSocketChannelPair();
+ }
+
+ /**
+ * Opens a socket pair of interconnected datagram channels.
+ *
+ * @return The new channel pair.
+ * @throws IOException on error.
+ */
+ public static AFSYSTEMSocketPair openDatagram() throws IOException {
+ return AFSYSTEMSelectorProvider.provider().openDatagramChannelPair();
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/IPUtil.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/IPUtil.java
new file mode 100644
index 000000000..d1c8cb44c
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/IPUtil.java
@@ -0,0 +1,173 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Some IP protocol-related helper methods.
+ *
+ * @author Christian Kohlschütter
+ */
+public final class IPUtil {
+ /**
+ * The length (in bytes) of the "domain" header used in loopback packet systems like UTUN_CONTROL.
+ */
+ public static final int DOMAIN_HEADER_LENGTH = 4; // bytes
+
+ /**
+ * The identifier for AF_INET (at least on Darwin).
+ */
+ public static final int DOMAIN_AF_INET = 2;
+
+ /**
+ * The length (in bytes) of an IPv4 header without options.
+ */
+ public static final int IPV4_DEFAULT_HEADER_SIZE = 20; // bytes
+
+ /**
+ * The ICMP protocol.
+ */
+ public static final byte AF_INET_PROTOCOL_ICMP = 1;
+
+ private IPUtil() {
+ throw new IllegalStateException("No instances");
+ }
+
+ /**
+ * Computes the checksum for an IPv4 header, and overwrites any existing checksum with the correct
+ * one.
+ *
+ * @param bb The buffer containing the IPv4 header
+ * @param start The beginning position of the header in the buffer.
+ * @param end The end position (exclusive) of the header in the buffer.
+ * @return The computed 16-bit checksum
+ */
+ public static int checksumIPv4header(ByteBuffer bb, int start, int end) {
+ return checksumIPstyle(bb, start, end, 10);
+ }
+
+ /**
+ * Computes the checksum for an ICMP header, and overwrites any existing checksum with the correct
+ * one.
+ *
+ * Also see RFC 792 .
+ *
+ * @param bb The buffer containing the ICMP header
+ * @param start The beginning position of the header in the buffer.
+ * @param end The end position (exclusive) of the header in the buffer.
+ * @return The computed 16-bit checksum
+ */
+ public static int checksumICMPheader(ByteBuffer bb, int start, int end) {
+ return checksumIPstyle(bb, start, end, 2);
+ }
+
+ /**
+ * Computes the 16-bit checksum for some header used in IP networking, and overwrites any existing
+ * checksum with the correct one.
+ *
+ * Also see RFC 1071 .
+ *
+ * @param bb The buffer containing the ICMP header
+ * @param start The beginning position of the header in the buffer.
+ * @param end The end position (exclusive) of the header in the buffer.
+ * @param checksumOffset The offset from start for an existing 16-bit checksum that is to be
+ * ignored.
+ * @return The computed 16-bit checksum
+ */
+ private static int checksumIPstyle(ByteBuffer bb, int start, int end, int checksumOffset) {
+ final int checksumAt = start + checksumOffset;
+ int sum = 0;
+
+ if (checksumOffset >= end) {
+ throw new IllegalArgumentException("checksumOffset");
+ }
+
+ // While we could pretend the checksum is 0 (by ignoring the computation at position
+ // checksumAt), we zero it out here, and later put the correct checksum back in.
+ // This should not only be faster than two for-loops or checking the position prior to adding,
+ // it also puts the correct checksum in place, which can come in handy when composing packets.
+ // It is also the recommended strategy as per RFC 1071. The downside is that we modify the
+ // contents of the buffer, but that's OK since we control the API.
+ bb.putShort(checksumAt, (short) 0);
+
+ for (int i = start; i < end; i += 2) {
+ int v = bb.getShort(i) & 0xFFFF;
+
+ sum += v;
+
+ int overflow = (sum & ~0xFFFF);
+ if (overflow != 0) {
+ // overflow -> add carry and trim to 16-bit
+ sum = (sum + (overflow >>> 16)) & 0xFFFF;
+ }
+ }
+
+ int checksum = (~sum) & 0xFFFF;
+
+ // fix checksum
+ bb.putShort(checksumAt, (short) checksum);
+
+ return checksum;
+ }
+
+ /**
+ * Put (write) an IPv4 header to the given byte buffer, using the given parameters.
+ *
+ * This should write exactly 20 bytes to the buffer. The buffer position then is at the end of the
+ * header.
+ *
+ * @param bb The target byte buffer.
+ * @param payloadLength The length of the payload (excluding the IPv4 header).
+ * @param protocol The protocol identifier.
+ * @param srcIP The source IPv4 address.
+ * @param dstIP The destination IPv4 address.
+ */
+ public static void putIPv4Header(ByteBuffer bb, int payloadLength, byte protocol, int srcIP,
+ int dstIP) {
+ bb.put((byte) 0x45); // IPv4, 5*4=20 bytes header
+ bb.put((byte) 0); // TOS/DSCP
+ bb.putShort((short) (20 + payloadLength)); // total length = header + payload
+ bb.putShort((short) 0); // identification
+ bb.putShort((short) 0); // flags and fragment offset
+ bb.put((byte) 65); // TTL
+ bb.put(protocol); // protocol (e.g., ICMP)
+ bb.putShort((short) 0); // header checksum (placeholder)
+ bb.putInt(srcIP);
+ bb.putInt(dstIP);
+ // end of header (20 bytes)
+ }
+
+ /**
+ * Put (write) an ICMP echo response header to the given byte buffer, using the given parameters.
+ *
+ * @param bb The target byte buffer.
+ * @param echoIdentifier The identifier, from the ICMP echo request.
+ * @param sequenceNumber The sequence number, from the ICMP echo request.
+ * @param payload The payload, from the ICMP echo request.
+ */
+ public static void putICMPEchoResponse(ByteBuffer bb, short echoIdentifier, short sequenceNumber,
+ ByteBuffer payload) {
+ bb.put((byte) 0); // Echo response
+ bb.put((byte) 0); // Echo has no other code
+ bb.putShort((short) 0); // ICMP checksum (placeholder)
+ bb.putShort(echoIdentifier); // ICMP echo identifier
+ bb.putShort(sequenceNumber); // ICMP echo sequence number
+ bb.put(payload);
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/WellKnownKernelControlNames.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/WellKnownKernelControlNames.java
new file mode 100644
index 000000000..c1e7dce71
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/WellKnownKernelControlNames.java
@@ -0,0 +1,186 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+/**
+ * Well-known AF_SYSTEM control names.
+ *
+ * Most of these can only be accessed by the superuser (root). Unless otherwise specified, one
+ * usually accesses these as datagrams (SOCK_DGRAM).
+ *
+ * You can see which control names are registered via {@code netstat -an}; check for the IDs below
+ * "Registered kernel control modules".
+ *
+ * Also see New OSX Book Volume 1 Chapter 16
+ *
+ * @author Christian Kohlschütter
+ */
+public enum WellKnownKernelControlNames {
+
+ /**
+ * {@code com.apple.netsrc}. Network/route policies and statistics.
+ *
+ * Available to non-root.
+ *
+ * See https://github.com/apple-oss-distributions/xnu/blob/main/bsd/net/netsrc.h and
+ * https://github.com/apple-oss-distributions/xnu/blob/main/bsd/net/netsrc.c, as well as
+ * https://github.com/appleopen/Libinfo/blob/master/lookup.subproj/si_compare.c
+ */
+ NETSRC("com.apple.netsrc"), //
+
+ /**
+ * {@code com.apple.network.statistics}. Live socket statistics and notifications.
+ *
+ * Available to non-root.
+ *
+ * See {@code http://newosxbook.com/src.jl?tree=listings&file=lsock.c} as well as
+ * https://github.com/packetzero/libntstat
+ */
+ NETWORK_STATISTICS("com.apple.network.statistics"), //
+
+ /**
+ * {@code com.apple.flow-divert}. MPTCP flow diversions (XNU-2422).
+ *
+ * See https://github.com/apple-oss-distributions/xnu/blob/main/bsd/netinet/flow_divert.c and
+ * https://github.com/apple-oss-distributions/xnu/blob/main/bsd/netinet/flow_divert.h
+ */
+ FLOW_DIVERT("com.apple.flow-divert"), //
+
+ /**
+ * {@code com.apple.net.netagent}.
+ */
+ NET_NETAGENT("com.apple.net.netagent"), //
+
+ /**
+ * {@code com.apple.content-filter}.
+ */
+ CONTENT_FILTER("com.apple.content-filter"), //
+
+ /**
+ * {@code com.apple.net.utun_control}. User-mode tunneling (VPN).
+ */
+ UTUN_CONTROL("com.apple.net.utun_control"), //
+
+ /**
+ * {@code com.apple.net.ipsec_control}.
+ */
+ IPSEC_CONTROL("com.apple.net.ipsec_control"), //
+
+ /**
+ * {@code com.apple.network.tcp_ccdebug}. Requires SOCK_STREAM.
+ */
+ NETWORK_TCP_CCDEBUG("com.apple.network.tcp_ccdebug"), //
+
+ /**
+ * {@code com.apple.network.advisory}.
+ */
+ NETWORK_ADVISORY("com.apple.network.advisory"), //
+
+ /**
+ * {@code com.apple.net.rvi_control}.
+ */
+ NET_RVI_CONTROL("com.apple.net.rvi_control"), //
+
+ /**
+ * {@code com.apple.nke.sockwall}.
+ */
+ NKE_SOCKWALL("com.apple.nke.sockwall"), //
+
+ /**
+ * {@code com.apple.spmi.nfc}. Available to non-root. Requires SOCK_STREAM.
+ */
+ SPMI_NFC("com.apple.spmi.nfc"), //
+
+ /**
+ * {@code com.apple.packet-mangler}.
+ */
+ PACKET_MANGLER("com.apple.packet-mangler"), //
+
+ /**
+ * {@code com.apple.net.necp_control}.
+ */
+ NECP_CONTROL("com.apple.net.necp_control"), //
+
+ /**
+ * {@code com.apple.fileutil.kext.stateful.ctl}.
+ */
+ FILEUTIL_KEXT_STATEFUL_CTL("com.apple.fileutil.kext.stateful.ctl"), //
+
+ /**
+ * {@code com.apple.fileutil.kext.stateless.ctl}.
+ */
+ FILEUTIL_KEXT_STATELESS_CTL("com.apple.fileutil.kext.stateless.ctl"), //
+
+ /**
+ * {@code com.apple.mcx.kernctl.alr}.
+ */
+ MCX_KERNCTL_ALR("com.apple.mcx.kernctl.alr"), //
+
+ /**
+ * {@code com.apple.nke.webcontentfilter}.
+ */
+ NKE_WEBCONTENTFILTER("com.apple.nke.webcontentfilter"), //
+
+ /**
+ * {@code com.apple.uart.wlan-debug}.
+ */
+ UART_WLAN_DEBUG("com.apple.uart.wlan-debug"), //
+
+ /**
+ * {@code com.apple.uart.sk.wlan-debug}.
+ */
+ UART_SK_WLAN_DEBUG("com.apple.uart.sk.wlan-debug"), //
+
+ /**
+ * {@code com.apple.uart.debug-console}.
+ */
+ UART_DEBUG_CONSOLE("com.apple.uart.debug-console"), //
+
+ /**
+ * {@code com.apple.uart.sk.debug-console}.
+ */
+ UART_SK_DEBUG_CONSOLE("com.apple.uart.sk.debug-console"), //
+
+ /**
+ * {@code com.apple.userspace_ethernet}.
+ */
+ USERSPACE_ETHERNET("com.apple.userspace_ethernet"), //
+
+ ;
+
+ // non-Apple:
+ // - com.avira.fac
+ // - com.vmware.kext.vmci
+ // - com.vmware.kext.vmnet
+ // - com.vmware.kext.vmx86
+
+ private final String name;
+
+ WellKnownKernelControlNames(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the control name identifier.
+ *
+ * @return The name.
+ */
+ public String getControlName() {
+ return name;
+ }
+}
diff --git a/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/package-info.java b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/package-info.java
new file mode 100644
index 000000000..31e82a8ce
--- /dev/null
+++ b/junixsocket-darwin/src/main/java/org/newsclub/net/unix/darwin/system/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * The junixsocket implementation for Darwin AF_SYSTEM sockets.
+ */
+package org.newsclub.net.unix.darwin.system;
diff --git a/junixsocket-darwin/src/site/site.xml b/junixsocket-darwin/src/site/site.xml
new file mode 100644
index 000000000..873972284
--- /dev/null
+++ b/junixsocket-darwin/src/site/site.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ org.apache.maven.skins
+ maven-fluido-skin
+
+
+
+
+ kohlschutter/junixsocket
+ right
+
+
+
+
+
+ ${project.name}
+
+
+
+ ${project.scm.url}
+
+
+
+
+
+
+
diff --git a/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/SelftestProvider.java b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/SelftestProvider.java
new file mode 100644
index 000000000..06003e99a
--- /dev/null
+++ b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/SelftestProvider.java
@@ -0,0 +1,116 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin;
+
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.newsclub.net.unix.darwin.system.KernelControlNamesTest;
+import org.newsclub.net.unix.darwin.system.UtunTest;
+
+/**
+ * Provides references to all "junixsocket-afystem" tests that should be included in
+ * junixsocket-selftest.
+ *
+ * @author Christian Kohlschütter
+ */
+@SuppressWarnings("PMD.CouplingBetweenObjects")
+public class SelftestProvider {
+ private static final String MODULE = "junixsocket-darwin";
+ final Map>> testMap = new LinkedHashMap<>(); // NOPMD.LooseCoupling
+
+ // CPD-OFF
+
+ @SuppressWarnings({"PMD.ExcessiveMethodLength", "PMD.UnnecessaryFullyQualifiedName"})
+ public SelftestProvider() {
+ registerTest(MODULE, KernelControlNamesTest.class);
+ registerTest(MODULE, UtunTest.class);
+
+ // registerTest(AFSYSTEMExtensionsTest.class);
+ //
+ // registerTest(AcceptTimeoutTest.class);
+ //
+ // registerTest(AncillaryMessageTest.class);
+ //
+ // registerTest(AvailableTest.class);
+ //
+ // registerTest(BufferOverflowTest.class);
+ //
+ // registerTest(CancelAcceptTest.class);
+ //
+ // registerTest(DatagramSocketTest.class);
+ //
+ // registerTest(EndOfFileTest.class);
+ //
+ // disabled: FinalizeTest
+ //
+ // registerTest(ReadWriteTest.class);
+ //
+ // registerTest(SelectorTest.class);
+ //
+ // registerTest(ServerSocketCloseTest.class);
+ //
+ // registerTest(ServerSocketTest.class);
+ //
+ // registerTest(SocketChannelTest.class);
+ //
+ // registerTest(SocketOptionsTest.class);
+ //
+ // registerTest(SocketPairTest.class);
+ //
+ // registerTest(SocketTest.class);
+ //
+ // registerTest(SoTimeoutTest.class);
+ //
+ // registerTest(StandardSocketOptionsTest.class);
+ //
+ // registerTest(TcpNoDelayTest.class);
+ //
+ // registerTest(ThroughputTest.class);
+ }
+
+ public Set modulesDisabledByDefault() {
+ return Collections.emptySet();
+ }
+
+ // private void registerTest(Class extends SocketTestBase> test) {
+ // registerTest(MODULE, test);
+ // }
+
+ private void registerTest(String group, Class> test) {
+ if (test != null) {
+ testMap.computeIfAbsent(group, (key) -> new LinkedHashSet<>()).add(test);
+ }
+ }
+
+ public Map[]> tests() {
+ Map[]> tests = new LinkedHashMap<>();
+ testMap.forEach((key, set) -> {
+ tests.put(key, set.toArray(new Class>[0]));
+ });
+
+ return tests;
+ }
+
+ public void printAdditionalProperties(PrintWriter out) {
+ }
+}
diff --git a/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/IPUtilTest.java b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/IPUtilTest.java
new file mode 100644
index 000000000..1a0a00682
--- /dev/null
+++ b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/IPUtilTest.java
@@ -0,0 +1,45 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.nio.ByteBuffer;
+
+import org.junit.jupiter.api.Test;
+
+public class IPUtilTest {
+
+ @Test
+ public void testIPHeaderChecksum() {
+ // example from https://www.thegeekstuff.com/2012/05/ip-header-checksum/
+ ByteBuffer bb = ByteBuffer.wrap(new byte[] {
+ 0x45, 0x00, //
+ 0x00, 0x3c, //
+ 0x1c, 0x46, //
+ 0x40, 0x00, //
+ 0x40, 0x06, //
+ 0x00, 0x00, //
+ (byte) 0xac, 0x10, //
+ 0x0a, 0x63, //
+ (byte) 0xac, 0x10, //
+ 0x0a, 0x0c});
+
+ assertEquals(0xB1E6, IPUtil.checksumIPv4header(bb, 0, bb.remaining()));
+ }
+}
diff --git a/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/KernelControlNamesTest.java b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/KernelControlNamesTest.java
new file mode 100644
index 000000000..59f9ad959
--- /dev/null
+++ b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/KernelControlNamesTest.java
@@ -0,0 +1,58 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.net.SocketException;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.junit.jupiter.api.Test;
+
+public class KernelControlNamesTest {
+ @Test
+ // @AFSocketCapabilityRequirement(AFSocketCapability.CAPABILITY_DARWIN)
+ public void testStandardKernelControlNames() throws Exception {
+ try (AFSYSTEMDatagramSocket socket = AFSYSTEMDatagramSocket.newInstance()) {
+ assertThrows(IOException.class, () -> socket.getNodeIdentity("definitely.missing"));
+
+ int errors = 0;
+ Set ids = new LinkedHashSet<>();
+ for (WellKnownKernelControlNames n : WellKnownKernelControlNames.values()) {
+ int id;
+ try {
+ id = socket.getNodeIdentity(n.getControlName());
+ assertTrue(id > 0, "id should be a positive integer");
+ ids.add(id);
+ } catch (SocketException e) {
+ errors++;
+ continue;
+ }
+ }
+
+ System.out.println("Resolved control names " + ids.size() + "/" + WellKnownKernelControlNames
+ .values().length);
+
+ assertEquals(WellKnownKernelControlNames.values().length - errors, ids.size());
+ }
+ }
+}
diff --git a/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/UtunTest.java b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/UtunTest.java
new file mode 100644
index 000000000..3e8a15df1
--- /dev/null
+++ b/junixsocket-darwin/src/test/java/org/newsclub/net/unix/darwin/system/UtunTest.java
@@ -0,0 +1,271 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.darwin.system;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.time.Duration;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.Test;
+import org.newsclub.net.unix.AFSYSTEMSocketAddress;
+import org.newsclub.net.unix.AFSYSTEMSocketAddress.SysAddr;
+import org.newsclub.net.unix.AFSocketCapability;
+import org.newsclub.net.unix.AFSocketCapabilityRequirement;
+
+import com.kohlschutter.testutil.ExecutionEnvironmentRequirement;
+import com.kohlschutter.testutil.ExecutionEnvironmentRequirement.Rule;
+
+/**
+ * Demo code to exercise AF_SYSTEM with UTUN_CONTROL.
+ *
+ * Creates a PtP VPN tunnel, sends a ping via Java SDK code, parses the ICMP echo request (ping)
+ * packet, and responds with a hand-crafted ICMP echo reply (pong).
+ *
+ * @author Christian Kohlschütter
+ */
+@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
+public class UtunTest {
+ private static final Inet4Address UTUN_SRC_IP;
+ private static final Inet4Address UTUN_DST_IP;
+
+ static {
+ try {
+ UTUN_SRC_IP = (Inet4Address) InetAddress.getByName("169.254.3.4"); // "this host"
+ UTUN_DST_IP = (Inet4Address) InetAddress.getByName("169.254.3.5"); // "other end"
+ } catch (UnknownHostException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Dummy method to indicate the given parameter is not checked by our test code.
+ *
+ * @param v The parameter.
+ * @return The parameter.
+ */
+ private static Object unchecked(Object v) {
+ return v;
+ }
+
+ /**
+ * Returns the given IPv4 address as an integer.
+ *
+ * @param addr The IPv4 address object.
+ * @return The integer.
+ */
+ private static int getAddressAsInt(Inet4Address addr) {
+ // In the JDK implementation of Inet4Address, this happens to be the hash code.
+ return addr.hashCode();
+ }
+
+ @SuppressWarnings({
+ "checkstyle:VariableDeclarationUsageDistance", "PMD.JUnitTestContainsTooManyAsserts",
+ "PMD.AvoidBranchingStatementAsLastInLoop"})
+ @Test
+ @ExecutionEnvironmentRequirement(root = Rule.REQUIRED)
+ @AFSocketCapabilityRequirement(AFSocketCapability.CAPABILITY_DARWIN)
+ public void testTunnelPingPong() throws Exception {
+ try (AFSYSTEMDatagramSocket socket = AFSYSTEMDatagramSocket.newInstance()) {
+ int id = socket.getNodeIdentity(WellKnownKernelControlNames.UTUN_CONTROL);
+
+ // NOTE: Connecting requires root privileges, but we could do that in a separate process
+ // and send the socket FD via AF_UNIX to a non-privileged helper process.
+ try {
+ socket.connect(AFSYSTEMSocketAddress.ofSysAddrIdUnit(SysAddr.AF_SYS_CONTROL, id, 0));
+ } catch (SocketException e) {
+ assumeTrue(false, "Could not connect to UTUN_CONTROL: " + e);
+ return;
+ }
+
+ assertTimeoutPreemptively(Duration.ofSeconds(5), () -> {
+
+ AFSYSTEMSocketAddress rsa = socket.getRemoteSocketAddress();
+ Objects.requireNonNull(rsa);
+
+ assertEquals(SysAddr.AF_SYS_CONTROL, rsa.getSysAddr());
+ assertEquals(id, rsa.getId());
+ assertNotEquals(0, rsa.getUnit()); // utunN: N=(unit-1), e.g., unit=9 -> utun8
+
+ String utun = "utun" + (rsa.getUnit() - 1);
+ // System.out.println(utun);
+
+ Process p = Runtime.getRuntime().exec(new String[] {
+ "/sbin/ifconfig", utun, UTUN_SRC_IP.getHostAddress(), UTUN_DST_IP.getHostAddress()});
+ int rcIfconfig;
+ try {
+ rcIfconfig = p.waitFor();
+ } finally {
+ p.destroyForcibly();
+ }
+
+ assertEquals(0, rcIfconfig, "Could not set IP address for " + utun);
+
+ AFSYSTEMDatagramChannel channel = socket.getChannel();
+ ByteBuffer bb = ByteBuffer.allocateDirect(1500).order(ByteOrder.BIG_ENDIAN);
+
+ CompletableFuture ping = CompletableFuture.supplyAsync(() -> {
+ try {
+ return UTUN_DST_IP.isReachable(1000);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ });
+
+ while (channel.read(bb) >= 0) {
+ bb.flip();
+
+ // Request: Domain (AF_INET) + IPv4 header + ICMP header + ICMP payload
+
+ int totalSize = bb.remaining();
+ // assertEquals(76, totalSize); // 4 byte domain header + 72 bytes packet length
+
+ int domain = bb.getInt();
+ assertEquals(IPUtil.DOMAIN_AF_INET, domain, "Expect domain 2 (AF_INET)");
+
+ int ipHeaderStartPos = bb.position();
+
+ int versionAndIHL = bb.get() & 0xFF;
+ int version = versionAndIHL >> 4;
+ assertEquals(4, version, "expect IPv4 packet");
+
+ // see https://en.wikipedia.org/wiki/Internet_Protocol_version_4#Header
+
+ int ihl = versionAndIHL & 0b1111;
+ int ihlBytes = ihl * 32 /* bit */ / 8;
+ assertTrue(ihlBytes >= 20, "expect (at least) 20 bytes header length");
+
+ int tosDSCP = (bb.get() & 0xFF);
+ unchecked(tosDSCP);
+
+ int totalLen = (bb.getShort() & 0xFFFF);
+ assertEquals(totalSize - 4, totalLen);
+
+ int identification = (bb.getShort() & 0xFFFF);
+ unchecked(identification);
+
+ int flagsAndFragmentOffset = (bb.getShort() & 0xFFFF);
+ int flags = flagsAndFragmentOffset >> 13;
+ int fragmentOffset = flagsAndFragmentOffset & 0b1_1111_1111_1111;
+ assertEquals(0, flags);
+ assertEquals(0, fragmentOffset);
+
+ int ttl = bb.get() & 0xFF;
+ assertNotEquals(0, ttl); // e.g., 65
+
+ int protocol = bb.get() & 0xFF;
+ assertEquals(IPUtil.AF_INET_PROTOCOL_ICMP, protocol); // 1 == ICMP
+
+ int headerChecksum = bb.getShort() & 0xFFFF;
+ // see below for verification
+
+ int srcIP = bb.getInt();
+ int dstIP = bb.getInt();
+
+ assertEquals(getAddressAsInt(UTUN_SRC_IP), srcIP); // 10.250.3.4
+ assertEquals(getAddressAsInt(UTUN_DST_IP), dstIP); // 10.250.3.5
+
+ // when ihl=5 -> ihlBytes=ihl*4=20, there are no more options
+ // but let's check nevertheless...
+
+ int remainingHeaderLength = ihlBytes - 20;
+ if (remainingHeaderLength > 0) {
+ System.err.println("Warning: Found unexpected Options section in IPv4 header; len="
+ + remainingHeaderLength);
+ bb.position(bb.position() + remainingHeaderLength);
+ }
+
+ // we're at the end of the IPv4 header
+
+ int computedHeaderChecksum = IPUtil.checksumIPv4header(bb, ipHeaderStartPos, bb
+ .position());
+ assertEquals(computedHeaderChecksum, headerChecksum);
+
+ int icmpSize = bb.remaining();
+ // assertEquals(52, icmpSize); // ICMP header + optional data
+
+ int icmpBeginPosition = bb.position();
+
+ // begin ICMP header
+ int icmpType = bb.get() & 0xFF;
+ assertEquals(8, icmpType); // 8 = Echo Request
+
+ int icmpCode = bb.get() & 0xFF;
+ assertEquals(0, icmpCode); // Echo Request has no other Code
+
+ int icmpChecksum = bb.getShort() & 0xFFFF; // checked below
+
+ int icmpEchoIdentifier = bb.getShort() & 0xFFFF;
+ int icmpEchoSequenceNumber = bb.getShort() & 0xFFFF;
+
+ unchecked(icmpEchoIdentifier);
+ assertEquals(1, icmpEchoSequenceNumber); // first echo packet
+
+ int icmpChecksumComputed = //
+ IPUtil.checksumICMPheader(bb, icmpBeginPosition, bb.position() + bb.remaining());
+ assertEquals(icmpChecksumComputed, icmpChecksum);
+
+ // Now it's time to craft an echo response
+ // Response: "AF_INET" + IPv4 header + ICMP header + ICMP payload from echo request
+
+ ByteBuffer response = ByteBuffer.allocate(IPUtil.DOMAIN_HEADER_LENGTH
+ + IPUtil.IPV4_DEFAULT_HEADER_SIZE + icmpSize).order(ByteOrder.BIG_ENDIAN);
+ response.putInt(IPUtil.DOMAIN_AF_INET);
+ IPUtil.putIPv4Header(response, icmpSize, IPUtil.AF_INET_PROTOCOL_ICMP, dstIP, srcIP);
+
+ int responsePayloadStart = response.position();
+ IPUtil.checksumIPv4header(response, IPUtil.DOMAIN_HEADER_LENGTH, responsePayloadStart);
+
+ IPUtil.putICMPEchoResponse(response, (short) icmpEchoIdentifier,
+ (short) icmpEchoSequenceNumber, bb);
+ assertEquals(0, bb.remaining()); // writeEchoResponse consumed the payload
+ int responsePayloadEnd = response.position();
+
+ IPUtil.checksumICMPheader(response, responsePayloadStart, responsePayloadEnd);
+
+ response.flip();
+ int written = channel.write(response);
+ bb.clear();
+
+ assertEquals(response.capacity(), written);
+
+ assertTrue(ping.get(1, TimeUnit.SECONDS));
+
+ return;
+ }
+
+ fail("Nothing received");
+ });
+ }
+ }
+}
diff --git a/junixsocket-demo/.gitignore b/junixsocket-demo/.gitignore
index bf65d59b3..f4177d054 100644
--- a/junixsocket-demo/.gitignore
+++ b/junixsocket-demo/.gitignore
@@ -1 +1,3 @@
/target-eclipse/
+/juxclient.*
+/juxserver.*
diff --git a/junixsocket-demo/pom.xml b/junixsocket-demo/pom.xml
index 5f2b50659..c4dec5463 100644
--- a/junixsocket-demo/pom.xml
+++ b/junixsocket-demo/pom.xml
@@ -1,12 +1,14 @@
-
+
4.0.0
junixsocket-demo
jar
com.kohlschutter.junixsocket
junixsocket
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-demo
@@ -14,11 +16,10 @@
${project.parent.basedir}
8
-
Some example code to demo junixsocket's features
-
-
com.kohlschutter.junixsocket
@@ -47,31 +48,23 @@
${project.version}
- mysql
- mysql-connector-java
- 8.0.30
-
-
- com.google.protobuf
- protobuf-java
-
-
-
+ com.kohlschutter.junixsocket
+ junixsocket-ssl
+ ${project.version}
-
- com.google.protobuf
- protobuf-java
- 3.19.6
+ com.mysql
+ mysql-connector-j
+ 8.1.0
-
org.postgresql
postgresql
- 42.5.0
+ 42.6.0
provided
@@ -90,10 +83,24 @@
com.squareup.okhttp3
okhttp
- 4.10.0
+ 4.11.0
+
+
+ com.squareup.okio
+ okio
+ 3.5.0
+
+
+ org.apache.mina
+ mina-core
+ 2.2.3
+
+
+ io.netty
+ netty-all
+ 4.1.98.Final
-
diff --git a/junixsocket-demo/src/main/java/module-info.java b/junixsocket-demo/src/main/java/module-info.java
index 0082407bf..9fd50b997 100644
--- a/junixsocket-demo/src/main/java/module-info.java
+++ b/junixsocket-demo/src/main/java/module-info.java
@@ -3,18 +3,23 @@
*/
@SuppressWarnings("module") //
module org.newsclub.net.unix.demo {
+ requires com.kohlschutter.util;
requires org.newsclub.net.unix;
requires org.newsclub.net.unix.tipc;
requires org.newsclub.net.unix.server;
+ requires org.newsclub.net.unix.ssl;
requires org.newsclub.net.mysql;
requires transitive org.newsclub.net.unix.rmi;
requires java.rmi;
requires java.sql;
requires nanohttpd;
requires okhttp3;
- requires com.kohlschutter.util;
+ requires mina.core;
requires static com.kohlschutter.annotations.compiletime;
requires static org.eclipse.jdt.annotation;
+ requires io.netty.common;
+ requires io.netty.buffer;
+ requires io.netty.transport;
exports org.newsclub.net.unix.demo.rmi.services to java.rmi;
exports org.newsclub.net.unix.demo.rmi.fd to java.rmi;
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/mysql/demo/AFUNIXDatabaseSocketFactoryDemo.java b/junixsocket-demo/src/main/java/org/newsclub/net/mysql/demo/AFUNIXDatabaseSocketFactoryDemo.java
index a91d97440..88cb064a7 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/mysql/demo/AFUNIXDatabaseSocketFactoryDemo.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/mysql/demo/AFUNIXDatabaseSocketFactoryDemo.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
/**
* Demonstrates how to connect to a local MySQL server.
- *
+ *
* @author Christian Kohlschuetter
*/
public class AFUNIXDatabaseSocketFactoryDemo {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/DemoHelper.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/DemoHelper.java
index 50ca192f9..abc9502f9 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/DemoHelper.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/DemoHelper.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
* Just a helper class to simplify controlling the demo from the command line.
*/
public final class DemoHelper {
- @ExcludeFromCodeCoverageGeneratedReport
+ @ExcludeFromCodeCoverageGeneratedReport(reason = "unreachable")
private DemoHelper() {
throw new IllegalStateException("No instances");
}
@@ -45,7 +45,7 @@ private DemoHelper() {
/**
* Adds a key-value pair to a Properties instance. Takes values from a given system property and
* overrides the default value with it.
- *
+ *
* @param props The Properties instance to write to.
* @param key The name of the property.
* @param defaultValue The default value (for demo purposes)
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestClient.java
index 694577593..b40c58c29 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,12 +30,12 @@
/**
* A simple demo client.
- *
+ *
* Reads a server greeting string, then sends a "Hello Server" string as a response.
- *
+ *
* Finally, reads integers (via {@link DataInputStream}), then sends twice the sent value each,
* unless a "-123" magic number is read to indicate the end of the conversation.
- *
+ *
* @author Christian Kohlschütter
* @see SimpleTestServer
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestServer.java
index 9d80664ce..4f9596afe 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/SimpleTestServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,16 +31,17 @@
/**
* A simple demo server.
- *
+ *
* Sends a hello message (as a string), then reads back a response string.
- *
+ *
* Finally, sends integers (via {@link DataOutputStream}) from 1 to 5, expects an integer response
* of twice the sent value each, then sends a "-123" magic number to indicate the end of the
* conversation.
- *
+ *
* @author Christian Kohlschütter
* @see SimpleTestClient
*/
+@SuppressWarnings({"CatchAndPrintStackTrace" /* errorprone */, "PMD.CognitiveComplexity"})
public final class SimpleTestServer {
private static final int MAX_NUMBER = 5;
@@ -56,18 +57,18 @@ public static void main(String[] args) throws IOException {
try (AFUNIXServerSocket server = AFUNIXServerSocket.newInstance()) {
/*
* Uncomment the code below to change the bind behavior:
- *
+ *
* By default ("reuseAddress" is true), attempting to bind while another server is running on
* the same address will cause the first server to terminate, and the new server will take
* over the address. Depending on the operating system, this may involve connecting to the
* first server in order to "wake up" the accept call.
- *
+ *
* In this demo code, we use AFSocket.getConnectionStatus to see if the accepted connection is
* alive by sending
- *
+ *
* When "reuseAddress" is false, attempting to bind while another server is running won't
* disrupt the first connection. The second bind will throw a SocketException instead.
- *
+ *
* NOTE: "reuseAddress=true" may not yet be supported on certain operating systems, such as
* IBM i and z/OS. On these platforms, the behavior is as if "reuseAddress=false". Please
* reach out by filing an issue on https://github.com/kohlschutter/junixsocket/issues if this
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClient.java
index 7faf9b515..7b4b6b2b6 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
/**
* A demo program to configure and run several {@link AFSocket} client demos from the command line.
- *
+ *
* @author Christian Kohlschütter
*/
public final class DemoClient {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClientBase.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClientBase.java
index 886406806..07c86f2f4 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClientBase.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/DemoClientBase.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
/**
* An {@link AFUNIXSocket} client that's just good for demo purposes.
- *
+ *
* @author Christian Kohlschütter
*/
abstract class DemoClientBase {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadClient.java
index b5886ba52..6b9e6db37 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadFileHandleClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadFileHandleClient.java
index a4a113adb..951e93bbb 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadFileHandleClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadFileHandleClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadWriteClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadWriteClient.java
index cb71c581f..eb829c382 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadWriteClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/client/ReadWriteClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
/**
* A simple bidirectional Unix socket client that reads from/writes to stdin/stdout.
*/
+@SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
public final class ReadWriteClient extends DemoClientBase {
@Override
protected void handleSocket(Socket socket) throws IOException {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/jdbc/PostgresDemo.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/jdbc/PostgresDemo.java
index da854ab74..4f7fe3536 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/jdbc/PostgresDemo.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/jdbc/PostgresDemo.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
/**
* Demonstrates how to connect to a local PostgreSQL server via unix sockets.
- *
+ *
* @author Christian Kohlschuetter
* @see AFUNIXSocketFactory
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/mina/MinaTimeServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/mina/MinaTimeServer.java
new file mode 100644
index 000000000..abdc69ca8
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/mina/MinaTimeServer.java
@@ -0,0 +1,60 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.mina;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.mina.core.service.IoAcceptor;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
+import org.apache.mina.filter.logging.LoggingFilter;
+import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
+import org.newsclub.net.unix.AFUNIXSelectorProvider;
+import org.newsclub.net.unix.AFUNIXSocketAddress;
+
+/**
+ * Apache Mina-based Time server, modified to use junixsocket.
+ *
+ * Based on example code from
+ *
+ * Apache Mina user guide, chapter 2.2 — Sample TCP Server
+ */
+public class MinaTimeServer {
+ public static void main(String[] args) throws IOException {
+ int processorCount = Runtime.getRuntime().availableProcessors() + 1;
+
+ // IoAcceptor acceptor = new NioSocketAcceptor(processorCount); // from original example code
+ IoAcceptor acceptor = new NioSocketAcceptor(processorCount, AFUNIXSelectorProvider.provider());
+ // IoAcceptor acceptor = new NioSocketAcceptor(processorCount,
+ // AFTIPCSelectorProvider.provider());
+
+ acceptor.getFilterChain().addLast("logger", new LoggingFilter());
+ acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(
+ StandardCharsets.UTF_8)));
+ acceptor.setHandler(new TimeServerHandler());
+ acceptor.getSessionConfig().setReadBufferSize(2048);
+ acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
+
+ // acceptor.bind( new InetSocketAddress(PORT) ); // from original example code
+ acceptor.bind(AFUNIXSocketAddress.of(new File("/tmp/minatime")));
+ // acceptor.bind(AFTIPCSocketAddress.ofService(Scope.SCOPE_CLUSTER, 128, 1));
+ }
+}
\ No newline at end of file
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/mina/TimeServerHandler.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/mina/TimeServerHandler.java
new file mode 100644
index 000000000..036bdb76b
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/mina/TimeServerHandler.java
@@ -0,0 +1,56 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.mina;
+
+import java.util.Date;
+
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+/**
+ * Time server handler.
+ *
+ * Based on example code from
+ *
+ * Apache Mina user guide, chapter 2.2 — Sample TCP Server
+ */
+@SuppressWarnings("JavaUtilDate" /* errorprone */)
+class TimeServerHandler extends IoHandlerAdapter {
+ @Override
+ public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
+ cause.printStackTrace();
+ }
+
+ @Override
+ public void messageReceived(IoSession session, Object message) throws Exception {
+ String str = message.toString();
+ if ("quit".equalsIgnoreCase(str.trim())) {
+ session.closeNow();
+ return;
+ }
+ Date date = new Date();
+ session.write(date.toString());
+ System.out.println("Message written...");
+ }
+
+ @Override
+ public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
+ System.out.println("IDLE " + session.getIdleCount(status));
+ }
+}
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/nanohttpd/NanoHttpdServerDemo.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/nanohttpd/NanoHttpdServerDemo.java
index 133953cdb..fd4bf162b 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/nanohttpd/NanoHttpdServerDemo.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/nanohttpd/NanoHttpdServerDemo.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,9 +32,9 @@
/**
* Creates a {@link NanoHTTPD} server, bound to {@code /tmp/junixsocket-http-server.sock}.
- *
+ *
* Http requests on that socket should return "Hello world from <hostname>".
- *
+ *
* @author Christian Kohlschütter
* @see OkHttpClientDemo
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/netty/EchoServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/netty/EchoServer.java
new file mode 100644
index 000000000..3e7a6d377
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/netty/EchoServer.java
@@ -0,0 +1,93 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.netty;
+
+import java.io.File;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.Executor;
+
+import org.newsclub.net.unix.AFSocketAddress;
+import org.newsclub.net.unix.AFUNIXSelectorProvider;
+import org.newsclub.net.unix.AFUNIXSocketAddress;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+
+/**
+ * Echos any incoming data.
+ *
+ * Based on example code from Netty user
+ * guide for 4.x
+ */
+@SuppressWarnings("FutureReturnValueIgnored" /* errorprone */)
+public class EchoServer {
+ private final AFSocketAddress addr;
+
+ public EchoServer(AFSocketAddress addr) {
+ this.addr = addr;
+ }
+
+ public void run() throws Exception {
+ SelectorProvider provider = AFUNIXSelectorProvider.provider();
+ // SelectorProvider provider = AFTIPCSelectorProvider.provider();
+
+ // We need to specify our custom selector provider here (1), as well as in (3)
+ EventLoopGroup bossGroup = new NioEventLoopGroup(0, (Executor) null, provider); // (1)
+ EventLoopGroup workerGroup = new NioEventLoopGroup(0, (Executor) null, provider); // (1)
+ try {
+ ServerBootstrap b = new ServerBootstrap(); // (2)
+ b.group(bossGroup, workerGroup) //
+ .channelFactory(() -> new NioServerSocketChannel(provider)) // (3)
+ .childHandler(new ChannelInitializer() { // (4)
+ @Override
+ public void initChannel(SocketChannel ch) throws Exception {
+ ch.pipeline().addLast(new EchoServerHandler());
+ }
+ }) //
+ .option(ChannelOption.SO_BACKLOG, 128) // (5)
+ .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
+
+ // Bind and start to accept incoming connections.
+ ChannelFuture f = b.bind(addr).sync(); // (7)
+
+ // Wait until the server socket is closed.
+ // In this example, this does not happen, but you can do that to gracefully
+ // shut down your server.
+ f.channel().closeFuture().sync();
+ } finally {
+ workerGroup.shutdownGracefully();
+ bossGroup.shutdownGracefully();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ File path = new File("/tmp/nettyecho");
+ if (args.length > 0) {
+ path = new File(args[0]);
+ }
+
+ new EchoServer(AFUNIXSocketAddress.of(path)).run();
+ // new EchoServer(AFTIPCSocketAddress.ofService(Scope.SCOPE_CLUSTER, 128, 3)).run();
+ }
+}
\ No newline at end of file
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/netty/EchoServerHandler.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/netty/EchoServerHandler.java
new file mode 100644
index 000000000..635c074bd
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/netty/EchoServerHandler.java
@@ -0,0 +1,44 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.netty;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+/**
+ * Handles a server-side channel.
+ *
+ * Based on example code from Netty user
+ * guide for 4.x
+ */
+@SuppressWarnings("FutureReturnValueIgnored" /* errorprone */ )
+class EchoServerHandler extends ChannelInboundHandlerAdapter { // (1)
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) {
+ ctx.write(msg); // (1)
+ ctx.flush(); // (2)
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
+ // Close the connection when an exception is raised.
+ cause.printStackTrace();
+ ctx.close();
+ }
+}
\ No newline at end of file
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientDemo.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientDemo.java
index 4d4086b1d..102c17284 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientDemo.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientDemo.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,9 +38,9 @@
/**
* Connects to {@code /tmp/junixsocket-http-server.sock} and performs an http request over that
* socket, using the OkHttp HTTP client library.
- *
+ *
* If that socket is bound by {@link NanoHttpdServerDemo}, the expected output is "Hello world".
- *
+ *
* @author Christian Kohlschütter
* @see NanoHttpdServerDemo
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientTIPCDemo.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientTIPCDemo.java
index 1e1f9d8d6..5fca3b868 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientTIPCDemo.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/okhttp/OkHttpClientTIPCDemo.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,13 +39,14 @@
/**
* Connects to TIPC service 8080.1 and performs an HTTP request over that socket, using the
* OkHttp HTTP client library.
- *
+ *
* If that socket is bound by {@link NanoHttpdServerDemo}, the expected output is "Hello world from
* <hostname>" (start {@link NanoHttpdServerDemo} with {@code --url tipc://8080.1}.
- *
+ *
* @author Christian Kohlschütter
* @see NanoHttpdServerDemo
*/
+@SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
public class OkHttpClientTIPCDemo {
public static void main(String[] args) throws IOException, InterruptedException {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/HelloWorldImpl.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/HelloWorldImpl.java
index 6e3d12d3c..03b7a78b3 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/HelloWorldImpl.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/HelloWorldImpl.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
/**
* The implementation of the very simple {@link HelloWorld} service.
- *
+ *
* @author Christian Kohlschütter
*/
public class HelloWorldImpl implements HelloWorld {
@@ -37,7 +37,7 @@ public class HelloWorldImpl implements HelloWorld {
/**
* Creates a new {@link HelloWorld} implementation.
- *
+ *
* @param naming The naming instance to use.
*/
@SuppressFBWarnings("EI_EXPOSE_REP")
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClient.java
index aef5a3a6a..abc790c85 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
/**
* A simple RMI client. Locates the RMI registry via AF_UNIX sockets and calls
* {@link HelloWorld#hello()}.
- *
+ *
* @author Christian Kohlschütter
*/
public final class SimpleRMIClient {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClientActingAsServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClientActingAsServer.java
index 082856410..6e1542081 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClientActingAsServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIClientActingAsServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,9 +30,10 @@
/**
* A simple RMI client. Locates the RMI registry via AF_UNIX sockets and calls
* {@link HelloWorld#hello()}.
- *
+ *
* @author Christian Kohlschütter
*/
+@SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
public final class SimpleRMIClientActingAsServer {
public static void main(String[] args) throws IOException, NotBoundException {
AFUNIXNaming naming = AFUNIXNaming.getInstance();
@@ -57,16 +58,16 @@ public static void main(String[] args) throws IOException, NotBoundException {
System.out.println("Calling HelloWorld...");
System.out.println(obj.hello() + " " + obj.world() + "!");
- /**
+ /*
* Uncommenting the line below keeps this instance running.
- *
+ *
* Try it and run SimpleRMIClient to see the difference.
*/
naming.unexportAndUnbind("world", world);
- /**
+ /*
* Also try to remotely shut down the registry.
- *
+ *
* This will not succeed if the server set {@code naming.setRemoteShutdownAllowed(false)}. See
* {@link SimpleRMIServer}
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIServer.java
index c7e73c41f..fea30e84b 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/SimpleRMIServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
/**
* A very simple RMI server. Provides a registry and the implementation of the {@link HelloWorld}
* service.
- *
+ *
* @author Christian Kohlschütter
*/
public final class SimpleRMIServer {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/WorldImpl.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/WorldImpl.java
index 1c100b131..170356e83 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/WorldImpl.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/WorldImpl.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
/**
* The implementation of the very simple {@link World} service.
- *
+ *
* @author Christian Kohlschütter
*/
public class WorldImpl implements World {
@@ -31,7 +31,7 @@ public class WorldImpl implements World {
/**
* Creates a new {@link World} instance.
- *
+ *
* @param text The text to return upon calling {@link #world()}.
*/
public WorldImpl(String text) {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamClient.java
index 991def136..33c216c18 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamClient.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamClient.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
/**
* Demonstrates how to read files via FileDescriptors that are exchanged via RMI.
- *
+ *
* @author Christian Kohlschütter
* @see StreamServer
*/
@@ -42,7 +42,7 @@ private StreamClient() {
/**
* {@link StreamClient} command-line tool.
- *
+ *
* @param args Command-line arguments.
* @throws IOException on error.
* @throws NotBoundException if the server cannot be reached.
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServer.java
index b432a7ca9..1e94fe74f 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,14 +24,14 @@
/**
* Demonstrates how to read/write files via FileDescriptors that are exchanged via RMI.
- *
+ *
* This allows reading/writing from and to files that are otherwise not even accessible by the user.
* For example, starting the {@link StreamServer} as root and the {@link StreamClient} as a
* non-privileged user will allow the non-privileged user to read files only accessible to root.
- *
+ *
* NOTE: For obvious security reasons, running this server without modification is not advised for
* anything other than demo purposes.
- *
+ *
* @author Christian Kohlschütter
* @see StreamClient
*/
@@ -42,7 +42,7 @@ private StreamServer() {
/**
* {@link StreamServer} command-line tool.
- *
+ *
* @param args Command-line arguments.
* @throws IOException on error.
* @throws AlreadyBoundException if there was already a server running.
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServiceImpl.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServiceImpl.java
index 6ac3eeb55..a00fb9cc2 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServiceImpl.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/fd/StreamServiceImpl.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
/**
* An implementation of {@link StreamService}.
- *
+ *
* @author Christian Kohlschütter
*/
public class StreamServiceImpl implements StreamService, Closeable {
@@ -43,7 +43,7 @@ public class StreamServiceImpl implements StreamService, Closeable {
/**
* Creates a new instance.
- *
+ *
* @param socketFactory The socket factory to use.
* @throws RemoteException on error.
*/
@@ -82,7 +82,7 @@ public RemoteCloseableImpl openForWriting(File path) throws IO
/**
* Checks if the given path may be accessed for reading.
- *
+ *
* @param path The path to check.
* @return {@code true} if permitted.
*/
@@ -92,7 +92,7 @@ protected boolean mayRead(File path) {
/**
* Checks if the given path may be accessed for writing.
- *
+ *
* @param path The path to check.
* @return {@code true} if permitted.
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/HelloWorld.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/HelloWorld.java
index bd004d294..1848f77e4 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/HelloWorld.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/HelloWorld.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,13 +22,13 @@
/**
* A very simple "hello world" service.
- *
+ *
* @author Christian Kohlschütter
*/
public interface HelloWorld extends Remote {
/**
* Returns "Hello".
- *
+ *
* @return "Hello"
* @throws IOException if the operation fails.
*/
@@ -36,7 +36,7 @@ public interface HelloWorld extends Remote {
/**
* Returns "World" (or something else?).
- *
+ *
* @return "World" (usually)
* @throws IOException if the operation fails.
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/StreamService.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/StreamService.java
index 5c56cf14b..90c01ae67 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/StreamService.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/StreamService.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,14 +28,14 @@
/**
* The {@link StreamServer}'s RMI service.
- *
+ *
* @author Christian Kohlschütter
* @see StreamServer
*/
public interface StreamService extends Remote {
/**
* Opens the given file for reading.
- *
+ *
* @param path The file to open.
* @return A remote instance for the file.
* @throws IOException on error.
@@ -44,7 +44,7 @@ public interface StreamService extends Remote {
/**
* Opens the given file for writing.
- *
+ *
* @param path The file to open.
* @return A remote instance for the file.
* @throws IOException on error.
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/World.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/World.java
index d8f341a0c..2cec6cd21 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/World.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/rmi/services/World.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,14 +22,14 @@
/**
* A very simple "world" service.
- *
+ *
* @author Christian Kohlschütter
* @see HelloWorld
*/
public interface World extends Remote {
/**
* Returns "World" (or something else?).
- *
+ *
* @return "World" (usually)
* @throws RemoteException if the operation fails.
*/
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ChargenServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ChargenServer.java
index 40338db84..ec8423b84 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ChargenServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ChargenServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
/**
* A multi-threaded unix socket server that implements a TCP-style character generator compliant
* with RFC864.
- *
+ *
* @author Christian Kohlschütter
*/
public final class ChargenServer extends DemoServerBase {
@@ -38,7 +38,7 @@ public final class ChargenServer extends DemoServerBase {
/**
* Defines a TCP-style character generator compliant with RFC864.
- *
+ *
* @see RFC864
*/
private interface Chargen {
@@ -83,9 +83,9 @@ private synchronized Chargen getChargen(Socket socket) throws SocketException {
/**
* A simple chargen implementation.
- *
+ *
* Even though this looks straightforward, it's not the fastest implementation.
- *
+ *
* @see FastChargen
*/
private static final class SimpleChargen implements Chargen {
@@ -113,7 +113,7 @@ public void write(Socket socket) throws IOException {
/**
* A fast chargen implementation, using a pre-built data buffer that is just large enough to
* always send a full array of bytes matching the socket's send buffer capacity.
- *
+ *
* @see SimpleChargen
*/
private static final class FastChargen implements Chargen {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/DemoServerBase.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/DemoServerBase.java
index c52f3d14c..92f96d556 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/DemoServerBase.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/DemoServerBase.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,9 +30,10 @@
/**
* An {@link SocketServer} that's just good for demo purposes.
- *
+ *
* @author Christian Kohlschütter
*/
+@SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
abstract class DemoServerBase extends SocketServer {
public DemoServerBase(SocketAddress listenAddress) {
super(listenAddress);
@@ -117,16 +118,16 @@ protected void onSocketExceptionAfterAccept(Socket socket, SocketException e) {
}
@Override
- protected void onServingException(Socket socket, Exception e) {
+ protected void onServingException(Socket socket, Throwable t) {
if (socket.isClosed()) {
// "Broken pipe", etc.
- System.out.println("The other end disconnected (" + e.getMessage() + "): " + socket);
+ System.out.println("The other end disconnected (" + t.getMessage() + "): " + socket);
return;
}
System.err.println("Exception thrown in " + socket + ", connected: " + socket.isConnected()
+ ", " + socket.isBound() + "," + socket.isClosed() + "," + socket.isInputShutdown() + ","
+ socket.isOutputShutdown());
- e.printStackTrace();
+ t.printStackTrace();
}
@Override
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/EchoServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/EchoServer.java
index aac916a28..28bd499fc 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/EchoServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/EchoServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
/**
* A multi-threaded unix socket server that simply echoes all input, byte per byte.
- *
+ *
* @author Christian Kohlschütter
*/
public final class EchoServer extends DemoServerBase {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/NullServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/NullServer.java
index ac600b8a8..0ce8a9ef3 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/NullServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/NullServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
/**
* A multi-threaded unix socket server that simply reads all input, byte per byte, not doing
* anything else with it.
- *
+ *
* @author Christian Kohlschütter
*/
public final class NullServer extends DemoServerBase {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SendFileHandleServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SendFileHandleServer.java
index 281b52578..afca4da81 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SendFileHandleServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SendFileHandleServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,9 +30,10 @@
/**
* A multi-threaded unix socket server that simply reads all input, byte per byte, not doing
* anything else with it.
- *
+ *
* @author Christian Kohlschütter
*/
+@SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
public final class SendFileHandleServer extends DemoServerBase {
private final File file;
@@ -49,7 +50,7 @@ protected void doServeSocket(Socket socket) throws IOException {
doServeSocket((AFUNIXSocket) socket);
}
- protected void doServeSocket(AFUNIXSocket socket) throws IOException {
+ private void doServeSocket(AFUNIXSocket socket) throws IOException {
try (InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
FileInputStream fin = new FileInputStream(file)) {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SocketServerDemo.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SocketServerDemo.java
index a23c742e6..fddf11534 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SocketServerDemo.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/SocketServerDemo.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
/**
* A demo program to configure and run several {@link SocketServer} demos from the command line.
- *
+ *
* @author Christian Kohlschütter
*/
public final class SocketServerDemo {
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ZeroServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ZeroServer.java
index 752f4c55f..32c38a861 100644
--- a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ZeroServer.java
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/server/ZeroServer.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
/**
* A multi-threaded unix socket server that simply writes null-bytes, and does not attempt to read
* anything.
- *
+ *
* @author Christian Kohlschütter
*/
// CPD-OFF
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoClient.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoClient.java
new file mode 100644
index 000000000..ac36748f6
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoClient.java
@@ -0,0 +1,92 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.ssl;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.security.auth.DestroyFailedException;
+
+import org.newsclub.net.unix.AFUNIXSocket;
+import org.newsclub.net.unix.AFUNIXSocketAddress;
+import org.newsclub.net.unix.ssl.SSLContextBuilder;
+
+/**
+ * A simple SSL demo client.
+ *
+ * @author Christian Kohlschütter
+ * @see SSLDemoServer
+ * @see SSLDemoPrerequisites
+ */
+public class SSLDemoClient {
+ public static void main(String[] args) throws InterruptedException, IOException,
+ GeneralSecurityException, DestroyFailedException {
+
+ // Enable to see SSL debugging
+ // System.setProperty("javax.net.debug", "all");
+
+ AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(new File("/tmp/ssldemo"));
+
+ SSLSocketFactory clientSocketFactory = SSLContextBuilder.forClient() //
+ .withKeyStore(new File("juxclient.p12"), () -> "clientpass".toCharArray()) //
+ .withTrustStore(new File("juxclient.truststore"), () -> "clienttrustpass".toCharArray())
+ .withDefaultSSLParameters((p) -> {
+ // A simple way to disable some undesired protocols:
+ // SSLParametersUtil.disableProtocols(p, "TLSv1.0", "TLSv1.1", "TLSv1.2");
+
+ // Uncomment to perform endpoint checking of server certificates
+ // p.setEndpointIdentificationAlgorithm("HTTPS");
+
+ }) //
+ .buildAndDestroyBuilder().getSocketFactory();
+
+ System.out.println("Connecting to " + addr);
+
+ try (AFUNIXSocket plainSocket = AFUNIXSocket.connectTo(addr);
+ SSLSocket sslSocket = (SSLSocket) clientSocketFactory.createSocket(plainSocket,
+ // This hostname is sent to the server, unless we define an SNI hostname below
+ "localhost.junixsocket", //
+ plainSocket.getPort(), false)) {
+
+ // Setting the client mode manually is not necessary when using SSLContextBuilder
+ // sslSocket.setUseClientMode(false);
+
+ // Uncomment to send SNI hostname to server
+ // SSLParametersUtil.setSNIServerName(sslSocket, new SNIHostName("subdomain.example.com"));
+
+ try (InputStream in = sslSocket.getInputStream();
+ OutputStream out = sslSocket.getOutputStream()) {
+ plainSocket.setOutboundFileDescriptors(FileDescriptor.err);
+ System.out.println("Writing byte...");
+ out.write(0xAF);
+ out.flush();
+
+ byte[] by = new byte[11];
+ int r = in.read(by);
+ System.out.println("Received string: " + new String(by, 0, r, StandardCharsets.UTF_8));
+ }
+ }
+ }
+}
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoPrerequisites.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoPrerequisites.java
new file mode 100644
index 000000000..49812e994
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoPrerequisites.java
@@ -0,0 +1,195 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.ssl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * SSL-over-UNIX sockets demo.
+ *
+ * Prerequisites:
+ *
+ *
+ * Create server public/private key pair, valid for ~10 years, Store it as a PKCS12 file named
+ * "{@code juxserver.p12}":
+ *
+ * {@code keytool -genkeypair -alias juxserver -keyalg RSA -keysize 2048
+ * -storetype PKCS12 -validity 3650 -ext san=dns:localhost.junixsocket
+ * -dname "CN=First and Last, OU=Organizational Unit, O=Organization, L=City, ST=State, C=XX"
+ * -keystore juxserver.p12 -storepass serverpass}
+ *
+ * Omit {@code -dname "CN=..."} to interactively specify the distinguished name for the certificate.
+ *
+ * You may verify the contents of this p12 file via
+ * {@code keytool -list -v -keystore juxserver.p12 -storepass serverpass}; omit the
+ * {@code -storepass...} parameters to specify the password interactively for additional security.
+ *
+ * Export the server's public key as a X.509 certificate:
+ *
+ * {@code keytool -exportcert -alias juxserver -keystore juxserver.p12 -storepass serverpass -file juxserver.pem}
+ *
+ * You may verify the contents of the certificate file via
+ * {@code keytool -printcert -file juxserver.pem}
+ * Import the server's X.509 certificate into the client truststore:
+ *
+ * {@code keytool -importcert -alias juxserver -keystore juxclient.truststore -storepass clienttrustpass
+ * -file juxserver.pem -noprompt}
+ *
+ * Omit {@code -noprompt} to interactively verify the imported certificate.
+ *
+ *
+ * You may verify the contents of this truststore via
+ * {@code keytool -list -v -keystore juxclient.truststore -storepass clienttrustpass}; omit the
+ * {@code -storepass...} parameters to specify the password interactively for additional security.
+ *
+ *
+ *
+ * If you want client authentication as well, perform these additional steps:
+ *
+ * Create client public/private key pair, valid for ~10 years, Store it as a PKCS12 file named
+ * "{@code juxclient.p12}":
+ *
+ * {@code keytool -genkeypair -alias juxclient -keyalg RSA -keysize 2048 -storetype PKCS12
+ * -validity 3650 -ext san=dns:localhost.junixsocket
+ * -dname "CN=First and Last, OU=Organizational Unit, O=Organization, L=City, ST=State, C=XX"
+ * -keystore juxclient.p12 -storepass clientpass}
+ *
+ * Omit {@code -dname "CN=..."} to interactively specify the distinguished name for the certificate.
+ *
+ * You may verify the contents of this p12 file via
+ * {@code keytool -list -v -keystore juxclient.p12 -storepass clientpass}; omit the
+ * {@code -storepass...} parameters to specify the password interactively for additional security.
+ *
+ * Export the client's public key as a X.509 certificate:
+ *
+ * {@code keytool -exportcert -alias juxclient -keystore juxclient.p12 -storepass clientpass -file juxclient.pem}
+ *
+ * You may verify the contents of the certificate file via
+ * {@code keytool -printcert -file juxclient.pem}
+ * Import the client's X.509 certificate into the servers truststore:
+ *
+ * {@code keytool -importcert -alias juxclient -keystore juxserver.truststore -storepass servertrustpass
+ * -file juxclient.pem -noprompt}
+ *
+ * Omit {@code -noprompt} to interactively verify the imported certificate.
+ *
+ *
+ * You may verify the contents of this truststore via
+ * {@code keytool -list -v -keystore juxserver.truststore -storepass servertrustpass}; omit the
+ * {@code -storepass...} parameters to specify the password interactively for additional security.
+ *
+ *
+ *
+ * @author Christian Kohlschütter
+ * @see org.newsclub.net.unix.demo.ssl.SSLDemoServer
+ * @see org.newsclub.net.unix.demo.ssl.SSLDemoClient
+ */
+@SuppressWarnings({
+ "FutureReturnValueIgnored", // errorprone
+ "CatchAndPrintStackTrace", // errorprone
+})
+public class SSLDemoPrerequisites {
+ private static final boolean runCommand(String explanation, String... command) throws IOException,
+ InterruptedException {
+ System.out.println(explanation + "...");
+
+ StringBuilder sb = new StringBuilder();
+ for (String c : command) {
+ sb.append(" ");
+ if (c.isEmpty() || c.contains(" ") || c.contains("\"")) {
+ sb.append("\"" + c.replace("\"", "\\\"") + "\"");
+ } else {
+ sb.append(c);
+ }
+ }
+ System.out.println("#" + sb);
+
+ Process process = Runtime.getRuntime().exec(command);
+
+ CompletableFuture.runAsync(() -> {
+ try (InputStream stdout = process.getInputStream()) {
+ byte[] buf = new byte[1024];
+ int r;
+ while ((r = stdout.read(buf)) >= 0) {
+ System.out.write(buf, 0, r);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ CompletableFuture.runAsync(() -> {
+ try (InputStream stderr = process.getErrorStream()) {
+ byte[] buf = new byte[1024];
+ int r;
+ while ((r = stderr.read(buf)) >= 0) {
+ System.err.write(buf, 0, r);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+
+ int rc = process.waitFor();
+ System.out.println("rc=" + rc);
+ System.out.println();
+ return rc == 0;
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Working directory: " + new File("").getAbsolutePath());
+ System.out.println();
+
+ boolean success = true;
+
+ success &= runCommand("Generating server key pair", //
+ "keytool", "-genkeypair", "-alias", "juxserver", "-keyalg", "RSA", "-keysize", "2048",
+ "-storetype", "PKCS12", "-validity", "3650", "-ext", "san=dns:localhost.junixsocket",
+ "-dname",
+ "CN=First and Last, OU=Organizational Unit, O=Organization, L=City, ST=State, C=XX",
+ "-keystore", "juxserver.p12", "-storepass", "serverpass");
+
+ success &= runCommand("Exporting server certificate", //
+ ("keytool -exportcert -alias juxserver -keystore juxserver.p12 -storepass serverpass -file juxserver.pem")
+ .split("[ ]+"));
+
+ success &= runCommand("Importing server certificate into client truststore", //
+ ("keytool -importcert -alias juxserver -keystore juxclient.truststore -storepass clienttrustpass"
+ + " -file juxserver.pem -noprompt").split("[ ]+"));
+
+ success &= runCommand("Generating client key pair (optional, only for client authentication)", //
+ "keytool", "-genkeypair", "-alias", "juxclient", "-keyalg", "RSA", "-keysize", "2048",
+ "-storetype", "PKCS12", "-validity", "3650", "-ext", "san=dns:localhost.junixsocket",
+ "-dname",
+ "CN=First and Last, OU=Organizational Unit, O=Organization, L=City, ST=State, C=XX",
+ "-keystore", "juxclient.p12", "-storepass", "clientpass");
+
+ success &= runCommand("Exporting client certificate (optional, only for client authentication)", //
+ ("keytool -exportcert -alias juxclient -keystore juxclient.p12 -storepass clientpass -file juxclient.pem")
+ .split("[ ]+"));
+
+ success &= runCommand(
+ "Importing client certificate server client truststore (optional, only for client authentication)", //
+ ("keytool -importcert -alias juxclient -keystore juxserver.truststore -storepass servertrustpass"
+ + " -file juxclient.pem -noprompt").split("[ ]+"));
+
+ System.out.println("DONE. All successful=" + success);
+ }
+}
diff --git a/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoServer.java b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoServer.java
new file mode 100644
index 000000000..2ec8b8d73
--- /dev/null
+++ b/junixsocket-demo/src/main/java/org/newsclub/net/unix/demo/ssl/SSLDemoServer.java
@@ -0,0 +1,146 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.demo.ssl;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SNIMatcher;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.security.auth.DestroyFailedException;
+
+import org.newsclub.net.unix.AFSocket;
+import org.newsclub.net.unix.AFUNIXSocket;
+import org.newsclub.net.unix.AFUNIXSocketAddress;
+import org.newsclub.net.unix.FileDescriptorCast;
+import org.newsclub.net.unix.server.AFSocketServer;
+import org.newsclub.net.unix.ssl.SNIHostnameCapture;
+import org.newsclub.net.unix.ssl.SSLContextBuilder;
+
+/**
+ * A simple SSL demo server.
+ *
+ * @author Christian Kohlschütter
+ * @see SSLDemoClient
+ * @see SSLDemoPrerequisites
+ */
+@SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
+public class SSLDemoServer {
+ public static void main(String[] args) throws InterruptedException, IOException,
+ GeneralSecurityException, DestroyFailedException {
+
+ // Enable to see SSL debugging
+ // System.setProperty("javax.net.debug", "all");
+
+ AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(new File("/tmp/ssldemo"));
+
+ SSLSocketFactory serverSocketFactory = SSLContextBuilder.forServer() //
+ .withKeyStore(new File("juxserver.p12"), () -> "serverpass".toCharArray()) //
+ .withTrustStore(new File("juxserver.truststore"), () -> "servertrustpass".toCharArray()) //
+ .withDefaultSSLParameters((p) -> {
+ // A simple way to disable some undesired protocols:
+ // SSLParametersUtil.disableProtocols(p, "TLSv1.0", "TLSv1.1", "TLSv1.2");
+
+ // Uncomment to require client-authentication
+ // (which is meaningful in the context of UNIX sockets)
+ // p.setNeedClientAuth(true);
+
+ // Uncomment to perform endpoint checking of client certificates
+ // p.setEndpointIdentificationAlgorithm("HTTPS");
+ }) //
+ .buildAndDestroyBuilder().getSocketFactory();
+
+ AFSocketServer server = new AFSocketServer(addr) {
+
+ // Match any SNI hostname, including none sent
+ final SNIMatcher sniHostnameMatcher = SNIHostnameCapture.ACCEPT_ANY_HOSTNAME;
+
+ // Replace with code below to enforce receiving a valid SNI hostname
+ // final SNIMatcher sniHostnameMatcher = SNIHostName.createSNIMatcher("(^|.+?\\.)" + Pattern
+ // .quote("example.com"));
+
+ @Override
+ protected void doServeSocket(AFSocket extends AFUNIXSocketAddress> plainSocket)
+ throws IOException {
+ try (SSLSocket sslSocket = (SSLSocket) serverSocketFactory.createSocket(plainSocket,
+ // This is considered the peer name (the client's name)
+ "localhost.junixsocket", plainSocket.getPort(), //
+ // you can also replace the above line with:
+ // null,
+ false)) {
+
+ // Setting the client mode manually is not necessary when using SSLContextBuilder
+ // sslSocket.setUseClientMode(false);
+
+ SNIHostnameCapture sniHostname = SNIHostnameCapture.configure(sslSocket,
+ sniHostnameMatcher);
+
+ // Set to 0 to disable receiving file descriptors, etc.
+ plainSocket.setAncillaryReceiveBufferSize(1); // rounds up to minimum buffer size
+
+ sslSocket.startHandshake();
+ // Make sure the handshake is complete before we check the hostname
+ // (otherwise: IllegalStateException)
+ try {
+ if (sniHostname.isComplete(1, TimeUnit.SECONDS)) {
+ System.out.println("Requested SNI hostname: " + sniHostname.getHostname());
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ try (InputStream in = sslSocket.getInputStream();
+ OutputStream out = sslSocket.getOutputStream();) {
+ System.out.println("Received byte: " + Integer.toHexString(in.read()));
+
+ System.out.println("Sending hello...");
+ out.write("Hello World".getBytes(StandardCharsets.UTF_8));
+
+ FileDescriptor[] fds = ((AFUNIXSocket) plainSocket).getReceivedFileDescriptors();
+ if (fds.length > 0) {
+ System.out.println("File descriptor received: " + Arrays.asList(fds));
+ System.out.println(
+ "Sending an extra message directly to a FileDescriptor of the other process...");
+ try (PrintStream ps = new PrintStream(FileDescriptorCast.using(fds[0]).as(
+ OutputStream.class), true, Charset.defaultCharset().name())) {
+ ps.println("Greetings from the server, right to your stderr");
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onServingException(AFSocket extends AFUNIXSocketAddress> socket,
+ Exception e) {
+ e.printStackTrace();
+ }
+ };
+ server.startAndWaitToBecomeReady();
+ }
+}
diff --git a/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.p12 b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.p12
new file mode 100644
index 000000000..870b0bb64
Binary files /dev/null and b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.p12 differ
diff --git a/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.pem b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.pem
new file mode 100644
index 000000000..0f2f8b017
Binary files /dev/null and b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.pem differ
diff --git a/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.truststore b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.truststore
new file mode 100644
index 000000000..d476eb937
Binary files /dev/null and b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxclient.truststore differ
diff --git a/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.p12 b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.p12
new file mode 100644
index 000000000..a6ba9f1bd
Binary files /dev/null and b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.p12 differ
diff --git a/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.pem b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.pem
new file mode 100644
index 000000000..f1bcac763
Binary files /dev/null and b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.pem differ
diff --git a/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.truststore b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.truststore
new file mode 100644
index 000000000..f0352b0db
Binary files /dev/null and b/junixsocket-demo/src/main/resources/org/newsclub/net/unix/demo/ssl/juxserver.truststore differ
diff --git a/junixsocket-dist/pom.xml b/junixsocket-dist/pom.xml
index 941f9937a..8da8fa991 100644
--- a/junixsocket-dist/pom.xml
+++ b/junixsocket-dist/pom.xml
@@ -8,7 +8,7 @@
com.kohlschutter.junixsocket
junixsocket
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-dist
@@ -61,12 +61,16 @@
release
+
+
+ release
+
+
org.apache.maven.plugins
maven-assembly-plugin
- 3.1.1
build-dist
diff --git a/junixsocket-jetty-12/pom.xml b/junixsocket-jetty-12/pom.xml
new file mode 100644
index 000000000..00196c3e6
--- /dev/null
+++ b/junixsocket-jetty-12/pom.xml
@@ -0,0 +1,91 @@
+
+
+ 4.0.0
+ junixsocket-jetty-12
+ jar
+
+ com.kohlschutter.junixsocket
+ junixsocket
+ 2.8.2
+ ../pom.xml
+
+ junixsocket-jetty
+
+ ${project.parent.basedir}
+ 12.0.1
+
+
+ junixsocket for Jetty 12 (currently test-only; use
+ junixsocket-jetty as a dependency)
+
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-core
+ ${project.version}
+ pom
+
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-jetty
+ ${project.version}
+ test
+
+
+ org.eclipse.jetty
+ jetty-server
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-server
+ ${jetty.version}
+ provided
+
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.9
+ test
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.11.0
+ test
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-common
+ ${project.version}
+ tests
+ test
+
+
+ org.eclipse.jetty
+ jetty-client
+ ${jetty.version}
+ test
+
+
+
+ org.hamcrest
+ hamcrest
+ 2.2
+ test
+
+
+
diff --git a/junixsocket-jetty-12/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java b/junixsocket-jetty-12/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java
new file mode 100644
index 000000000..84804d5c0
--- /dev/null
+++ b/junixsocket-jetty-12/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java
@@ -0,0 +1,356 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2022 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//
+// ========================================================================
+// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.unixdomain.server;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.client.ContentResponse;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpProxy;
+import org.eclipse.jetty.client.ProxyProtocolClientConnectionFactory.V1;
+import org.eclipse.jetty.client.ProxyProtocolClientConnectionFactory.V2;
+import org.eclipse.jetty.client.transport.HttpClientTransportDynamic;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.io.ClientConnector;
+import org.eclipse.jetty.server.ConnectionFactory;
+import org.eclipse.jetty.server.ConnectionMetaData;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.ProxyConnectionFactory;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.component.LifeCycle;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.newsclub.net.unix.AFSocketAddress;
+import org.newsclub.net.unix.AFUNIXSocketAddress;
+import org.newsclub.net.unix.jetty.AFSocketClientConnector;
+import org.newsclub.net.unix.jetty.AFSocketServerConnector;
+
+public class UnixDomainTest {
+ private static final Class> unixDomainSocketAddressClass = probe();
+
+ private static Class> probe() {
+ try {
+ return ClassLoader.getPlatformClassLoader().loadClass("java.net.UnixDomainSocketAddress");
+ } catch (Throwable x) {
+ return null;
+ }
+ }
+
+ private ConnectionFactory[] factories = new ConnectionFactory[] {new HttpConnectionFactory()};
+ private Server server;
+ private Path unixDomainPath;
+
+ @BeforeAll
+ public static void setUp() {
+ System.setProperty("org.slf4j.simpleLogger.log.org.eclipse.jetty", "error");
+ }
+
+ private void start(Handler handler) throws Exception {
+ server = new Server();
+ // UnixDomainServerConnector connector = new UnixDomainServerConnector(server, factories);
+ AFSocketServerConnector connector = new AFSocketServerConnector(server, factories);
+ String dir = System.getProperty("jetty.unixdomain.dir", System.getProperty("java.io.tmpdir"));
+ assertNotNull(dir);
+ File dirFile = new File(dir);
+ dirFile.mkdirs();
+ unixDomainPath = Files.createTempFile(dirFile.toPath(), "unix_", ".sock");
+ assertTrue(unixDomainPath.toAbsolutePath().toString().length() < 108,
+ "Unix-Domain path too long");
+ Files.delete(unixDomainPath);
+ // connector.setUnixDomainPath(unixDomainPath);
+ connector.setListenSocketAddress(AFUNIXSocketAddress.of(unixDomainPath));
+ server.addConnector(connector);
+ server.setHandler(handler);
+ server.start();
+ }
+
+ @AfterEach
+ public void dispose() {
+ LifeCycle.stop(server);
+ }
+
+ @Test
+ public void testHTTPOverUnixDomain() throws Exception {
+ String uri = "http://localhost:1234/path";
+ start(new Handler.Abstract() {
+
+ @Override
+ public boolean handle(Request request, Response response, Callback callback)
+ throws Exception {
+ // Verify the URI is preserved.
+ assertEquals(uri, request.getHttpURI().toString());
+
+ // Verify the SocketAddresses.
+ ConnectionMetaData connectionMetaData = request.getConnectionMetaData();
+ SocketAddress local = connectionMetaData.getLocalSocketAddress();
+ SocketAddress remote = connectionMetaData.getRemoteSocketAddress();
+
+ assertThat(local, Matchers.instanceOf(AFSocketAddress.class));
+ if (remote != null) {
+ // remote should be null if not connected
+ assertThat(remote, Matchers.instanceOf(AFSocketAddress.class));
+ }
+
+ assertDoesNotThrow(connectionMetaData::toString);
+
+ response.write(true, ByteBuffer.allocate(0), new Callback() {});
+
+ return true;
+ }
+ });
+
+ // ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath);
+ ClientConnector clientConnector = AFSocketClientConnector.withSocketAddress(AFUNIXSocketAddress
+ .of(unixDomainPath));
+ HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
+ httpClient.start();
+ try {
+ ContentResponse response = httpClient.newRequest(uri).timeout(5, TimeUnit.SECONDS).send();
+
+ assertEquals(HttpStatus.OK_200, response.getStatus());
+ } finally {
+ httpClient.stop();
+ }
+ }
+
+ @Test
+ public void testHTTPOverUnixDomainWithHTTPProxy() throws Exception {
+ int fakeProxyPort = 4567;
+ int fakeServerPort = 5678;
+ start(new Handler.Abstract() {
+ @Override
+ public boolean handle(Request request, Response response, Callback callback)
+ throws Exception {
+ // Proxied requests must have an absolute URI.
+ HttpURI uri = request.getHttpURI();
+ assertNotNull(uri.getScheme());
+ assertEquals(fakeServerPort, uri.getPort());
+
+ response.write(true, ByteBuffer.allocate(0), new Callback() {});
+
+ return true;
+ }
+ });
+
+ // ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath);
+ ClientConnector clientConnector = AFSocketClientConnector.withSocketAddress(AFUNIXSocketAddress
+ .of(unixDomainPath));
+
+ HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
+ httpClient.getProxyConfiguration().addProxy(new HttpProxy("localhost", fakeProxyPort));
+ httpClient.start();
+ try {
+ ContentResponse response = httpClient.newRequest("localhost", fakeServerPort).timeout(5,
+ TimeUnit.SECONDS).send();
+
+ assertEquals(HttpStatus.OK_200, response.getStatus());
+ } finally {
+ httpClient.stop();
+ }
+ }
+
+ @Test
+ public void testHTTPOverUnixDomainWithProxyProtocol() throws Exception {
+ String srcAddr = "/proxySrcAddr";
+ String dstAddr = "/proxyDstAddr";
+ factories = new ConnectionFactory[] {new ProxyConnectionFactory(), new HttpConnectionFactory()};
+ start(new Handler.Abstract() {
+ @Override
+ public boolean handle(Request request, Response response, Callback callback)
+ throws Exception {
+ ConnectionMetaData connectionMetaData = request.getConnectionMetaData();
+
+ String target = request.getHttpURI().getPath();
+
+ if ("/v1".equals(target)) {
+ // As PROXYv1 does not support UNIX, the wrapped EndPoint data is used.
+ Path localPath = toUnixDomainPath(connectionMetaData.getLocalSocketAddress());
+ assertThat(localPath, Matchers.equalTo(unixDomainPath));
+ } else if ("/v2".equals(target)) {
+ SocketAddress localSocketAddress = connectionMetaData.getLocalSocketAddress();
+ if (localSocketAddress != null) {
+ assertThat(toUnixDomainPath(localSocketAddress).toString(), Matchers.equalTo(separators(
+ dstAddr)));
+ }
+ SocketAddress remoteSocketAddress = connectionMetaData.getRemoteSocketAddress();
+ if (remoteSocketAddress != null) {
+ assertThat(toUnixDomainPath(remoteSocketAddress).toString(), Matchers.equalTo(
+ separators(srcAddr)));
+ }
+ } else {
+ Assertions.fail("Invalid PROXY protocol version " + target);
+ }
+
+ response.write(true, ByteBuffer.allocate(0), new Callback() {});
+
+ return true;
+ }
+ });
+
+ // Java 11+ portable way to implement SocketChannelWithAddress.Factory.
+ // ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath);
+ ClientConnector clientConnector = AFSocketClientConnector.withSocketAddress(AFUNIXSocketAddress
+ .of(unixDomainPath));
+
+ HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
+ httpClient.start();
+ try {
+ // Try PROXYv1 with the PROXY information retrieved from the EndPoint.
+ // PROXYv1 does not support the UNIX family.
+ ContentResponse response1 = httpClient.newRequest("localhost", 0).path("/v1").tag(
+ new V1.Tag()).timeout(5, TimeUnit.SECONDS).send();
+
+ assertEquals(HttpStatus.OK_200, response1.getStatus());
+
+ // Try PROXYv2 with explicit PROXY information.
+ V2.Tag tag = new V2.Tag(V2.Tag.Command.PROXY, V2.Tag.Family.UNIX, V2.Tag.Protocol.STREAM,
+ srcAddr, 0, dstAddr, 0, null);
+ ContentResponse response2 = httpClient.newRequest("localhost", 0).path("/v2").tag(tag)
+ .timeout(5, TimeUnit.SECONDS).send();
+
+ assertEquals(HttpStatus.OK_200, response2.getStatus());
+ } finally {
+ httpClient.stop();
+ }
+ }
+
+ @Test
+ public void testInvalidUnixDomainPath() {
+ server = new Server();
+ // UnixDomainServerConnector connector = new UnixDomainServerConnector(server, factories);
+ AFSocketServerConnector connector = new AFSocketServerConnector(server, factories);
+
+ // connector.setUnixDomainPath(new File("/does/not/exist").toPath());
+ try {
+ connector.setListenSocketAddress(AFUNIXSocketAddress.of(new File("/does/not/exist")
+ .toPath()));
+ } catch (SocketException e) {
+ throw new IllegalStateException(e);
+ }
+
+ server.addConnector(connector);
+ assertThrows(IOException.class, () -> server.start());
+ }
+
+ private static Path toUnixDomainPath(SocketAddress address) {
+ Objects.requireNonNull(address, "address");
+
+ if (address instanceof AFUNIXSocketAddress) {
+ return new File(((AFUNIXSocketAddress) address).getPath()).toPath();
+ } else if (unixDomainSocketAddressClass != null) {
+ try {
+ return (Path) unixDomainSocketAddressClass.getMethod("getPath").invoke(address);
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ Assertions.fail(e);
+ throw new AssertionError(e);
+ }
+ } else {
+ throw new IllegalStateException("Unsupported socket address class " + address.getClass()
+ + ": " + address);
+ }
+ }
+
+ public static String separators(String path) {
+ StringBuilder ret = new StringBuilder();
+ for (int i = 0, n = path.length(); i < n; i++) {
+ char c = path.charAt(i);
+ if ((c == '/') || (c == '\\')) {
+ ret.append(File.separatorChar);
+ } else {
+ ret.append(c);
+ }
+ }
+ return ret.toString();
+ }
+
+ @Test
+ public void testLargeBody() throws Exception {
+ String uri = "http://localhost:1234/path";
+
+ byte[] payload = new byte[512 * 1024]; // 512k
+ new Random().nextBytes(payload);
+
+ start(new Handler.Abstract() {
+ @Override
+ public boolean handle(Request request, Response response, Callback callback)
+ throws Exception {
+ response.getHeaders().put(HttpHeader.CONTENT_TYPE, "application/octet-stream");
+
+ response.write(true, ByteBuffer.wrap(payload), new Callback() {});
+
+ return true;
+ }
+ });
+
+ // ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath);
+ ClientConnector clientConnector = AFSocketClientConnector.withSocketAddress(AFUNIXSocketAddress
+ .of(unixDomainPath));
+ HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
+ httpClient.start();
+ try {
+ ContentResponse response = httpClient.newRequest(uri).timeout(5, TimeUnit.SECONDS).send();
+
+ assertEquals(HttpStatus.OK_200, response.getStatus());
+ byte[] data = response.getContent();
+ assertArrayEquals(payload, data);
+ } finally {
+ httpClient.stop();
+ }
+ }
+}
\ No newline at end of file
diff --git a/junixsocket-jetty-12/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java b/junixsocket-jetty-12/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java
new file mode 100644
index 000000000..30cde6070
--- /dev/null
+++ b/junixsocket-jetty-12/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java
@@ -0,0 +1,122 @@
+/*
+ * junixsocket
+ *
+ * Copyright 2009-2023 Christian Kohlschütter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.newsclub.net.unix.jetty;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.BufferedReader;
+import java.time.Duration;
+
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.newsclub.net.unix.AFSocketAddress;
+import org.newsclub.net.unix.AFSocketFactory;
+import org.newsclub.net.unix.domain.AFUNIXAddressSpecifics;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+public class AFSocketServerConnectorTest {
+ @BeforeAll
+ public static void setUp() {
+ System.setProperty("org.slf4j.simpleLogger.log.org.eclipse.jetty.server", "error");
+ }
+
+ @Test
+ public void testServerAFUNIX() throws Exception {
+ AFSocketAddress addr = (AFSocketAddress) AFUNIXAddressSpecifics.INSTANCE
+ .newTempAddressForDatagram();
+ Server server1 = newServer(addr);
+ checkConnection(addr);
+ assertTrue(server1.isRunning());
+
+ Server server2 = newServer(addr);
+
+ // isDeleteOnClose is smart enough to not delete the wrong socket
+ assertTrue(addr.getFile().exists());
+
+ server1.join();
+ assertFalse(server1.isRunning());
+ server2.stop();
+ server2.join();
+ assertFalse(addr.getFile().exists()); // isDeleteOnClose=true by default
+ }
+
+ private void checkConnection(AFSocketAddress addr) throws Exception {
+ OkHttpClient.Builder builder = new OkHttpClient.Builder() //
+ .socketFactory(new AFSocketFactory.FixedAddressSocketFactory(addr)) //
+ .callTimeout(Duration.ofMinutes(1));
+
+ OkHttpClient client = builder.build();
+
+ Request request = new Request.Builder().url("http://localhost/").build();
+ try (Response response = client.newCall(request).execute()) {
+ assertEquals(404, response.code());
+ assertNotNull(response.header("Server"));
+
+ ResponseBody body = response.body();
+ assertNotNull(body);
+
+ BufferedReader br = new BufferedReader(body.charStream());
+ int l = 0;
+ while (br.readLine() != null) {
+ l++;
+ }
+ assertNotEquals(0, l);
+ }
+ }
+
+ private static Server newServer(AFSocketAddress addr) throws Exception {
+ Server server = new Server();
+
+ // below code is based upon
+ // https://www.eclipse.org/jetty/documentation/jetty-10/programming-guide/index.html
+
+ // The number of acceptor threads.
+ int acceptors = 1;
+
+ // The number of selectors.
+ int selectors = 1;
+
+ // Create a ServerConnector instance.
+ AFSocketServerConnector connector = new AFSocketServerConnector(server, acceptors, selectors,
+ new HttpConnectionFactory());
+
+ // The AFSocketAddress to listen to.
+ connector.setListenSocketAddress(addr);
+
+ // The accept queue size.
+ connector.setAcceptQueueSize(128);
+
+ // Try to automatically stop server if another instance reuses our address
+ connector.setMayStopServer(true);
+
+ server.addConnector(connector);
+ server.start();
+
+ return server;
+ }
+}
diff --git a/junixsocket-jetty/pom.xml b/junixsocket-jetty/pom.xml
index be05bc148..577de4a69 100644
--- a/junixsocket-jetty/pom.xml
+++ b/junixsocket-jetty/pom.xml
@@ -1,22 +1,39 @@
-
+
4.0.0
junixsocket-jetty
jar
com.kohlschutter.junixsocket
junixsocket
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-jetty
${project.parent.basedir}
- 11.0.12
+ 11.0.16
junixsocket for Jetty
+
+
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+
+
+ false
+
+
+
+
+
+
com.kohlschutter.junixsocket
@@ -34,13 +51,13 @@
org.slf4j
slf4j-simple
- 2.0.3
+ 2.0.9
test
com.squareup.okhttp3
okhttp
- 4.10.0
+ 4.11.0
test
@@ -56,6 +73,14 @@
${jetty.version}
test
+
org.hamcrest
hamcrest
@@ -63,4 +88,4 @@
test
-
\ No newline at end of file
+
diff --git a/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketClientConnector.java b/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketClientConnector.java
index 5dee06881..6e7b26b73 100644
--- a/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketClientConnector.java
+++ b/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketClientConnector.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,11 +32,11 @@
/**
* A {@link Connector} implementation for junixsocket server socket channels (Unix domains etc.)
- *
+ *
* Based upon jetty's ClientConnector.
- *
+ *
* This implementation should work with jetty version 10.0.8 or newer.
- *
+ *
* @author Christian Kohlschütter
*/
public final class AFSocketClientConnector extends ClientConnector {
@@ -50,7 +50,7 @@ private AFSocketClientConnector(AFSocketAddress addr) {
/**
* Returns a new {@link ClientConnector} configured to use given {@link AFSocketAddress} for
* communication with junixsocket sockets.
- *
+ *
* @param addr The socket address.
* @return The client connector.
*/
diff --git a/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketServerConnector.java b/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketServerConnector.java
index 7991b8186..ac37bb477 100644
--- a/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketServerConnector.java
+++ b/junixsocket-jetty/src/main/java/org/newsclub/net/unix/jetty/AFSocketServerConnector.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,11 +50,9 @@
import java.util.EventListener;
import java.util.Locale;
import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicReference;
-import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
@@ -81,12 +79,13 @@
/**
* A {@link Connector} implementation for junixsocket server socket channels (Unix domains etc.)
- *
+ *
* Based upon jetty's UnixDomainServerConnector.
- *
+ *
* This implementation should work with jetty version 9.4.12 or newer.
*/
@ManagedObject
+@SuppressWarnings("PMD.CouplingBetweenObjects")
public class AFSocketServerConnector extends AbstractConnector {
private static final Logger LOG = LoggerFactory.getLogger(AbstractConnector.class);
@@ -100,12 +99,13 @@ public class AFSocketServerConnector extends AbstractConnector {
private int acceptedSendBufferSize;
private boolean mayStopServer = false;
+ private boolean mayStopServerForce = false;
private final Class extends EventListener> selectorManagerListenerClass;
private final Server server;
/**
* Creates a new {@link AFSocketServerConnector}.
- *
+ *
* @param server The server this connector will be added to. Must not be null.
* @param factories The Connection Factories to use.
*/
@@ -115,7 +115,7 @@ public AFSocketServerConnector(Server server, ConnectionFactory... factories) {
/**
* Creates a new {@link AFSocketServerConnector}.
- *
+ *
* @param server The server this connector will be added to. Must not be null.
* @param acceptors the number of acceptor threads to use, or -1 for a default value. If 0, then
* no acceptor threads will be launched and some other mechanism will need to be used to
@@ -130,13 +130,13 @@ public AFSocketServerConnector(Server server, int acceptors, int selectors,
/**
* Creates a new {@link AFSocketServerConnector}.
- *
+ *
* @param server The server this connector will be added to. Must not be null.
* @param executor An executor for this connector or null to use the servers executor
* @param scheduler A scheduler for this connector or null to either a {@link Scheduler} set as a
* server bean or if none set, then a new {@link ScheduledExecutorScheduler} instance.
* @param pool A buffer pool for this connector or null to either a {@link ByteBufferPool} set as
- * a server bean or none set, the new {@link ArrayByteBufferPool} instance.
+ * a server bean or none set, the new {code ArrayByteBufferPool} instance.
* @param acceptors the number of acceptor threads to use, or -1 for a default value. If 0, then
* no acceptor threads will be launched and some other mechanism will need to be used to
* accept new connections.
@@ -144,6 +144,7 @@ public AFSocketServerConnector(Server server, int acceptors, int selectors,
* @param factories The Connection Factories to use.
*/
@SuppressFBWarnings("EI_EXPOSE_REP2")
+ @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
public AFSocketServerConnector(Server server, Executor executor, Scheduler scheduler,
ByteBufferPool pool, int acceptors, int selectors, ConnectionFactory... factories) {
super(server, executor, scheduler, pool, acceptors, factories.length > 0 ? factories
@@ -172,14 +173,15 @@ private SelectorManager newSelectorManager(Executor executor, Scheduler schedule
/**
* Returns the Unix-Domain path this connector listens to.
- *
+ *
* Added for compatibility with jetty's {@code UnixDomainServerConnector}.
- *
+ *
* @return The Unix-Domain path this connector listens to.
* @deprecated Use {@link #getListenSocketAddress()} instead.
* @see #getListenSocketAddress()
*/
@ManagedAttribute("The Unix-Domain path this connector listens to")
+ @Deprecated
public Path getUnixDomainPath() {
if (listenSocketAddress instanceof AFUNIXSocketAddress) {
AFUNIXSocketAddress addr = (AFUNIXSocketAddress) listenSocketAddress;
@@ -196,13 +198,14 @@ public Path getUnixDomainPath() {
/**
* Sets the Unix-Domain path this connector listens to.
- *
+ *
* Added for compatibility with jetty's {@code UnixDomainServerConnector}.
- *
+ *
* @param unixDomainPath The path.
* @deprecated Use {@link #setListenSocketAddress(AFSocketAddress)} instead.
* @see #setListenSocketAddress(AFSocketAddress)
*/
+ @Deprecated
public void setUnixDomainPath(Path unixDomainPath) {
try {
this.listenSocketAddress = AFUNIXSocketAddress.of(unixDomainPath);
@@ -213,7 +216,7 @@ public void setUnixDomainPath(Path unixDomainPath) {
/**
* Returns the socket address this connector listens to.
- *
+ *
* @return The socket address, or {@code null} if none set.
*/
@ManagedAttribute("The socket address this connector listens to")
@@ -224,7 +227,7 @@ public AFSocketAddress getListenSocketAddress() {
/**
* Sets the socket address this connector listens to.
- *
+ *
* @param addr The socket address, or {@code null}.
*/
@SuppressFBWarnings("EI_EXPOSE_REP2")
@@ -234,7 +237,7 @@ public void setListenSocketAddress(AFSocketAddress addr) {
/**
* Checks whether this connector uses a server channel inherited from the JVM.
- *
+ *
* @return {@code true} if so.
*/
@ManagedAttribute("Whether this connector uses a server channel inherited from the JVM")
@@ -244,7 +247,7 @@ public boolean isInheritChannel() {
/**
* Sets whether this connector uses a server channel inherited from the JVM.
- *
+ *
* @param inheritChannel {@code true} if so.
*/
public void setInheritChannel(boolean inheritChannel) {
@@ -253,7 +256,7 @@ public void setInheritChannel(boolean inheritChannel) {
/**
* Returns the accept queue size (backlog) for the server socket.
- *
+ *
* @return The backlog.
*/
@ManagedAttribute("The accept queue size (backlog) for the server socket")
@@ -263,7 +266,7 @@ public int getAcceptQueueSize() {
/**
* Sets the accept queue size (backlog) for the server socket.
- *
+ *
* @param acceptQueueSize The backlog.
*/
public void setAcceptQueueSize(int acceptQueueSize) {
@@ -272,7 +275,7 @@ public void setAcceptQueueSize(int acceptQueueSize) {
/**
* Returns the SO_RCVBUF size for accepted sockets.
- *
+ *
* @return The buffer size.
*/
@ManagedAttribute("The SO_RCVBUF option for accepted sockets")
@@ -282,7 +285,7 @@ public int getAcceptedReceiveBufferSize() {
/**
* Sets the SO_RCVBUF size for accepted sockets.
- *
+ *
* @param acceptedReceiveBufferSize The buffer size.
*/
public void setAcceptedReceiveBufferSize(int acceptedReceiveBufferSize) {
@@ -291,7 +294,7 @@ public void setAcceptedReceiveBufferSize(int acceptedReceiveBufferSize) {
/**
* Returns the SO_SNDBUF size for accepted sockets.
- *
+ *
* @return The buffer size.
*/
@ManagedAttribute("The SO_SNDBUF option for accepted sockets")
@@ -301,7 +304,7 @@ public int getAcceptedSendBufferSize() {
/**
* Sets the SO_SNDBUF size for accepted sockets.
- *
+ *
* @param acceptedSendBufferSize The buffer size.
*/
public void setAcceptedSendBufferSize(int acceptedSendBufferSize) {
@@ -342,45 +345,35 @@ protected void accept(int acceptorID) throws IOException {
takenOver = !((AFServerSocketChannel>) sc).isLocalSocketAddressValid();
}
- if (takenOver) {
- ExecutorService es = Executors.newSingleThreadExecutor();
- try {
- LOG.warn("Another server has taken over our address");
- es.execute(() -> {
- Connector[] connectors = server.getConnectors();
-
- boolean shutdownServer;
- if (connectors == null) {
- shutdownServer = true;
- } else {
- shutdownServer = true;
- for (Connector conn : connectors) {
- if (conn != AFSocketServerConnector.this && conn.isRunning()) { // NOPMD.CompareObjectsWithEquals
- shutdownServer = false;
- break;
- }
- }
- }
-
- if (shutdownServer && mayStopServer) {
- LOG.warn("Server has no other connectors; shutting down: " + server); // NOPMD
-
- try {
- server.stop();
- } catch (Exception e1) {
- LOG.warn("Exception upon stopping " + server, e1); // NOPMD
- }
- }
- });
- } finally {
- es.shutdown();
- }
+ if (takenOver && isMayStopServer()) {
+ LOG.warn("Another server has taken over our address");
+ ForkJoinPool.commonPool().execute(this::checkServerStop);
}
throw (ClosedByInterruptException) new ClosedByInterruptException().initCause(e);
}
}
}
+ private void checkServerStop() {
+ Connector[] connectors = server.getConnectors();
+
+ if (connectors != null && !isMayStopServerForce()) {
+ for (Connector conn : connectors) {
+ if (conn != AFSocketServerConnector.this && conn.isRunning()) { // NOPMD.CompareObjectsWithEquals
+ return; // don't stop
+ }
+ }
+ }
+
+ LOG.warn("Server has no other connectors; shutting down: " + server); // NOPMD
+
+ try {
+ server.stop();
+ } catch (Exception e1) {
+ LOG.warn("Exception upon stopping " + server, e1); // NOPMD
+ }
+ }
+
private void accepted(SocketChannel channel) throws IOException {
channel.configureBlocking(false);
configure(channel);
@@ -390,7 +383,7 @@ private void accepted(SocketChannel channel) throws IOException {
/**
* Configures an incoming {@link SocketChannel}, setting socket options such as receive and send
* buffer sizes.
- *
+ *
* @param channel The socket channel to configure.
* @throws IOException on error.
*/
@@ -533,7 +526,7 @@ protected void endPointClosed(EndPoint endpoint) {
/**
* Checks if this connector may stop the server when it's no longer able to serve and no other
* connectors are available.
- *
+ *
* @return {@code true} if so.
*/
@ManagedAttribute("Whether this connector may stop the server when it's no longer able to"
@@ -545,10 +538,35 @@ public boolean isMayStopServer() {
/**
* Sets if this connector may stop the server when it's no longer able to serve and no other
* connectors are available.
- *
+ *
* @param mayStopServer {@code true} if so.
*/
public void setMayStopServer(boolean mayStopServer) {
this.mayStopServer = mayStopServer;
}
+
+ /**
+ * Checks if this connector may stop the server when it's no longer able to serve, even if other
+ * connectors are available.
+ *
+ * @return {@code true} if so.
+ */
+ @ManagedAttribute("Whether this connector may stop the server when it's no longer able to"
+ + " serve, even if other connectors are available")
+ public boolean isMayStopServerForce() {
+ return mayStopServerForce;
+ }
+
+ /**
+ * Sets if this connector may stop the server when it's no longer able to serve and no other
+ * connectors are available.
+ *
+ * @param b {@code true} if so (which then also implies {@code setMayStopServer(true)}
+ */
+ public void setMayStopServerForce(boolean b) {
+ if (b) {
+ setMayStopServer(true);
+ }
+ this.mayStopServerForce = b;
+ }
}
diff --git a/junixsocket-jetty/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java b/junixsocket-jetty/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java
index 78b2027e5..8a5dd61ee 100644
--- a/junixsocket-jetty/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java
+++ b/junixsocket-jetty/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java
@@ -31,6 +31,7 @@
package org.eclipse.jetty.unixdomain.server;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -45,6 +46,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
+import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
@@ -75,6 +77,7 @@
import org.newsclub.net.unix.jetty.AFSocketClientConnector;
import org.newsclub.net.unix.jetty.AFSocketServerConnector;
+import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -193,7 +196,7 @@ public void handle(String target, Request jettyRequest, HttpServletRequest reque
.of(unixDomainPath));
HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
- httpClient.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", fakeProxyPort));
+ httpClient.getProxyConfiguration().addProxy(new HttpProxy("localhost", fakeProxyPort));
httpClient.start();
try {
ContentResponse response = httpClient.newRequest("localhost", fakeServerPort).timeout(5,
@@ -308,7 +311,8 @@ private static Path toUnixDomainPath(SocketAddress address) {
public static String separators(String path) {
StringBuilder ret = new StringBuilder();
- for (char c : path.toCharArray()) {
+ for (int i = 0, n = path.length(); i < n; i++) {
+ char c = path.charAt(i);
if ((c == '/') || (c == '\\')) {
ret.append(File.separatorChar);
} else {
@@ -317,4 +321,40 @@ public static String separators(String path) {
}
return ret.toString();
}
+
+ @Test
+ public void testLargeBody() throws Exception {
+ String uri = "http://localhost:1234/path";
+
+ byte[] payload = new byte[512 * 1024]; // 512k
+ new Random().nextBytes(payload);
+
+ start(new AbstractHandler() {
+ @Override
+ public void handle(String target, Request jettyRequest, HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ jettyRequest.setHandled(true);
+
+ response.setContentType(" application/octet-stream");
+ try (ServletOutputStream out = response.getOutputStream()) {
+ out.write(payload);
+ }
+ }
+ });
+
+ // ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath);
+ ClientConnector clientConnector = AFSocketClientConnector.withSocketAddress(AFUNIXSocketAddress
+ .of(unixDomainPath));
+ HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
+ httpClient.start();
+ try {
+ ContentResponse response = httpClient.newRequest(uri).timeout(5, TimeUnit.SECONDS).send();
+
+ assertEquals(HttpStatus.OK_200, response.getStatus());
+ byte[] data = response.getContent();
+ assertArrayEquals(payload, data);
+ } finally {
+ httpClient.stop();
+ }
+ }
}
\ No newline at end of file
diff --git a/junixsocket-jetty/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java b/junixsocket-jetty/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java
index 7f281526f..30cde6070 100644
--- a/junixsocket-jetty/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java
+++ b/junixsocket-jetty/src/test/java/org/newsclub/net/unix/jetty/AFSocketServerConnectorTest.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/junixsocket-mysql/pom.xml b/junixsocket-mysql/pom.xml
index bacd7f4a3..318325d64 100644
--- a/junixsocket-mysql/pom.xml
+++ b/junixsocket-mysql/pom.xml
@@ -6,7 +6,7 @@
com.kohlschutter.junixsocket
junixsocket
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-mysql
@@ -23,9 +23,10 @@
${project.version}
- mysql
- mysql-connector-java
- 8.0.30
+
+ com.mysql
+ mysql-connector-j
+ 8.1.0
provided
diff --git a/junixsocket-mysql/src/main/java/module-info.java b/junixsocket-mysql/src/main/java/module-info.java
index 300b929d6..ed6b7ba1f 100644
--- a/junixsocket-mysql/src/main/java/module-info.java
+++ b/junixsocket-mysql/src/main/java/module-info.java
@@ -8,7 +8,8 @@
requires java.sql;
requires java.base;
- requires mysql.connector.java;
+ // requires mysql.connector.java; // until 8.0.30
+ requires transitive mysql.connector.j; // from 8.0.31
requires static com.kohlschutter.annotations.compiletime;
requires static org.eclipse.jdt.annotation;
diff --git a/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactory.java b/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactory.java
index 4693d062b..19a725c14 100644
--- a/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactory.java
+++ b/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactory.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,13 +31,13 @@
/**
* Connect to mysql databases (and compatibles) using UNIX domain sockets.
- *
+ *
* NOTE: This SocketFactory currently implements the "old" Connector/J SocketFactory. This may
* change in the future.
- *
+ *
* For the time being, see AFUNIXDatabaseSocketFactoryCJ to forcibly use the new "CJ"-style
* SocketFactory.
- *
+ *
* @see AFUNIXDatabaseSocketFactoryCJ
*/
@SuppressWarnings("deprecation")
diff --git a/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactoryCJ.java b/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactoryCJ.java
index e378ccb41..4749e81ef 100644
--- a/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactoryCJ.java
+++ b/junixsocket-mysql/src/main/java/org/newsclub/net/mysql/AFUNIXDatabaseSocketFactoryCJ.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
*/
package org.newsclub.net.mysql;
-import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
@@ -38,7 +37,6 @@
*/
public class AFUNIXDatabaseSocketFactoryCJ implements SocketFactory {
private AFUNIXSocket rawSocket;
- private Socket sslSocket;
/**
* Creates a new instance.
@@ -46,11 +44,11 @@ public class AFUNIXDatabaseSocketFactoryCJ implements SocketFactory {
public AFUNIXDatabaseSocketFactoryCJ() {
}
- @SuppressWarnings({"unchecked", "exports"})
+ @SuppressWarnings({"unchecked"})
@SuppressFBWarnings("EI_EXPOSE_REP")
@Override
- public T connect(String hostname, int portNumber, PropertySet props,
- int loginTimeout) throws IOException {
+ public Socket connect(String hostname, int portNumber, PropertySet props, int loginTimeout)
+ throws IOException {
// Adjust the path to your MySQL socket by setting the
// "junixsocket.file" property
// If no socket path is given, use the default: /tmp/mysql.sock
@@ -64,17 +62,15 @@ public T connect(String hostname, int portNumber, Property
final File socketFile = new File(sock);
this.rawSocket = AFUNIXSocket.connectTo(AFUNIXSocketAddress.of(socketFile));
- this.sslSocket = rawSocket;
- return (T) rawSocket;
+ return rawSocket;
}
- @SuppressWarnings({"unchecked", "exports"})
+ @SuppressWarnings({"unchecked"})
@SuppressFBWarnings("EI_EXPOSE_REP")
@Override
- public T performTlsHandshake(SocketConnection socketConnection,
- ServerSession serverSession) throws IOException {
- this.sslSocket = ExportControlled.performTlsHandshake(this.rawSocket, socketConnection,
+ public Socket performTlsHandshake(SocketConnection socketConnection, ServerSession serverSession)
+ throws IOException {
+ return ExportControlled.performTlsHandshake(this.rawSocket, socketConnection,
serverSession == null ? null : serverSession.getServerVersion(), null);
- return (T) this.sslSocket;
}
}
diff --git a/junixsocket-native-android/META-INF/MANIFEST.MF b/junixsocket-native-android/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..4b797f9d8
--- /dev/null
+++ b/junixsocket-native-android/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Created-By: Maven JAR Plugin 3.3.0
+Build-Jdk-Spec: 20
+Multi-Release: true
+
diff --git a/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/git.properties b/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/git.properties
new file mode 100644
index 000000000..c7e13a5b3
--- /dev/null
+++ b/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/git.properties
@@ -0,0 +1,7 @@
+#Generated by Git-Commit-Id-Plugin
+git.build.version=2.7.0-SNAPSHOT
+git.commit.id.abbrev=edf13c8
+git.commit.id.describe=junixsocket-2.6.2-46-gedf13c8-dirty
+git.commit.id.full=edf13c8c86092b6094ad7443c5a8cee2bec9aa96
+git.commit.time=2023-06-17T17\:30\:21+02\:00
+git.dirty=true
diff --git a/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/pom.properties b/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/pom.properties
new file mode 100644
index 000000000..4d210ef64
--- /dev/null
+++ b/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/pom.properties
@@ -0,0 +1,3 @@
+artifactId=junixsocket-native-android
+groupId=com.kohlschutter.junixsocket
+version=2.7.0-SNAPSHOT
diff --git a/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/pom.xml b/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/pom.xml
new file mode 100644
index 000000000..5bd5a6112
--- /dev/null
+++ b/junixsocket-native-android/META-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-android/pom.xml
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+ junixsocket-native-android
+
+ jar
+
+
+ com.kohlschutter.junixsocket
+ junixsocket
+ 2.7.0-SNAPSHOT
+ ../pom.xml
+
+ junixsocket-native-android
+
+ ${project.parent.basedir}
+ aar
+
+
+ Native junixsocket libraries for Android
+
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-common
+ ${project.version}
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-native
+ ${project.version}
+ aarch64-Android-clang-llvm-jni
+ nar
+
+
+
+
+
+ release
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ build-aar
+ package
+
+ jar
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ true
+
+
+
+
+
diff --git a/junixsocket-native-android/pom.xml b/junixsocket-native-android/pom.xml
new file mode 100644
index 000000000..4dc2c8bc7
--- /dev/null
+++ b/junixsocket-native-android/pom.xml
@@ -0,0 +1,164 @@
+
+
+ 4.0.0
+ junixsocket-native-android
+
+ pom
+
+
+ com.kohlschutter.junixsocket
+ junixsocket
+ 2.8.2
+ ../pom.xml
+
+ junixsocket-native-android
+
+ ${project.parent.basedir}
+ ${project.name}-${project.version}.aar
+
+
+ Native junixsocket libraries for Android
+
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-common
+ ${project.version}
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-native
+ ${project.version}
+ aarch64-Android-clang-llvm-jni
+ nar
+ provided
+ true
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-native
+ ${project.version}
+ x86_64-Android-clang-llvm-jni
+ nar
+ provided
+ true
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-native
+ ${project.version}
+ i686-Android-clang-llvm-jni
+ nar
+ provided
+ true
+
+
+ com.kohlschutter.junixsocket
+ junixsocket-native
+ ${project.version}
+ arm-Android-clang-llvm-jni
+ nar
+ provided
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ multirelease-jar
+ none
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ unpack-nars
+ package
+
+ unpack-dependencies
+
+
+ **/lib*.so
+ nar
+ ${project.build.directory}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ build-aar
+ package
+
+ single
+
+
+
+ src/assembly/aar.xml
+
+ ${aarFinalName}
+ false
+ false
+
+
+
+
+
+ com.kohlschutter.mavenplugins
+ copy-rename-maven-plugin
+
+
+ rename-zip-to-aar
+ package
+
+ rename
+
+
+
+ ${project.build.directory}/${aarFinalName}.zip
+
+ ${project.build.directory}/${aarFinalName}
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-aar
+ package
+
+ attach-artifact
+
+
+
+
+
+ ${project.build.directory}/${aarFinalName}
+
+ aar
+
+
+
+
+
+
+
+
+
diff --git a/junixsocket-native-android/src/aar/AndroidManifest.xml b/junixsocket-native-android/src/aar/AndroidManifest.xml
new file mode 100644
index 000000000..0d7dd678f
--- /dev/null
+++ b/junixsocket-native-android/src/aar/AndroidManifest.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/junixsocket-native-android/src/aar/R.txt b/junixsocket-native-android/src/aar/R.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/junixsocket-native-android/src/aar/classes.jar b/junixsocket-native-android/src/aar/classes.jar
new file mode 100644
index 000000000..84e5ed105
Binary files /dev/null and b/junixsocket-native-android/src/aar/classes.jar differ
diff --git a/junixsocket-native-android/src/assembly/aar.xml b/junixsocket-native-android/src/assembly/aar.xml
new file mode 100644
index 000000000..1b9cc6a28
--- /dev/null
+++ b/junixsocket-native-android/src/assembly/aar.xml
@@ -0,0 +1,51 @@
+
+ aar
+
+
+ zip
+
+
+ false
+ false
+
+
+
+ ${project.basedir}/src/aar
+
+
+ *
+
+
+
+ res
+
+ **/*
+
+
+
+
+
+
+ ${project.build.directory}/lib/aarch64-Android-clang/jni/libjunixsocket-native-${project.version}.so
+ jni/arm64-v8a
+ libjunixsocket-native.so
+
+
+ ${project.build.directory}/lib/x86_64-Android-clang/jni/libjunixsocket-native-${project.version}.so
+ jni/x86_64
+ libjunixsocket-native.so
+
+
+ ${project.build.directory}/lib/i686-Android-clang/jni/libjunixsocket-native-${project.version}.so
+ jni/x86
+ libjunixsocket-native.so
+
+
+ ${project.build.directory}/lib/arm-Android-clang/jni/libjunixsocket-native-${project.version}.so
+ jni/armeabi-v7a
+ libjunixsocket-native.so
+
+
+
diff --git a/junixsocket-native-common/pom.xml b/junixsocket-native-common/pom.xml
index 49bf4aaaf..69be02b85 100644
--- a/junixsocket-native-common/pom.xml
+++ b/junixsocket-native-common/pom.xml
@@ -7,7 +7,7 @@
com.kohlschutter.junixsocket
junixsocket
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-native-common
@@ -103,8 +103,7 @@
release
- cross
- true
+ release
@@ -164,6 +163,17 @@
runtime
true
+
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-native-cross
@@ -31,6 +31,11 @@
release
+
+
+ release
+
+
false
true
@@ -106,6 +111,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -132,6 +138,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -165,6 +172,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -198,6 +206,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -231,6 +240,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -264,6 +274,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -297,6 +308,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -330,6 +342,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -363,6 +376,143 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
+
+
+
+
+ crosscompile-aarch64-Android-clang
+
+ run
+
+
+ ${junixsocket.cross.disabled}
+ true
+ true
+
+ clean
+ install
+
+ ${project.basedir}/../
+
+ junixsocket-native
+
+
+ llvm
+
+
+ aarch64-Android-clang
+ true
+ ${project.build.directory}/junixsocket-native-aarch64-Android-clang-llvm
+ aarch64-linux-android30
+ so
+ aarch64-Android-clang-llvm-jni
+ ${ignorant}
+ ${gpgkeyname}
+ ${gpg.executable}
+ ${retrolambda}
+
+
+
+
+ crosscompile-x86_64-Android-clang
+
+ run
+
+
+ ${junixsocket.cross.disabled}
+ true
+ true
+
+ clean
+ install
+
+ ${project.basedir}/../
+
+ junixsocket-native
+
+
+ llvm
+
+
+ x86_64-Android-clang
+ true
+ ${project.build.directory}/junixsocket-native-x86_64-Android-clang-llvm
+ x86_64-linux-android30
+ so
+ x86_64-Android-clang-llvm-jni
+ ${ignorant}
+ ${gpgkeyname}
+ ${gpg.executable}
+ ${retrolambda}
+
+
+
+
+ crosscompile-i686-Android-clang
+
+ run
+
+
+ ${junixsocket.cross.disabled}
+ true
+ true
+
+ clean
+ install
+
+ ${project.basedir}/../
+
+ junixsocket-native
+
+
+ llvm
+
+
+ i686-Android-clang
+ true
+ ${project.build.directory}/junixsocket-native-i686-Android-clang-llvm
+ i686-linux-android30
+ so
+ i686-Android-clang-llvm-jni
+ ${ignorant}
+ ${gpgkeyname}
+ ${gpg.executable}
+ ${retrolambda}
+
+
+
+
+ crosscompile-arm-Android-clang
+
+ run
+
+
+ ${junixsocket.cross.disabled}
+ true
+ true
+
+ clean
+ install
+
+ ${project.basedir}/../
+
+ junixsocket-native
+
+
+ llvm
+
+
+ arm-Android-clang
+ true
+ ${project.build.directory}/junixsocket-native-arm-Android-clang-llvm
+ arm-linux-androideabi30
+ so
+ arm-Android-clang-llvm-jni
+ ${ignorant}
+ ${gpgkeyname}
+ ${gpg.executable}
+ ${retrolambda}
@@ -397,6 +547,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -431,6 +582,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -464,6 +616,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -497,6 +650,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -530,6 +684,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -563,6 +718,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -597,6 +753,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -630,6 +787,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -662,6 +820,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -694,6 +853,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -726,6 +886,7 @@
${ignorant}
${gpgkeyname}
${gpg.executable}
+ ${retrolambda}
@@ -847,6 +1008,70 @@
false
+
+ install-aarch64-Android-clang
+ ${junixsocket.cross.install-phase}
+
+ install-file
+
+
+ ${project.build.directory}/junixsocket-native-aarch64-Android-clang-llvm/junixsocket-native-${project.version}-aarch64-Android-clang-jni.nar
+ ${project.groupId}
+ junixsocket-native
+ ${project.version}
+ nar
+ aarch64-Android-clang-llvm-jni
+ false
+
+
+
+ install-x86_64-Android-clang
+ ${junixsocket.cross.install-phase}
+
+ install-file
+
+
+ ${project.build.directory}/junixsocket-native-x86_64-Android-clang-llvm/junixsocket-native-${project.version}-x86_64-Android-clang-jni.nar
+ ${project.groupId}
+ junixsocket-native
+ ${project.version}
+ nar
+ x86_64-Android-clang-llvm-jni
+ false
+
+
+
+ install-i686-Android-clang
+ ${junixsocket.cross.install-phase}
+
+ install-file
+
+
+ ${project.build.directory}/junixsocket-native-i686-Android-clang-llvm/junixsocket-native-${project.version}-i686-Android-clang-jni.nar
+ ${project.groupId}
+ junixsocket-native
+ ${project.version}
+ nar
+ i686-Android-clang-llvm-jni
+ false
+
+
+
+ install-arm-Android-clang
+ ${junixsocket.cross.install-phase}
+
+ install-file
+
+
+ ${project.build.directory}/junixsocket-native-arm-Android-clang-llvm/junixsocket-native-${project.version}-arm-Android-clang-jni.nar
+ ${project.groupId}
+ junixsocket-native
+ ${project.version}
+ nar
+ arm-Android-clang-llvm-jni
+ false
+
+
- 2.6.1
+ 2.8.2
../pom.xml
junixsocket-native-custom
diff --git a/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/NarMetadata.java b/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/NarMetadata.java
index 4613c7e5a..90c999be0 100644
--- a/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/NarMetadata.java
+++ b/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/NarMetadata.java
@@ -1,7 +1,7 @@
/*
* junixsocket
*
- * Copyright 2009-2022 Christian Kohlschütter
+ * Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,11 +21,11 @@
/**
* Marker class to find native libraries in the classpath.
- *
+ *
* @author Christian Kohlschütter
*/
public final class NarMetadata {
- @ExcludeFromCodeCoverageGeneratedReport
+ @ExcludeFromCodeCoverageGeneratedReport(reason = "unreachable")
private NarMetadata() {
throw new IllegalStateException("No instances");
}
diff --git a/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/package-info.java b/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/package-info.java
index 068069722..6d0528155 100644
--- a/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/package-info.java
+++ b/junixsocket-native-custom/src/main/java/org/newsclub/lib/junixsocket/custom/package-info.java
@@ -1,11 +1,11 @@
/**
* Helper package to identify the Maven artifact with JNI libraries for specific architectures.
- *
+ *
* There are multiple artifacts with the same identifier (junixsocket-native), one per architecture.
- *
+ *
* If you want to run junixsocket on your architecture, you need to make sure that the correct one
* is in the classpath.
- *
+ *
* See "junixsocket-native-common" for an artifact containing the commonly used architectures.
*/
package org.newsclub.lib.junixsocket.custom;
diff --git a/junixsocket-native-custom/src/main/java7/multirelease.md b/junixsocket-native-custom/src/main/java7/multirelease.md
new file mode 100644
index 000000000..713e9e182
--- /dev/null
+++ b/junixsocket-native-custom/src/main/java7/multirelease.md
@@ -0,0 +1,3 @@
+This repository is kept compatible with Java 7.
+
+Do not remove this file, it is used as a marker by the Maven build scripts.
diff --git a/junixsocket-native-custom/src/main/resources/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-custom/reflect-config.json b/junixsocket-native-custom/src/main/resources/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-custom/reflect-config.json
new file mode 100644
index 000000000..3ca368701
--- /dev/null
+++ b/junixsocket-native-custom/src/main/resources/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-custom/reflect-config.json
@@ -0,0 +1,5 @@
+[
+{
+ "name":"org.newsclub.lib.junixsocket.custom.NarMetadata"
+}
+]
diff --git a/junixsocket-native-custom/src/main/resources/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-custom/resource-config.json b/junixsocket-native-custom/src/main/resources/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-custom/resource-config.json
new file mode 100644
index 000000000..6ea5af423
--- /dev/null
+++ b/junixsocket-native-custom/src/main/resources/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-custom/resource-config.json
@@ -0,0 +1,9 @@
+{
+ "resources":{
+ "includes":[
+ {
+ "pattern":"\\QMETA-INF/maven/com.kohlschutter.junixsocket/junixsocket-native-custom/pom.properties\\E"
+ }
+ ]},
+ "bundles":[]
+}
\ No newline at end of file
diff --git a/junixsocket-native-graalvm/bin/build-selftest b/junixsocket-native-graalvm/bin/build-selftest
index 396095776..372a8af8e 100755
--- a/junixsocket-native-graalvm/bin/build-selftest
+++ b/junixsocket-native-graalvm/bin/build-selftest
@@ -8,6 +8,8 @@
#
cd "$(dirname $0)/../"
+[[ -n "$GRAALVM_HOME" ]] && export PATH="$GRAALVM_HOME"/bin:$PATH
+
java -version 2>&1 | grep -q GraalVM
if [[ $? -ne 0 ]]; then
echo Error: JVM is not a GraalVM. >&2
@@ -74,7 +76,7 @@ echo jar: $jar
echo
echo Running junixsocket-selftest with GraalVM native-image-agent...
-( set -x ; java -agentlib:native-image-agent=config-output-dir=${tmpDir}/native-image.{pid} -Dselftest.skip.junixsocket-rmi=force -jar "$jar" >/dev/null )
+( set -x ; java -agentlib:native-image-agent=config-output-dir=${tmpDir}/native-image.{pid} -jar "$jar" >/dev/null )
if [[ $? -ne 0 ]]; then
echo "Error: junixsocket-selftest failed" >&2
diff --git a/junixsocket-native-graalvm/bin/graalvm b/junixsocket-native-graalvm/bin/graalvm
deleted file mode 100755
index d06e042bd..000000000
--- a/junixsocket-native-graalvm/bin/graalvm
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-java -version 2>&1 | grep -q GraalVM
-if [[ $? -eq 0 ]]; then
- exec $@
-fi
-
-# FIXME auto-detect
-export JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-ce-java17-22.2.0/Contents/Home
-export PATH=$JAVA_HOME/bin:$PATH
-exec $@
diff --git a/junixsocket-native-graalvm/bin/with-graalvm b/junixsocket-native-graalvm/bin/with-graalvm
new file mode 100755
index 000000000..4f5389a26
--- /dev/null
+++ b/junixsocket-native-graalvm/bin/with-graalvm
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+#
+# junixsocket
+# Copyright 2009-2022 Christian Kohlschütter
+# SPDX-License-Identifier: Apache-2.0
+#
+# Script to detect and enable GraalVM.
+#
+# When run without arguments, an eval-able string like "GRAALVM_HOME=/path/to/graalvm" is emitted.
+# Otherwise, the arguments are executed with the determined GraalVM in path (GRAALVM_HOME, JAVA_HOME and PATH set accordingly).
+#
+java -version 2>&1 | grep -q GraalVM
+if [[ $? -eq 0 ]]; then
+ exec $@
+fi
+
+if [[ -z "$GRAALVM_HOME" ]]; then
+ for d in $(find /Library/Java/JavaVirtualMachines /usr/lib/jvm -maxdepth 1 -type d -name "*graalvm*" 2>/dev/null | sort -r); do
+ if [[ -e "$d/bin/java" ]]; then
+ export GRAALVM_HOME="$d"
+ break
+ elif [[ -e "$d/Contents/Home/bin/java" ]]; then
+ export GRAALVM_HOME="$d/Contents/Home"
+ break
+ fi
+ done
+fi
+
+if [[ -z "$GRAALVM_HOME" ]]; then
+ echo "Error: Could not determine GRAALVM_HOME -- Please set manually" >&2
+ exit 1
+else
+ if [[ $# -eq 0 ]]; then
+ echo "GRAALVM_HOME=$GRAALVM_HOME"
+ fi
+fi
+
+export JAVA_HOME="$GRAALVM_HOME"
+export PATH=$JAVA_HOME/bin:$PATH
+exec -- $@
diff --git a/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/jni-config.json b/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/jni-config.json
index 50078f6a3..f34a2d534 100644
--- a/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/jni-config.json
+++ b/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/jni-config.json
@@ -8,6 +8,10 @@
"name":"java.lang.Boolean",
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
},
+{
+ "name":"java.lang.Class",
+ "methods":[{"name":"getName","parameterTypes":[] }]
+},
{
"name":"java.lang.IllegalStateException",
"methods":[{"name":"","parameterTypes":["java.lang.String"] }]
@@ -18,15 +22,16 @@
},
{
"name":"java.lang.Integer",
- "methods":[
- {"name":"","parameterTypes":["int"] },
- {"name":"intValue","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":["int"] }, {"name":"intValue","parameterTypes":[] }]
},
{
"name":"java.lang.NullPointerException",
"methods":[{"name":"","parameterTypes":["java.lang.String"] }]
},
+{
+ "name":"java.lang.Object",
+ "methods":[{"name":"getClass","parameterTypes":[] }]
+},
{
"name":"java.lang.ProcessBuilder$RedirectPipeImpl",
"fields":[{"name":"fd"}],
@@ -34,24 +39,23 @@
},
{
"name":"java.lang.String",
- "methods":[
- {"name":"lastIndexOf","parameterTypes":["int"] },
- {"name":"substring","parameterTypes":["int"] }
- ]
+ "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }]
},
{
"name":"java.lang.System",
- "methods":[
- {"name":"getProperty","parameterTypes":["java.lang.String"] },
- {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }
- ]
+ "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }]
+},
+{
+ "name":"java.lang.ThreadLocal",
+ "methods":[{"name":"get","parameterTypes":[] }]
},
{
"name":"java.net.DatagramSocket"
},
{
"name":"java.net.InetSocketAddress",
- "fields":[{"name":"holder"}]
+ "fields":[{"name":"holder"}],
+ "methods":[{"name":"","parameterTypes":["int"] }]
},
{
"name":"java.net.InetSocketAddress$InetSocketAddressHolder",
@@ -86,14 +90,7 @@
},
{
"name":"org.newsclub.net.unix.AFSelector$PollFd",
- "fields":[
- {"name":"fds"},
- {"name":"ops"},
- {"name":"rops"}
- ]
-},
-{
- "name":"org.newsclub.net.unix.AFTIPCSocketAddress"
+ "fields":[{"name":"fds"}, {"name":"ops"}, {"name":"rops"}]
},
{
"name":"org.newsclub.net.unix.AFUNIXDatagramSocket"
@@ -109,11 +106,7 @@
},
{
"name":"org.newsclub.net.unix.AFUNIXSocketCredentials",
- "fields":[
- {"name":"gids"},
- {"name":"pid"},
- {"name":"uid"}
- ],
+ "fields":[{"name":"gids"}, {"name":"pid"}, {"name":"uid"}],
"methods":[{"name":"setUUID","parameterTypes":["java.lang.String"] }]
},
{
@@ -122,20 +115,17 @@
},
{
"name":"org.newsclub.net.unix.AncillaryDataSupport",
- "fields":[
- {"name":"ancillaryReceiveBuffer"},
- {"name":"pendingFileDescriptors"}
- ],
- "methods":[
- {"name":"receiveFileDescriptors","parameterTypes":["int[]"] },
- {"name":"setTipcDestName","parameterTypes":["int","int","int"] },
- {"name":"setTipcErrorInfo","parameterTypes":["int","int"] }
- ]
+ "fields":[{"name":"ancillaryReceiveBuffer"}, {"name":"pendingFileDescriptors"}],
+ "methods":[{"name":"receiveFileDescriptors","parameterTypes":["int[]"] }, {"name":"setTipcDestName","parameterTypes":["int","int","int"] }, {"name":"setTipcErrorInfo","parameterTypes":["int","int"] }]
},
{
"name":"org.newsclub.net.unix.InvalidArgumentSocketException",
"methods":[{"name":"","parameterTypes":["java.lang.String"] }]
},
+{
+ "name":"org.newsclub.net.unix.NoSuchDeviceSocketException",
+ "methods":[{"name":"","parameterTypes":["java.lang.String"] }]
+},
{
"name":"org.newsclub.net.unix.OperationNotSupportedSocketException",
"methods":[{"name":"","parameterTypes":["java.lang.String"] }]
@@ -144,24 +134,32 @@
"name":"org.newsclub.net.unix.StdinSocketApp",
"methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }]
},
+{
+ "name":"org.newsclub.net.unix.darwin.system.AFSYSTEMDatagramSocket"
+},
+{
+ "name":"org.newsclub.net.unix.darwin.system.AFSYSTEMSocket"
+},
{
"name":"org.newsclub.net.unix.selftest.Selftest",
"methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }]
},
{
"name":"org.newsclub.net.unix.tipc.AFTIPCGroupRequest",
- "methods":[
- {"name":"fromNative","parameterTypes":["int","int","int","int"] },
- {"name":"getFlagsValue","parameterTypes":[] },
- {"name":"getInstance","parameterTypes":[] },
- {"name":"getScopeId","parameterTypes":[] },
- {"name":"getType","parameterTypes":[] }
- ]
+ "methods":[{"name":"fromNative","parameterTypes":["int","int","int","int"] }, {"name":"getFlagsValue","parameterTypes":[] }, {"name":"getInstance","parameterTypes":[] }, {"name":"getScopeId","parameterTypes":[] }, {"name":"getType","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.vsock.AFVSOCKDatagramSocket"
},
{
"name":"org.newsclub.net.unix.vsock.AFVSOCKSocket"
+},
+{
+ "name":"sun.rmi.transport.tcp.TCPTransport",
+ "fields":[{"name":"threadConnectionHandler"}]
+},
+{
+ "name":"sun.rmi.transport.tcp.TCPTransport$ConnectionHandler",
+ "fields":[{"name":"socket"}]
}
]
\ No newline at end of file
diff --git a/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/proxy-config.json b/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/proxy-config.json
index 32960f8ce..4941ba893 100644
--- a/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/proxy-config.json
+++ b/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/proxy-config.json
@@ -1,2 +1,17 @@
[
+ {
+ "interfaces":["org.newsclub.net.unix.rmi.AFRMIService"]
+ },
+ {
+ "interfaces":["org.newsclub.net.unix.rmi.Hello"]
+ },
+ {
+ "interfaces":["org.newsclub.net.unix.rmi.NaiveFileInputStreamRemote"]
+ },
+ {
+ "interfaces":["org.newsclub.net.unix.rmi.RemoteCloseable"]
+ },
+ {
+ "interfaces":["org.newsclub.net.unix.rmi.TestService"]
+ }
]
\ No newline at end of file
diff --git a/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/reflect-config.json b/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/reflect-config.json
index a0f66c8c9..c4af29bf7 100644
--- a/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/reflect-config.json
+++ b/junixsocket-native-graalvm/output/META-INF/native-image/com.kohlschutter.junixsocket/junixsocket-native-graalvm/reflect-config.json
@@ -1,4 +1,42 @@
[
+{
+ "name":"[B"
+},
+{
+ "name":"[J"
+},
+{
+ "name":"[Ljava.lang.StackTraceElement;"
+},
+{
+ "name":"[Ljava.lang.String;"
+},
+{
+ "name":"[Ljava.rmi.server.ObjID;"
+},
+{
+ "name":"[Lsun.security.pkcs.SignerInfo;"
+},
+{
+ "name":"apple.security.AppleProvider",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.kohlschutter.testutil.AvailabilityExecutionCondition",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.kohlschutter.testutil.AvailabilityRequirement",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"com.kohlschutter.testutil.ExecutionEnvironmentExecutionCondition",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.kohlschutter.testutil.ExecutionEnvironmentRequirement",
+ "queryAllPublicMethods":true
+},
{
"name":"com.kohlschutter.testutil.ProcessUtilCondition",
"methods":[{"name":"","parameterTypes":[] }]
@@ -7,19 +45,221 @@
"name":"com.kohlschutter.testutil.ProcessUtilRequirement",
"queryAllPublicMethods":true
},
+{
+ "name":"com.sun.crypto.provider.AESCipher$General",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.AESKeyGenerator",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.ARCFOURCipher",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.DESCipher",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.DESedeCipher",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.DHParameters",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.HmacCore$HmacSHA256",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.HmacCore$HmacSHA384",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA256",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndDES",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_256",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.PBES2Parameters$General",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.sun.crypto.provider.TlsMasterSecretGenerator",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"com.wolfssl.provider.jce.WolfCryptProvider"
+},
+{
+ "name":"com.wolfssl.provider.jsse.WolfSSLProvider"
+},
+{
+ "name":"iaik.security.jsse.provider.IAIKJSSEProvider"
+},
+{
+ "name":"iaik.security.provider.IAIK"
+},
+{
+ "name":"java.io.IOException"
+},
+{
+ "name":"java.lang.Exception"
+},
+{
+ "name":"java.lang.Number"
+},
{
"name":"java.lang.ProcessBuilder$RedirectPipeImpl"
},
+{
+ "name":"java.lang.String"
+},
+{
+ "name":"java.lang.Thread",
+ "fields":[{"name":"threadLocalRandomProbe"}]
+},
+{
+ "name":"java.lang.Throwable"
+},
+{
+ "name":"java.lang.reflect.Proxy"
+},
+{
+ "name":"java.net.InetSocketAddress"
+},
+{
+ "name":"java.net.UnixDomainSocketAddress"
+},
{
"name":"java.nio.channels.spi.AbstractSelectableChannel"
},
+{
+ "name":"java.rmi.NoSuchObjectException"
+},
+{
+ "name":"java.rmi.Remote",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"java.rmi.RemoteException"
+},
+{
+ "name":"java.rmi.dgc.Lease"
+},
+{
+ "name":"java.rmi.dgc.VMID"
+},
+{
+ "name":"java.rmi.registry.Registry",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"java.rmi.server.ObjID"
+},
+{
+ "name":"java.rmi.server.RemoteObject"
+},
+{
+ "name":"java.rmi.server.RemoteObjectInvocationHandler"
+},
+{
+ "name":"java.rmi.server.UID"
+},
+{
+ "name":"java.security.AlgorithmParametersSpi"
+},
+{
+ "name":"java.security.KeyStoreSpi"
+},
{
"name":"java.security.SecureRandomParameters"
},
+{
+ "name":"java.security.cert.CertStoreParameters"
+},
+{
+ "name":"java.security.interfaces.RSAPrivateKey"
+},
+{
+ "name":"java.security.interfaces.RSAPublicKey"
+},
+{
+ "name":"java.util.Collections$EmptyList"
+},
+{
+ "name":"java.util.Date"
+},
+{
+ "name":"java.util.UUID"
+},
+{
+ "name":"java.util.concurrent.ForkJoinTask",
+ "fields":[{"name":"aux"}, {"name":"status"}]
+},
+{
+ "name":"java.util.concurrent.atomic.AtomicBoolean",
+ "fields":[{"name":"value"}]
+},
+{
+ "name":"java.util.concurrent.atomic.AtomicInteger"
+},
+{
+ "name":"java.util.concurrent.atomic.AtomicReference",
+ "fields":[{"name":"value"}]
+},
+{
+ "name":"java.util.concurrent.atomic.Striped64",
+ "fields":[{"name":"base"}, {"name":"cellsBusy"}]
+},
+{
+ "name":"java.util.function.Consumer",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"javax.security.auth.x500.X500Principal",
+ "fields":[{"name":"thisX500Name"}],
+ "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }]
+},
+{
+ "name":"jdk.internal.misc.Unsafe"
+},
{
"name":"org.apiguardian.api.API",
"queryAllPublicMethods":true
},
+{
+ "name":"org.bouncycastle.jce.provider.BouncyCastleProvider"
+},
+{
+ "name":"org.bouncycastle.jsse.provider.BouncyCastleJsseProvider"
+},
+{
+ "name":"org.bouncycastle.tls.TlsException"
+},
+{
+ "name":"org.conscrypt.Conscrypt"
+},
+{
+ "name":"org.junit.internal.AssumptionViolatedException"
+},
{
"name":"org.junit.jupiter.api.MethodOrderer$MethodName",
"methods":[{"name":"","parameterTypes":[] }]
@@ -32,6 +272,10 @@
"name":"org.junit.jupiter.api.TestMethodOrder",
"queryAllPublicMethods":true
},
+{
+ "name":"org.junit.jupiter.api.TestTemplate",
+ "queryAllPublicMethods":true
+},
{
"name":"org.junit.jupiter.api.Timeout",
"queryAllPublicMethods":true
@@ -44,6 +288,41 @@
"name":"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource",
"methods":[{"name":"","parameterTypes":[] }]
},
+{
+ "name":"org.junit.jupiter.params.ParameterizedTest",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.junit.jupiter.params.ParameterizedTestExtension",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider",
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.junit.jupiter.params.provider.ArgumentsProvider",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.junit.jupiter.params.provider.ArgumentsSource",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.junit.jupiter.params.provider.EnumArgumentsProvider",
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"org.junit.jupiter.params.provider.EnumSource",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.junit.jupiter.params.support.AnnotationConsumer",
+ "queryAllPublicMethods":true
+},
{
"name":"org.junit.platform.commons.annotation.Testable",
"queryAllPublicMethods":true
@@ -54,6 +333,10 @@
{
"name":"org.newsclub.lib.junixsocket.custom.NarMetadata"
},
+{
+ "name":"org.newsclub.net.unix.AFSYSTEMSocketAddress",
+ "methods":[{"name":"addressFamily","parameterTypes":[] }]
+},
{
"name":"org.newsclub.net.unix.AFSocketCapabilityCondition",
"methods":[{"name":"","parameterTypes":[] }]
@@ -73,16 +356,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testGeneric","parameterTypes":[] },
- {"name":"testParseFail","parameterTypes":[] },
- {"name":"testSchemesAvailable","parameterTypes":[] },
- {"name":"testServiceRangeURI","parameterTypes":[] },
- {"name":"testServiceURI","parameterTypes":[] },
- {"name":"testSocatString","parameterTypes":[] },
- {"name":"testSocketURI","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testGeneric","parameterTypes":[] }, {"name":"testParseFail","parameterTypes":[] }, {"name":"testSchemesAvailable","parameterTypes":[] }, {"name":"testServiceRangeURI","parameterTypes":[] }, {"name":"testServiceURI","parameterTypes":[] }, {"name":"testSocatString","parameterTypes":[] }, {"name":"testSocketURI","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.AFUNIXSocketAddress",
@@ -95,18 +369,10 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testAbstractNamespace","parameterTypes":[] },
- {"name":"testFileScheme","parameterTypes":[] },
- {"name":"testHttpUnix","parameterTypes":[] },
- {"name":"testParseURIandBack","parameterTypes":[] },
- {"name":"testSchemesAvailable","parameterTypes":[] },
- {"name":"testSocatString","parameterTypes":[] },
- {"name":"testURITemplate","parameterTypes":[] },
- {"name":"testURITemplateWithPortNumber","parameterTypes":[] },
- {"name":"testUnixScheme","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testAbstractNamespace","parameterTypes":[] }, {"name":"testCraftDeserialization","parameterTypes":[] }, {"name":"testFileScheme","parameterTypes":[] }, {"name":"testHttpUnix","parameterTypes":[] }, {"name":"testParseURIandBack","parameterTypes":[] }, {"name":"testSchemesAvailable","parameterTypes":[] }, {"name":"testSerialize","parameterTypes":[] }, {"name":"testSocatString","parameterTypes":[] }, {"name":"testURITemplate","parameterTypes":[] }, {"name":"testURITemplateWithPortNumber","parameterTypes":[] }, {"name":"testUnixScheme","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.AFUNIXSocketCredentials"
},
{
"name":"org.newsclub.net.unix.AFVSOCKSocketAddress",
@@ -118,11 +384,10 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testAcceptWithoutBindToService","parameterTypes":[] },
- {"name":"testCatchTimeout","parameterTypes":[] },
- {"name":"testTimeoutAfterDelay","parameterTypes":[] }
- ]
+ "methods":[{"name":"testAcceptWithoutBindToService","parameterTypes":[] }, {"name":"testCatchTimeout","parameterTypes":[] }, {"name":"testTimeoutAfterDelay","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.AddressUnavailableSocketException"
},
{
"name":"org.newsclub.net.unix.AncillaryMessageTest",
@@ -137,10 +402,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testAvailableAtClient","parameterTypes":[] },
- {"name":"testAvailableAtServer","parameterTypes":[] }
- ]
+ "methods":[{"name":"testAvailableAtClient","parameterTypes":[] }, {"name":"testAvailableAtServer","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.BufferOverflowTest",
@@ -148,13 +410,16 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"readOutOfBounds","parameterTypes":[] },
- {"name":"readUpTo","parameterTypes":[] },
- {"name":"setUp","parameterTypes":[] },
- {"name":"tearDown","parameterTypes":[] },
- {"name":"writeOverflow","parameterTypes":[] }
- ]
+ "methods":[{"name":"readOutOfBounds","parameterTypes":[] }, {"name":"readUpTo","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }, {"name":"writeOverflow","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.BuildPropertiesTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testHasProperties","parameterTypes":[] }, {"name":"testNotEmpty","parameterTypes":[] }, {"name":"testResolved","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.CancelAcceptTest",
@@ -170,11 +435,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testBindConnect","parameterTypes":[] },
- {"name":"testPeekTimeout","parameterTypes":[] },
- {"name":"testReadTimeout","parameterTypes":[] }
- ]
+ "methods":[{"name":"testBindConnect","parameterTypes":[] }, {"name":"testChannelSendTo","parameterTypes":[] }, {"name":"testPeekTimeout","parameterTypes":[] }, {"name":"testReadTimeout","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.EndOfFileTest",
@@ -182,17 +443,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"bidirectionalSanity","parameterTypes":[] },
- {"name":"clientReadEof","parameterTypes":[] },
- {"name":"clientWriteToSocketClosedByClient","parameterTypes":[] },
- {"name":"clientWriteToSocketClosedByServer","parameterTypes":[] },
- {"name":"serverReadEof","parameterTypes":[] },
- {"name":"serverWriteToSocketClosedByClient","parameterTypes":[] },
- {"name":"serverWriteToSocketClosedByServer","parameterTypes":[] },
- {"name":"setUp","parameterTypes":[] },
- {"name":"tearDown","parameterTypes":[] }
- ]
+ "methods":[{"name":"bidirectionalSanity","parameterTypes":[] }, {"name":"clientReadEof","parameterTypes":[] }, {"name":"clientWriteToSocketClosedByClient","parameterTypes":[] }, {"name":"clientWriteToSocketClosedByServer","parameterTypes":[] }, {"name":"serverReadEof","parameterTypes":[] }, {"name":"serverWriteToSocketClosedByClient","parameterTypes":[] }, {"name":"serverWriteToSocketClosedByServer","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.FileDescriptorCastTest",
@@ -201,14 +452,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testAvailableTypes","parameterTypes":[] },
- {"name":"testInvalidFileDescriptor","parameterTypes":[] },
- {"name":"testPipe","parameterTypes":[] },
- {"name":"testRandomAccessFile","parameterTypes":[] },
- {"name":"testStdout","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testAvailableTypes","parameterTypes":[] }, {"name":"testCastAsInteger","parameterTypes":[] }, {"name":"testInvalidFileDescriptor","parameterTypes":[] }, {"name":"testPipe","parameterTypes":[] }, {"name":"testRandomAccessFile","parameterTypes":[] }, {"name":"testStdout","parameterTypes":[] }, {"name":"testUnsafeCast","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.InetAddressTest",
@@ -217,13 +461,16 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testFromToBytes","parameterTypes":[] },
- {"name":"testHostnameString","parameterTypes":[] },
- {"name":"testHostnameStringEndsWithJunixSocket","parameterTypes":[] },
- {"name":"testIsLoopbackAddress","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testFromToBytes","parameterTypes":[] }, {"name":"testHostnameString","parameterTypes":[] }, {"name":"testHostnameStringEndsWithJunixSocket","parameterTypes":[] }, {"name":"testIsLoopbackAddress","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.InvalidArgumentSocketException"
+},
+{
+ "name":"org.newsclub.net.unix.NoSuchDeviceSocketException"
+},
+{
+ "name":"org.newsclub.net.unix.OperationNotSupportedSocketException"
},
{
"name":"org.newsclub.net.unix.PipeTest",
@@ -232,11 +479,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testPipe","parameterTypes":[] },
- {"name":"testPipeRecvHang","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testPipe","parameterTypes":[] }, {"name":"testPipeRecvHang","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.ReadWriteTest",
@@ -244,12 +487,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testReceiveDataByteForByteSendByteForByte","parameterTypes":[] },
- {"name":"testReceiveDataByteForByteSendWithByteArray","parameterTypes":[] },
- {"name":"testReceiveWithByteArraySendByteForByte","parameterTypes":[] },
- {"name":"testReceiveWithByteArraySendWithByteArray","parameterTypes":[] }
- ]
+ "methods":[{"name":"testReceiveDataByteForByteSendByteForByte","parameterTypes":[] }, {"name":"testReceiveDataByteForByteSendWithByteArray","parameterTypes":[] }, {"name":"testReceiveWithByteArraySendByteForByte","parameterTypes":[] }, {"name":"testReceiveWithByteArraySendWithByteArray","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SelectorTest",
@@ -257,20 +495,11 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testCancelSelect","parameterTypes":[] },
- {"name":"testClosedSelectorSelect","parameterTypes":[] },
- {"name":"testClosedSelectorWakeup","parameterTypes":[] },
- {"name":"testConnectionCloseEventualClientDisconnect","parameterTypes":[] },
- {"name":"testConnectionCloseEventualClientDisconnectKeepLooping","parameterTypes":[] },
- {"name":"testConnectionCloseImmediateClientDisconnect","parameterTypes":[] },
- {"name":"testConnectionCloseImmediateClientDisconnectKeepLooping","parameterTypes":[] },
- {"name":"testNonBlockingAccept","parameterTypes":[] }
- ]
+ "methods":[{"name":"testCancelSelect","parameterTypes":[] }, {"name":"testClosedSelectorSelect","parameterTypes":[] }, {"name":"testClosedSelectorWakeup","parameterTypes":[] }, {"name":"testConnectionCloseEventualClientDisconnect","parameterTypes":[] }, {"name":"testConnectionCloseEventualClientDisconnectKeepLooping","parameterTypes":[] }, {"name":"testConnectionCloseImmediateClientDisconnect","parameterTypes":[] }, {"name":"testConnectionCloseImmediateClientDisconnectKeepLooping","parameterTypes":[] }, {"name":"testNonBlockingAccept","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SelftestDiagnosticsHelper",
- "methods":[{"name":"initError","parameterTypes":[] }]
+ "methods":[{"name":"buildProperties","parameterTypes":[] }, {"name":"initError","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.ServerSocketCloseTest",
@@ -278,10 +507,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testUnblockAcceptsWithSoTimeout","parameterTypes":[] },
- {"name":"testUnblockAcceptsWithoutSoTimeout","parameterTypes":[] }
- ]
+ "methods":[{"name":"testUnblockAcceptsWithSoTimeout","parameterTypes":[] }, {"name":"testUnblockAcceptsWithoutSoTimeout","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.ServerSocketTest",
@@ -289,11 +515,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testBindBadArguments","parameterTypes":[] },
- {"name":"testCloseable","parameterTypes":[] },
- {"name":"testUnboundServerSocket","parameterTypes":[] }
- ]
+ "methods":[{"name":"testBindBadArguments","parameterTypes":[] }, {"name":"testCloseable","parameterTypes":[] }, {"name":"testUnboundServerSocket","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SoTimeoutTest",
@@ -301,12 +523,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"issue14Fail","parameterTypes":[] },
- {"name":"issue14Pass","parameterTypes":[] },
- {"name":"testSocketTimeoutExceptionRead","parameterTypes":[] },
- {"name":"testSocketTimeoutExceptionWrite","parameterTypes":[] }
- ]
+ "methods":[{"name":"issue14Fail","parameterTypes":[] }, {"name":"issue14Pass","parameterTypes":[] }, {"name":"testSocketTimeoutExceptionRead","parameterTypes":[] }, {"name":"testSocketTimeoutExceptionWrite","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SocketChannelTest",
@@ -314,11 +531,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testDoubleBindAddressNotReusable","parameterTypes":[] },
- {"name":"testDoubleBindAddressReusable","parameterTypes":[] },
- {"name":"testNonBlockingConnect","parameterTypes":[] }
- ]
+ "methods":[{"name":"testByteBufferWithPositionOffset","parameterTypes":[] }, {"name":"testDoubleBindAddressNotReusable","parameterTypes":[] }, {"name":"testDoubleBindAddressReusable","parameterTypes":[] }, {"name":"testNonBlockingConnect","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SocketOptionsTest",
@@ -333,10 +546,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testDatagramPair","parameterTypes":[] },
- {"name":"testSocketPair","parameterTypes":[] }
- ]
+ "methods":[{"name":"testDatagramPair","parameterTypes":[] }, {"name":"testSocketPair","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SocketTest",
@@ -344,12 +554,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testBindBadArguments","parameterTypes":[] },
- {"name":"testCloseable","parameterTypes":[] },
- {"name":"testConnectBadArguments","parameterTypes":[] },
- {"name":"testUnconnectedSocket","parameterTypes":[] }
- ]
+ "methods":[{"name":"testBindBadArguments","parameterTypes":[] }, {"name":"testCloseable","parameterTypes":[] }, {"name":"testConnectBadArguments","parameterTypes":[] }, {"name":"testUnconnectedSocket","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.SocketTestBase",
@@ -357,10 +562,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"ensureSocketFileIsDeleted","parameterTypes":[] },
- {"name":"tearDownClass","parameterTypes":[] }
- ]
+ "methods":[{"name":"ensureSocketFileIsDeleted","parameterTypes":[] }, {"name":"tearDownClass","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.StandardSocketOptionsTest",
@@ -368,12 +570,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"afterEach","parameterTypes":[] },
- {"name":"beforeEach","parameterTypes":[] },
- {"name":"testSocketOptions","parameterTypes":[] },
- {"name":"testUnconnectedServerSocketOptions","parameterTypes":[] }
- ]
+ "methods":[{"name":"afterEach","parameterTypes":[] }, {"name":"beforeEach","parameterTypes":[] }, {"name":"testSocketOptions","parameterTypes":[] }, {"name":"testUnconnectedServerSocketOptions","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.TcpNoDelayTest",
@@ -381,10 +578,7 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testDefaultImpl","parameterTypes":[] },
- {"name":"testStrictImpl","parameterTypes":[] }
- ]
+ "methods":[{"name":"testDefaultImpl","parameterTypes":[] }, {"name":"testStrictImpl","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.ThroughputTest",
@@ -392,16 +586,28 @@
"allDeclaredClasses":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
- "methods":[
- {"name":"testDatagramChannel","parameterTypes":[] },
- {"name":"testDatagramChannelDirect","parameterTypes":[] },
- {"name":"testDatagramChannelNonBlocking","parameterTypes":[] },
- {"name":"testDatagramChannelNonBlockingDirect","parameterTypes":[] },
- {"name":"testDatagramPacket","parameterTypes":[] },
- {"name":"testSocket","parameterTypes":[] },
- {"name":"testSocketChannel","parameterTypes":[] },
- {"name":"testSocketChannelDirectBuffer","parameterTypes":[] }
- ]
+ "methods":[{"name":"testDatagramChannel","parameterTypes":[] }, {"name":"testDatagramChannelDirect","parameterTypes":[] }, {"name":"testDatagramChannelNonBlocking","parameterTypes":[] }, {"name":"testDatagramChannelNonBlockingDirect","parameterTypes":[] }, {"name":"testDatagramPacket","parameterTypes":[] }, {"name":"testSocket","parameterTypes":[] }, {"name":"testSocketChannel","parameterTypes":[] }, {"name":"testSocketChannelDirectBuffer","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.darwin.system.AFSYSTEMSelectorProvider"
+},
+{
+ "name":"org.newsclub.net.unix.darwin.system.KernelControlNamesTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testStandardKernelControlNames","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.darwin.system.UtunTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.AbstractNamespaceTest",
@@ -454,7 +660,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[{"name":"","parameterTypes":[] }]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testSeqPacket","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.EndOfFileTest",
@@ -472,18 +678,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testDatagramFileChannel","parameterTypes":[] },
- {"name":"testDatagramPorts","parameterTypes":[] },
- {"name":"testDatagramSocket","parameterTypes":[] },
- {"name":"testForkedVMRedirectStdin","parameterTypes":[] },
- {"name":"testServer","parameterTypes":[] },
- {"name":"testSocketPair","parameterTypes":[] },
- {"name":"testSocketPairNative","parameterTypes":[] },
- {"name":"testSocketPorts","parameterTypes":[] },
- {"name":"testUnconnectedServerAsSocket","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testDatagramFileChannel","parameterTypes":[] }, {"name":"testDatagramPorts","parameterTypes":[] }, {"name":"testDatagramSocket","parameterTypes":[] }, {"name":"testForkedVMRedirectStdin","parameterTypes":[] }, {"name":"testServer","parameterTypes":[] }, {"name":"testSocketPair","parameterTypes":[] }, {"name":"testSocketPairNative","parameterTypes":[] }, {"name":"testSocketPorts","parameterTypes":[] }, {"name":"testUnconnectedServerAsSocket","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.FileDescriptorsTest",
@@ -492,18 +687,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testAncillaryReceiveBufferTooSmall","parameterTypes":[] },
- {"name":"testBadFileDescriptor","parameterTypes":[] },
- {"name":"testDatagramSocket","parameterTypes":[] },
- {"name":"testEmptyFileDescriptorArray","parameterTypes":[] },
- {"name":"testFileInputStream","parameterTypes":[] },
- {"name":"testFileInputStreamPartiallyConsumed","parameterTypes":[] },
- {"name":"testNoAncillaryReceiveBuffer","parameterTypes":[] },
- {"name":"testNullFileDescriptorArray","parameterTypes":[] },
- {"name":"testSendRecvFileDescriptors","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testAncillaryReceiveBufferTooSmall","parameterTypes":[] }, {"name":"testBadFileDescriptor","parameterTypes":[] }, {"name":"testDatagramSocket","parameterTypes":[] }, {"name":"testEmptyFileDescriptorArray","parameterTypes":[] }, {"name":"testFileInputStream","parameterTypes":[] }, {"name":"testFileInputStreamPartiallyConsumed","parameterTypes":[] }, {"name":"testNoAncillaryReceiveBuffer","parameterTypes":[] }, {"name":"testNullFileDescriptorArray","parameterTypes":[] }, {"name":"testSendRecvFileDescriptors","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.PeerCredentialsTest",
@@ -512,12 +696,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"ensureSameCreds","parameterTypes":[] },
- {"name":"testDatagramSocket","parameterTypes":[] },
- {"name":"testSocketsSameProcess","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"ensureSameCreds","parameterTypes":[] }, {"name":"testDatagramSocket","parameterTypes":[] }, {"name":"testSocketsSameProcess","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.ReadWriteTest",
@@ -553,10 +732,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testSupported","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testSupported","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.SoTimeoutTest",
@@ -574,16 +750,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testAbstractNamespace","parameterTypes":[] },
- {"name":"testByteConstructor","parameterTypes":[] },
- {"name":"testEmptyAddress","parameterTypes":[] },
- {"name":"testInetAddress","parameterTypes":[] },
- {"name":"testLegacyConstructor","parameterTypes":[] },
- {"name":"testPath","parameterTypes":[] },
- {"name":"testPort","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testAbstractNamespace","parameterTypes":[] }, {"name":"testByteConstructor","parameterTypes":[] }, {"name":"testEmptyAddress","parameterTypes":[] }, {"name":"testInetAddress","parameterTypes":[] }, {"name":"testLargePort","parameterTypes":[] }, {"name":"testLegacyConstructor","parameterTypes":[] }, {"name":"testPath","parameterTypes":[] }, {"name":"testPort","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.SocketChannelTest",
@@ -601,15 +768,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testFactoryArg","parameterTypes":[] },
- {"name":"testSystemProperty","parameterTypes":[] },
- {"name":"testURISchemeCeateSocketThenConnect","parameterTypes":[] },
- {"name":"testURISchemeCeateSocketWithHostnameValidCases","parameterTypes":[] },
- {"name":"testURISchemeCeateSocketWithIllegalArguments","parameterTypes":[] },
- {"name":"testURISchemeCeateSocketWithInvalidHostname","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testFactoryArg","parameterTypes":[] }, {"name":"testSystemProperty","parameterTypes":[] }, {"name":"testURISchemeCeateSocketThenConnect","parameterTypes":[] }, {"name":"testURISchemeCeateSocketWithHostnameValidCases","parameterTypes":[] }, {"name":"testURISchemeCeateSocketWithIllegalArguments","parameterTypes":[] }, {"name":"testURISchemeCeateSocketWithInvalidHostname","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.SocketPairTest",
@@ -627,15 +786,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testLoadedLibrary","parameterTypes":[] },
- {"name":"testMain","parameterTypes":[] },
- {"name":"testReceivedFileDescriptorsUnconnected","parameterTypes":[] },
- {"name":"testSupported","parameterTypes":[] },
- {"name":"testSupports","parameterTypes":[] },
- {"name":"testVersion","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testLoadedLibrary","parameterTypes":[] }, {"name":"testMain","parameterTypes":[] }, {"name":"testReceivedFileDescriptorsUnconnected","parameterTypes":[] }, {"name":"testSupported","parameterTypes":[] }, {"name":"testSupports","parameterTypes":[] }, {"name":"testVersion","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.domain.StandardSocketOptionsTest",
@@ -664,6 +815,211 @@
"queryAllDeclaredConstructors":true,
"methods":[{"name":"","parameterTypes":[] }]
},
+{
+ "name":"org.newsclub.net.unix.domain.ThroughputTestShim",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"testJEP380","parameterTypes":[] }, {"name":"testJEP380direct","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.domain.UnixDomainSocketAddressTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testConvertUnixDomainSocketAddress","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFRMIService",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFRMIServiceImpl_Stub"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFRMISocketFactory"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFRegistry$1_Stub"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFSocketCapabilityCondition",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFSocketCapabilityRequirement",
+ "queryAllPublicMethods":true
+},
+{
+ "name":"org.newsclub.net.unix.rmi.AFUNIXRMISocketFactory"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.Hello",
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"hello","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.HelloImpl_Stub"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.JunixsocketVersionTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testVersion","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.NaiveFileInputStreamRemote",
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"close","parameterTypes":[] }, {"name":"getRemoteFileDescriptor","parameterTypes":[] }, {"name":"read","parameterTypes":[] }, {"name":"readAllBytes","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.NaiveFileInputStreamRemoteImpl_Stub"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RMIPeerCredentialsTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testRemotePeerCredentials","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RegistryTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testDoubleCreateRegistry","parameterTypes":[] }, {"name":"testExportAndBind","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseable",
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"close","parameterTypes":[] }, {"name":"get","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableImpl_Stub"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testRemoteCloseableWithACloseableThing","parameterTypes":[] }, {"name":"testRemoteCloseableWithANotCloseableThing","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableThing$IsCloseable"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableThing$NotCloseable"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableThingImpl"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableThingImpl$IsCloseableImpl"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteCloseableThingImpl$NotCloseableImpl"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteFileDescriptor"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteFileDescriptorBase"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteFileDescriptorTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testFindSocketFactory","parameterTypes":[] }, {"name":"testReadWrite","parameterTypes":[] }, {"name":"testRemoteStdout","parameterTypes":[] }, {"name":"testRemoteStdoutNoop","parameterTypes":[] }, {"name":"testServiceProxy","parameterTypes":[] }, {"name":"testWriteAndReadHello","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteFileInput"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.RemoteFileOutput"
+},
+{
+ "name":"org.newsclub.net.unix.rmi.ShutdownHookTestBase",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"tearDownClass","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.TestBase",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"setUp","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.TestService",
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"input","parameterTypes":[] }, {"name":"input","parameterTypes":["long"] }, {"name":"naiveInputStreamRemote","parameterTypes":[] }, {"name":"output","parameterTypes":[] }, {"name":"remoteCloseable","parameterTypes":["java.lang.Class"] }, {"name":"remoteCloseableThingNumberOfCloseCalls","parameterTypes":["java.lang.Class"] }, {"name":"remoteCloseableThingResetNumberOfCloseCalls","parameterTypes":["java.lang.Class"] }, {"name":"remotePeerCredentials","parameterTypes":[] }, {"name":"stdout","parameterTypes":[] }, {"name":"verifyContents","parameterTypes":["byte[]"] }]
+},
+{
+ "name":"org.newsclub.net.unix.rmi.TestServiceImpl_Stub"
+},
+{
+ "name":"org.newsclub.net.unix.ssl.ProviderTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testDumpDefaultProviders","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.ssl.SNIHostnameCaptureTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testSNISuccessExpectDefault_NO_serverNullDefault_NO_clientEmptyDefault_NO","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_NO_serverNullDefault_NO_clientEmptyDefault_YES","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_NO_serverNullDefault_YES_clientEmptyDefault_NO","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_NO_serverNullDefault_YES_clientEmptyDefault_YES","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_YES_serverNullDefault_NO_clientEmptyDefault_NO","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_YES_serverNullDefault_NO_clientEmptyDefault_YES","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_YES_serverNullDefault_YES_clientEmptyDefault_NO","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSNISuccessExpectDefault_YES_serverNullDefault_YES_clientEmptyDefault_YES","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testWonkySSLSocket","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.ssl.SSLContextBuilderTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testBadProtocol","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testBothKeyManagersAndKeyStore","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testBothKeyStoreAndKeyManagers","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testBothTrustManagersAndTrustStore","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testBothTrustStoreAndTrustManagers","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testClientAuthRequired","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testClientAuthRequiredButClientIsNotSendingAKey","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testClientAuthRequiredButClientKeyIsNotTrusted","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testClientHasNoTrustStore","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testDestroyablePasswordSupplier","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testDestroyablePasswordSupplierDestroyed","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testKeyStoreFileNotFound","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testKeyStoreNullPasswordSupplied","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testKeyStoreNullPasswordSupplier","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testKeyStoreNullURL","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testKeyStoreURLNotFound","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testNoClientAuth","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSSLEngineMethods","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testServerAndClientBlindlyTrustAnything","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testServerSocketFactoryMethods","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testServerSocketFactoryMethodsForCodeCoverageOnly","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSocketFactoryMethods","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testSocketFactoryMethodsForCodeCoverageOnly","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testTrustStoreFileNotFound","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testTrustStoreNullPasswordSupplied","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testTrustStoreNullPasswordSupplier","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testTrustStoreNullURL","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testTrustStoreURLNotFound","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testUndestroyablePasswordSupplier","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testUndestroyablePasswordSuppliers","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testWithDefaultParameters1","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testWithDefaultParameters2","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }]
+},
+{
+ "name":"org.newsclub.net.unix.ssl.SSLTestBase",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "methods":[{"name":"afterAll","parameterTypes":[] }, {"name":"beforeAll","parameterTypes":[] }]
+},
+{
+ "name":"org.newsclub.net.unix.ssl.ValidatingX509TrustManagerTest",
+ "allDeclaredFields":true,
+ "allDeclaredClasses":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllPublicMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testInspectTrustedCertificateExpired","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testInspectTrustedCertificateExpiredNested","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testInspectTrustedCertificateExpiredNestedFilter","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testInspectTrustedCertificateNotExpired","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testInspectTrustedClientCertificate","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testInspectTrustedClientCertificateExpired","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }, {"name":"testInspectTrustedClientCertificateExpiredNested","parameterTypes":["org.newsclub.net.unix.ssl.SSLTestBase$TestSSLConfiguration"] }]
+},
{
"name":"org.newsclub.net.unix.tipc.AFTIPCSelectorProvider"
},
@@ -834,10 +1190,7 @@
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[
- {"name":"","parameterTypes":[] },
- {"name":"testGetLocalID","parameterTypes":[] }
- ]
+ "methods":[{"name":"","parameterTypes":[] }, {"name":"testGetLocalID","parameterTypes":[] }]
},
{
"name":"org.newsclub.net.unix.vsock.AFVSOCKSelectorProvider"
@@ -991,11 +1344,172 @@
"queryAllDeclaredConstructors":true
},
{
- "name":"sun.security.provider.NativePRNG",
+ "name":"org.openjsse.net.ssl.OpenJSSE"
+},
+{
+ "name":"sun.rmi.registry.RegistryImpl_Skel",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"sun.rmi.registry.RegistryImpl_Stub",
+ "methods":[{"name":"","parameterTypes":["java.rmi.server.RemoteRef"] }]
+},
+{
+ "name":"sun.rmi.server.UnicastRef2",
"methods":[{"name":"","parameterTypes":[] }]
},
+{
+ "name":"sun.rmi.transport.DGCImpl_Skel",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"sun.rmi.transport.DGCImpl_Stub",
+ "methods":[{"name":"","parameterTypes":["java.rmi.server.RemoteRef"] }]
+},
+{
+ "name":"sun.security.pkcs12.PKCS12KeyStore",
+ "methods":[{"name":"","parameterTypes":[] }]
+},
+{
+ "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12",
+ "methods":[{"name":"