1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.Closeable;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.lang.ProcessBuilder.Redirect;
24 import java.net.InetSocketAddress;
25 import java.net.ServerSocket;
26 import java.net.Socket;
27 import java.net.SocketAddress;
28 import java.net.SocketException;
29 import java.nio.ByteBuffer;
30 import java.nio.channels.SelectionKey;
31 import java.nio.channels.spi.AbstractSelectableChannel;
32 import java.util.concurrent.atomic.AtomicBoolean;
33
34 import org.newsclub.net.unix.AFSelector.PollFd;
35
36 import com.kohlschutter.annotations.compiletime.ExcludeFromCodeCoverageGeneratedReport;
37 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
38
39
40
41
42
43
44 final class NativeUnixSocket {
45 private static final AtomicBoolean LOADED = new AtomicBoolean(false);
46
47 static final int DOMAIN_GENERIC = -1;
48 static final int DOMAIN_UNIX = 1;
49 static final int DOMAIN_TIPC = 30;
50 static final int DOMAIN_VSOCK = 40;
51 static final int DOMAIN_SYSTEM = 32;
52
53 static final int SOCK_STREAM = 1;
54 static final int SOCK_DGRAM = 2;
55 static final int SOCK_RAW = 3;
56 static final int SOCK_RDM = 4;
57 static final int SOCK_SEQPACKET = 5;
58
59 static final int OPT_LOOKUP_SENDER = 1;
60 static final int OPT_PEEK = 2;
61 static final int OPT_NON_BLOCKING = 4;
62
63
64
65
66 static final int OPT_NON_SOCKET = 8;
67
68 static final int OPT_DGRAM_MODE = 16;
69
70 static final int BIND_OPT_REUSE = 1;
71
72 static final int SOCKETSTATUS_INVALID = -1;
73 static final int SOCKETSTATUS_UNKNOWN = 0;
74 static final int SOCKETSTATUS_BOUND = 1;
75 static final int SOCKETSTATUS_CONNECTED = 2;
76
77 @SuppressWarnings("StaticAssignmentOfThrowable" )
78 private static Throwable initError = null;
79
80 static final int SHUT_RD = 0;
81 static final int SHUT_WR = 1;
82 static final int SHUT_RD_WR = 2;
83
84 @ExcludeFromCodeCoverageGeneratedReport(reason = "unreachable")
85 private NativeUnixSocket() {
86 throw new UnsupportedOperationException("No instances");
87 }
88
89 static {
90 boolean loadSuccessful = false;
91 try (NativeLibraryLoader nll = new NativeLibraryLoader()) {
92 nll.loadLibrary();
93 loadSuccessful = true;
94 } catch (RuntimeException | Error e) {
95 initError = e;
96 StackTraceUtil.printStackTraceSevere(e);
97 } finally {
98 setLoaded(loadSuccessful);
99 }
100
101 AFAddressFamily.registerAddressFamily("generic", NativeUnixSocket.DOMAIN_GENERIC,
102 "org.newsclub.net.unix.AFGenericSocketAddress");
103 AFAddressFamily.registerAddressFamily("un", NativeUnixSocket.DOMAIN_UNIX,
104 "org.newsclub.net.unix.AFUNIXSocketAddress");
105 AFAddressFamily.registerAddressFamily("tipc", NativeUnixSocket.DOMAIN_TIPC,
106 "org.newsclub.net.unix.AFTIPCSocketAddress");
107 AFAddressFamily.registerAddressFamily("vsock", NativeUnixSocket.DOMAIN_VSOCK,
108 "org.newsclub.net.unix.AFVSOCKSocketAddress");
109 AFAddressFamily.registerAddressFamily("system", NativeUnixSocket.DOMAIN_SYSTEM,
110 "org.newsclub.net.unix.AFSYSTEMSocketAddress");
111 }
112
113 static boolean isLoaded() {
114 return LOADED.get();
115 }
116
117 static void ensureSupported() throws UnsupportedOperationException {
118 if (!isLoaded()) {
119 throw unsupportedException();
120 }
121 }
122
123 static UnsupportedOperationException unsupportedException() {
124 if (!isLoaded()) {
125 return (UnsupportedOperationException) new UnsupportedOperationException(
126 "junixsocket may not be fully supported on this platform").initCause(initError);
127 } else {
128 return null;
129 }
130 }
131
132 static Throwable retrieveInitError() {
133 return initError;
134 }
135
136 static void initPre() {
137
138 tryResolveClass(AbstractSelectableChannel.class.getName());
139 tryResolveClass("java.lang.ProcessBuilder$RedirectPipeImpl");
140 tryResolveClass(InetSocketAddress.class.getName());
141 tryResolveClass(InvalidArgumentSocketException.class.getName());
142 tryResolveClass(AddressUnavailableSocketException.class.getName());
143 tryResolveClass(OperationNotSupportedSocketException.class.getName());
144 tryResolveClass(NoSuchDeviceSocketException.class.getName());
145 tryResolveClass(BrokenPipeSocketException.class.getName());
146 tryResolveClass(ConnectionResetSocketException.class.getName());
147 tryResolveClass(SocketClosedException.class.getName());
148 }
149
150 private static void tryResolveClass(String className) {
151 try {
152 Class.forName(className);
153 } catch (Exception e) {
154
155 }
156 }
157
158 @SuppressFBWarnings("THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION")
159 static native void init() throws Exception;
160
161 @SuppressFBWarnings("THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION")
162 static native void destroy() throws Exception;
163
164
165
166
167
168
169 static native void noop();
170
171 static native int capabilities();
172
173 static native byte[] sockname(int domain, FileDescriptor fd, boolean peer);
174
175 static native long bind(ByteBuffer sockaddr, int sockaddrLen, FileDescriptor fd, int options)
176 throws IOException;
177
178 static native void listen(FileDescriptor fd, int backlog) throws IOException;
179
180 static native boolean accept(ByteBuffer sockaddr, int sockaddrLen, FileDescriptor fdServer,
181 FileDescriptor fd, long inode, int timeout) throws IOException;
182
183 static native boolean connect(ByteBuffer sockaddr, int sockaddrLen, FileDescriptor fd, long inode)
184 throws IOException;
185
186 static native boolean finishConnect(FileDescriptor fd) throws IOException;
187
188 static native void disconnect(FileDescriptor fd) throws IOException;
189
190 static native int socketStatus(FileDescriptor fd) throws IOException;
191
192 static native FileDescriptor duplicate(FileDescriptor fdSource, FileDescriptor fdTarget)
193 throws IOException;
194
195 static native Class<?> primaryType(FileDescriptor fd) throws IOException;
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 static native int read(FileDescriptor fd, byte[] buf, int off, int len, int options,
211 AncillaryDataSupport ancillaryDataSupport, int timeoutMillis) throws IOException;
212
213
214
215
216
217
218
219
220
221
222
223
224
225 static native int write(FileDescriptor fd, byte[] buf, int off, int len, int options,
226 AncillaryDataSupport ancillaryDataSupport) throws IOException;
227
228 static native int receive(FileDescriptor fd, ByteBuffer directBuffer, int offset, int length,
229 ByteBuffer directSocketAddressOut, int options, AncillaryDataSupport ancillaryDataSupport,
230 int timeoutMillis) throws IOException;
231
232 static native int send(FileDescriptor fd, ByteBuffer directBuffer, int offset, int length,
233 ByteBuffer directSocketAddress, int addrLen, int options,
234 AncillaryDataSupport ancillaryDataSupport) throws IOException;
235
236 static native void close(FileDescriptor fd) throws IOException;
237
238 static native void shutdown(FileDescriptor fd, int mode) throws IOException;
239
240 static native int getSocketOptionInt(FileDescriptor fd, int optionId) throws IOException;
241
242 static native void setSocketOptionInt(FileDescriptor fd, int optionId, int value)
243 throws IOException;
244
245 static native <T> T getSocketOption(FileDescriptor fd, int level, int optionName,
246 Class<T> valueType) throws IOException;
247
248 static native void setSocketOption(FileDescriptor fd, int level, int optionName, Object value)
249 throws IOException;
250
251 static native int available(FileDescriptor fd, ByteBuffer buf) throws IOException;
252
253 static native AFUNIXSocketCredentials peerCredentials(FileDescriptor fd,
254 AFUNIXSocketCredentials creds) throws IOException;
255
256 static native void initServerImpl(ServerSocket serverSocket, AFSocketImpl<?> impl)
257 throws IOException;
258
259 static native void createSocket(FileDescriptor fdesc, int domain, int type) throws IOException;
260
261 static native void setPort(SocketAddress addr, int port);
262
263 static native void initFD(FileDescriptor fdesc, int fd) throws IOException;
264
265 static native int getFD(FileDescriptor fdesc) throws IOException;
266
267 static native void copyFileDescriptor(FileDescriptor source, FileDescriptor target)
268 throws IOException;
269
270 static native void attachCloseable(FileDescriptor fdesc, Closeable closeable)
271 throws SocketException;
272
273 static native int maxAddressLength();
274
275 static native int sockAddrLength(int domain);
276
277 static native int ancillaryBufMinLen();
278
279 static native byte[] sockAddrToBytes(int domain, ByteBuffer sockAddrDirect);
280
281 static native int bytesToSockAddr(int domain, ByteBuffer sockAddrDirectBuf, byte[] address);
282
283 @SuppressFBWarnings("THROWS_METHOD_THROWS_RUNTIMEEXCEPTION")
284 static void setPort1(SocketAddress addr, int port) throws SocketException {
285 if (port < 0) {
286 throw new IllegalArgumentException("port out of range:" + port);
287 }
288
289 try {
290 setPort(addr, port);
291 } catch (RuntimeException e) {
292 throw e;
293 } catch (Exception e) {
294 throw (SocketException) new SocketException("Could not set port").initCause(e);
295 }
296 }
297
298 static native Socket currentRMISocket();
299
300 static native boolean initPipe(FileDescriptor source, FileDescriptor sink, boolean selectable)
301 throws IOException;
302
303 static native int poll(PollFd pollFd, int timeout) throws IOException;
304
305 static native void configureBlocking(FileDescriptor fd, boolean blocking) throws IOException;
306
307
308
309
310
311
312
313
314 static native int checkBlocking(FileDescriptor fd) throws IOException;
315
316 static native void socketPair(int domain, int type, FileDescriptor fd, FileDescriptor fd2);
317
318 static native Redirect initRedirect(FileDescriptor fd);
319
320 static native void deregisterSelectionKey(AbstractSelectableChannel chann, SelectionKey key);
321
322 static native byte[] tipcGetNodeId(int peer) throws IOException;
323
324 static native byte[] tipcGetLinkName(int peer, int bearerId) throws IOException;
325
326 static native int sockAddrNativeDataOffset();
327
328 static native int sockAddrNativeFamilyOffset();
329
330 static native int sockTypeToNative(int type) throws IOException;
331
332 static native int vsockGetLocalCID() throws IOException;
333
334 static native int systemResolveCtlId(FileDescriptor fd, String ctlName) throws IOException;
335
336 static void setLoaded(boolean successful) {
337 LOADED.compareAndSet(false, successful);
338 }
339 }