Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/net/NetMulticastSocket.java
41152 views
1
/*
2
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
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
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.net;
27
28
import java.io.IOException;
29
import java.io.UncheckedIOException;
30
import java.nio.channels.DatagramChannel;
31
import java.security.AccessController;
32
import java.security.PrivilegedExceptionAction;
33
import java.util.Enumeration;
34
import java.util.Objects;
35
import java.util.Set;
36
import java.util.Collections;
37
38
/**
39
* A multicast datagram socket that delegates socket operations to a
40
* {@link DatagramSocketImpl}.
41
*
42
* This class overrides every public method defined by {@link DatagramSocket}
43
* and {@link MulticastSocket}.
44
*/
45
final class NetMulticastSocket extends MulticastSocket {
46
/**
47
* Various states of this socket.
48
*/
49
private boolean bound = false;
50
private boolean closed = false;
51
private volatile boolean created;
52
private final Object closeLock = new Object();
53
54
/*
55
* The implementation of this DatagramSocket.
56
*/
57
private final DatagramSocketImpl impl;
58
59
/**
60
* Are we using an older DatagramSocketImpl?
61
*/
62
private final boolean oldImpl;
63
64
/**
65
* Set when a socket is ST_CONNECTED until we are certain
66
* that any packets which might have been received prior
67
* to calling connect() but not read by the application
68
* have been read. During this time we check the source
69
* address of all packets received to be sure they are from
70
* the connected destination. Other packets are read but
71
* silently dropped.
72
*/
73
private boolean explicitFilter = false;
74
private int bytesLeftToFilter;
75
/*
76
* Connection state:
77
* ST_NOT_CONNECTED = socket not connected
78
* ST_CONNECTED = socket connected
79
* ST_CONNECTED_NO_IMPL = socket connected but not at impl level
80
*/
81
static final int ST_NOT_CONNECTED = 0;
82
static final int ST_CONNECTED = 1;
83
static final int ST_CONNECTED_NO_IMPL = 2;
84
85
int connectState = ST_NOT_CONNECTED;
86
87
/*
88
* Connected address & port
89
*/
90
InetAddress connectedAddress = null;
91
int connectedPort = -1;
92
93
/**
94
* This constructor is also used by {@link DatagramSocket#DatagramSocket(DatagramSocketImpl)}.
95
* @param impl The impl used in this instance.
96
*/
97
NetMulticastSocket(DatagramSocketImpl impl) {
98
super((MulticastSocket) null);
99
this.impl = Objects.requireNonNull(impl);
100
this.oldImpl = checkOldImpl(impl);
101
}
102
103
/**
104
* Connects this socket to a remote socket address (IP address + port number).
105
* Binds socket if not already bound.
106
*
107
* @param address The remote address.
108
* @param port The remote port
109
* @throws SocketException if binding the socket fails.
110
*/
111
private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
112
if (port < 0 || port > 0xFFFF) {
113
throw new IllegalArgumentException("connect: " + port);
114
}
115
if (address == null) {
116
throw new IllegalArgumentException("connect: null address");
117
}
118
checkAddress(address, "connect");
119
if (isClosed())
120
return;
121
@SuppressWarnings("removal")
122
SecurityManager security = System.getSecurityManager();
123
if (security != null) {
124
if (address.isMulticastAddress()) {
125
security.checkMulticast(address);
126
} else {
127
security.checkConnect(address.getHostAddress(), port);
128
security.checkAccept(address.getHostAddress(), port);
129
}
130
}
131
132
if (port == 0) {
133
throw new SocketException("Can't connect to port 0");
134
}
135
if (!isBound())
136
bind(new InetSocketAddress(0));
137
138
// old impls do not support connect/disconnect
139
if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
140
((AbstractPlainDatagramSocketImpl) impl).nativeConnectDisabled())) {
141
connectState = ST_CONNECTED_NO_IMPL;
142
} else {
143
try {
144
getImpl().connect(address, port);
145
146
// socket is now connected by the impl
147
connectState = ST_CONNECTED;
148
// Do we need to filter some packets?
149
int avail = getImpl().dataAvailable();
150
if (avail == -1) {
151
throw new SocketException();
152
}
153
explicitFilter = avail > 0;
154
if (explicitFilter) {
155
bytesLeftToFilter = getReceiveBufferSize();
156
}
157
} catch (SocketException se) {
158
159
// connection will be emulated by DatagramSocket
160
connectState = ST_CONNECTED_NO_IMPL;
161
}
162
}
163
164
connectedAddress = address;
165
connectedPort = port;
166
}
167
168
/**
169
* Return true if the given DatagramSocketImpl is an "old" impl. An old impl
170
* is one that doesn't implement the abstract methods added in Java SE 1.4.
171
*/
172
@SuppressWarnings("removal")
173
private static boolean checkOldImpl(DatagramSocketImpl impl) {
174
// DatagramSocketImpl.peekData() is a protected method, therefore we need to use
175
// getDeclaredMethod, therefore we need permission to access the member
176
try {
177
AccessController.doPrivileged(
178
new PrivilegedExceptionAction<>() {
179
public Void run() throws NoSuchMethodException {
180
Class<?>[] cl = new Class<?>[1];
181
cl[0] = DatagramPacket.class;
182
impl.getClass().getDeclaredMethod("peekData", cl);
183
return null;
184
}
185
});
186
return false;
187
} catch (java.security.PrivilegedActionException e) {
188
return true;
189
}
190
}
191
192
/**
193
* Return the {@code DatagramSocketImpl} attached to this socket,
194
* creating the socket if not already created.
195
*
196
* @return the {@code DatagramSocketImpl} attached to that
197
* DatagramSocket
198
* @throws SocketException if creating the socket fails
199
* @since 1.4
200
*/
201
final DatagramSocketImpl getImpl() throws SocketException {
202
if (!created) {
203
synchronized (this) {
204
if (!created) {
205
impl.create();
206
created = true;
207
}
208
}
209
}
210
return impl;
211
}
212
213
@Override
214
public synchronized void bind(SocketAddress addr) throws SocketException {
215
if (isClosed())
216
throw new SocketException("Socket is closed");
217
if (isBound())
218
throw new SocketException("already bound");
219
if (addr == null)
220
addr = new InetSocketAddress(0);
221
if (!(addr instanceof InetSocketAddress epoint))
222
throw new IllegalArgumentException("Unsupported address type!");
223
if (epoint.isUnresolved())
224
throw new SocketException("Unresolved address");
225
InetAddress iaddr = epoint.getAddress();
226
int port = epoint.getPort();
227
checkAddress(iaddr, "bind");
228
@SuppressWarnings("removal")
229
SecurityManager sec = System.getSecurityManager();
230
if (sec != null) {
231
sec.checkListen(port);
232
}
233
try {
234
getImpl().bind(port, iaddr);
235
} catch (SocketException e) {
236
getImpl().close();
237
throw e;
238
}
239
bound = true;
240
}
241
242
static void checkAddress(InetAddress addr, String op) {
243
if (addr == null) {
244
return;
245
}
246
if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
247
throw new IllegalArgumentException(op + ": invalid address type");
248
}
249
}
250
251
@Override
252
public void connect(InetAddress address, int port) {
253
try {
254
connectInternal(address, port);
255
} catch (SocketException se) {
256
throw new UncheckedIOException("connect failed", se);
257
}
258
}
259
260
@Override
261
public void connect(SocketAddress addr) throws SocketException {
262
if (addr == null)
263
throw new IllegalArgumentException("Address can't be null");
264
if (!(addr instanceof InetSocketAddress epoint))
265
throw new IllegalArgumentException("Unsupported address type");
266
if (epoint.isUnresolved())
267
throw new SocketException("Unresolved address");
268
connectInternal(epoint.getAddress(), epoint.getPort());
269
}
270
271
@Override
272
public void disconnect() {
273
synchronized (this) {
274
if (isClosed())
275
return;
276
if (connectState == ST_CONNECTED) {
277
impl.disconnect();
278
}
279
connectedAddress = null;
280
connectedPort = -1;
281
connectState = ST_NOT_CONNECTED;
282
explicitFilter = false;
283
}
284
}
285
286
@Override
287
public boolean isBound() {
288
return bound;
289
}
290
291
@Override
292
public boolean isConnected() {
293
return connectState != ST_NOT_CONNECTED;
294
}
295
296
@Override
297
public InetAddress getInetAddress() {
298
return connectedAddress;
299
}
300
301
@Override
302
public int getPort() {
303
return connectedPort;
304
}
305
306
@Override
307
public SocketAddress getRemoteSocketAddress() {
308
if (!isConnected())
309
return null;
310
return new InetSocketAddress(getInetAddress(), getPort());
311
}
312
313
@Override
314
public SocketAddress getLocalSocketAddress() {
315
if (isClosed())
316
return null;
317
if (!isBound())
318
return null;
319
return new InetSocketAddress(getLocalAddress(), getLocalPort());
320
}
321
322
@Override
323
public void send(DatagramPacket p) throws IOException {
324
synchronized (p) {
325
if (isClosed())
326
throw new SocketException("Socket is closed");
327
InetAddress packetAddress = p.getAddress();
328
int packetPort = p.getPort();
329
checkAddress(packetAddress, "send");
330
if (connectState == ST_NOT_CONNECTED) {
331
if (packetAddress == null) {
332
throw new IllegalArgumentException("Address not set");
333
}
334
if (packetPort < 0 || packetPort > 0xFFFF)
335
throw new IllegalArgumentException("port out of range: " + packetPort);
336
// check the address is ok with the security manager on every send.
337
@SuppressWarnings("removal")
338
SecurityManager security = System.getSecurityManager();
339
340
// The reason you want to synchronize on datagram packet
341
// is because you don't want an applet to change the address
342
// while you are trying to send the packet for example
343
// after the security check but before the send.
344
if (security != null) {
345
if (packetAddress.isMulticastAddress()) {
346
security.checkMulticast(packetAddress);
347
} else {
348
security.checkConnect(packetAddress.getHostAddress(),
349
packetPort);
350
}
351
}
352
if (packetPort == 0) {
353
throw new SocketException("Can't send to port 0");
354
}
355
} else {
356
// we're connected
357
if (packetAddress == null) {
358
p.setAddress(connectedAddress);
359
p.setPort(connectedPort);
360
} else if ((!packetAddress.equals(connectedAddress)) ||
361
packetPort != connectedPort) {
362
throw new IllegalArgumentException("connected address " +
363
"and packet address" +
364
" differ");
365
}
366
}
367
// Check whether the socket is bound
368
if (!isBound())
369
bind(new InetSocketAddress(0));
370
// call the method to send
371
getImpl().send(p);
372
}
373
}
374
375
@Override
376
public synchronized void receive(DatagramPacket p) throws IOException {
377
synchronized (p) {
378
if (!isBound())
379
bind(new InetSocketAddress(0));
380
if (connectState == ST_NOT_CONNECTED) {
381
// check the address is ok with the security manager before every recv.
382
@SuppressWarnings("removal")
383
SecurityManager security = System.getSecurityManager();
384
if (security != null) {
385
while (true) {
386
String peekAd = null;
387
int peekPort = 0;
388
// peek at the packet to see who it is from.
389
if (!oldImpl) {
390
// We can use the new peekData() API
391
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
392
peekPort = getImpl().peekData(peekPacket);
393
peekAd = peekPacket.getAddress().getHostAddress();
394
} else {
395
InetAddress adr = new InetAddress();
396
peekPort = getImpl().peek(adr);
397
peekAd = adr.getHostAddress();
398
}
399
try {
400
security.checkAccept(peekAd, peekPort);
401
// security check succeeded - so now break
402
// and recv the packet.
403
break;
404
} catch (SecurityException se) {
405
// Throw away the offending packet by consuming
406
// it in a tmp buffer.
407
DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
408
getImpl().receive(tmp);
409
410
// silently discard the offending packet
411
// and continue: unknown/malicious
412
// entities on nets should not make
413
// runtime throw security exception and
414
// disrupt the applet by sending random
415
// datagram packets.
416
continue;
417
}
418
} // end of while
419
}
420
}
421
DatagramPacket tmp = null;
422
if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) {
423
// We have to do the filtering the old fashioned way since
424
// the native impl doesn't support connect or the connect
425
// via the impl failed, or .. "explicitFilter" may be set when
426
// a socket is connected via the impl, for a period of time
427
// when packets from other sources might be queued on socket.
428
boolean stop = false;
429
while (!stop) {
430
InetAddress peekAddress = null;
431
int peekPort = -1;
432
// peek at the packet to see who it is from.
433
if (!oldImpl) {
434
// We can use the new peekData() API
435
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
436
peekPort = getImpl().peekData(peekPacket);
437
peekAddress = peekPacket.getAddress();
438
} else {
439
// this api only works for IPv4
440
peekAddress = new InetAddress();
441
peekPort = getImpl().peek(peekAddress);
442
}
443
if ((!connectedAddress.equals(peekAddress)) ||
444
(connectedPort != peekPort)) {
445
// throw the packet away and silently continue
446
tmp = new DatagramPacket(
447
new byte[1024], 1024);
448
getImpl().receive(tmp);
449
if (explicitFilter) {
450
if (checkFiltering(tmp)) {
451
stop = true;
452
}
453
}
454
} else {
455
stop = true;
456
}
457
}
458
}
459
// If the security check succeeds, or the datagram is
460
// connected then receive the packet
461
getImpl().receive(p);
462
if (explicitFilter && tmp == null) {
463
// packet was not filtered, account for it here
464
checkFiltering(p);
465
}
466
}
467
}
468
469
private boolean checkFiltering(DatagramPacket p) throws SocketException {
470
bytesLeftToFilter -= p.getLength();
471
if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) {
472
explicitFilter = false;
473
return true;
474
}
475
return false;
476
}
477
478
@Override
479
public InetAddress getLocalAddress() {
480
if (isClosed())
481
return null;
482
InetAddress in;
483
try {
484
in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
485
if (in.isAnyLocalAddress()) {
486
in = InetAddress.anyLocalAddress();
487
}
488
@SuppressWarnings("removal")
489
SecurityManager s = System.getSecurityManager();
490
if (s != null) {
491
s.checkConnect(in.getHostAddress(), -1);
492
}
493
} catch (Exception e) {
494
in = InetAddress.anyLocalAddress(); // "0.0.0.0"
495
}
496
return in;
497
}
498
499
@Override
500
public int getLocalPort() {
501
if (isClosed())
502
return -1;
503
try {
504
return getImpl().getLocalPort();
505
} catch (Exception e) {
506
return 0;
507
}
508
}
509
510
@Override
511
public synchronized void setSoTimeout(int timeout) throws SocketException {
512
if (isClosed())
513
throw new SocketException("Socket is closed");
514
if (timeout < 0)
515
throw new IllegalArgumentException("timeout < 0");
516
getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
517
}
518
519
@Override
520
public synchronized int getSoTimeout() throws SocketException {
521
if (isClosed())
522
throw new SocketException("Socket is closed");
523
if (getImpl() == null)
524
return 0;
525
Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
526
/* extra type safety */
527
if (o instanceof Integer) {
528
return ((Integer) o).intValue();
529
} else {
530
return 0;
531
}
532
}
533
534
@Override
535
public synchronized void setSendBufferSize(int size) throws SocketException {
536
if (!(size > 0)) {
537
throw new IllegalArgumentException("negative send size");
538
}
539
if (isClosed())
540
throw new SocketException("Socket is closed");
541
getImpl().setOption(SocketOptions.SO_SNDBUF, size);
542
}
543
544
@Override
545
public synchronized int getSendBufferSize() throws SocketException {
546
if (isClosed())
547
throw new SocketException("Socket is closed");
548
int result = 0;
549
Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
550
if (o instanceof Integer) {
551
result = ((Integer) o).intValue();
552
}
553
return result;
554
}
555
556
@Override
557
public synchronized void setReceiveBufferSize(int size) throws SocketException {
558
if (size <= 0) {
559
throw new IllegalArgumentException("invalid receive size");
560
}
561
if (isClosed())
562
throw new SocketException("Socket is closed");
563
getImpl().setOption(SocketOptions.SO_RCVBUF, size);
564
}
565
566
@Override
567
public synchronized int getReceiveBufferSize() throws SocketException {
568
if (isClosed())
569
throw new SocketException("Socket is closed");
570
int result = 0;
571
Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
572
if (o instanceof Integer) {
573
result = ((Integer) o).intValue();
574
}
575
return result;
576
}
577
578
@Override
579
public synchronized void setReuseAddress(boolean on) throws SocketException {
580
if (isClosed())
581
throw new SocketException("Socket is closed");
582
// Integer instead of Boolean for compatibility with older DatagramSocketImpl
583
if (oldImpl)
584
getImpl().setOption(SocketOptions.SO_REUSEADDR, on ? -1 : 0);
585
else
586
getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
587
}
588
589
@Override
590
public synchronized boolean getReuseAddress() throws SocketException {
591
if (isClosed())
592
throw new SocketException("Socket is closed");
593
Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
594
return ((Boolean) o).booleanValue();
595
}
596
597
@Override
598
public synchronized void setBroadcast(boolean on) throws SocketException {
599
if (isClosed())
600
throw new SocketException("Socket is closed");
601
getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on));
602
}
603
604
@Override
605
public synchronized boolean getBroadcast() throws SocketException {
606
if (isClosed())
607
throw new SocketException("Socket is closed");
608
return ((Boolean) (getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue();
609
}
610
611
@Override
612
public synchronized void setTrafficClass(int tc) throws SocketException {
613
if (tc < 0 || tc > 255)
614
throw new IllegalArgumentException("tc is not in range 0 -- 255");
615
616
if (isClosed())
617
throw new SocketException("Socket is closed");
618
try {
619
getImpl().setOption(SocketOptions.IP_TOS, tc);
620
} catch (SocketException se) {
621
// not supported if socket already connected
622
// Solaris returns error in such cases
623
if (!isConnected())
624
throw se;
625
}
626
}
627
628
@Override
629
public synchronized int getTrafficClass() throws SocketException {
630
if (isClosed())
631
throw new SocketException("Socket is closed");
632
return ((Integer) (getImpl().getOption(SocketOptions.IP_TOS))).intValue();
633
}
634
635
@Override
636
public void close() {
637
synchronized (closeLock) {
638
if (isClosed())
639
return;
640
impl.close();
641
closed = true;
642
}
643
}
644
645
@Override
646
public boolean isClosed() {
647
synchronized (closeLock) {
648
return closed;
649
}
650
}
651
652
@Override
653
public <T> DatagramSocket setOption(SocketOption<T> name, T value)
654
throws IOException
655
{
656
Objects.requireNonNull(name);
657
if (isClosed())
658
throw new SocketException("Socket is closed");
659
getImpl().setOption(name, value);
660
return this;
661
}
662
663
@Override
664
public <T> T getOption(SocketOption<T> name) throws IOException {
665
Objects.requireNonNull(name);
666
if (isClosed())
667
throw new SocketException("Socket is closed");
668
return getImpl().getOption(name);
669
}
670
671
private volatile Set<SocketOption<?>> options;
672
private final Object optionsLock = new Object();
673
674
@Override
675
public Set<SocketOption<?>> supportedOptions() {
676
Set<SocketOption<?>> options = this.options;
677
if (options != null)
678
return options;
679
synchronized (optionsLock) {
680
options = this.options;
681
if (options != null) {
682
return options;
683
}
684
try {
685
DatagramSocketImpl impl = getImpl();
686
options = Collections.unmodifiableSet(impl.supportedOptions());
687
} catch (IOException e) {
688
options = Collections.emptySet();
689
}
690
return this.options = options;
691
}
692
}
693
694
// Multicast socket support
695
696
/**
697
* Used on some platforms to record if an outgoing interface
698
* has been set for this socket.
699
*/
700
private boolean interfaceSet;
701
702
/**
703
* The lock on the socket's TTL. This is for set/getTTL and
704
* send(packet,ttl).
705
*/
706
private final Object ttlLock = new Object();
707
708
/**
709
* The lock on the socket's interface - used by setInterface
710
* and getInterface
711
*/
712
private final Object infLock = new Object();
713
714
/**
715
* The "last" interface set by setInterface on this MulticastSocket
716
*/
717
private InetAddress infAddress = null;
718
719
@Deprecated
720
@Override
721
public void setTTL(byte ttl) throws IOException {
722
if (isClosed())
723
throw new SocketException("Socket is closed");
724
getImpl().setTTL(ttl);
725
}
726
727
@Override
728
public void setTimeToLive(int ttl) throws IOException {
729
if (ttl < 0 || ttl > 255) {
730
throw new IllegalArgumentException("ttl out of range");
731
}
732
if (isClosed())
733
throw new SocketException("Socket is closed");
734
getImpl().setTimeToLive(ttl);
735
}
736
737
@Deprecated
738
@Override
739
public byte getTTL() throws IOException {
740
if (isClosed())
741
throw new SocketException("Socket is closed");
742
return getImpl().getTTL();
743
}
744
745
@Override
746
public int getTimeToLive() throws IOException {
747
if (isClosed())
748
throw new SocketException("Socket is closed");
749
return getImpl().getTimeToLive();
750
}
751
752
@Override
753
@Deprecated
754
public void joinGroup(InetAddress mcastaddr) throws IOException {
755
if (isClosed()) {
756
throw new SocketException("Socket is closed");
757
}
758
759
checkAddress(mcastaddr, "joinGroup");
760
@SuppressWarnings("removal")
761
SecurityManager security = System.getSecurityManager();
762
if (security != null) {
763
security.checkMulticast(mcastaddr);
764
}
765
766
if (!mcastaddr.isMulticastAddress()) {
767
throw new SocketException("Not a multicast address");
768
}
769
770
/**
771
* required for some platforms where it's not possible to join
772
* a group without setting the interface first.
773
*/
774
NetworkInterface defaultInterface = NetworkInterface.getDefault();
775
776
if (!interfaceSet && defaultInterface != null) {
777
setNetworkInterface(defaultInterface);
778
}
779
780
getImpl().join(mcastaddr);
781
}
782
783
@Override
784
@Deprecated
785
public void leaveGroup(InetAddress mcastaddr) throws IOException {
786
if (isClosed()) {
787
throw new SocketException("Socket is closed");
788
}
789
790
checkAddress(mcastaddr, "leaveGroup");
791
@SuppressWarnings("removal")
792
SecurityManager security = System.getSecurityManager();
793
if (security != null) {
794
security.checkMulticast(mcastaddr);
795
}
796
797
if (!mcastaddr.isMulticastAddress()) {
798
throw new SocketException("Not a multicast address");
799
}
800
801
getImpl().leave(mcastaddr);
802
}
803
804
@Override
805
public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
806
throws IOException {
807
if (isClosed())
808
throw new SocketException("Socket is closed");
809
810
if (!(mcastaddr instanceof InetSocketAddress addr))
811
throw new IllegalArgumentException("Unsupported address type");
812
813
if (oldImpl)
814
throw new UnsupportedOperationException();
815
816
checkAddress(addr.getAddress(), "joinGroup");
817
@SuppressWarnings("removal")
818
SecurityManager security = System.getSecurityManager();
819
if (security != null) {
820
security.checkMulticast(addr.getAddress());
821
}
822
823
if (!addr.getAddress().isMulticastAddress()) {
824
throw new SocketException("Not a multicast address");
825
}
826
827
getImpl().joinGroup(mcastaddr, netIf);
828
}
829
830
@Override
831
public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
832
throws IOException {
833
if (isClosed())
834
throw new SocketException("Socket is closed");
835
836
if (!(mcastaddr instanceof InetSocketAddress addr))
837
throw new IllegalArgumentException("Unsupported address type");
838
839
if (oldImpl)
840
throw new UnsupportedOperationException();
841
842
checkAddress(addr.getAddress(), "leaveGroup");
843
@SuppressWarnings("removal")
844
SecurityManager security = System.getSecurityManager();
845
if (security != null) {
846
security.checkMulticast(addr.getAddress());
847
}
848
849
if (!addr.getAddress().isMulticastAddress()) {
850
throw new SocketException("Not a multicast address");
851
}
852
853
getImpl().leaveGroup(mcastaddr, netIf);
854
}
855
856
@Override
857
@Deprecated
858
public void setInterface(InetAddress inf) throws SocketException {
859
if (isClosed()) {
860
throw new SocketException("Socket is closed");
861
}
862
checkAddress(inf, "setInterface");
863
synchronized (infLock) {
864
getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
865
infAddress = inf;
866
interfaceSet = true;
867
}
868
}
869
870
@Override
871
@Deprecated
872
public InetAddress getInterface() throws SocketException {
873
if (isClosed()) {
874
throw new SocketException("Socket is closed");
875
}
876
synchronized (infLock) {
877
InetAddress ia =
878
(InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
879
880
/**
881
* No previous setInterface or interface can be
882
* set using setNetworkInterface
883
*/
884
if (infAddress == null) {
885
return ia;
886
}
887
888
/**
889
* Same interface set with setInterface?
890
*/
891
if (ia.equals(infAddress)) {
892
return ia;
893
}
894
895
/**
896
* Different InetAddress from what we set with setInterface
897
* so enumerate the current interface to see if the
898
* address set by setInterface is bound to this interface.
899
*/
900
try {
901
NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
902
Enumeration<InetAddress> addrs = ni.getInetAddresses();
903
while (addrs.hasMoreElements()) {
904
InetAddress addr = addrs.nextElement();
905
if (addr.equals(infAddress)) {
906
return infAddress;
907
}
908
}
909
910
/**
911
* No match so reset infAddress to indicate that the
912
* interface has changed via means
913
*/
914
infAddress = null;
915
return ia;
916
} catch (Exception e) {
917
return ia;
918
}
919
}
920
}
921
922
@Override
923
public void setNetworkInterface(NetworkInterface netIf)
924
throws SocketException {
925
926
synchronized (infLock) {
927
getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf);
928
infAddress = null;
929
interfaceSet = true;
930
}
931
}
932
933
@Override
934
public NetworkInterface getNetworkInterface() throws SocketException {
935
NetworkInterface ni
936
= (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
937
if (ni == null) {
938
InetAddress[] addrs = new InetAddress[1];
939
addrs[0] = InetAddress.anyLocalAddress();
940
return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
941
} else {
942
return ni;
943
}
944
}
945
946
@Override
947
@Deprecated
948
public void setLoopbackMode(boolean disable) throws SocketException {
949
getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable));
950
}
951
952
@Override
953
@Deprecated
954
public boolean getLoopbackMode() throws SocketException {
955
return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue();
956
}
957
958
@SuppressWarnings("removal")
959
@Deprecated
960
@Override
961
public void send(DatagramPacket p, byte ttl)
962
throws IOException {
963
if (isClosed())
964
throw new SocketException("Socket is closed");
965
synchronized(ttlLock) {
966
synchronized(p) {
967
InetAddress packetAddress = p.getAddress();
968
checkAddress(packetAddress, "send");
969
if (connectState == NetMulticastSocket.ST_NOT_CONNECTED) {
970
if (packetAddress == null) {
971
throw new IllegalArgumentException("Address not set");
972
}
973
// Security manager makes sure that the multicast address
974
// is allowed one and that the ttl used is less
975
// than the allowed maxttl.
976
SecurityManager security = System.getSecurityManager();
977
if (security != null) {
978
if (packetAddress.isMulticastAddress()) {
979
security.checkMulticast(packetAddress, ttl);
980
} else {
981
security.checkConnect(packetAddress.getHostAddress(),
982
p.getPort());
983
}
984
}
985
} else {
986
// we're connected
987
if (packetAddress == null) {
988
p.setAddress(connectedAddress);
989
p.setPort(connectedPort);
990
} else if ((!packetAddress.equals(connectedAddress)) ||
991
p.getPort() != connectedPort) {
992
throw new IllegalArgumentException("connected address and packet address" +
993
" differ");
994
}
995
}
996
byte dttl = getTTL();
997
try {
998
if (ttl != dttl) {
999
// set the ttl
1000
getImpl().setTTL(ttl);
1001
}
1002
if (p.getPort() == 0) {
1003
throw new SocketException("Can't send to port 0");
1004
}
1005
// call the datagram method to send
1006
getImpl().send(p);
1007
} finally {
1008
// set it back to default
1009
if (ttl != dttl) {
1010
getImpl().setTTL(dttl);
1011
}
1012
}
1013
} // synch p
1014
} //synch ttl
1015
} //method
1016
}
1017
1018