1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.epoll;
17
18 import io.netty.channel.ChannelException;
19 import io.netty.channel.DefaultFileRegion;
20 import io.netty.channel.socket.InternetProtocolFamily;
21 import io.netty.channel.socket.SocketProtocolFamily;
22 import io.netty.channel.unix.Errors;
23 import io.netty.channel.unix.NativeInetAddress;
24 import io.netty.channel.unix.PeerCredentials;
25 import io.netty.channel.unix.Socket;
26 import io.netty.util.internal.SocketUtils;
27 import io.netty.util.internal.UnstableApi;
28
29 import java.io.IOException;
30 import java.net.Inet6Address;
31 import java.net.InetAddress;
32 import java.net.NetworkInterface;
33 import java.net.UnknownHostException;
34 import java.util.Enumeration;
35
36 import static io.netty.channel.unix.Errors.ioResult;
37 import static io.netty.channel.unix.Errors.newIOException;
38
39
40
41
42 @UnstableApi
43 public final class LinuxSocket extends Socket {
44 private static final long MAX_UINT32_T = 0xFFFFFFFFL;
45
46 LinuxSocket(int fd) {
47 super(fd);
48 }
49
50 SocketProtocolFamily family() {
51 return ipv6 ? SocketProtocolFamily.INET6 : SocketProtocolFamily.INET;
52 }
53
54 int sendmmsg(NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
55 int offset, int len) throws IOException {
56 return Native.sendmmsg(intValue(), ipv6, msgs, offset, len);
57 }
58
59 int recvmmsg(NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
60 int offset, int len) throws IOException {
61 return Native.recvmmsg(intValue(), ipv6, msgs, offset, len);
62 }
63
64 int recvmsg(NativeDatagramPacketArray.NativeDatagramPacket msg) throws IOException {
65 return Native.recvmsg(intValue(), ipv6, msg);
66 }
67
68 void setTimeToLive(int ttl) throws IOException {
69 setTimeToLive(intValue(), ttl);
70 }
71
72 void setInterface(InetAddress address) throws IOException {
73 final NativeInetAddress a = NativeInetAddress.newInstance(address);
74 setInterface(intValue(), ipv6, a.address(), a.scopeId(), interfaceIndex(address));
75 }
76
77 void setNetworkInterface(NetworkInterface netInterface) throws IOException {
78 InetAddress address = deriveInetAddress(netInterface, family() == SocketProtocolFamily.INET6);
79 if (address.equals(family() == SocketProtocolFamily.INET ? Native.INET_ANY : Native.INET6_ANY)) {
80 throw new IOException("NetworkInterface does not support " + family());
81 }
82 final NativeInetAddress nativeAddress = NativeInetAddress.newInstance(address);
83 setInterface(intValue(), ipv6, nativeAddress.address(), nativeAddress.scopeId(), interfaceIndex(netInterface));
84 }
85
86 InetAddress getInterface() throws IOException {
87 NetworkInterface inf = getNetworkInterface();
88 if (inf != null) {
89 Enumeration<InetAddress> addresses = SocketUtils.addressesFromNetworkInterface(inf);
90 if (addresses.hasMoreElements()) {
91 return addresses.nextElement();
92 }
93 }
94 return null;
95 }
96
97 NetworkInterface getNetworkInterface() throws IOException {
98 int ret = getInterface(intValue(), ipv6);
99 if (ipv6) {
100 return NetworkInterface.getByIndex(ret);
101 }
102 InetAddress address = inetAddress(ret);
103 return address != null ? NetworkInterface.getByInetAddress(address) : null;
104 }
105
106 private static InetAddress inetAddress(int value) {
107 byte[] var1 = {
108 (byte) (value >>> 24 & 255),
109 (byte) (value >>> 16 & 255),
110 (byte) (value >>> 8 & 255),
111 (byte) (value & 255)
112 };
113
114 try {
115 return InetAddress.getByAddress(var1);
116 } catch (UnknownHostException ignore) {
117 return null;
118 }
119 }
120
121 void joinGroup(InetAddress group, NetworkInterface netInterface, InetAddress source) throws IOException {
122 final NativeInetAddress g = NativeInetAddress.newInstance(group);
123 final boolean isIpv6 = group instanceof Inet6Address;
124 final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
125 if (source != null) {
126 if (source.getClass() != group.getClass()) {
127 throw new IllegalArgumentException("Source address is different type to group");
128 }
129 final NativeInetAddress s = NativeInetAddress.newInstance(source);
130 joinSsmGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(),
131 g.scopeId(), interfaceIndex(netInterface), s.address());
132 } else {
133 joinGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
134 }
135 }
136
137 void leaveGroup(InetAddress group, NetworkInterface netInterface, InetAddress source) throws IOException {
138 final NativeInetAddress g = NativeInetAddress.newInstance(group);
139 final boolean isIpv6 = group instanceof Inet6Address;
140 final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
141 if (source != null) {
142 if (source.getClass() != group.getClass()) {
143 throw new IllegalArgumentException("Source address is different type to group");
144 }
145 final NativeInetAddress s = NativeInetAddress.newInstance(source);
146 leaveSsmGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(),
147 g.scopeId(), interfaceIndex(netInterface), s.address());
148 } else {
149 leaveGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
150 }
151 }
152
153 private static int interfaceIndex(NetworkInterface networkInterface) {
154 return networkInterface.getIndex();
155 }
156
157 private static int interfaceIndex(InetAddress address) throws IOException {
158 NetworkInterface iface = NetworkInterface.getByInetAddress(address);
159 if (iface != null) {
160 return iface.getIndex();
161 }
162 return -1;
163 }
164
165 void setTcpDeferAccept(int deferAccept) throws IOException {
166 setTcpDeferAccept(intValue(), deferAccept);
167 }
168
169 void setTcpQuickAck(boolean quickAck) throws IOException {
170 setTcpQuickAck(intValue(), quickAck ? 1 : 0);
171 }
172
173 void setTcpCork(boolean tcpCork) throws IOException {
174 setTcpCork(intValue(), tcpCork ? 1 : 0);
175 }
176
177 void setSoBusyPoll(int loopMicros) throws IOException {
178 setSoBusyPoll(intValue(), loopMicros);
179 }
180
181 void setTcpNotSentLowAt(long tcpNotSentLowAt) throws IOException {
182 if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) {
183 throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t");
184 }
185 setTcpNotSentLowAt(intValue(), (int) tcpNotSentLowAt);
186 }
187
188 void setTcpFastOpen(int tcpFastopenBacklog) throws IOException {
189 setTcpFastOpen(intValue(), tcpFastopenBacklog);
190 }
191
192 void setTcpKeepIdle(int seconds) throws IOException {
193 setTcpKeepIdle(intValue(), seconds);
194 }
195
196 void setTcpKeepIntvl(int seconds) throws IOException {
197 setTcpKeepIntvl(intValue(), seconds);
198 }
199
200 void setTcpKeepCnt(int probes) throws IOException {
201 setTcpKeepCnt(intValue(), probes);
202 }
203
204 void setTcpUserTimeout(int milliseconds) throws IOException {
205 setTcpUserTimeout(intValue(), milliseconds);
206 }
207
208 void setIpBindAddressNoPort(boolean enabled) throws IOException {
209 setIpBindAddressNoPort(intValue(), enabled ? 1 : 0);
210 }
211
212 void setIpFreeBind(boolean enabled) throws IOException {
213 setIpFreeBind(intValue(), enabled ? 1 : 0);
214 }
215
216 void setIpTransparent(boolean enabled) throws IOException {
217 setIpTransparent(intValue(), enabled ? 1 : 0);
218 }
219
220 void setIpRecvOrigDestAddr(boolean enabled) throws IOException {
221 setIpRecvOrigDestAddr(intValue(), enabled ? 1 : 0);
222 }
223
224 int getTimeToLive() throws IOException {
225 return getTimeToLive(intValue());
226 }
227
228 void getTcpInfo(EpollTcpInfo info) throws IOException {
229 getTcpInfo(intValue(), info.info);
230 }
231
232 void setTcpMd5Sig(InetAddress address, byte[] key) throws IOException {
233 final NativeInetAddress a = NativeInetAddress.newInstance(address);
234 setTcpMd5Sig(intValue(), ipv6, a.address(), a.scopeId(), key);
235 }
236
237 boolean isTcpCork() throws IOException {
238 return isTcpCork(intValue()) != 0;
239 }
240
241 int getSoBusyPoll() throws IOException {
242 return getSoBusyPoll(intValue());
243 }
244
245 int getTcpDeferAccept() throws IOException {
246 return getTcpDeferAccept(intValue());
247 }
248
249 boolean isTcpQuickAck() throws IOException {
250 return isTcpQuickAck(intValue()) != 0;
251 }
252
253 long getTcpNotSentLowAt() throws IOException {
254 return getTcpNotSentLowAt(intValue()) & MAX_UINT32_T;
255 }
256
257 int getTcpKeepIdle() throws IOException {
258 return getTcpKeepIdle(intValue());
259 }
260
261 int getTcpKeepIntvl() throws IOException {
262 return getTcpKeepIntvl(intValue());
263 }
264
265 int getTcpKeepCnt() throws IOException {
266 return getTcpKeepCnt(intValue());
267 }
268
269 int getTcpUserTimeout() throws IOException {
270 return getTcpUserTimeout(intValue());
271 }
272
273 boolean isIpBindAddressNoPort() throws IOException {
274 return isIpBindAddressNoPort(intValue()) != 0;
275 }
276
277 boolean isIpFreeBind() throws IOException {
278 return isIpFreeBind(intValue()) != 0;
279 }
280
281 boolean isIpTransparent() throws IOException {
282 return isIpTransparent(intValue()) != 0;
283 }
284
285 boolean isIpRecvOrigDestAddr() throws IOException {
286 return isIpRecvOrigDestAddr(intValue()) != 0;
287 }
288
289 PeerCredentials getPeerCredentials() throws IOException {
290 return getPeerCredentials(intValue());
291 }
292
293 boolean isLoopbackModeDisabled() throws IOException {
294 return getIpMulticastLoop(intValue(), ipv6) == 0;
295 }
296
297 void setLoopbackModeDisabled(boolean loopbackModeDisabled) throws IOException {
298 setIpMulticastLoop(intValue(), ipv6, loopbackModeDisabled ? 0 : 1);
299 }
300
301 boolean isUdpGro() throws IOException {
302 return isUdpGro(intValue()) != 0;
303 }
304
305 void setUdpGro(boolean gro) throws IOException {
306 setUdpGro(intValue(), gro ? 1 : 0);
307 }
308
309 long sendFile(DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException {
310
311
312 src.open();
313
314 long res = sendFile(intValue(), src, baseOffset, offset, length);
315 if (res >= 0) {
316 return res;
317 }
318 return ioResult("sendfile", (int) res);
319 }
320
321 public void bindVSock(VSockAddress address) throws IOException {
322 int res = bindVSock(intValue(), address.getCid(), address.getPort());
323 if (res < 0) {
324 throw newIOException("bindVSock", res);
325 }
326 }
327
328 public boolean connectVSock(VSockAddress address) throws IOException {
329 int res = connectVSock(intValue(), address.getCid(), address.getPort());
330 if (res < 0) {
331 return Errors.handleConnectErrno("connectVSock", res);
332 }
333 return true;
334 }
335
336 public VSockAddress remoteVSockAddress() {
337 byte[] addr = remoteVSockAddress(intValue());
338 if (addr == null) {
339 return null;
340 }
341 int cid = getIntAt(addr, 0);
342 int port = getIntAt(addr, 4);
343 return new VSockAddress(cid, port);
344 }
345
346 public VSockAddress localVSockAddress() {
347 byte[] addr = localVSockAddress(intValue());
348 if (addr == null) {
349 return null;
350 }
351 int cid = getIntAt(addr, 0);
352 int port = getIntAt(addr, 4);
353 return new VSockAddress(cid, port);
354 }
355
356 private static int getIntAt(byte[] array, int startIndex) {
357 return array[startIndex] << 24 | (array[startIndex + 1] & 0xFF) << 16
358 | (array[startIndex + 2] & 0xFF) << 8 | (array[startIndex + 3] & 0xFF);
359 }
360
361 private static InetAddress deriveInetAddress(NetworkInterface netInterface, boolean ipv6) {
362 final InetAddress ipAny = ipv6 ? Native.INET6_ANY : Native.INET_ANY;
363 if (netInterface != null) {
364 final Enumeration<InetAddress> ias = netInterface.getInetAddresses();
365 while (ias.hasMoreElements()) {
366 final InetAddress ia = ias.nextElement();
367 final boolean isV6 = ia instanceof Inet6Address;
368 if (isV6 == ipv6) {
369 return ia;
370 }
371 }
372 }
373 return ipAny;
374 }
375
376 public static LinuxSocket newSocket(int fd) {
377 return new LinuxSocket(fd);
378 }
379
380 public static LinuxSocket newVSockStream() {
381 return new LinuxSocket(newVSockStream0());
382 }
383
384 static int newVSockStream0() {
385 int res = newVSockStreamFd();
386 if (res < 0) {
387 throw new ChannelException(newIOException("newVSockStream", res));
388 }
389 return res;
390 }
391
392 public static LinuxSocket newSocketStream(boolean ipv6) {
393 return new LinuxSocket(newSocketStream0(ipv6));
394 }
395
396
397
398
399 @Deprecated
400 public static LinuxSocket newSocketStream(InternetProtocolFamily protocol) {
401 return new LinuxSocket(newSocketStream0(protocol));
402 }
403
404 public static LinuxSocket newSocketStream(SocketProtocolFamily protocol) {
405 return new LinuxSocket(newSocketStream0(protocol));
406 }
407
408 public static LinuxSocket newSocketStream() {
409 return newSocketStream(isIPv6Preferred());
410 }
411
412 public static LinuxSocket newSocketDgram(boolean ipv6) {
413 return new LinuxSocket(newSocketDgram0(ipv6));
414 }
415
416
417
418
419 @Deprecated
420 public static LinuxSocket newSocketDgram(InternetProtocolFamily family) {
421 return new LinuxSocket(newSocketDgram0(family));
422 }
423
424 public static LinuxSocket newSocketDgram(SocketProtocolFamily family) {
425 return new LinuxSocket(newSocketDgram0(family));
426 }
427
428 public static LinuxSocket newSocketDgram() {
429 return newSocketDgram(isIPv6Preferred());
430 }
431
432 public static LinuxSocket newSocketDomain() {
433 return new LinuxSocket(newSocketDomain0());
434 }
435
436 public static LinuxSocket newSocketDomainDgram() {
437 return new LinuxSocket(newSocketDomainDgram0());
438 }
439
440 private static native int newVSockStreamFd();
441 private static native int bindVSock(int fd, int cid, int port);
442 private static native int connectVSock(int fd, int cid, int port);
443 private static native byte[] remoteVSockAddress(int fd);
444 private static native byte[] localVSockAddress(int fd);
445
446 private static native void joinGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
447 int scopeId, int interfaceIndex) throws IOException;
448 private static native void joinSsmGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
449 int scopeId, int interfaceIndex, byte[] source) throws IOException;
450 private static native void leaveGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
451 int scopeId, int interfaceIndex) throws IOException;
452 private static native void leaveSsmGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
453 int scopeId, int interfaceIndex, byte[] source) throws IOException;
454 private static native long sendFile(int socketFd, DefaultFileRegion src, long baseOffset,
455 long offset, long length) throws IOException;
456
457 private static native int getTcpDeferAccept(int fd) throws IOException;
458 private static native int isTcpQuickAck(int fd) throws IOException;
459 private static native int isTcpCork(int fd) throws IOException;
460 private static native int getSoBusyPoll(int fd) throws IOException;
461 private static native int getTcpNotSentLowAt(int fd) throws IOException;
462 private static native int getTcpKeepIdle(int fd) throws IOException;
463 private static native int getTcpKeepIntvl(int fd) throws IOException;
464 private static native int getTcpKeepCnt(int fd) throws IOException;
465 private static native int getTcpUserTimeout(int fd) throws IOException;
466 private static native int getTimeToLive(int fd) throws IOException;
467 private static native int isIpBindAddressNoPort(int fd) throws IOException;
468 private static native int isIpFreeBind(int fd) throws IOException;
469 private static native int isIpTransparent(int fd) throws IOException;
470 private static native int isIpRecvOrigDestAddr(int fd) throws IOException;
471 private static native void getTcpInfo(int fd, long[] array) throws IOException;
472 private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
473
474 private static native void setTcpDeferAccept(int fd, int deferAccept) throws IOException;
475 private static native void setTcpQuickAck(int fd, int quickAck) throws IOException;
476 private static native void setTcpCork(int fd, int tcpCork) throws IOException;
477 private static native void setSoBusyPoll(int fd, int loopMicros) throws IOException;
478 private static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt) throws IOException;
479 private static native void setTcpFastOpen(int fd, int tcpFastopenBacklog) throws IOException;
480 private static native void setTcpKeepIdle(int fd, int seconds) throws IOException;
481 private static native void setTcpKeepIntvl(int fd, int seconds) throws IOException;
482 private static native void setTcpKeepCnt(int fd, int probes) throws IOException;
483 private static native void setTcpUserTimeout(int fd, int milliseconds)throws IOException;
484 private static native void setIpBindAddressNoPort(int fd, int ipBindAddressNoPort) throws IOException;
485 private static native void setIpFreeBind(int fd, int freeBind) throws IOException;
486 private static native void setIpTransparent(int fd, int transparent) throws IOException;
487 private static native void setIpRecvOrigDestAddr(int fd, int transparent) throws IOException;
488 private static native void setTcpMd5Sig(
489 int fd, boolean ipv6, byte[] address, int scopeId, byte[] key) throws IOException;
490 private static native void setInterface(
491 int fd, boolean ipv6, byte[] interfaceAddress, int scopeId, int networkInterfaceIndex) throws IOException;
492 private static native int getInterface(int fd, boolean ipv6);
493 private static native int getIpMulticastLoop(int fd, boolean ipv6) throws IOException;
494 private static native void setIpMulticastLoop(int fd, boolean ipv6, int enabled) throws IOException;
495 private static native void setTimeToLive(int fd, int ttl) throws IOException;
496 private static native int isUdpGro(int fd) throws IOException;
497 private static native void setUdpGro(int fd, int gro) throws IOException;
498 }