1
16 package io.netty.channel.epoll;
17
18 import io.netty.channel.ChannelException;
19 import io.netty.channel.DefaultFileRegion;
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.channel.socket.InternetProtocolFamily;
24 import io.netty.util.internal.PlatformDependent;
25 import io.netty.util.internal.SocketUtils;
26
27 import java.io.IOException;
28 import java.net.InetAddress;
29 import java.net.Inet6Address;
30 import java.net.NetworkInterface;
31 import java.net.UnknownHostException;
32 import java.util.Enumeration;
33
34 import static io.netty.channel.unix.Errors.ioResult;
35
36
39 final class LinuxSocket extends Socket {
40 static final InetAddress INET6_ANY = unsafeInetAddrByName("::");
41 private static final InetAddress INET_ANY = unsafeInetAddrByName("0.0.0.0");
42 private static final long MAX_UINT32_T = 0xFFFFFFFFL;
43
44 LinuxSocket(int fd) {
45 super(fd);
46 }
47
48 InternetProtocolFamily family() {
49 return ipv6 ? InternetProtocolFamily.IPv6 : InternetProtocolFamily.IPv4;
50 }
51
52 int sendmmsg(NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
53 int offset, int len) throws IOException {
54 return Native.sendmmsg(intValue(), ipv6, msgs, offset, len);
55 }
56
57 int recvmmsg(NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
58 int offset, int len) throws IOException {
59 return Native.recvmmsg(intValue(), ipv6, msgs, offset, len);
60 }
61
62 void setTimeToLive(int ttl) throws IOException {
63 setTimeToLive(intValue(), ttl);
64 }
65
66 void setInterface(InetAddress address) throws IOException {
67 final NativeInetAddress a = NativeInetAddress.newInstance(address);
68 setInterface(intValue(), ipv6, a.address(), a.scopeId(), interfaceIndex(address));
69 }
70
71 void setNetworkInterface(NetworkInterface netInterface) throws IOException {
72 InetAddress address = deriveInetAddress(netInterface, family() == InternetProtocolFamily.IPv6);
73 if (address.equals(family() == InternetProtocolFamily.IPv4 ? INET_ANY : INET6_ANY)) {
74 throw new IOException("NetworkInterface does not support " + family());
75 }
76 final NativeInetAddress nativeAddress = NativeInetAddress.newInstance(address);
77 setInterface(intValue(), ipv6, nativeAddress.address(), nativeAddress.scopeId(), interfaceIndex(netInterface));
78 }
79
80 InetAddress getInterface() throws IOException {
81 NetworkInterface inf = getNetworkInterface();
82 if (inf != null) {
83 Enumeration<InetAddress> addresses = SocketUtils.addressesFromNetworkInterface(inf);
84 if (addresses.hasMoreElements()) {
85 return addresses.nextElement();
86 }
87 }
88 return null;
89 }
90
91 NetworkInterface getNetworkInterface() throws IOException {
92 int ret = getInterface(intValue(), ipv6);
93 if (ipv6) {
94 return PlatformDependent.javaVersion() >= 7 ? NetworkInterface.getByIndex(ret) : null;
95 }
96 InetAddress address = inetAddress(ret);
97 return address != null ? NetworkInterface.getByInetAddress(address) : null;
98 }
99
100 private static InetAddress inetAddress(int value) {
101 byte[] var1 = {
102 (byte) (value >>> 24 & 255),
103 (byte) (value >>> 16 & 255),
104 (byte) (value >>> 8 & 255),
105 (byte) (value & 255)
106 };
107
108 try {
109 return InetAddress.getByAddress(var1);
110 } catch (UnknownHostException ignore) {
111 return null;
112 }
113 }
114
115 void joinGroup(InetAddress group, NetworkInterface netInterface, InetAddress source) throws IOException {
116 final NativeInetAddress g = NativeInetAddress.newInstance(group);
117 final boolean isIpv6 = group instanceof Inet6Address;
118 final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
119 if (source != null) {
120 final NativeInetAddress s = NativeInetAddress.newInstance(source);
121 joinSsmGroup(intValue(), ipv6, g.address(), i.address(),
122 g.scopeId(), interfaceIndex(netInterface), s.address());
123 } else {
124 joinGroup(intValue(), ipv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
125 }
126 }
127
128 void leaveGroup(InetAddress group, NetworkInterface netInterface, InetAddress source) throws IOException {
129 final NativeInetAddress g = NativeInetAddress.newInstance(group);
130 final boolean isIpv6 = group instanceof Inet6Address;
131 final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
132 if (source != null) {
133 final NativeInetAddress s = NativeInetAddress.newInstance(source);
134 leaveSsmGroup(intValue(), ipv6, g.address(), i.address(),
135 g.scopeId(), interfaceIndex(netInterface), s.address());
136 } else {
137 leaveGroup(intValue(), ipv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
138 }
139 }
140
141 private static int interfaceIndex(NetworkInterface networkInterface) {
142 return PlatformDependent.javaVersion() >= 7 ? networkInterface.getIndex() : -1;
143 }
144
145 private static int interfaceIndex(InetAddress address) throws IOException {
146 if (PlatformDependent.javaVersion() >= 7) {
147 NetworkInterface iface = NetworkInterface.getByInetAddress(address);
148 if (iface != null) {
149 return iface.getIndex();
150 }
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(EpollTcpInfo 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 long sendFile(DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException {
292
293
294 src.open();
295
296 long res = sendFile(intValue(), src, baseOffset, offset, length);
297 if (res >= 0) {
298 return res;
299 }
300 return ioResult("sendfile", (int) res);
301 }
302
303 private static InetAddress deriveInetAddress(NetworkInterface netInterface, boolean ipv6) {
304 final InetAddress ipAny = ipv6 ? INET6_ANY : INET_ANY;
305 if (netInterface != null) {
306 final Enumeration<InetAddress> ias = netInterface.getInetAddresses();
307 while (ias.hasMoreElements()) {
308 final InetAddress ia = ias.nextElement();
309 final boolean isV6 = ia instanceof Inet6Address;
310 if (isV6 == ipv6) {
311 return ia;
312 }
313 }
314 }
315 return ipAny;
316 }
317
318 public static LinuxSocket newSocketStream(boolean ipv6) {
319 return new LinuxSocket(newSocketStream0(ipv6));
320 }
321
322 public static LinuxSocket newSocketStream() {
323 return newSocketStream(isIPv6Preferred());
324 }
325
326 public static LinuxSocket newSocketDgram(boolean ipv6) {
327 return new LinuxSocket(newSocketDgram0(ipv6));
328 }
329
330 public static LinuxSocket newSocketDgram() {
331 return newSocketDgram(isIPv6Preferred());
332 }
333
334 public static LinuxSocket newSocketDomain() {
335 return new LinuxSocket(newSocketDomain0());
336 }
337
338 private static InetAddress unsafeInetAddrByName(String inetName) {
339 try {
340 return InetAddress.getByName(inetName);
341 } catch (UnknownHostException uhe) {
342 throw new ChannelException(uhe);
343 }
344 }
345
346 private static native void joinGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
347 int scopeId, int interfaceIndex) throws IOException;
348 private static native void joinSsmGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
349 int scopeId, int interfaceIndex, byte[] source) throws IOException;
350 private static native void leaveGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
351 int scopeId, int interfaceIndex) throws IOException;
352 private static native void leaveSsmGroup(int fd, boolean ipv6, byte[] group, byte[] interfaceAddress,
353 int scopeId, int interfaceIndex, byte[] source) throws IOException;
354 private static native long sendFile(int socketFd, DefaultFileRegion src, long baseOffset,
355 long offset, long length) throws IOException;
356
357 private static native int getTcpDeferAccept(int fd) throws IOException;
358 private static native int isTcpQuickAck(int fd) throws IOException;
359 private static native int isTcpCork(int fd) throws IOException;
360 private static native int getSoBusyPoll(int fd) throws IOException;
361 private static native int getTcpNotSentLowAt(int fd) throws IOException;
362 private static native int getTcpKeepIdle(int fd) throws IOException;
363 private static native int getTcpKeepIntvl(int fd) throws IOException;
364 private static native int getTcpKeepCnt(int fd) throws IOException;
365 private static native int getTcpUserTimeout(int fd) throws IOException;
366 private static native int getTimeToLive(int fd) throws IOException;
367 private static native int isIpFreeBind(int fd) throws IOException;
368 private static native int isIpTransparent(int fd) throws IOException;
369 private static native int isIpRecvOrigDestAddr(int fd) throws IOException;
370 private static native void getTcpInfo(int fd, long[] array) throws IOException;
371 private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
372 private static native int isTcpFastOpenConnect(int fd) throws IOException;
373
374 private static native void setTcpDeferAccept(int fd, int deferAccept) throws IOException;
375 private static native void setTcpQuickAck(int fd, int quickAck) throws IOException;
376 private static native void setTcpCork(int fd, int tcpCork) throws IOException;
377 private static native void setSoBusyPoll(int fd, int loopMicros) throws IOException;
378 private static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt) throws IOException;
379 private static native void setTcpFastOpen(int fd, int tcpFastopenBacklog) throws IOException;
380 private static native void setTcpFastOpenConnect(int fd, int tcpFastOpenConnect) throws IOException;
381 private static native void setTcpKeepIdle(int fd, int seconds) throws IOException;
382 private static native void setTcpKeepIntvl(int fd, int seconds) throws IOException;
383 private static native void setTcpKeepCnt(int fd, int probes) throws IOException;
384 private static native void setTcpUserTimeout(int fd, int milliseconds)throws IOException;
385 private static native void setIpFreeBind(int fd, int freeBind) throws IOException;
386 private static native void setIpTransparent(int fd, int transparent) throws IOException;
387 private static native void setIpRecvOrigDestAddr(int fd, int transparent) throws IOException;
388 private static native void setTcpMd5Sig(
389 int fd, boolean ipv6, byte[] address, int scopeId, byte[] key) throws IOException;
390 private static native void setInterface(
391 int fd, boolean ipv6, byte[] interfaceAddress, int scopeId, int networkInterfaceIndex) throws IOException;
392 private static native int getInterface(int fd, boolean ipv6);
393 private static native int getIpMulticastLoop(int fd, boolean ipv6) throws IOException;
394 private static native void setIpMulticastLoop(int fd, boolean ipv6, int enabled) throws IOException;
395 private static native void setTimeToLive(int fd, int ttl) throws IOException;
396 }
397