1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.kqueue;
17
18 import io.netty.channel.DefaultFileRegion;
19 import io.netty.channel.unix.FileDescriptor;
20 import io.netty.channel.unix.PeerCredentials;
21 import io.netty.channel.unix.Unix;
22 import io.netty.util.internal.ClassInitializerUtil;
23 import io.netty.util.internal.NativeLibraryLoader;
24 import io.netty.util.internal.PlatformDependent;
25 import io.netty.util.internal.ThrowableUtil;
26 import io.netty.util.internal.logging.InternalLogger;
27 import io.netty.util.internal.logging.InternalLoggerFactory;
28
29 import java.io.IOException;
30 import java.nio.channels.FileChannel;
31
32 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.connectDataIdempotent;
33 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.connectResumeOnReadWrite;
34 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evAdd;
35 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evClear;
36 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evDelete;
37 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evDisable;
38 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evEOF;
39 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evEnable;
40 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evError;
41 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evfiltRead;
42 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evfiltSock;
43 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evfiltUser;
44 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.evfiltWrite;
45 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.fastOpenClient;
46 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.fastOpenServer;
47 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.noteConnReset;
48 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.noteDisconnected;
49 import static io.netty.channel.kqueue.KQueueStaticallyReferencedJniMethods.noteReadClosed;
50 import static io.netty.channel.unix.Errors.newIOException;
51
52
53
54
55
56 final class Native {
57 private static final InternalLogger logger = InternalLoggerFactory.getInstance(Native.class);
58
59 static {
60
61
62
63
64
65 ClassInitializerUtil.tryLoadClasses(Native.class,
66
67 PeerCredentials.class, DefaultFileRegion.class, FileChannel.class, java.io.FileDescriptor.class
68 );
69
70 try {
71
72
73 sizeofKEvent();
74 } catch (UnsatisfiedLinkError ignore) {
75
76 loadNativeLibrary();
77 }
78 Unix.registerInternal(new Runnable() {
79 @Override
80 public void run() {
81 registerUnix();
82 }
83 });
84 }
85
86 private static native int registerUnix();
87
88 static final short EV_ADD = evAdd();
89 static final short EV_ENABLE = evEnable();
90 static final short EV_DISABLE = evDisable();
91 static final short EV_DELETE = evDelete();
92 static final short EV_CLEAR = evClear();
93 static final short EV_ERROR = evError();
94 static final short EV_EOF = evEOF();
95
96 static final int NOTE_READCLOSED = noteReadClosed();
97 static final int NOTE_CONNRESET = noteConnReset();
98 static final int NOTE_DISCONNECTED = noteDisconnected();
99
100 static final int NOTE_RDHUP = NOTE_READCLOSED | NOTE_CONNRESET | NOTE_DISCONNECTED;
101
102
103 static final short EV_ADD_CLEAR_ENABLE = (short) (EV_ADD | EV_CLEAR | EV_ENABLE);
104 static final short EV_DELETE_DISABLE = (short) (EV_DELETE | EV_DISABLE);
105
106 static final short EVFILT_READ = evfiltRead();
107 static final short EVFILT_WRITE = evfiltWrite();
108 static final short EVFILT_USER = evfiltUser();
109 static final short EVFILT_SOCK = evfiltSock();
110
111
112 private static final int CONNECT_RESUME_ON_READ_WRITE = connectResumeOnReadWrite();
113 private static final int CONNECT_DATA_IDEMPOTENT = connectDataIdempotent();
114 static final int CONNECT_TCP_FASTOPEN = CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT;
115 static final boolean IS_SUPPORTING_TCP_FASTOPEN_CLIENT = isSupportingFastOpenClient();
116 static final boolean IS_SUPPORTING_TCP_FASTOPEN_SERVER = isSupportingFastOpenServer();
117
118 static FileDescriptor newKQueue() {
119 return new FileDescriptor(kqueueCreate());
120 }
121
122 static int keventWait(int kqueueFd, KQueueEventArray changeList, KQueueEventArray eventList,
123 int tvSec, int tvNsec) throws IOException {
124 int ready = keventWait(kqueueFd, changeList.memoryAddress(), changeList.size(),
125 eventList.memoryAddress(), eventList.capacity(), tvSec, tvNsec);
126 if (ready < 0) {
127 throw newIOException("kevent", ready);
128 }
129 return ready;
130 }
131
132 private static native int kqueueCreate();
133 private static native int keventWait(int kqueueFd, long changeListAddress, int changeListLength,
134 long eventListAddress, int eventListLength, int tvSec, int tvNsec);
135 static native int keventTriggerUserEvent(int kqueueFd, int ident);
136 static native int keventAddUserEvent(int kqueueFd, int ident);
137
138
139 static native int sizeofKEvent();
140 static native int offsetofKEventIdent();
141 static native int offsetofKEventFlags();
142 static native int offsetofKEventFFlags();
143 static native int offsetofKEventFilter();
144 static native int offsetofKeventData();
145
146 private static void loadNativeLibrary() {
147 String name = PlatformDependent.normalizedOs();
148 if (!"osx".equals(name) && !name.contains("bsd")) {
149 throw new IllegalStateException("Only supported on OSX/BSD");
150 }
151 String staticLibName = "netty_transport_native_kqueue";
152 String sharedLibName = staticLibName + '_' + PlatformDependent.normalizedArch();
153 ClassLoader cl = PlatformDependent.getClassLoader(Native.class);
154 try {
155 NativeLibraryLoader.load(sharedLibName, cl);
156 } catch (UnsatisfiedLinkError e1) {
157 try {
158 NativeLibraryLoader.load(staticLibName, cl);
159 logger.debug("Failed to load {}", sharedLibName, e1);
160 } catch (UnsatisfiedLinkError e2) {
161 ThrowableUtil.addSuppressed(e1, e2);
162 throw e1;
163 }
164 }
165 }
166
167 private static boolean isSupportingFastOpenClient() {
168 try {
169 return fastOpenClient() == 1;
170 } catch (Exception e) {
171 logger.debug("Failed to probe fastOpenClient sysctl, assuming client-side TCP FastOpen cannot be used.", e);
172 }
173 return false;
174 }
175
176 private static boolean isSupportingFastOpenServer() {
177 try {
178 return fastOpenServer() == 1;
179 } catch (Exception e) {
180 logger.debug("Failed to probe fastOpenServer sysctl, assuming server-side TCP FastOpen cannot be used.", e);
181 }
182 return false;
183 }
184
185 private Native() {
186
187 }
188 }