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