1
16 package io.netty.channel.epoll;
17
18 import io.netty.channel.unix.FileDescriptor;
19 import io.netty.channel.unix.Socket;
20 import io.netty.util.internal.NativeLibraryLoader;
21 import io.netty.util.internal.PlatformDependent;
22 import io.netty.util.internal.SystemPropertyUtil;
23 import io.netty.util.internal.ThrowableUtil;
24 import io.netty.util.internal.logging.InternalLogger;
25 import io.netty.util.internal.logging.InternalLoggerFactory;
26
27 import java.io.IOException;
28 import java.nio.channels.Selector;
29 import java.util.Locale;
30
31 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollerr;
32 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollet;
33 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollin;
34 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollout;
35 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollrdhup;
36 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.isSupportingRecvmmsg;
37 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.isSupportingSendmmsg;
38 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.isSupportingTcpFastopen;
39 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.kernelVersion;
40 import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.tcpMd5SigMaxKeyLen;
41 import static io.netty.channel.unix.Errors.ioResult;
42 import static io.netty.channel.unix.Errors.newIOException;
43
44
49 public final class Native {
50 private static final InternalLogger logger = InternalLoggerFactory.getInstance(Native.class);
51
52 static {
53 Selector selector = null;
54 try {
55
56
57
58
59 selector = Selector.open();
60 } catch (IOException ignore) {
61
62 }
63 try {
64
65
66 offsetofEpollData();
67 } catch (UnsatisfiedLinkError ignore) {
68
69 loadNativeLibrary();
70 } finally {
71 try {
72 if (selector != null) {
73 selector.close();
74 }
75 } catch (IOException ignore) {
76
77 }
78 }
79 Socket.initialize();
80 }
81
82
83 public static final int EPOLLIN = epollin();
84 public static final int EPOLLOUT = epollout();
85 public static final int EPOLLRDHUP = epollrdhup();
86 public static final int EPOLLET = epollet();
87 public static final int EPOLLERR = epollerr();
88
89 public static final boolean IS_SUPPORTING_SENDMMSG = isSupportingSendmmsg();
90 static final boolean IS_SUPPORTING_RECVMMSG = isSupportingRecvmmsg();
91
92 public static final boolean IS_SUPPORTING_TCP_FASTOPEN = isSupportingTcpFastopen();
93 public static final int TCP_MD5SIG_MAXKEYLEN = tcpMd5SigMaxKeyLen();
94 public static final String KERNEL_VERSION = kernelVersion();
95
96 public static FileDescriptor newEventFd() {
97 return new FileDescriptor(eventFd());
98 }
99
100 public static FileDescriptor newTimerFd() {
101 return new FileDescriptor(timerFd());
102 }
103
104 private static native int eventFd();
105 private static native int timerFd();
106 public static native void eventFdWrite(int fd, long value);
107 public static native void eventFdRead(int fd);
108 static native void timerFdRead(int fd);
109 static native void timerFdSetTime(int fd, int sec, int nsec) throws IOException;
110
111 public static FileDescriptor newEpollCreate() {
112 return new FileDescriptor(epollCreate());
113 }
114
115 private static native int epollCreate();
116
117
120 @Deprecated
121 public static int epollWait(FileDescriptor epollFd, EpollEventArray events, FileDescriptor timerFd,
122 int timeoutSec, int timeoutNs) throws IOException {
123 if (timeoutSec == 0 && timeoutNs == 0) {
124
125 return epollWait(epollFd, events, 0);
126 }
127 if (timeoutSec == Integer.MAX_VALUE) {
128
129 timeoutSec = 0;
130 timeoutNs = 0;
131 }
132 int ready = epollWait0(epollFd.intValue(), events.memoryAddress(), events.length(), timerFd.intValue(),
133 timeoutSec, timeoutNs);
134 if (ready < 0) {
135 throw newIOException("epoll_wait", ready);
136 }
137 return ready;
138 }
139
140 static int epollWait(FileDescriptor epollFd, EpollEventArray events, boolean immediatePoll) throws IOException {
141 return epollWait(epollFd, events, immediatePoll ? 0 : -1);
142 }
143
144
147 static int epollWait(FileDescriptor epollFd, EpollEventArray events, int timeoutMillis) throws IOException {
148 int ready = epollWait(epollFd.intValue(), events.memoryAddress(), events.length(), timeoutMillis);
149 if (ready < 0) {
150 throw newIOException("epoll_wait", ready);
151 }
152 return ready;
153 }
154
155
160 public static int epollBusyWait(FileDescriptor epollFd, EpollEventArray events) throws IOException {
161 int ready = epollBusyWait0(epollFd.intValue(), events.memoryAddress(), events.length());
162 if (ready < 0) {
163 throw newIOException("epoll_wait", ready);
164 }
165 return ready;
166 }
167
168 private static native int epollWait0(int efd, long address, int len, int timerFd, int timeoutSec, int timeoutNs);
169 private static native int epollWait(int efd, long address, int len, int timeout);
170 private static native int epollBusyWait0(int efd, long address, int len);
171
172 public static void epollCtlAdd(int efd, final int fd, final int flags) throws IOException {
173 int res = epollCtlAdd0(efd, fd, flags);
174 if (res < 0) {
175 throw newIOException("epoll_ctl", res);
176 }
177 }
178 private static native int epollCtlAdd0(int efd, int fd, int flags);
179
180 public static void epollCtlMod(int efd, final int fd, final int flags) throws IOException {
181 int res = epollCtlMod0(efd, fd, flags);
182 if (res < 0) {
183 throw newIOException("epoll_ctl", res);
184 }
185 }
186 private static native int epollCtlMod0(int efd, int fd, int flags);
187
188 public static void epollCtlDel(int efd, final int fd) throws IOException {
189 int res = epollCtlDel0(efd, fd);
190 if (res < 0) {
191 throw newIOException("epoll_ctl", res);
192 }
193 }
194 private static native int epollCtlDel0(int efd, int fd);
195
196
197 public static int splice(int fd, long offIn, int fdOut, long offOut, long len) throws IOException {
198 int res = splice0(fd, offIn, fdOut, offOut, len);
199 if (res >= 0) {
200 return res;
201 }
202 return ioResult("splice", res);
203 }
204
205 private static native int splice0(int fd, long offIn, int fdOut, long offOut, long len);
206
207 @Deprecated
208 public static int sendmmsg(int fd, NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
209 int offset, int len) throws IOException {
210 return sendmmsg(fd, Socket.isIPv6Preferred(), msgs, offset, len);
211 }
212
213 static int sendmmsg(int fd, boolean ipv6, NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
214 int offset, int len) throws IOException {
215 int res = sendmmsg0(fd, ipv6, msgs, offset, len);
216 if (res >= 0) {
217 return res;
218 }
219 return ioResult("sendmmsg", res);
220 }
221
222 private static native int sendmmsg0(
223 int fd, boolean ipv6, NativeDatagramPacketArray.NativeDatagramPacket[] msgs, int offset, int len);
224
225 static int recvmmsg(int fd, boolean ipv6, NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
226 int offset, int len) throws IOException {
227 int res = recvmmsg0(fd, ipv6, msgs, offset, len);
228 if (res >= 0) {
229 return res;
230 }
231 return ioResult("recvmmsg", res);
232 }
233
234 private static native int recvmmsg0(
235 int fd, boolean ipv6, NativeDatagramPacketArray.NativeDatagramPacket[] msgs, int offset, int len);
236
237
238 public static native int sizeofEpollEvent();
239 public static native int offsetofEpollData();
240
241 private static void loadNativeLibrary() {
242 String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim();
243 if (!name.startsWith("linux")) {
244 throw new IllegalStateException("Only supported on Linux");
245 }
246 String staticLibName = "netty_transport_native_epoll";
247 String sharedLibName = staticLibName + '_' + PlatformDependent.normalizedArch();
248 ClassLoader cl = PlatformDependent.getClassLoader(Native.class);
249 try {
250 NativeLibraryLoader.load(sharedLibName, cl);
251 } catch (UnsatisfiedLinkError e1) {
252 try {
253 NativeLibraryLoader.load(staticLibName, cl);
254 logger.debug("Failed to load {}", sharedLibName, e1);
255 } catch (UnsatisfiedLinkError e2) {
256 ThrowableUtil.addSuppressed(e1, e2);
257 throw e1;
258 }
259 }
260 }
261
262 private Native() {
263
264 }
265 }
266