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.FileNotFoundException;
23 import java.io.IOException;
24 import java.lang.ProcessBuilder.Redirect;
25 import java.lang.reflect.InvocationTargetException;
26 import java.net.InetSocketAddress;
27 import java.net.ServerSocket;
28 import java.net.Socket;
29 import java.net.SocketAddress;
30 import java.net.SocketException;
31 import java.nio.ByteBuffer;
32 import java.nio.channels.SelectionKey;
33 import java.nio.channels.spi.AbstractSelectableChannel;
34 import java.nio.file.FileAlreadyExistsException;
35 import java.util.concurrent.atomic.AtomicBoolean;
36
37 import org.newsclub.net.unix.AFSelector.PollFd;
38
39 import com.kohlschutter.annotations.compiletime.ExcludeFromCodeCoverageGeneratedReport;
40 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
41
42
43
44
45
46
47 final class NativeUnixSocket {
48 private static final AtomicBoolean LOADED = new AtomicBoolean(false);
49
50 static final int DOMAIN_GENERIC = -1;
51 static final int DOMAIN_UNIX = 1;
52 static final int DOMAIN_TIPC = 30;
53 static final int DOMAIN_VSOCK = 40;
54 static final int DOMAIN_SYSTEM = 32;
55
56 static final int SOCK_STREAM = 1;
57 static final int SOCK_DGRAM = 2;
58 static final int SOCK_RAW = 3;
59 static final int SOCK_RDM = 4;
60 static final int SOCK_SEQPACKET = 5;
61
62 static final int OPT_LOOKUP_SENDER = 1;
63 static final int OPT_PEEK = 2;
64 static final int OPT_NON_BLOCKING = 4;
65
66
67
68
69 static final int OPT_NON_SOCKET = 8;
70
71 static final int OPT_DGRAM_MODE = 16;
72
73 static final int BIND_OPT_REUSE = 1;
74
75 static final int SOCKETSTATUS_INVALID = -1;
76 static final int SOCKETSTATUS_UNKNOWN = 0;
77 static final int SOCKETSTATUS_BOUND = 1;
78 static final int SOCKETSTATUS_CONNECTED = 2;
79
80 @SuppressWarnings("StaticAssignmentOfThrowable" )
81 private static Throwable initError = null;
82
83 static final int SHUT_RD = 0;
84 static final int SHUT_WR = 1;
85 static final int SHUT_RD_WR = 2;
86
87 static final int S_IRUSR = 0400;
88 static final int S_IWUSR = 0200;
89 static final int S_IRGRP = 0040;
90 static final int S_IWGRP = 0020;
91 static final int S_IROTH = 0004;
92 static final int S_IWOTH = 0002;
93
94 static final int MOPT_RDONLY = 1 << 0;
95 static final int MOPT_CREAT = 1 << 2;
96 static final int MOPT_EXCL = 1 << 3;
97 static final int MOPT_TRUNC = 1 << 4;
98 static final int MOPT_SEALABLE = 1 << 5;
99 static final int MOPT_SECRET = 1 << 6;
100 static final int MOPT_UNLINK_UPON_CLOSE = 1 << 7;
101
102 static final int MMODE_READ = 1 << 0;
103 static final int MMODE_WRITE = 1 << 1;
104 static final int MMODE_COPY_ON_WRITE = 1 << 2;
105 static final int MMODE_SYNC = 1 << 3;
106 static final int MMODE_FIXED = 1 << 4;
107 static final int MMODE_ANONYMOUS = 1 << 5;
108 static final int MMODE_PLACEHOLDER = 1 << 6;
109
110 static final int MADV_NORMAL = 1 << 0;
111 static final int MADV_FREE = 1 << 1;
112 static final int MADV_FREE_NOW = 1 << 2;
113 static final int MADV_WILLNEED = 1 << 3;
114 static final int MADV_DONTNEED = 1 << 4;
115 static final int MADV_SEQUENTIAL = 1 << 5;
116 static final int MADV_RANDOM = 1 << 6;
117
118 @ExcludeFromCodeCoverageGeneratedReport(reason = "unreachable")
119 private NativeUnixSocket() {
120 throw new UnsupportedOperationException("No instances");
121 }
122
123 static {
124 boolean loadSuccessful = false;
125 try (NativeLibraryLoader nll = new NativeLibraryLoader()) {
126 nll.loadLibrary();
127 loadSuccessful = true;
128 } catch (RuntimeException | Error e) {
129 initError = e;
130 StackTraceUtil.printStackTraceSevere(e);
131 } finally {
132 setLoaded(loadSuccessful);
133 }
134
135 AFAddressFamily.registerAddressFamily("generic", NativeUnixSocket.DOMAIN_GENERIC,
136 "org.newsclub.net.unix.AFGenericSocketAddress");
137 AFAddressFamily.registerAddressFamily("un", NativeUnixSocket.DOMAIN_UNIX,
138 "org.newsclub.net.unix.AFUNIXSocketAddress");
139 AFAddressFamily.registerAddressFamily("tipc", NativeUnixSocket.DOMAIN_TIPC,
140 "org.newsclub.net.unix.AFTIPCSocketAddress");
141 AFAddressFamily.registerAddressFamily("vsock", NativeUnixSocket.DOMAIN_VSOCK,
142 "org.newsclub.net.unix.AFVSOCKSocketAddress");
143 AFAddressFamily.registerAddressFamily("system", NativeUnixSocket.DOMAIN_SYSTEM,
144 "org.newsclub.net.unix.AFSYSTEMSocketAddress");
145
146 initSharedMemory();
147 }
148
149 static boolean isLoaded() {
150 return LOADED.get();
151 }
152
153 private static void initSharedMemory() {
154 try {
155 Class<?> sharedMemory = Class.forName("org.newsclub.net.unix.memory.SharedMemory");
156 if (sharedMemory != null) {
157 sharedMemory.getMethod("init", MemoryImplUtilInternal.class).invoke(null,
158 new MemoryImplUtilInternal());
159 }
160 } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException
161 | NoSuchMethodException | SecurityException e) {
162
163 }
164 }
165
166 static void ensureSupported() throws UnsupportedOperationException {
167 if (!isLoaded()) {
168 throw unsupportedException();
169 }
170 }
171
172 static UnsupportedOperationException unsupportedException() {
173 if (!isLoaded()) {
174 return (UnsupportedOperationException) new UnsupportedOperationException(
175 "junixsocket may not be fully supported on this platform").initCause(initError);
176 } else {
177 return null;
178 }
179 }
180
181 static Throwable retrieveInitError() {
182 return initError;
183 }
184
185 static void initPre() {
186
187 tryResolveClass(AbstractSelectableChannel.class.getName());
188 tryResolveClass("java.lang.ProcessBuilder$RedirectPipeImpl");
189 tryResolveClass(InetSocketAddress.class.getName());
190 tryResolveClass(InvalidArgumentSocketException.class.getName());
191 tryResolveClass(AddressUnavailableSocketException.class.getName());
192 tryResolveClass(OperationNotSupportedSocketException.class.getName());
193 tryResolveClass(NoSuchDeviceSocketException.class.getName());
194 tryResolveClass(BrokenPipeSocketException.class.getName());
195 tryResolveClass(ConnectionResetSocketException.class.getName());
196 tryResolveClass(SocketClosedException.class.getName());
197 tryResolveClass(FileNotFoundException.class.getName());
198 tryResolveClass(FileAlreadyExistsException.class.getName());
199 tryResolveClass(IOException.class.getName());
200 tryResolveClass(OperationNotSupportedIOException.class.getName());
201 }
202
203 private static void tryResolveClass(String className) {
204 try {
205 Class.forName(className);
206 } catch (Exception e) {
207
208 }
209 }
210
211 @SuppressFBWarnings("THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION")
212 static native void init() throws Exception;
213
214 @SuppressFBWarnings("THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION")
215 static native void destroy() throws Exception;
216
217
218
219
220
221
222 static native void noop();
223
224 static native int capabilities();
225
226 static native byte[] sockname(int domain, FileDescriptor fd, boolean peer);
227
228 static native long bind(ByteBuffer sockaddr, int sockaddrLen, FileDescriptor fd, int options)
229 throws IOException;
230
231 static native void listen(FileDescriptor fd, int backlog) throws IOException;
232
233 static native boolean accept(ByteBuffer sockaddr, int sockaddrLen, FileDescriptor fdServer,
234 FileDescriptor fd, long inode, int timeout) throws IOException;
235
236 static native boolean connect(ByteBuffer sockaddr, int sockaddrLen, FileDescriptor fd, long inode)
237 throws IOException;
238
239 static native boolean finishConnect(FileDescriptor fd) throws IOException;
240
241 static native void disconnect(FileDescriptor fd) throws IOException;
242
243 static native int socketStatus(FileDescriptor fd) throws IOException;
244
245 static native FileDescriptor duplicate(FileDescriptor fdSource, FileDescriptor fdTarget)
246 throws IOException;
247
248 static native Class<?> primaryType(FileDescriptor fd) throws IOException;
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 static native int read(FileDescriptor fd, byte[] buf, int off, int len, int options,
264 AncillaryDataSupport ancillaryDataSupport, int timeoutMillis) throws IOException;
265
266
267
268
269
270
271
272
273
274
275
276
277
278 static native int write(FileDescriptor fd, byte[] buf, int off, int len, int options,
279 AncillaryDataSupport ancillaryDataSupport) throws IOException;
280
281 static native int receive(FileDescriptor fd, ByteBuffer directBuffer, int offset, int length,
282 ByteBuffer directSocketAddressOut, int options, AncillaryDataSupport ancillaryDataSupport,
283 int timeoutMillis) throws IOException;
284
285 static native int send(FileDescriptor fd, ByteBuffer directBuffer, int offset, int length,
286 ByteBuffer directSocketAddress, int addrLen, int options,
287 AncillaryDataSupport ancillaryDataSupport) throws IOException;
288
289 static native void close(FileDescriptor fd) throws IOException;
290
291 static native void shutdown(FileDescriptor fd, int mode) throws IOException;
292
293 static native int getSocketOptionInt(FileDescriptor fd, int optionId) throws IOException;
294
295 static native void setSocketOptionInt(FileDescriptor fd, int optionId, int value)
296 throws IOException;
297
298 static native <T> T getSocketOption(FileDescriptor fd, int level, int optionName,
299 Class<T> valueType) throws IOException;
300
301 static native void setSocketOption(FileDescriptor fd, int level, int optionName, Object value)
302 throws IOException;
303
304 static native int available(FileDescriptor fd, ByteBuffer buf) throws IOException;
305
306 static native AFUNIXSocketCredentials peerCredentials(FileDescriptor fd,
307 AFUNIXSocketCredentials creds) throws IOException;
308
309 static native void initServerImpl(ServerSocket serverSocket, AFSocketImpl<?> impl)
310 throws IOException;
311
312 static native void createSocket(FileDescriptor fdesc, int domain, int type) throws IOException;
313
314 static native void setPort(SocketAddress addr, int port);
315
316 static native void initFD(FileDescriptor fdesc, int fd) throws IOException;
317
318 static native int getFD(FileDescriptor fdesc) throws IOException;
319
320 static native void copyFileDescriptor(FileDescriptor source, FileDescriptor target)
321 throws IOException;
322
323 static native void attachCloseable(FileDescriptor fdesc, Closeable closeable)
324 throws SocketException;
325
326 static native int maxAddressLength();
327
328 static native int sockAddrLength(int domain);
329
330 static native int ancillaryBufMinLen();
331
332 static native byte[] sockAddrToBytes(int domain, ByteBuffer sockAddrDirect);
333
334 static native int bytesToSockAddr(int domain, ByteBuffer sockAddrDirectBuf, byte[] address);
335
336 @SuppressFBWarnings("THROWS_METHOD_THROWS_RUNTIMEEXCEPTION")
337 static void setPort1(SocketAddress addr, int port) throws SocketException {
338 if (port < 0) {
339 throw new IllegalArgumentException("port out of range:" + port);
340 }
341
342 try {
343 setPort(addr, port);
344 } catch (RuntimeException e) {
345 throw e;
346 } catch (Exception e) {
347 throw (SocketException) new SocketException("Could not set port").initCause(e);
348 }
349 }
350
351 static native Socket currentRMISocket();
352
353 static native boolean initPipe(FileDescriptor source, FileDescriptor sink, boolean selectable)
354 throws IOException;
355
356 static native int poll(PollFd pollFd, int timeout) throws IOException;
357
358 static native void configureBlocking(FileDescriptor fd, boolean blocking) throws IOException;
359
360
361
362
363
364
365
366
367 static native int checkBlocking(FileDescriptor fd) throws IOException;
368
369 static native void socketPair(int domain, int type, FileDescriptor fd, FileDescriptor fd2);
370
371 static native Redirect initRedirect(FileDescriptor fd);
372
373 static native void deregisterSelectionKey(AbstractSelectableChannel chann, SelectionKey key);
374
375 static native byte[] tipcGetNodeId(int peer) throws IOException;
376
377 static native byte[] tipcGetLinkName(int peer, int bearerId) throws IOException;
378
379 static native int sockAddrNativeDataOffset();
380
381 static native int sockAddrNativeFamilyOffset();
382
383 static native int sockTypeToNative(int type) throws IOException;
384
385 static native int vsockGetLocalCID() throws IOException;
386
387 static native int systemResolveCtlId(FileDescriptor fd, String ctlName) throws IOException;
388
389 static native int systemCtlIdCount(FileDescriptor fd) throws IOException;
390
391 static void setLoaded(boolean successful) {
392 LOADED.compareAndSet(false, successful);
393 }
394
395 static native void shmUnlink(String name) throws IOException;
396
397 static native long shmOpen(FileDescriptor fdOut, String name, long truncateLength, int mode,
398 int options) throws IOException;
399
400 static native long sharedMemoryAllocationSize();
401
402 static native ByteBuffer mmapShm(Object arenaSegment, FileDescriptor fd, long offset, long length,
403 int mmode, int duplicates) throws IOException;
404
405 static native void unmap(long address, long byteSize, int duplicates, boolean ignoreError)
406 throws IOException;
407
408 static native long mmap(long address, FileDescriptor fdObj, long offset, long length, int mmode,
409 FileDescriptor extraFd) throws IOException;
410
411 static native ByteBuffer mappedBuffer(long address, long length, FileDescriptor fdRef, int mmode,
412 Object arenaSegment) throws IOException;
413
414 static native void madvise(long address, long byteSize, int madv, boolean ignoreError)
415 throws IOException;
416
417 static native boolean futexWait(long address, int value, int timeoutMillis) throws IOException;
418
419 static native boolean futexWake(long address, boolean wakeAll) throws IOException;
420
421 static native boolean needToTrackSharedMemory();
422
423 static native boolean futexIsInterProcess();
424
425 static native long sizeOfSharedMemory(FileDescriptor fdObj) throws IOException;
426 }