1 /* |
1 /* |
2 * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
40 import java.nio.ByteBuffer; |
40 import java.nio.ByteBuffer; |
41 import java.nio.channels.ClosedChannelException; |
41 import java.nio.channels.ClosedChannelException; |
42 import java.nio.channels.DatagramChannel; |
42 import java.nio.channels.DatagramChannel; |
43 import java.nio.channels.IllegalBlockingModeException; |
43 import java.nio.channels.IllegalBlockingModeException; |
44 import java.util.Objects; |
44 import java.util.Objects; |
|
45 import java.util.Set; |
45 |
46 |
46 |
47 |
47 // Make a datagram-socket channel look like a datagram socket. |
48 // Make a datagram-socket channel look like a datagram socket. |
48 // |
49 // |
49 // The methods in this class are defined in exactly the same order as in |
50 // The methods in this class are defined in exactly the same order as in |
50 // java.net.DatagramSocket so as to simplify tracking future changes to that |
51 // java.net.DatagramSocket so as to simplify tracking future changes to that |
51 // class. |
52 // class. |
52 // |
53 // |
53 |
54 |
54 public class DatagramSocketAdaptor |
55 class DatagramSocketAdaptor |
55 extends DatagramSocket |
56 extends DatagramSocket |
56 { |
57 { |
57 // The channel being adapted |
58 // The channel being adapted |
58 private final DatagramChannelImpl dc; |
59 private final DatagramChannelImpl dc; |
59 |
60 |
60 // Timeout "option" value for receives |
61 // Timeout "option" value for receives |
61 private volatile int timeout; |
62 private volatile int timeout; |
62 |
63 |
63 // ## super will create a useless impl |
64 // ## super will create a useless impl |
64 private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException { |
65 private DatagramSocketAdaptor(DatagramChannelImpl dc) { |
65 // Invoke the DatagramSocketAdaptor(SocketAddress) constructor, |
66 // Invoke the DatagramSocketAdaptor(SocketAddress) constructor, |
66 // passing a dummy DatagramSocketImpl object to avoid any native |
67 // passing a dummy DatagramSocketImpl object to avoid any native |
67 // resource allocation in super class and invoking our bind method |
68 // resource allocation in super class and invoking our bind method |
68 // before the dc field is initialized. |
69 // before the dc field is initialized. |
69 super(dummyDatagramSocket); |
70 super(dummyDatagramSocket); |
70 this.dc = dc; |
71 this.dc = dc; |
71 } |
72 } |
72 |
73 |
73 public static DatagramSocket create(DatagramChannelImpl dc) { |
74 static DatagramSocket create(DatagramChannelImpl dc) { |
74 try { |
75 return new DatagramSocketAdaptor(dc); |
75 return new DatagramSocketAdaptor(dc); |
|
76 } catch (IOException x) { |
|
77 throw new Error(x); |
|
78 } |
|
79 } |
76 } |
80 |
77 |
81 private void connectInternal(SocketAddress remote) |
78 private void connectInternal(SocketAddress remote) |
82 throws SocketException |
79 throws SocketException |
83 { |
80 { |
94 } catch (Exception x) { |
91 } catch (Exception x) { |
95 Net.translateToSocketException(x); |
92 Net.translateToSocketException(x); |
96 } |
93 } |
97 } |
94 } |
98 |
95 |
|
96 @Override |
99 public void bind(SocketAddress local) throws SocketException { |
97 public void bind(SocketAddress local) throws SocketException { |
100 try { |
98 try { |
101 if (local == null) |
99 if (local == null) |
102 local = new InetSocketAddress(0); |
100 local = new InetSocketAddress(0); |
103 dc.bind(local); |
101 dc.bind(local); |
104 } catch (Exception x) { |
102 } catch (Exception x) { |
105 Net.translateToSocketException(x); |
103 Net.translateToSocketException(x); |
106 } |
104 } |
107 } |
105 } |
108 |
106 |
|
107 @Override |
109 public void connect(InetAddress address, int port) { |
108 public void connect(InetAddress address, int port) { |
110 try { |
109 try { |
111 connectInternal(new InetSocketAddress(address, port)); |
110 connectInternal(new InetSocketAddress(address, port)); |
112 } catch (SocketException x) { |
111 } catch (SocketException x) { |
113 // Yes, j.n.DatagramSocket really does this |
112 // Yes, j.n.DatagramSocket really does this |
114 } |
113 } |
115 } |
114 } |
116 |
115 |
|
116 @Override |
117 public void connect(SocketAddress remote) throws SocketException { |
117 public void connect(SocketAddress remote) throws SocketException { |
118 Objects.requireNonNull(remote, "Address can't be null"); |
118 Objects.requireNonNull(remote, "Address can't be null"); |
119 connectInternal(remote); |
119 connectInternal(remote); |
120 } |
120 } |
121 |
121 |
|
122 @Override |
122 public void disconnect() { |
123 public void disconnect() { |
123 try { |
124 try { |
124 dc.disconnect(); |
125 dc.disconnect(); |
125 } catch (IOException x) { |
126 } catch (IOException x) { |
126 throw new Error(x); |
127 throw new Error(x); |
127 } |
128 } |
128 } |
129 } |
129 |
130 |
|
131 @Override |
130 public boolean isBound() { |
132 public boolean isBound() { |
131 return dc.localAddress() != null; |
133 return dc.localAddress() != null; |
132 } |
134 } |
133 |
135 |
|
136 @Override |
134 public boolean isConnected() { |
137 public boolean isConnected() { |
135 return dc.remoteAddress() != null; |
138 return dc.remoteAddress() != null; |
136 } |
139 } |
137 |
140 |
|
141 @Override |
138 public InetAddress getInetAddress() { |
142 public InetAddress getInetAddress() { |
139 InetSocketAddress remote = dc.remoteAddress(); |
143 InetSocketAddress remote = dc.remoteAddress(); |
140 return (remote != null) ? remote.getAddress() : null; |
144 return (remote != null) ? remote.getAddress() : null; |
141 } |
145 } |
142 |
146 |
|
147 @Override |
143 public int getPort() { |
148 public int getPort() { |
144 InetSocketAddress remote = dc.remoteAddress(); |
149 InetSocketAddress remote = dc.remoteAddress(); |
145 return (remote != null) ? remote.getPort() : -1; |
150 return (remote != null) ? remote.getPort() : -1; |
146 } |
151 } |
147 |
152 |
|
153 @Override |
|
154 public SocketAddress getRemoteSocketAddress() { |
|
155 return dc.remoteAddress(); |
|
156 } |
|
157 |
|
158 @Override |
|
159 public SocketAddress getLocalSocketAddress() { |
|
160 return dc.localAddress(); |
|
161 } |
|
162 |
|
163 @Override |
148 public void send(DatagramPacket p) throws IOException { |
164 public void send(DatagramPacket p) throws IOException { |
149 synchronized (dc.blockingLock()) { |
165 synchronized (dc.blockingLock()) { |
150 if (!dc.isBlocking()) |
166 if (!dc.isBlocking()) |
151 throw new IllegalBlockingModeException(); |
167 throw new IllegalBlockingModeException(); |
152 try { |
168 try { |
246 } catch (Exception x) { |
265 } catch (Exception x) { |
247 } |
266 } |
248 return 0; |
267 return 0; |
249 } |
268 } |
250 |
269 |
|
270 @Override |
251 public void setSoTimeout(int timeout) throws SocketException { |
271 public void setSoTimeout(int timeout) throws SocketException { |
|
272 if (!dc.isOpen()) |
|
273 throw new SocketException("Socket is closed"); |
|
274 if (timeout < 0) |
|
275 throw new IllegalArgumentException("timeout < 0"); |
252 this.timeout = timeout; |
276 this.timeout = timeout; |
253 } |
277 } |
254 |
278 |
|
279 @Override |
255 public int getSoTimeout() throws SocketException { |
280 public int getSoTimeout() throws SocketException { |
|
281 if (!dc.isOpen()) |
|
282 throw new SocketException("Socket is closed"); |
256 return timeout; |
283 return timeout; |
257 } |
284 } |
258 |
285 |
259 private void setBooleanOption(SocketOption<Boolean> name, boolean value) |
286 private void setBooleanOption(SocketOption<Boolean> name, boolean value) |
260 throws SocketException |
287 throws SocketException |
292 Net.translateToSocketException(x); |
319 Net.translateToSocketException(x); |
293 return -1; // keep compiler happy |
320 return -1; // keep compiler happy |
294 } |
321 } |
295 } |
322 } |
296 |
323 |
|
324 @Override |
297 public void setSendBufferSize(int size) throws SocketException { |
325 public void setSendBufferSize(int size) throws SocketException { |
298 if (size <= 0) |
326 if (size <= 0) |
299 throw new IllegalArgumentException("Invalid send size"); |
327 throw new IllegalArgumentException("Invalid send size"); |
300 setIntOption(StandardSocketOptions.SO_SNDBUF, size); |
328 setIntOption(StandardSocketOptions.SO_SNDBUF, size); |
301 } |
329 } |
302 |
330 |
|
331 @Override |
303 public int getSendBufferSize() throws SocketException { |
332 public int getSendBufferSize() throws SocketException { |
304 return getIntOption(StandardSocketOptions.SO_SNDBUF); |
333 return getIntOption(StandardSocketOptions.SO_SNDBUF); |
305 } |
334 } |
306 |
335 |
|
336 @Override |
307 public void setReceiveBufferSize(int size) throws SocketException { |
337 public void setReceiveBufferSize(int size) throws SocketException { |
308 if (size <= 0) |
338 if (size <= 0) |
309 throw new IllegalArgumentException("Invalid receive size"); |
339 throw new IllegalArgumentException("Invalid receive size"); |
310 setIntOption(StandardSocketOptions.SO_RCVBUF, size); |
340 setIntOption(StandardSocketOptions.SO_RCVBUF, size); |
311 } |
341 } |
312 |
342 |
|
343 @Override |
313 public int getReceiveBufferSize() throws SocketException { |
344 public int getReceiveBufferSize() throws SocketException { |
314 return getIntOption(StandardSocketOptions.SO_RCVBUF); |
345 return getIntOption(StandardSocketOptions.SO_RCVBUF); |
315 } |
346 } |
316 |
347 |
|
348 @Override |
317 public void setReuseAddress(boolean on) throws SocketException { |
349 public void setReuseAddress(boolean on) throws SocketException { |
318 setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on); |
350 setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on); |
319 } |
351 } |
320 |
352 |
|
353 @Override |
321 public boolean getReuseAddress() throws SocketException { |
354 public boolean getReuseAddress() throws SocketException { |
322 return getBooleanOption(StandardSocketOptions.SO_REUSEADDR); |
355 return getBooleanOption(StandardSocketOptions.SO_REUSEADDR); |
323 |
356 |
324 } |
357 } |
325 |
358 |
|
359 @Override |
326 public void setBroadcast(boolean on) throws SocketException { |
360 public void setBroadcast(boolean on) throws SocketException { |
327 setBooleanOption(StandardSocketOptions.SO_BROADCAST, on); |
361 setBooleanOption(StandardSocketOptions.SO_BROADCAST, on); |
328 } |
362 } |
329 |
363 |
|
364 @Override |
330 public boolean getBroadcast() throws SocketException { |
365 public boolean getBroadcast() throws SocketException { |
331 return getBooleanOption(StandardSocketOptions.SO_BROADCAST); |
366 return getBooleanOption(StandardSocketOptions.SO_BROADCAST); |
332 } |
367 } |
333 |
368 |
|
369 @Override |
334 public void setTrafficClass(int tc) throws SocketException { |
370 public void setTrafficClass(int tc) throws SocketException { |
335 setIntOption(StandardSocketOptions.IP_TOS, tc); |
371 setIntOption(StandardSocketOptions.IP_TOS, tc); |
336 } |
372 } |
337 |
373 |
|
374 @Override |
338 public int getTrafficClass() throws SocketException { |
375 public int getTrafficClass() throws SocketException { |
339 return getIntOption(StandardSocketOptions.IP_TOS); |
376 return getIntOption(StandardSocketOptions.IP_TOS); |
340 } |
377 } |
341 |
378 |
|
379 @Override |
342 public void close() { |
380 public void close() { |
343 try { |
381 try { |
344 dc.close(); |
382 dc.close(); |
345 } catch (IOException x) { |
383 } catch (IOException x) { |
346 throw new Error(x); |
384 throw new Error(x); |
347 } |
385 } |
348 } |
386 } |
349 |
387 |
|
388 @Override |
350 public boolean isClosed() { |
389 public boolean isClosed() { |
351 return !dc.isOpen(); |
390 return !dc.isOpen(); |
352 } |
391 } |
353 |
392 |
|
393 @Override |
354 public DatagramChannel getChannel() { |
394 public DatagramChannel getChannel() { |
355 return dc; |
395 return dc; |
|
396 } |
|
397 |
|
398 @Override |
|
399 public <T> DatagramSocket setOption(SocketOption<T> name, T value) throws IOException { |
|
400 dc.setOption(name, value); |
|
401 return this; |
|
402 } |
|
403 |
|
404 @Override |
|
405 public <T> T getOption(SocketOption<T> name) throws IOException { |
|
406 return dc.getOption(name); |
|
407 } |
|
408 |
|
409 @Override |
|
410 public Set<SocketOption<?>> supportedOptions() { |
|
411 return dc.supportedOptions(); |
356 } |
412 } |
357 |
413 |
358 /* |
414 /* |
359 * A dummy implementation of DatagramSocketImpl that can be passed to the |
415 * A dummy implementation of DatagramSocketImpl that can be passed to the |
360 * DatagramSocket constructor so that no native resources are allocated in |
416 * DatagramSocket constructor so that no native resources are allocated in |