1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.uring;
17
18 import io.netty.channel.ChannelException;
19 import io.netty.channel.socket.SocketProtocolFamily;
20 import io.netty.channel.unix.NativeInetAddress;
21 import io.netty.channel.unix.PeerCredentials;
22 import io.netty.channel.unix.Socket;
23 import io.netty.util.internal.SocketUtils;
24
25 import java.io.IOException;
26 import java.net.Inet6Address;
27 import java.net.InetAddress;
28 import java.net.NetworkInterface;
29 import java.net.UnknownHostException;
30 import java.util.Enumeration;
31
32
33
34
35 final class LinuxSocket extends Socket {
36 static final InetAddress INET6_ANY = unsafeInetAddrByName("::");
37 private static final InetAddress INET_ANY = unsafeInetAddrByName("0.0.0.0");
38 private static final long MAX_UINT32_T = 0xFFFFFFFFL;
39
40 LinuxSocket(int fd) {
41 super(fd);
42 }
43
44 SocketProtocolFamily family() {
45 return ipv6 ? SocketProtocolFamily.INET6 : SocketProtocolFamily.INET;
46 }
47
48 @Override
49 public boolean markClosed() {
50 return super.markClosed();
51 }
52
53 void setTimeToLive(int ttl) throws IOException {
54 setTimeToLive(intValue(), ttl);
55 }
56
57 void setInterface(InetAddress address) throws IOException {
58 final NativeInetAddress a = NativeInetAddress.newInstance(address);
59 setInterface(intValue(), ipv6, a.address(), a.scopeId(), interfaceIndex(address));
60 }
61
62 void setNetworkInterface(NetworkInterface netInterface) throws IOException {
63 InetAddress address = deriveInetAddress(netInterface, family() == SocketProtocolFamily.INET6);
64 if (address.equals(family() == SocketProtocolFamily.INET ? INET_ANY : INET6_ANY)) {
65 throw new IOException("NetworkInterface does not support " + family());
66 }
67 final NativeInetAddress nativeAddress = NativeInetAddress.newInstance(address);
68 setInterface(intValue(), ipv6, nativeAddress.address(), nativeAddress.scopeId(), interfaceIndex(netInterface));
69 }
70
71 InetAddress getInterface() throws IOException {
72 NetworkInterface inf = getNetworkInterface();
73 if (inf != null) {
74 Enumeration<InetAddress> addresses = SocketUtils.addressesFromNetworkInterface(inf);
75 if (addresses.hasMoreElements()) {
76 return addresses.nextElement();
77 }
78 }
79 return null;
80 }
81
82 NetworkInterface getNetworkInterface() throws IOException {
83 int ret = getInterface(intValue(), ipv6);
84 if (ipv6) {
85 return NetworkInterface.getByIndex(ret);
86 }
87 InetAddress address = inetAddress(ret);
88 return address != null ? NetworkInterface.getByInetAddress(address) : null;
89 }
90
91 private static InetAddress inetAddress(int value) {
92 byte[] var1 = {
93 (byte) (value >>> 24 & 255),
94 (byte) (value >>> 16 & 255),
95 (byte) (value >>> 8 & 255),
96 (byte) (value & 255)
97 };
98
99 try {
100 return InetAddress.getByAddress(var1);
101 } catch (UnknownHostException ignore) {
102 return null;
103 }
104 }
105
106 void joinGroup(InetAddress group, NetworkInterface netInterface, InetAddress source) throws IOException {
107 final NativeInetAddress g = NativeInetAddress.newInstance(group);
108 final boolean isIpv6 = group instanceof Inet6Address;
109 final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
110 if (source != null) {
111 final NativeInetAddress s = NativeInetAddress.newInstance(source);
112 joinSsmGroup(intValue(), ipv6, g.address(), i.address(),
113 g.scopeId(), interfaceIndex(netInterface), s.address());
114 } else {
115 joinGroup(intValue(), ipv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
116 }
117 }
118
119 void leaveGroup(InetAddress group, NetworkInterface netInterface, InetAddress source) throws IOException {
120 final NativeInetAddress g = NativeInetAddress.newInstance(group);
121 final boolean isIpv6 = group instanceof Inet6Address;
122 final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
123 if (source != null) {
124 final NativeInetAddress s = NativeInetAddress.newInstance(source);
125 leaveSsmGroup(intValue(), ipv6, g.address(), i.address(),
126 g.scopeId(), interfaceIndex(netInterface), s.address());
127 } else {
128 leaveGroup(intValue(), ipv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
129 }
130 }
131
132 private static int interfaceIndex(NetworkInterface networkInterface) {
133 return networkInterface.getIndex();
134 }
135
136 private static int interfaceIndex(InetAddress address) throws IOException {
137 NetworkInterface iface = NetworkInterface.getByInetAddress(address);
138 if (iface != null) {
139 return iface.getIndex();
140 }
141 return -1;
142 }
143
144 void setTcpDeferAccept(int deferAccept) throws IOException {
145 setTcpDeferAccept(intValue(), deferAccept);
146 }
147
148 void setTcpQuickAck(boolean quickAck) throws IOException {
149 setTcpQuickAck(intValue(), quickAck ? 1 : 0);
150 }
151
152 void setTcpCork(boolean tcpCork) throws IOException {
153 setTcpCork(intValue(), tcpCork ? 1 : 0);
154 }
155
156 void setSoBusyPoll(int loopMicros) throws IOException {
157 setSoBusyPoll(intValue(), loopMicros);
158 }
159
160 void setTcpNotSentLowAt(long tcpNotSentLowAt) throws IOException {
161 if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) {
162 throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t");
163 }
164 setTcpNotSentLowAt(intValue(), (int) tcpNotSentLowAt);
165 }
166
167 void setTcpFastOpen(int tcpFastopenBacklog) throws IOException {
168 setTcpFastOpen(intValue(), tcpFastopenBacklog);
169 }
170
171 void setTcpFastOpenConnect(boolean tcpFastOpenConnect) throws IOException {
172 setTcpFastOpenConnect(intValue(), tcpFastOpenConnect ? 1 : 0);
173 }
174
175 boolean isTcpFastOpenConnect() throws IOException {
176 return isTcpFastOpenConnect(intValue()) != 0;
177 }
178
179 void setTcpKeepIdle(int seconds) throws IOException {
180 setTcpKeepIdle(intValue(), seconds);
181 }
182
183 void setTcpKeepIntvl(int seconds) throws IOException {
184 setTcpKeepIntvl(intValue(), seconds);
185 }
186
187 void setTcpKeepCnt(int probes) throws IOException {
188 setTcpKeepCnt(intValue(), probes);
189 }
190
191 void setTcpUserTimeout(int milliseconds) throws IOException {
192 setTcpUserTimeout(intValue(), milliseconds);
193 }
194
195 void setIpFreeBind(boolean enabled) throws IOException {
196 setIpFreeBind(intValue(), enabled ? 1 : 0);
197 }
198
199 void setIpTransparent(boolean enabled) throws IOException {
200 setIpTransparent(intValue(), enabled ? 1 : 0);
201 }
202
203 void setIpRecvOrigDestAddr(boolean enabled) throws IOException {
204 setIpRecvOrigDestAddr(intValue(), enabled ? 1 : 0);
205 }
206
207 int getTimeToLive() throws IOException {
208 return getTimeToLive(intValue());
209 }
210
211 void getTcpInfo(IoUringTcpInfo info) throws IOException {
212 getTcpInfo(intValue(), info.info);
213 }
214
215 void setTcpMd5Sig(InetAddress address, byte[] key) throws IOException {
216 final NativeInetAddress a = NativeInetAddress.newInstance(address);
217 setTcpMd5Sig(intValue(), ipv6, a.address(), a.scopeId(), key);
218 }
219
220 boolean isTcpCork() throws IOException {
221 return isTcpCork(intValue()) != 0;
222 }
223
224 int getSoBusyPoll() throws IOException {
225 return getSoBusyPoll(intValue());
226 }
227
228 int getTcpDeferAccept() throws IOException {
229 return getTcpDeferAccept(intValue());
230 }
231
232 boolean isTcpQuickAck() throws IOException {
233 return isTcpQuickAck(intValue()) != 0;
234 }
235
236 long getTcpNotSentLowAt() throws IOException {
237 return getTcpNotSentLowAt(intValue()) & MAX_UINT32_T;
238 }
239
240 int getTcpKeepIdle() throws IOException {
241 return getTcpKeepIdle(intValue());
242 }
243
244 int getTcpKeepIntvl() throws IOException {
245 return getTcpKeepIntvl(intValue());
246 }
247
248 int getTcpKeepCnt() throws IOException {
249 return getTcpKeepCnt(intValue());
250 }
251
252 int getTcpUserTimeout() throws IOException {
253 return getTcpUserTimeout(intValue());
254 }
255
256 boolean isIpFreeBind() throws IOException {
257 return isIpFreeBind(intValue()) != 0;
258 }
259
260 boolean isIpTransparent() throws IOException {
261 return isIpTransparent(intValue()) != 0;
262 }
263
264 boolean isIpRecvOrigDestAddr() throws IOException {
265 return isIpRecvOrigDestAddr(intValue()) != 0;
266 }
267
268 PeerCredentials getPeerCredentials() throws IOException {
269 return getPeerCredentials(intValue());
270 }
271
272 boolean isLoopbackModeDisabled() throws IOException {
273 return getIpMulticastLoop(intValue(), ipv6) == 0;
274 }
275
276 void setLoopbackModeDisabled(boolean loopbackModeDisabled) throws IOException {
277 setIpMulticastLoop(intValue(), ipv6, loopbackModeDisabled ? 0 : 1);
278 }
279
280 void setUdpGro(boolean gro) throws IOException {
281 setUdpGro(intValue(), gro ? 1 : 0);
282 }
283
284 private static InetAddress deriveInetAddress(NetworkInterface netInterface, boolean ipv6) {
285 final InetAddress ipAny = ipv6 ? INET6_ANY : INET_ANY;
286 if (netInterface != null) {
287 final Enumeration<InetAddress> ias = netInterface.getInetAddresses();
288 while (ias.hasMoreElements()) {
289 final InetAddress ia = ias.nextElement();
290 final boolean isV6 = ia instanceof Inet6Address;
291 if (isV6 == ipv6) {
292 return ia;
293 }
294 }
295 }
296 return ipAny;
297 }
298
299 boolean isIpv6() {
300 return ipv6;
301 }
302
303 public static LinuxSocket newSocketStream(boolean ipv6) {
304 return new LinuxSocket(newSocketStream0(ipv6));
305 }
306
307 public static LinuxSocket newSocketStream() {
308 return newSocketStream(isIPv6Preferred());
309 }
310
311 public static LinuxSocket newSocketDgram(boolean ipv6) {
312 return new LinuxSocket(newSocketDgram0(ipv6));
313 }
314
315 public static LinuxSocket newSocketDgram() {
316 return newSocketDgram(isIPv6Preferred());
317 }
318
319 public static LinuxSocket newSocketDomain() {
320 return new LinuxSocket(newSocketDomain0());
321 }
322
323 private static InetAddress unsafeInetAddrByName(String inetName) {
324 try {
325 return InetAddress.getByName(inetName);
326 } catch (UnknownHostException uhe) {
327 throw new ChannelException(uhe);
328 }
329 }
330
331 private static native void joinGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
332 int scopeId, int interfaceIndex) throws IOException;
333 private static native void joinSsmGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
334 int scopeId, int interfaceIndex, byte[] source) throws IOException;
335 private static native void leaveGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
336 int scopeId, int interfaceIndex) throws IOException;
337 private static native void leaveSsmGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
338 int scopeId, int interfaceIndex, byte[] source) throws IOException;
339
340 private static native int getTcpDeferAccept(int fd) throws IOException;
341 private static native int isTcpQuickAck(int fd) throws IOException;
342 private static native int isTcpCork(int fd) throws IOException;
343 private static native int getSoBusyPoll(int fd) throws IOException;
344 private static native int getTcpNotSentLowAt(int fd) throws IOException;
345 private static native int getTcpKeepIdle(int fd) throws IOException;
346 private static native int getTcpKeepIntvl(int fd) throws IOException;
347 private static native int getTcpKeepCnt(int fd) throws IOException;
348 private static native int getTcpUserTimeout(int fd) throws IOException;
349 private static native int getTimeToLive(int fd) throws IOException;
350 private static native int isIpFreeBind(int fd) throws IOException;
351 private static native int isIpTransparent(int fd) throws IOException;
352 private static native int isIpRecvOrigDestAddr(int fd) throws IOException;
353 private static native void getTcpInfo(int fd, long[] array) throws IOException;
354 private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
355 private static native int isTcpFastOpenConnect(int fd) throws IOException;
356
357 private static native void setTcpDeferAccept(int fd, int deferAccept) throws IOException;
358 private static native void setTcpQuickAck(int fd, int quickAck) throws IOException;
359 private static native void setTcpCork(int fd, int tcpCork) throws IOException;
360 private static native void setSoBusyPoll(int fd, int loopMicros) throws IOException;
361 private static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt) throws IOException;
362 private static native void setTcpFastOpen(int fd, int tcpFastopenBacklog) throws IOException;
363 private static native void setTcpFastOpenConnect(int fd, int tcpFastOpenConnect) throws IOException;
364 private static native void setTcpKeepIdle(int fd, int seconds) throws IOException;
365 private static native void setTcpKeepIntvl(int fd, int seconds) throws IOException;
366 private static native void setTcpKeepCnt(int fd, int probes) throws IOException;
367 private static native void setTcpUserTimeout(int fd, int milliseconds)throws IOException;
368 private static native void setIpFreeBind(int fd, int freeBind) throws IOException;
369 private static native void setIpTransparent(int fd, int transparent) throws IOException;
370 private static native void setIpRecvOrigDestAddr(int fd, int transparent) throws IOException;
371 private static native void setTcpMd5Sig(
372 int fd, boolean ipv6, byte[] address, int scopeId, byte[] key) throws IOException;
373 private static native void setInterface(
374 int fd, boolean ipv6, byte[] interfaceAddress, int scopeId, int networkInterfaceIndex) throws IOException;
375 private static native int getInterface(int fd, boolean ipv6);
376 private static native int getIpMulticastLoop(int fd, boolean ipv6) throws IOException;
377 private static native void setIpMulticastLoop(int fd, boolean ipv6, int enabled) throws IOException;
378 private static native void setTimeToLive(int fd, int ttl) throws IOException;
379 private static native int makeBlocking(int fd) throws IOException;
380 private static native void setUdpGro(int fd, int gro) throws IOException;
381 }