View Javadoc
1   /*
2    * Copyright 2015 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty5.channel.unix;
17  
18  import io.netty5.channel.ChannelException;
19  import io.netty5.channel.socket.DomainSocketAddress;
20  import io.netty5.channel.socket.SocketProtocolFamily;
21  import io.netty5.util.CharsetUtil;
22  import io.netty5.util.NetUtil;
23  
24  import java.io.IOException;
25  import java.net.Inet6Address;
26  import java.net.InetAddress;
27  import java.net.InetSocketAddress;
28  import java.net.PortUnreachableException;
29  import java.net.ProtocolFamily;
30  import java.net.SocketAddress;
31  import java.nio.ByteBuffer;
32  import java.nio.channels.ClosedChannelException;
33  import java.util.Objects;
34  
35  import static io.netty5.channel.unix.Errors.ERRNO_EAGAIN_NEGATIVE;
36  import static io.netty5.channel.unix.Errors.ERRNO_EINPROGRESS_NEGATIVE;
37  import static io.netty5.channel.unix.Errors.ERRNO_EWOULDBLOCK_NEGATIVE;
38  import static io.netty5.channel.unix.Errors.ERROR_ECONNREFUSED_NEGATIVE;
39  import static io.netty5.channel.unix.Errors.handleConnectErrno;
40  import static io.netty5.channel.unix.Errors.ioResult;
41  import static io.netty5.channel.unix.Errors.newIOException;
42  import static io.netty5.channel.unix.NativeInetAddress.address;
43  import static io.netty5.channel.unix.NativeInetAddress.ipv4MappedIpv6Address;
44  
45  /**
46   * Provides a JNI bridge to native socket operations.
47   * <strong>Internal usage only!</strong>
48   */
49  public class Socket extends FileDescriptor {
50  
51      private static volatile boolean isIpv6Preferred;
52  
53      @Deprecated
54      public static final int UDS_SUN_PATH_SIZE = 100;
55  
56      private final SocketProtocolFamily protocolFamily;
57  
58      protected final boolean ipv6;
59  
60      public Socket(int fd, SocketProtocolFamily protocolFamily) {
61          super(fd);
62          ipv6 = isIPv6(fd);
63          this.protocolFamily = Objects.requireNonNull(protocolFamily, "protocolFamily");
64      }
65      /**
66       * Returns {@code true} if we should use IPv6 internally, {@code false} otherwise.
67       */
68      private boolean useIpv6(InetAddress address) {
69          return useIpv6(this, address);
70      }
71  
72      /**
73       * Returns {@code true} if the given socket and address combination should use IPv6 internally,
74       * {@code false} otherwise.
75       */
76      protected static boolean useIpv6(Socket socket, InetAddress address) {
77          return socket.ipv6 || address instanceof Inet6Address;
78      }
79  
80      public final SocketProtocolFamily protocolFamily() {
81          return protocolFamily;
82      }
83  
84      public final void shutdown() throws IOException {
85          shutdown(true, true);
86      }
87  
88      public final void shutdown(boolean read, boolean write) throws IOException {
89          for (;;) {
90              // We need to only shutdown what has not been shutdown yet, and if there is no change we should not
91              // shutdown anything. This is because if the underlying FD is reused and we still have an object which
92              // represents the previous incarnation of the FD we need to be sure we don't inadvertently shutdown the
93              // "new" FD without explicitly having a change.
94              final int oldState = state;
95              if (isClosed(oldState)) {
96                  throw new ClosedChannelException();
97              }
98              int newState = oldState;
99              if (read && !isInputShutdown(newState)) {
100                 newState = inputShutdown(newState);
101             }
102             if (write && !isOutputShutdown(newState)) {
103                 newState = outputShutdown(newState);
104             }
105 
106             // If there is no change in state, then we should not take any action.
107             if (newState == oldState) {
108                 return;
109             }
110             if (casState(oldState, newState)) {
111                 break;
112             }
113         }
114         int res = shutdown(fd, read, write);
115         if (res < 0) {
116             ioResult("shutdown", res);
117         }
118     }
119 
120     public final boolean isShutdown() {
121         int state = this.state;
122         return isInputShutdown(state) && isOutputShutdown(state);
123     }
124 
125     public final boolean isInputShutdown() {
126         return isInputShutdown(state);
127     }
128 
129     public final boolean isOutputShutdown() {
130         return isOutputShutdown(state);
131     }
132 
133     public final int sendTo(ByteBuffer buf, int pos, int limit, InetAddress addr, int port) throws IOException {
134         return sendTo(buf, pos, limit, addr, port, false);
135     }
136 
137     public final int sendTo(ByteBuffer buf, int pos, int limit, InetAddress addr, int port, boolean fastOpen)
138             throws IOException {
139         // just duplicate the toNativeInetAddress code here to minimize object creation as this method is expected
140         // to be called frequently
141         byte[] address;
142         int scopeId;
143         if (addr instanceof Inet6Address) {
144             address = addr.getAddress();
145             scopeId = ((Inet6Address) addr).getScopeId();
146         } else {
147             // convert to ipv4 mapped ipv6 address;
148             scopeId = 0;
149             address = ipv4MappedIpv6Address(addr.getAddress());
150         }
151         int flags = fastOpen ? msgFastopen() : 0;
152         int res = sendTo(fd, useIpv6(addr), buf, pos, limit, address, scopeId, port, flags);
153         if (res >= 0) {
154             return res;
155         }
156         if (res == ERRNO_EINPROGRESS_NEGATIVE && fastOpen) {
157             // This happens when we (as a client) have no pre-existing cookie for doing a fast-open connection.
158             // In this case, our TCP connection will be established normally, but no data was transmitted at this time.
159             // We'll just transmit the data with normal writes later.
160             return 0;
161         }
162         if (res == ERROR_ECONNREFUSED_NEGATIVE) {
163             throw new PortUnreachableException("sendTo failed");
164         }
165         return ioResult("sendTo", res);
166     }
167 
168     public final int sendToDomainSocket(ByteBuffer buf, int pos, int limit, byte[] path) throws IOException {
169         int res = sendToDomainSocket(fd, buf, pos, limit, path);
170         if (res >= 0) {
171             return res;
172         }
173         return ioResult("sendToDomainSocket", res);
174     }
175 
176     public final int sendToAddress(long memoryAddress, int pos, int limit, InetAddress addr, int port)
177             throws IOException {
178         return sendToAddress(memoryAddress, pos, limit, addr, port, false);
179     }
180 
181     public final int sendToAddress(long memoryAddress, int pos, int limit, InetAddress addr, int port,
182                                    boolean fastOpen) throws IOException {
183         // just duplicate the toNativeInetAddress code here to minimize object creation as this method is expected
184         // to be called frequently
185         byte[] address;
186         int scopeId;
187         if (addr instanceof Inet6Address) {
188             address = addr.getAddress();
189             scopeId = ((Inet6Address) addr).getScopeId();
190         } else {
191             // convert to ipv4 mapped ipv6 address;
192             scopeId = 0;
193             address = ipv4MappedIpv6Address(addr.getAddress());
194         }
195         int flags = fastOpen ? msgFastopen() : 0;
196         int res = sendToAddress(fd, useIpv6(addr), memoryAddress, pos, limit, address, scopeId, port, flags);
197         if (res >= 0) {
198             return res;
199         }
200         if (res == ERRNO_EINPROGRESS_NEGATIVE && fastOpen) {
201             // This happens when we (as a client) have no pre-existing cookie for doing a fast-open connection.
202             // In this case, our TCP connection will be established normally, but no data was transmitted at this time.
203             // We'll just transmit the data with normal writes later.
204             return 0;
205         }
206         if (res == ERROR_ECONNREFUSED_NEGATIVE) {
207             throw new PortUnreachableException("sendToAddress failed");
208         }
209         return ioResult("sendToAddress", res);
210     }
211 
212     public final int sendToAddressDomainSocket(long memoryAddress, int pos, int limit, byte[] path) throws IOException {
213         int res = sendToAddressDomainSocket(fd, memoryAddress, pos, limit, path);
214         if (res >= 0) {
215             return res;
216         }
217         return ioResult("sendToAddressDomainSocket", res);
218     }
219 
220     public final int sendToAddresses(long memoryAddress, int length, InetAddress addr, int port) throws IOException {
221         return sendToAddresses(memoryAddress, length, addr, port, false);
222     }
223 
224     public final int sendToAddresses(long memoryAddress, int length, InetAddress addr, int port, boolean fastOpen)
225             throws IOException {
226         // just duplicate the toNativeInetAddress code here to minimize object creation as this method is expected
227         // to be called frequently
228         byte[] address;
229         int scopeId;
230         if (addr instanceof Inet6Address) {
231             address = addr.getAddress();
232             scopeId = ((Inet6Address) addr).getScopeId();
233         } else {
234             // convert to ipv4 mapped ipv6 address;
235             scopeId = 0;
236             address = ipv4MappedIpv6Address(addr.getAddress());
237         }
238         int flags = fastOpen ? msgFastopen() : 0;
239         int res = sendToAddresses(fd, useIpv6(addr), memoryAddress, length, address, scopeId, port, flags);
240         if (res >= 0) {
241             return res;
242         }
243         if (res == ERRNO_EINPROGRESS_NEGATIVE && fastOpen) {
244             // This happens when we (as a client) have no pre-existing cookie for doing a fast-open connection.
245             // In this case, our TCP connection will be established normally, but no data was transmitted at this time.
246             // We'll just transmit the data with normal writes later.
247             return 0;
248         }
249         if (res == ERROR_ECONNREFUSED_NEGATIVE) {
250             throw new PortUnreachableException("sendToAddresses failed");
251         }
252         return ioResult("sendToAddresses", res);
253     }
254 
255     public final int sendToAddressesDomainSocket(long memoryAddress, int length, byte[] path) throws IOException {
256         int res = sendToAddressesDomainSocket(fd, memoryAddress, length, path);
257         if (res >= 0) {
258             return res;
259         }
260         return ioResult("sendToAddressesDomainSocket", res);
261     }
262 
263     public final DatagramSocketAddress recvFrom(ByteBuffer buf, int pos, int limit) throws IOException {
264         return recvFrom(fd, buf, pos, limit);
265     }
266 
267     public final DatagramSocketAddress recvFromAddress(long memoryAddress, int pos, int limit) throws IOException {
268         return recvFromAddress(fd, memoryAddress, pos, limit);
269     }
270 
271     public final DomainDatagramSocketAddress recvFromDomainSocket(ByteBuffer buf, int pos, int limit)
272             throws IOException {
273         return recvFromDomainSocket(fd, buf, pos, limit);
274     }
275 
276     public final DomainDatagramSocketAddress recvFromAddressDomainSocket(long memoryAddress, int pos, int limit)
277             throws IOException {
278         return recvFromAddressDomainSocket(fd, memoryAddress, pos, limit);
279     }
280 
281     public final int recvFd() throws IOException {
282         int res = recvFd(fd);
283         if (res > 0) {
284             return res;
285         }
286         if (res == 0) {
287             return -1;
288         }
289 
290         if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) {
291             // Everything consumed so just return -1 here.
292             return 0;
293         }
294         throw newIOException("recvFd", res);
295     }
296 
297     public final int sendFd(int fdToSend) throws IOException {
298         int res = sendFd(fd, fdToSend);
299         if (res >= 0) {
300             return res;
301         }
302         if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) {
303             // Everything consumed so just return -1 here.
304             return -1;
305         }
306         throw newIOException("sendFd", res);
307     }
308 
309     public final boolean connect(SocketAddress socketAddress) throws IOException {
310         int res;
311         if (socketAddress instanceof InetSocketAddress) {
312             InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
313             InetAddress inetAddress = inetSocketAddress.getAddress();
314             NativeInetAddress address = NativeInetAddress.newInstance(inetAddress);
315             res = connect(fd, useIpv6(inetAddress), address.address, address.scopeId, inetSocketAddress.getPort());
316         } else if (socketAddress instanceof DomainSocketAddress) {
317             DomainSocketAddress unixDomainSocketAddress = (DomainSocketAddress) socketAddress;
318             res = connectDomainSocket(fd, unixDomainSocketAddress.path().getBytes(CharsetUtil.UTF_8));
319         } else {
320             throw new Error("Unexpected SocketAddress implementation " + socketAddress);
321         }
322         if (res < 0) {
323             return handleConnectErrno("connect", res);
324         }
325         return true;
326     }
327 
328     public final boolean finishConnect() throws IOException {
329         int res = finishConnect(fd);
330         if (res < 0) {
331             return handleConnectErrno("finishConnect", res);
332         }
333         return true;
334     }
335 
336     public final void disconnect() throws IOException {
337         int res = disconnect(fd, ipv6);
338         if (res < 0) {
339             handleConnectErrno("disconnect", res);
340         }
341     }
342 
343     public final void bind(SocketAddress socketAddress) throws IOException {
344         if (socketAddress instanceof InetSocketAddress) {
345             InetSocketAddress addr = (InetSocketAddress) socketAddress;
346             InetAddress inetAddress = addr.getAddress();
347             NativeInetAddress address = NativeInetAddress.newInstance(inetAddress);
348             int res = bind(fd, useIpv6(inetAddress), address.address, address.scopeId, addr.getPort());
349             if (res < 0) {
350                 throw newIOException("bind", res);
351             }
352         } else if (socketAddress instanceof DomainSocketAddress) {
353             DomainSocketAddress addr = (DomainSocketAddress) socketAddress;
354             int res = bindDomainSocket(fd, addr.path().getBytes(CharsetUtil.UTF_8));
355             if (res < 0) {
356                 throw newIOException("bind", res);
357             }
358         } else {
359             throw new Error("Unexpected SocketAddress implementation " + socketAddress);
360         }
361     }
362 
363     public final void listen(int backlog) throws IOException {
364         int res = listen(fd, backlog);
365         if (res < 0) {
366             throw newIOException("listen", res);
367         }
368     }
369 
370     public final int accept(byte[] addr) throws IOException {
371         int res = accept(fd, addr);
372         if (res >= 0) {
373             return res;
374         }
375         if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) {
376             // Everything consumed so just return -1 here.
377             return -1;
378         }
379         throw newIOException("accept", res);
380     }
381 
382     public final InetSocketAddress remoteAddress() {
383         byte[] addr = remoteAddress(fd);
384         // addr may be null if getpeername failed.
385         // See https://github.com/netty/netty/issues/3328
386         return addr == null ? null : address(addr, 0, addr.length);
387     }
388 
389     public final InetSocketAddress localAddress() {
390         byte[] addr = localAddress(fd);
391         // addr may be null if getpeername failed.
392         // See https://github.com/netty/netty/issues/3328
393         return addr == null ? null : address(addr, 0, addr.length);
394     }
395 
396     public final int getReceiveBufferSize() throws IOException {
397         return getReceiveBufferSize(fd);
398     }
399 
400     public final int getSendBufferSize() throws IOException {
401         return getSendBufferSize(fd);
402     }
403 
404     public final boolean isKeepAlive() throws IOException {
405         return isKeepAlive(fd) != 0;
406     }
407 
408     public final boolean isTcpNoDelay() throws IOException {
409         return isTcpNoDelay(fd) != 0;
410     }
411 
412     public final boolean isReuseAddress() throws IOException {
413         return isReuseAddress(fd) != 0;
414     }
415 
416     public final boolean isReusePort() throws IOException {
417         return isReusePort(fd) != 0;
418     }
419 
420     public final boolean isBroadcast() throws IOException {
421         return isBroadcast(fd) != 0;
422     }
423 
424     public final int getSoLinger() throws IOException {
425         return getSoLinger(fd);
426     }
427 
428     public final int getSoError() throws IOException {
429         return getSoError(fd);
430     }
431 
432     public final int getTrafficClass() throws IOException {
433         return getTrafficClass(fd, ipv6);
434     }
435 
436     public final void setKeepAlive(boolean keepAlive) throws IOException {
437         setKeepAlive(fd, keepAlive ? 1 : 0);
438     }
439 
440     public final void setReceiveBufferSize(int receiveBufferSize) throws IOException  {
441         setReceiveBufferSize(fd, receiveBufferSize);
442     }
443 
444     public final void setSendBufferSize(int sendBufferSize) throws IOException {
445         setSendBufferSize(fd, sendBufferSize);
446     }
447 
448     public final void setTcpNoDelay(boolean tcpNoDelay) throws IOException  {
449         setTcpNoDelay(fd, tcpNoDelay ? 1 : 0);
450     }
451 
452     public final void setSoLinger(int soLinger) throws IOException {
453         setSoLinger(fd, soLinger);
454     }
455 
456     public final void setReuseAddress(boolean reuseAddress) throws IOException {
457         setReuseAddress(fd, reuseAddress ? 1 : 0);
458     }
459 
460     public final void setReusePort(boolean reusePort) throws IOException {
461         setReusePort(fd, reusePort ? 1 : 0);
462     }
463 
464     public final void setBroadcast(boolean broadcast) throws IOException {
465         setBroadcast(fd, broadcast ? 1 : 0);
466     }
467 
468     public final void setTrafficClass(int trafficClass) throws IOException {
469         setTrafficClass(fd, ipv6, trafficClass);
470     }
471 
472     public void setIntOpt(int level, int optname, int optvalue) throws IOException {
473         setIntOpt(fd, level, optname, optvalue);
474     }
475 
476     public void setRawOpt(int level, int optname, ByteBuffer optvalue) throws IOException {
477         int limit = optvalue.limit();
478         if (optvalue.isDirect()) {
479             setRawOptAddress(fd, level, optname,
480                              Buffer.nativeAddressOf(optvalue) + optvalue.position(), optvalue.remaining());
481         } else if (optvalue.hasArray()) {
482             setRawOptArray(fd, level, optname,
483                     optvalue.array(), optvalue.arrayOffset() + optvalue.position(), optvalue.remaining());
484         } else {
485             byte[] bytes = new byte[optvalue.remaining()];
486             optvalue.duplicate().get(bytes);
487             setRawOptArray(fd, level, optname, bytes, 0, bytes.length);
488         }
489         optvalue.position(limit);
490     }
491 
492     public int getIntOpt(int level, int optname) throws IOException {
493         return getIntOpt(fd, level, optname);
494     }
495 
496     public void getRawOpt(int level, int optname, ByteBuffer out) throws IOException {
497         if (out.isDirect()) {
498             getRawOptAddress(fd, level, optname, Buffer.nativeAddressOf(out) + out.position() , out.remaining());
499         } else if (out.hasArray()) {
500             getRawOptArray(fd, level, optname, out.array(), out.position() + out.arrayOffset(), out.remaining());
501         } else {
502             byte[] outArray = new byte[out.remaining()];
503             getRawOptArray(fd, level, optname, outArray, 0, outArray.length);
504             out.put(outArray);
505         }
506         out.position(out.limit());
507     }
508 
509     public static boolean isIPv6Preferred() {
510         return isIpv6Preferred;
511     }
512 
513     public static boolean shouldUseIpv6(ProtocolFamily family) {
514         if (family == null) {
515             return isIPv6Preferred();
516         }
517         if (family == SocketProtocolFamily.INET) {
518             return false;
519         }
520         if (family == SocketProtocolFamily.INET6) {
521             return true;
522         }
523         throw new IllegalArgumentException("ProtocolFamily not supported: " + family);
524     }
525 
526     private static native boolean isIPv6Preferred0(boolean ipv4Preferred);
527 
528     private static native boolean isIPv6(int fd);
529 
530     @Override
531     public String toString() {
532         return "Socket{" +
533                 "fd=" + fd +
534                 ", family=" + protocolFamily +
535                 '}';
536     }
537 
538     public static Socket newSocketStream() {
539         return new Socket(newSocketStream0(), isIPv6Preferred() ?
540                 SocketProtocolFamily.INET6 : SocketProtocolFamily.INET);
541     }
542 
543     public static Socket newSocketDgram() {
544         return new Socket(newSocketDgram0(),  isIPv6Preferred() ?
545                 SocketProtocolFamily.INET6 : SocketProtocolFamily.INET);
546     }
547 
548     public static Socket newSocketDomain() {
549         return new Socket(newSocketDomain0(), SocketProtocolFamily.UNIX);
550     }
551 
552     public static Socket newSocketDomainDgram() {
553         return new Socket(newSocketDomainDgram0(), SocketProtocolFamily.UNIX);
554     }
555 
556     public static void initialize() {
557         isIpv6Preferred = isIPv6Preferred0(NetUtil.isIpV4StackPreferred());
558     }
559 
560     protected static int newSocketStream0() {
561         return newSocketStream0(isIPv6Preferred());
562     }
563 
564     protected static int newSocketStream0(ProtocolFamily protocol) {
565         return newSocketStream0(shouldUseIpv6(protocol));
566     }
567 
568     protected static int newSocketStream0(boolean ipv6) {
569         int res = newSocketStreamFd(ipv6);
570         if (res < 0) {
571             throw new ChannelException(newIOException("newSocketStream", res));
572         }
573         return res;
574     }
575 
576     protected static int newSocketDgram0() {
577         return newSocketDgram0(isIPv6Preferred());
578     }
579 
580     protected static int newSocketDgram0(ProtocolFamily family) {
581         return newSocketDgram0(shouldUseIpv6(family));
582     }
583 
584     protected static int newSocketDgram0(boolean ipv6) {
585         int res = newSocketDgramFd(ipv6);
586         if (res < 0) {
587             throw new ChannelException(newIOException("newSocketDgram", res));
588         }
589         return res;
590     }
591 
592     protected static int newSocketDomain0() {
593         int res = newSocketDomainFd();
594         if (res < 0) {
595             throw new ChannelException(newIOException("newSocketDomain", res));
596         }
597         return res;
598     }
599 
600     protected static int newSocketDomainDgram0() {
601         int res = newSocketDomainDgramFd();
602         if (res < 0) {
603             throw new ChannelException(newIOException("newSocketDomainDgram", res));
604         }
605         return res;
606     }
607 
608     private static native int shutdown(int fd, boolean read, boolean write);
609     private static native int connect(int fd, boolean ipv6, byte[] address, int scopeId, int port);
610     private static native int connectDomainSocket(int fd, byte[] path);
611     private static native int finishConnect(int fd);
612     private static native int disconnect(int fd, boolean ipv6);
613     private static native int bind(int fd, boolean ipv6, byte[] address, int scopeId, int port);
614     private static native int bindDomainSocket(int fd, byte[] path);
615     private static native int listen(int fd, int backlog);
616     private static native int accept(int fd, byte[] addr);
617 
618     private static native byte[] remoteAddress(int fd);
619     private static native byte[] localAddress(int fd);
620 
621     private static native int sendTo(
622             int fd, boolean ipv6, ByteBuffer buf, int pos, int limit, byte[] address, int scopeId, int port,
623             int flags);
624 
625     private static native int sendToAddress(
626             int fd, boolean ipv6, long memoryAddress, int pos, int limit, byte[] address, int scopeId, int port,
627             int flags);
628 
629     private static native int sendToAddresses(
630             int fd, boolean ipv6, long memoryAddress, int length, byte[] address, int scopeId, int port,
631             int flags);
632 
633     private static native int sendToDomainSocket(int fd, ByteBuffer buf, int pos, int limit, byte[] path);
634     private static native int sendToAddressDomainSocket(int fd, long memoryAddress, int pos, int limit, byte[] path);
635     private static native int sendToAddressesDomainSocket(int fd, long memoryAddress, int length, byte[] path);
636 
637     private static native DatagramSocketAddress recvFrom(
638             int fd, ByteBuffer buf, int pos, int limit) throws IOException;
639     private static native DatagramSocketAddress recvFromAddress(
640             int fd, long memoryAddress, int pos, int limit) throws IOException;
641     private static native DomainDatagramSocketAddress recvFromDomainSocket(
642             int fd, ByteBuffer buf, int pos, int limit) throws IOException;
643     private static native DomainDatagramSocketAddress recvFromAddressDomainSocket(
644             int fd, long memoryAddress, int pos, int limit) throws IOException;
645     private static native int recvFd(int fd);
646     private static native int sendFd(int socketFd, int fd);
647     private static native int msgFastopen();
648 
649     private static native int newSocketStreamFd(boolean ipv6);
650     private static native int newSocketDgramFd(boolean ipv6);
651     private static native int newSocketDomainFd();
652     private static native int newSocketDomainDgramFd();
653 
654     private static native int isReuseAddress(int fd) throws IOException;
655     private static native int isReusePort(int fd) throws IOException;
656     private static native int getReceiveBufferSize(int fd) throws IOException;
657     private static native int getSendBufferSize(int fd) throws IOException;
658     private static native int isKeepAlive(int fd) throws IOException;
659     private static native int isTcpNoDelay(int fd) throws IOException;
660     private static native int isBroadcast(int fd) throws IOException;
661     private static native int getSoLinger(int fd) throws IOException;
662     private static native int getSoError(int fd) throws IOException;
663     private static native int getTrafficClass(int fd, boolean ipv6) throws IOException;
664 
665     private static native void setReuseAddress(int fd, int reuseAddress) throws IOException;
666     private static native void setReusePort(int fd, int reuseAddress) throws IOException;
667     private static native void setKeepAlive(int fd, int keepAlive) throws IOException;
668     private static native void setReceiveBufferSize(int fd, int receiveBufferSize) throws IOException;
669     private static native void setSendBufferSize(int fd, int sendBufferSize) throws IOException;
670     private static native void setTcpNoDelay(int fd, int tcpNoDelay) throws IOException;
671     private static native void setSoLinger(int fd, int soLinger) throws IOException;
672     private static native void setBroadcast(int fd, int broadcast) throws IOException;
673     private static native void setTrafficClass(int fd, boolean ipv6, int trafficClass) throws IOException;
674 
675     private static native void setIntOpt(int fd, int level, int optname, int optvalue) throws IOException;
676     private static native void setRawOptArray(int fd, int level, int optname, byte[] optvalue, int offset, int length)
677             throws IOException;
678     private static native void setRawOptAddress(int fd, int level, int optname, long optvalueMemoryAddress, int length)
679             throws IOException;
680     private static native int getIntOpt(int fd, int level, int optname) throws IOException;
681     private static native void getRawOptArray(int fd, int level, int optname, byte[] out, int offset, int length)
682             throws IOException;
683     private static native void getRawOptAddress(int fd, int level, int optname, long outMemoryAddress, int length)
684             throws IOException;
685 }