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