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