1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import static java.util.Objects.requireNonNull;
21
22 import java.io.FileDescriptor;
23 import java.io.IOException;
24 import java.net.DatagramSocket;
25 import java.net.InetAddress;
26 import java.net.NetworkInterface;
27 import java.net.ProtocolFamily;
28 import java.net.Socket;
29 import java.net.SocketAddress;
30 import java.net.SocketOption;
31 import java.net.StandardProtocolFamily;
32 import java.nio.ByteBuffer;
33 import java.nio.channels.DatagramChannel;
34 import java.nio.channels.MembershipKey;
35 import java.nio.channels.spi.SelectorProvider;
36 import java.util.Set;
37
38 import org.eclipse.jdt.annotation.Nullable;
39
40 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
41
42
43
44
45
46
47
48 public abstract class AFDatagramChannel<A extends AFSocketAddress> extends DatagramChannel
49 implements AFSomeSocket, AFSocketExtensions, AFSomeSocketChannel {
50 private final AFDatagramSocket<A> afSocket;
51
52
53
54
55
56
57
58 protected AFDatagramChannel(AFSelectorProvider<A> selectorProvider, AFDatagramSocket<A> socket) {
59 super(selectorProvider);
60 this.afSocket = socket;
61 }
62
63
64
65
66
67
68 protected final AFDatagramSocket<A> getAFSocket() {
69 return afSocket;
70 }
71
72
73
74 @Override
75 public final MembershipKey join(InetAddress group, NetworkInterface interf) throws IOException {
76 throw new UnsupportedOperationException();
77 }
78
79 @Override
80 public final MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source)
81 throws IOException {
82 throw new UnsupportedOperationException();
83 }
84
85 @Override
86 public final AFDatagramChannel<A> bind(SocketAddress local) throws IOException {
87 afSocket.bind(local);
88 return this;
89 }
90
91 @SuppressFBWarnings("EI_EXPOSE_REP")
92 @Override
93 public final AFDatagramSocket<A> socket() {
94 return afSocket;
95 }
96
97
98
99
100
101
102 public final boolean isBound() {
103 return afSocket.isBound();
104 }
105
106 @Override
107 public final boolean isConnected() {
108 return afSocket.isConnected();
109 }
110
111 @Override
112 public final AFDatagramChannel<A> connect(SocketAddress remote) throws IOException {
113 afSocket.connect(remote);
114 return this;
115 }
116
117 @Override
118 public final AFDatagramChannel<A> disconnect() throws IOException {
119 afSocket.disconnect();
120 return this;
121 }
122
123 @Override
124 public final @Nullable A getRemoteAddress() throws IOException {
125 return getRemoteSocketAddress();
126 }
127
128 @Override
129 public final @Nullable A getRemoteSocketAddress() {
130 return afSocket.getRemoteSocketAddress();
131 }
132
133 @Override
134 public final @Nullable A getLocalAddress() throws IOException {
135 return getLocalSocketAddress();
136 }
137
138 @Override
139 public final @Nullable A getLocalSocketAddress() {
140 return afSocket.getLocalSocketAddress();
141 }
142
143 @Override
144 public final A receive(ByteBuffer dst) throws IOException {
145 boolean complete = false;
146 Exception exception = null;
147 try {
148 begin();
149 A ret = afSocket.getAFImpl().receive(dst);
150 complete = true;
151 return ret;
152 } catch (IOException e) {
153 throw InterruptibleChannelUtil.ioExceptionOrThrowRuntimeException(
154 (exception = InterruptibleChannelUtil.handleException(this, e)));
155 } finally {
156 InterruptibleChannelUtil.endInterruptable(this, this::end, complete, exception);
157 }
158 }
159
160 @Override
161 public final int send(ByteBuffer src, SocketAddress target) throws IOException {
162 boolean complete = false;
163 Exception exception = null;
164 try {
165 begin();
166 int ret = afSocket.getAFImpl().send(src, target);
167 complete = true;
168 return ret;
169 } catch (IOException e) {
170 throw InterruptibleChannelUtil.ioExceptionOrThrowRuntimeException(
171 (exception = InterruptibleChannelUtil.handleException(this, e)));
172 } finally {
173 InterruptibleChannelUtil.endInterruptable(this, this::end, complete, exception);
174 }
175 }
176
177 @Override
178 public final int read(ByteBuffer dst) throws IOException {
179 boolean complete = false;
180 Exception exception = null;
181 try {
182 begin();
183 int ret = afSocket.getAFImpl().read(dst, null);
184 complete = true;
185 return ret;
186 } catch (IOException e) {
187 throw InterruptibleChannelUtil.ioExceptionOrThrowRuntimeException(
188 (exception = InterruptibleChannelUtil.handleException(this, e)));
189 } finally {
190 InterruptibleChannelUtil.endInterruptable(this, this::end, complete, exception);
191 }
192 }
193
194 @Override
195 public final long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
196 if (length == 0) {
197 return 0;
198 }
199
200 return read(dsts[offset]);
201 }
202
203 @Override
204 public final int write(ByteBuffer src) throws IOException {
205 boolean complete = false;
206 Exception exception = null;
207 try {
208 begin();
209 int ret = afSocket.getAFImpl().write(src);
210 complete = true;
211 return ret;
212 } catch (IOException e) {
213 throw InterruptibleChannelUtil.ioExceptionOrThrowRuntimeException(
214 (exception = InterruptibleChannelUtil.handleException(this, e)));
215 } finally {
216 InterruptibleChannelUtil.endInterruptable(this, this::end, complete, exception);
217 }
218 }
219
220 @Override
221 public final long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
222 if (length == 0) {
223 return 0;
224 }
225
226 return write(srcs[offset]);
227 }
228
229 @Override
230 protected final void implCloseSelectableChannel() throws IOException {
231 getAFSocket().close();
232 }
233
234 @Override
235 protected final void implConfigureBlocking(boolean block) throws IOException {
236 getAFCore().implConfigureBlocking(block);
237 }
238
239 @Override
240 public final int getAncillaryReceiveBufferSize() {
241 return afSocket.getAncillaryReceiveBufferSize();
242 }
243
244 @Override
245 public final void setAncillaryReceiveBufferSize(int size) {
246 afSocket.setAncillaryReceiveBufferSize(size);
247 }
248
249 @Override
250 public final void ensureAncillaryReceiveBufferSize(int minSize) {
251 afSocket.ensureAncillaryReceiveBufferSize(minSize);
252 }
253
254 @Override
255 public final <T> AFDatagramChannel<A> setOption(SocketOption<T> name, T value)
256 throws IOException {
257 if (name instanceof AFSocketOption<?>) {
258 getAFCore().setOption((AFSocketOption<T>) name, value);
259 return this;
260 }
261 Integer optionId = SocketOptionsMapper.resolve(name);
262 if (optionId == null) {
263 throw new UnsupportedOperationException("unsupported option");
264 } else {
265 afSocket.getAFImpl().setOption(optionId, value);
266 }
267 return this;
268 }
269
270 @SuppressWarnings("unchecked")
271 @Override
272 public final <T> T getOption(SocketOption<T> name) throws IOException {
273 if (name instanceof AFSocketOption<?>) {
274 return getAFCore().getOption((AFSocketOption<T>) name);
275 }
276 Integer optionId = SocketOptionsMapper.resolve(name);
277 if (optionId == null) {
278 throw new UnsupportedOperationException("unsupported option");
279 } else {
280 return (T) afSocket.getAFImpl().getOption(optionId);
281 }
282 }
283
284 @Override
285 public final Set<SocketOption<?>> supportedOptions() {
286 return SocketOptionsMapper.SUPPORTED_SOCKET_OPTIONS;
287 }
288
289 final AFSocketCore getAFCore() {
290 return afSocket.getAFImpl().getCore();
291 }
292
293 @Override
294 public final FileDescriptor getFileDescriptor() throws IOException {
295 return afSocket.getFileDescriptor();
296 }
297
298
299
300
301
302
303
304
305
306 public final boolean isDeleteOnClose() {
307 return afSocket.isDeleteOnClose();
308 }
309
310
311
312
313
314
315
316
317
318 public final void setDeleteOnClose(boolean b) {
319 afSocket.setDeleteOnClose(b);
320 }
321
322 @Override
323 public void setShutdownOnClose(boolean enabled) {
324 getAFCore().setShutdownOnClose(enabled);
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338
339 @SuppressFBWarnings("HSM_HIDING_METHOD")
340 public static DatagramChannel open(ProtocolFamily family) throws IOException {
341 requireNonNull(family);
342
343 if (family instanceof AFProtocolFamily) {
344 return ((AFProtocolFamily) family).openDatagramChannel();
345 } else if ("UNIX".equals(family.name())) {
346 return AFUNIXDatagramChannel.open();
347 } else if (family instanceof StandardProtocolFamily) {
348 return DatagramChannel.open();
349 } else {
350 throw new UnsupportedOperationException("Protocol family not supported");
351 }
352 }
353 }