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