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 final int recvFd() throws IOException {
272         int res = recvFd(fd);
273         if (res > 0) {
274             return res;
275         }
276         if (res == 0) {
277             return -1;
278         }
279 
280         if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) {
281             // Everything consumed so just return -1 here.
282             return 0;
283         }
284         throw newIOException("recvFd", res);
285     }
286 
287     public final int sendFd(int fdToSend) throws IOException {
288         int res = sendFd(fd, fdToSend);
289         if (res >= 0) {
290             return res;
291         }
292         if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) {
293             // Everything consumed so just return -1 here.
294             return -1;
295         }
296         throw newIOException("sendFd", res);
297     }
298 
299     public final boolean connect(SocketAddress socketAddress) throws IOException {
300         int res;
301         if (socketAddress instanceof InetSocketAddress) {
302             InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
303             InetAddress inetAddress = inetSocketAddress.getAddress();
304             NativeInetAddress address = NativeInetAddress.newInstance(inetAddress);
305             res = connect(fd, useIpv6(inetAddress), address.address, address.scopeId, inetSocketAddress.getPort());
306         } else if (socketAddress instanceof DomainSocketAddress) {
307             DomainSocketAddress unixDomainSocketAddress = (DomainSocketAddress) socketAddress;
308             res = connectDomainSocket(fd, unixDomainSocketAddress.path().getBytes(CharsetUtil.UTF_8));
309         } else {
310             throw new Error("Unexpected SocketAddress implementation " + socketAddress);
311         }
312         if (res < 0) {
313             return handleConnectErrno("connect", res);
314         }
315         return true;
316     }
317 
318     public final boolean finishConnect() throws IOException {
319         int res = finishConnect(fd);
320         if (res < 0) {
321             return handleConnectErrno("finishConnect", res);
322         }
323         return true;
324     }
325 
326     public final void disconnect() throws IOException {
327         int res = disconnect(fd, ipv6);
328         if (res < 0) {
329             handleConnectErrno("disconnect", res);
330         }
331     }
332 
333     public final void bind(SocketAddress socketAddress) throws IOException {
334         if (socketAddress instanceof InetSocketAddress) {
335             InetSocketAddress addr = (InetSocketAddress) socketAddress;
336             InetAddress inetAddress = addr.getAddress();
337             NativeInetAddress address = NativeInetAddress.newInstance(inetAddress);
338             int res = bind(fd, useIpv6(inetAddress), address.address, address.scopeId, addr.getPort());
339             if (res < 0) {
340                 throw newIOException("bind", res);
341             }
342         } else if (socketAddress instanceof DomainSocketAddress) {
343             DomainSocketAddress addr = (DomainSocketAddress) socketAddress;
344             int res = bindDomainSocket(fd, addr.path().getBytes(CharsetUtil.UTF_8));
345             if (res < 0) {
346                 throw newIOException("bind", res);
347             }
348         } else {
349             throw new Error("Unexpected SocketAddress implementation " + socketAddress);
350         }
351     }
352 
353     public final void listen(int backlog) throws IOException {
354         int res = listen(fd, backlog);
355         if (res < 0) {
356             throw newIOException("listen", res);
357         }
358     }
359 
360     public final int accept(byte[] addr) throws IOException {
361         int res = accept(fd, addr);
362         if (res >= 0) {
363             return res;
364         }
365         if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) {
366             // Everything consumed so just return -1 here.
367             return -1;
368         }
369         throw newIOException("accept", res);
370     }
371 
372     public final InetSocketAddress remoteAddress() {
373         byte[] addr = remoteAddress(fd);
374         // addr may be null if getpeername failed.
375         // See https://github.com/netty/netty/issues/3328
376         return addr == null ? null : address(addr, 0, addr.length);
377     }
378 
379     public final InetSocketAddress localAddress() {
380         byte[] addr = localAddress(fd);
381         // addr may be null if getpeername failed.
382         // See https://github.com/netty/netty/issues/3328
383         return addr == null ? null : address(addr, 0, addr.length);
384     }
385 
386     public final int getReceiveBufferSize() throws IOException {
387         return getReceiveBufferSize(fd);
388     }
389 
390     public final int getSendBufferSize() throws IOException {
391         return getSendBufferSize(fd);
392     }
393 
394     public final boolean isKeepAlive() throws IOException {
395         return isKeepAlive(fd) != 0;
396     }
397 
398     public final boolean isTcpNoDelay() throws IOException {
399         return isTcpNoDelay(fd) != 0;
400     }
401 
402     public final boolean isReuseAddress() throws IOException {
403         return isReuseAddress(fd) != 0;
404     }
405 
406     public final boolean isReusePort() throws IOException {
407         return isReusePort(fd) != 0;
408     }
409 
410     public final boolean isBroadcast() throws IOException {
411         return isBroadcast(fd) != 0;
412     }
413 
414     public final int getSoLinger() throws IOException {
415         return getSoLinger(fd);
416     }
417 
418     public final int getSoError() throws IOException {
419         return getSoError(fd);
420     }
421 
422     public final int getTrafficClass() throws IOException {
423         return getTrafficClass(fd, ipv6);
424     }
425 
426     public final void setKeepAlive(boolean keepAlive) throws IOException {
427         setKeepAlive(fd, keepAlive ? 1 : 0);
428     }
429 
430     public final void setReceiveBufferSize(int receiveBufferSize) throws IOException  {
431         setReceiveBufferSize(fd, receiveBufferSize);
432     }
433 
434     public final void setSendBufferSize(int sendBufferSize) throws IOException {
435         setSendBufferSize(fd, sendBufferSize);
436     }
437 
438     public final void setTcpNoDelay(boolean tcpNoDelay) throws IOException  {
439         setTcpNoDelay(fd, tcpNoDelay ? 1 : 0);
440     }
441 
442     public final void setSoLinger(int soLinger) throws IOException {
443         setSoLinger(fd, soLinger);
444     }
445 
446     public final void setReuseAddress(boolean reuseAddress) throws IOException {
447         setReuseAddress(fd, reuseAddress ? 1 : 0);
448     }
449 
450     public final void setReusePort(boolean reusePort) throws IOException {
451         setReusePort(fd, reusePort ? 1 : 0);
452     }
453 
454     public final void setBroadcast(boolean broadcast) throws IOException {
455         setBroadcast(fd, broadcast ? 1 : 0);
456     }
457 
458     public final void setTrafficClass(int trafficClass) throws IOException {
459         setTrafficClass(fd, ipv6, trafficClass);
460     }
461 
462     public void setIntOpt(int level, int optname, int optvalue) throws IOException {
463         setIntOpt(fd, level, optname, optvalue);
464     }
465 
466     public void setRawOpt(int level, int optname, ByteBuffer optvalue) throws IOException {
467         int limit = optvalue.limit();
468         if (optvalue.isDirect()) {
469             setRawOptAddress(fd, level, optname,
470                     Buffer.memoryAddress(optvalue) + optvalue.position(), optvalue.remaining());
471         } else if (optvalue.hasArray()) {
472             setRawOptArray(fd, level, optname,
473                     optvalue.array(), optvalue.arrayOffset() + optvalue.position(), optvalue.remaining());
474         } else {
475             byte[] bytes = new byte[optvalue.remaining()];
476             optvalue.duplicate().get(bytes);
477             setRawOptArray(fd, level, optname, bytes, 0, bytes.length);
478         }
479         optvalue.position(limit);
480     }
481 
482     public int getIntOpt(int level, int optname) throws IOException {
483         return getIntOpt(fd, level, optname);
484     }
485 
486     public void getRawOpt(int level, int optname, ByteBuffer out) throws IOException {
487         if (out.isDirect()) {
488             getRawOptAddress(fd, level, optname, Buffer.memoryAddress(out) + out.position() , out.remaining());
489         } else if (out.hasArray()) {
490             getRawOptArray(fd, level, optname, out.array(), out.position() + out.arrayOffset(), out.remaining());
491         } else {
492             byte[] outArray = new byte[out.remaining()];
493             getRawOptArray(fd, level, optname, outArray, 0, outArray.length);
494             out.put(outArray);
495         }
496         out.position(out.limit());
497     }
498 
499     public static boolean isIPv6Preferred() {
500         return isIpv6Preferred;
501     }
502 
503     public static boolean shouldUseIpv6(InternetProtocolFamily family) {
504         return family == null ? isIPv6Preferred() :
505                         family == InternetProtocolFamily.IPv6;
506     }
507 
508     private static native boolean isIPv6Preferred0(boolean ipv4Preferred);
509 
510     private static native boolean isIPv6(int fd);
511 
512     @Override
513     public String toString() {
514         return "Socket{" +
515                 "fd=" + fd +
516                 '}';
517     }
518 
519     public static Socket newSocketStream() {
520         return new Socket(newSocketStream0());
521     }
522 
523     public static Socket newSocketDgram() {
524         return new Socket(newSocketDgram0());
525     }
526 
527     public static Socket newSocketDomain() {
528         return new Socket(newSocketDomain0());
529     }
530 
531     public static Socket newSocketDomainDgram() {
532         return new Socket(newSocketDomainDgram0());
533     }
534 
535     public static void initialize() {
536         isIpv6Preferred = isIPv6Preferred0(NetUtil.isIpV4StackPreferred());
537     }
538 
539     protected static int newSocketStream0() {
540         return newSocketStream0(isIPv6Preferred());
541     }
542 
543     protected static int newSocketStream0(InternetProtocolFamily protocol) {
544         return newSocketStream0(shouldUseIpv6(protocol));
545     }
546 
547     protected static int newSocketStream0(boolean ipv6) {
548         int res = newSocketStreamFd(ipv6);
549         if (res < 0) {
550             throw new ChannelException(newIOException("newSocketStream", res));
551         }
552         return res;
553     }
554 
555     protected static int newSocketDgram0() {
556         return newSocketDgram0(isIPv6Preferred());
557     }
558 
559     protected static int newSocketDgram0(InternetProtocolFamily family) {
560         return newSocketDgram0(shouldUseIpv6(family));
561     }
562 
563     protected static int newSocketDgram0(boolean ipv6) {
564         int res = newSocketDgramFd(ipv6);
565         if (res < 0) {
566             throw new ChannelException(newIOException("newSocketDgram", res));
567         }
568         return res;
569     }
570 
571     protected static int newSocketDomain0() {
572         int res = newSocketDomainFd();
573         if (res < 0) {
574             throw new ChannelException(newIOException("newSocketDomain", res));
575         }
576         return res;
577     }
578 
579     protected static int newSocketDomainDgram0() {
580         int res = newSocketDomainDgramFd();
581         if (res < 0) {
582             throw new ChannelException(newIOException("newSocketDomainDgram", res));
583         }
584         return res;
585     }
586 
587     private static native int shutdown(int fd, boolean read, boolean write);
588     private static native int connect(int fd, boolean ipv6, byte[] address, int scopeId, int port);
589     private static native int connectDomainSocket(int fd, byte[] path);
590     private static native int finishConnect(int fd);
591     private static native int disconnect(int fd, boolean ipv6);
592     private static native int bind(int fd, boolean ipv6, byte[] address, int scopeId, int port);
593     private static native int bindDomainSocket(int fd, byte[] path);
594     private static native int listen(int fd, int backlog);
595     private static native int accept(int fd, byte[] addr);
596 
597     private static native byte[] remoteAddress(int fd);
598     private static native byte[] localAddress(int fd);
599 
600     private static native int sendTo(
601             int fd, boolean ipv6, ByteBuffer buf, int pos, int limit, byte[] address, int scopeId, int port,
602             int flags);
603 
604     private static native int sendToAddress(
605             int fd, boolean ipv6, long memoryAddress, int pos, int limit, byte[] address, int scopeId, int port,
606             int flags);
607 
608     private static native int sendToAddresses(
609             int fd, boolean ipv6, long memoryAddress, int length, byte[] address, int scopeId, int port,
610             int flags);
611 
612     private static native int sendToDomainSocket(int fd, ByteBuffer buf, int pos, int limit, byte[] path);
613     private static native int sendToAddressDomainSocket(int fd, long memoryAddress, int pos, int limit, byte[] path);
614     private static native int sendToAddressesDomainSocket(int fd, long memoryAddress, int length, byte[] path);
615 
616     private static native DatagramSocketAddress recvFrom(
617             int fd, ByteBuffer buf, int pos, int limit) throws IOException;
618     private static native DatagramSocketAddress recvFromAddress(
619             int fd, long memoryAddress, int pos, int limit) throws IOException;
620     private static native DomainDatagramSocketAddress recvFromDomainSocket(
621             int fd, ByteBuffer buf, int pos, int limit) throws IOException;
622     private static native DomainDatagramSocketAddress recvFromAddressDomainSocket(
623             int fd, long memoryAddress, int pos, int limit) throws IOException;
624     private static native int recvFd(int fd);
625     private static native int sendFd(int socketFd, int fd);
626     private static native int msgFastopen();
627 
628     private static native int newSocketStreamFd(boolean ipv6);
629     private static native int newSocketDgramFd(boolean ipv6);
630     private static native int newSocketDomainFd();
631     private static native int newSocketDomainDgramFd();
632 
633     private static native int isReuseAddress(int fd) throws IOException;
634     private static native int isReusePort(int fd) throws IOException;
635     private static native int getReceiveBufferSize(int fd) throws IOException;
636     private static native int getSendBufferSize(int fd) throws IOException;
637     private static native int isKeepAlive(int fd) throws IOException;
638     private static native int isTcpNoDelay(int fd) throws IOException;
639     private static native int isBroadcast(int fd) throws IOException;
640     private static native int getSoLinger(int fd) throws IOException;
641     private static native int getSoError(int fd) throws IOException;
642     private static native int getTrafficClass(int fd, boolean ipv6) throws IOException;
643 
644     private static native void setReuseAddress(int fd, int reuseAddress) throws IOException;
645     private static native void setReusePort(int fd, int reuseAddress) throws IOException;
646     private static native void setKeepAlive(int fd, int keepAlive) throws IOException;
647     private static native void setReceiveBufferSize(int fd, int receiveBufferSize) throws IOException;
648     private static native void setSendBufferSize(int fd, int sendBufferSize) throws IOException;
649     private static native void setTcpNoDelay(int fd, int tcpNoDelay) throws IOException;
650     private static native void setSoLinger(int fd, int soLinger) throws IOException;
651     private static native void setBroadcast(int fd, int broadcast) throws IOException;
652     private static native void setTrafficClass(int fd, boolean ipv6, int trafficClass) throws IOException;
653 
654     private static native void setIntOpt(int fd, int level, int optname, int optvalue) throws IOException;
655     private static native void setRawOptArray(int fd, int level, int optname, byte[] optvalue, int offset, int length)
656             throws IOException;
657     private static native void setRawOptAddress(int fd, int level, int optname, long optvalueMemoryAddress, int length)
658             throws IOException;
659     private static native int getIntOpt(int fd, int level, int optname) throws IOException;
660     private static native void getRawOptArray(int fd, int level, int optname, byte[] out, int offset, int length)
661             throws IOException;
662     private static native void getRawOptAddress(int fd, int level, int optname, long outMemoryAddress, int length)
663             throws IOException;
664 }