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