History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/net/DatagramSocket.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/net/DatagramSocket.java+1257−0
@@ -0,0 +1,1257 @@
1+/*
2+ * Copyright (c) 1995, 2010, 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.FileDescriptor;
29+import java.io.IOException;
30+import java.io.InterruptedIOException;
31+import java.nio.channels.DatagramChannel;
32+import java.security.AccessController;
33+import java.security.PrivilegedExceptionAction;
34+
35+/**
36+ * This class represents a socket for sending and receiving datagram packets.
37+ *
38+ * <p>A datagram socket is the sending or receiving point for a packet
39+ * delivery service. Each packet sent or received on a datagram socket
40+ * is individually addressed and routed. Multiple packets sent from
41+ * one machine to another may be routed differently, and may arrive in
42+ * any order.
43+ *
44+ * <p> Where possible, a newly constructed {@code DatagramSocket} has the
45+ * {@link SocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
46+ * to allow the transmission of broadcast datagrams. In order to receive
47+ * broadcast packets a DatagramSocket should be bound to the wildcard address.
48+ * In some implementations, broadcast packets may also be received when
49+ * a DatagramSocket is bound to a more specific address.
50+ * <p>
51+ * Example:
52+ * <code>
53+ * DatagramSocket s = new DatagramSocket(null);
54+ * s.bind(new InetSocketAddress(8888));
55+ * </code>
56+ * Which is equivalent to:
57+ * <code>
58+ * DatagramSocket s = new DatagramSocket(8888);
59+ * </code>
60+ * Both cases will create a DatagramSocket able to receive broadcasts on
61+ * UDP port 8888.
62+ *
63+ * @author Pavani Diwanji
64+ * @see java.net.DatagramPacket
65+ * @see java.nio.channels.DatagramChannel
66+ * @since JDK1.0
67+ */
68+public
69+class DatagramSocket implements java.io.Closeable {
70+ /**
71+ * Various states of this socket.
72+ */
73+ private boolean created = false;
74+ private boolean bound = false;
75+ private boolean closed = false;
76+ private Object closeLock = new Object();
77+
78+ /*
79+ * The implementation of this DatagramSocket.
80+ */
81+ DatagramSocketImpl impl;
82+
83+ /**
84+ * Are we using an older DatagramSocketImpl?
85+ */
86+ boolean oldImpl = false;
87+
88+ /*
89+ * Connection state:
90+ * ST_NOT_CONNECTED = socket not connected
91+ * ST_CONNECTED = socket connected
92+ * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
93+ */
94+ static final int ST_NOT_CONNECTED = 0;
95+ static final int ST_CONNECTED = 1;
96+ static final int ST_CONNECTED_NO_IMPL = 2;
97+
98+ int connectState = ST_NOT_CONNECTED;
99+
100+ /*
101+ * Connected address & port
102+ */
103+ InetAddress connectedAddress = null;
104+ int connectedPort = -1;
105+
106+ /**
107+ * Connects this socket to a remote socket address (IP address + port number).
108+ * Binds socket if not already bound.
109+ * <p>
110+ * @param addr The remote address.
111+ * @param port The remote port
112+ * @throws SocketException if binding the socket fails.
113+ */
114+ private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
115+ if (port < 0 || port > 0xFFFF) {
116+ throw new IllegalArgumentException("connect: " + port);
117+ }
118+ if (address == null) {
119+ throw new IllegalArgumentException("connect: null address");
120+ }
121+ checkAddress (address, "connect");
122+ if (isClosed())
123+ return;
124+ SecurityManager security = System.getSecurityManager();
125+ if (security != null) {
126+ if (address.isMulticastAddress()) {
127+ security.checkMulticast(address);
128+ } else {
129+ security.checkConnect(address.getHostAddress(), port);
130+ security.checkAccept(address.getHostAddress(), port);
131+ }
132+ }
133+
134+ if (!isBound())
135+ bind(new InetSocketAddress(0));
136+
137+ // old impls do not support connect/disconnect
138+ if (oldImpl) {
139+ connectState = ST_CONNECTED_NO_IMPL;
140+ } else {
141+ try {
142+ getImpl().connect(address, port);
143+
144+ // socket is now connected by the impl
145+ connectState = ST_CONNECTED;
146+ } catch (SocketException se) {
147+
148+ // connection will be emulated by DatagramSocket
149+ connectState = ST_CONNECTED_NO_IMPL;
150+ }
151+ }
152+
153+ connectedAddress = address;
154+ connectedPort = port;
155+ }
156+
157+
158+ /**
159+ * Constructs a datagram socket and binds it to any available port
160+ * on the local host machine. The socket will be bound to the
161+ * {@link InetAddress#isAnyLocalAddress wildcard} address,
162+ * an IP address chosen by the kernel.
163+ *
164+ * <p>If there is a security manager,
165+ * its <code>checkListen</code> method is first called
166+ * with 0 as its argument to ensure the operation is allowed.
167+ * This could result in a SecurityException.
168+ *
169+ * @exception SocketException if the socket could not be opened,
170+ * or the socket could not bind to the specified local port.
171+ * @exception SecurityException if a security manager exists and its
172+ * <code>checkListen</code> method doesn't allow the operation.
173+ *
174+ * @see SecurityManager#checkListen
175+ */
176+ public DatagramSocket() throws SocketException {
177+ // create a datagram socket.
178+ createImpl();
179+ try {
180+ bind(new InetSocketAddress(0));
181+ } catch (SocketException se) {
182+ throw se;
183+ } catch(IOException e) {
184+ throw new SocketException(e.getMessage());
185+ }
186+ }
187+
188+ /**
189+ * Creates an unbound datagram socket with the specified
190+ * DatagramSocketImpl.
191+ *
192+ * @param impl an instance of a <B>DatagramSocketImpl</B>
193+ * the subclass wishes to use on the DatagramSocket.
194+ * @since 1.4
195+ */
196+ protected DatagramSocket(DatagramSocketImpl impl) {
197+ if (impl == null)
198+ throw new NullPointerException();
199+ this.impl = impl;
200+ checkOldImpl();
201+ }
202+
203+ /**
204+ * Creates a datagram socket, bound to the specified local
205+ * socket address.
206+ * <p>
207+ * If, if the address is <code>null</code>, creates an unbound socket.
208+ * <p>
209+ * <p>If there is a security manager,
210+ * its <code>checkListen</code> method is first called
211+ * with the port from the socket address
212+ * as its argument to ensure the operation is allowed.
213+ * This could result in a SecurityException.
214+ *
215+ * @param bindaddr local socket address to bind, or <code>null</code>
216+ * for an unbound socket.
217+ *
218+ * @exception SocketException if the socket could not be opened,
219+ * or the socket could not bind to the specified local port.
220+ * @exception SecurityException if a security manager exists and its
221+ * <code>checkListen</code> method doesn't allow the operation.
222+ *
223+ * @see SecurityManager#checkListen
224+ * @since 1.4
225+ */
226+ public DatagramSocket(SocketAddress bindaddr) throws SocketException {
227+ // create a datagram socket.
228+ createImpl();
229+ if (bindaddr != null) {
230+ bind(bindaddr);
231+ }
232+ }
233+
234+ /**
235+ * Constructs a datagram socket and binds it to the specified port
236+ * on the local host machine. The socket will be bound to the
237+ * {@link InetAddress#isAnyLocalAddress wildcard} address,
238+ * an IP address chosen by the kernel.
239+ *
240+ * <p>If there is a security manager,
241+ * its <code>checkListen</code> method is first called
242+ * with the <code>port</code> argument
243+ * as its argument to ensure the operation is allowed.
244+ * This could result in a SecurityException.
245+ *
246+ * @param port port to use.
247+ * @exception SocketException if the socket could not be opened,
248+ * or the socket could not bind to the specified local port.
249+ * @exception SecurityException if a security manager exists and its
250+ * <code>checkListen</code> method doesn't allow the operation.
251+ *
252+ * @see SecurityManager#checkListen
253+ */
254+ public DatagramSocket(int port) throws SocketException {
255+ this(port, null);
256+ }
257+
258+ /**
259+ * Creates a datagram socket, bound to the specified local
260+ * address. The local port must be between 0 and 65535 inclusive.
261+ * If the IP address is 0.0.0.0, the socket will be bound to the
262+ * {@link InetAddress#isAnyLocalAddress wildcard} address,
263+ * an IP address chosen by the kernel.
264+ *
265+ * <p>If there is a security manager,
266+ * its <code>checkListen</code> method is first called
267+ * with the <code>port</code> argument
268+ * as its argument to ensure the operation is allowed.
269+ * This could result in a SecurityException.
270+ *
271+ * @param port local port to use
272+ * @param laddr local address to bind
273+ *
274+ * @exception SocketException if the socket could not be opened,
275+ * or the socket could not bind to the specified local port.
276+ * @exception SecurityException if a security manager exists and its
277+ * <code>checkListen</code> method doesn't allow the operation.
278+ *
279+ * @see SecurityManager#checkListen
280+ * @since JDK1.1
281+ */
282+ public DatagramSocket(int port, InetAddress laddr) throws SocketException {
283+ this(new InetSocketAddress(laddr, port));
284+ }
285+
286+ private void checkOldImpl() {
287+ if (impl == null)
288+ return;
289+ // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
290+ // getDeclaredMethod, therefore we need permission to access the member
291+ try {
292+ AccessController.doPrivileged(
293+ new PrivilegedExceptionAction<Void>() {
294+ public Void run() throws NoSuchMethodException {
295+ Class[] cl = new Class[1];
296+ cl[0] = DatagramPacket.class;
297+ impl.getClass().getDeclaredMethod("peekData", cl);
298+ return null;
299+ }
300+ });
301+ } catch (java.security.PrivilegedActionException e) {
302+ oldImpl = true;
303+ }
304+ }
305+
306+ static Class implClass = null;
307+
308+ void createImpl() throws SocketException {
309+ if (impl == null) {
310+ if (factory != null) {
311+ impl = factory.createDatagramSocketImpl();
312+ checkOldImpl();
313+ } else {
314+ boolean isMulticast = (this instanceof MulticastSocket) ? true : false;
315+ impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast);
316+
317+ checkOldImpl();
318+ }
319+ }
320+ // creates a udp socket
321+ impl.create();
322+ created = true;
323+ }
324+
325+ /**
326+ * Get the <code>DatagramSocketImpl</code> attached to this socket,
327+ * creating it if necessary.
328+ *
329+ * @return the <code>DatagramSocketImpl</code> attached to that
330+ * DatagramSocket
331+ * @throws SocketException if creation fails.
332+ * @since 1.4
333+ */
334+ DatagramSocketImpl getImpl() throws SocketException {
335+ if (!created)
336+ createImpl();
337+ return impl;
338+ }
339+
340+ /**
341+ * Binds this DatagramSocket to a specific address & port.
342+ * <p>
343+ * If the address is <code>null</code>, then the system will pick up
344+ * an ephemeral port and a valid local address to bind the socket.
345+ *<p>
346+ * @param addr The address & port to bind to.
347+ * @throws SocketException if any error happens during the bind, or if the
348+ * socket is already bound.
349+ * @throws SecurityException if a security manager exists and its
350+ * <code>checkListen</code> method doesn't allow the operation.
351+ * @throws IllegalArgumentException if addr is a SocketAddress subclass
352+ * not supported by this socket.
353+ * @since 1.4
354+ */
355+ public synchronized void bind(SocketAddress addr) throws SocketException {
356+ if (isClosed())
357+ throw new SocketException("Socket is closed");
358+ if (isBound())
359+ throw new SocketException("already bound");
360+ if (addr == null)
361+ addr = new InetSocketAddress(0);
362+ if (!(addr instanceof InetSocketAddress))
363+ throw new IllegalArgumentException("Unsupported address type!");
364+ InetSocketAddress epoint = (InetSocketAddress) addr;
365+ if (epoint.isUnresolved())
366+ throw new SocketException("Unresolved address");
367+ InetAddress iaddr = epoint.getAddress();
368+ int port = epoint.getPort();
369+ checkAddress(iaddr, "bind");
370+ SecurityManager sec = System.getSecurityManager();
371+ if (sec != null) {
372+ sec.checkListen(port);
373+ }
374+ try {
375+ getImpl().bind(port, iaddr);
376+ } catch (SocketException e) {
377+ getImpl().close();
378+ throw e;
379+ }
380+ bound = true;
381+ }
382+
383+ void checkAddress (InetAddress addr, String op) {
384+ if (addr == null) {
385+ return;
386+ }
387+ if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
388+ throw new IllegalArgumentException(op + ": invalid address type");
389+ }
390+ }
391+
392+ /**
393+ * Connects the socket to a remote address for this socket. When a
394+ * socket is connected to a remote address, packets may only be
395+ * sent to or received from that address. By default a datagram
396+ * socket is not connected.
397+ *
398+ * <p>If the remote destination to which the socket is connected does not
399+ * exist, or is otherwise unreachable, and if an ICMP destination unreachable
400+ * packet has been received for that address, then a subsequent call to
401+ * send or receive may throw a PortUnreachableException. Note, there is no
402+ * guarantee that the exception will be thrown.
403+ *
404+ * <p> If a security manager has been installed then it is invoked to check
405+ * access to the remote address. Specifically, if the given {@code address}
406+ * is a {@link InetAddress#isMulticastAddress multicast address},
407+ * the security manager's {@link
408+ * java.lang.SecurityManager#checkMulticast(InetAddress)
409+ * checkMulticast} method is invoked with the given {@code address}.
410+ * Otherwise, the security manager's {@link
411+ * java.lang.SecurityManager#checkConnect(String,int) checkConnect}
412+ * and {@link java.lang.SecurityManager#checkAccept checkAccept} methods
413+ * are invoked, with the given {@code address} and {@code port}, to
414+ * verify that datagrams are permitted to be sent and received
415+ * respectively.
416+ *
417+ * <p> When a socket is connected, {@link #receive receive} and
418+ * {@link #send send} <b>will not perform any security checks</b>
419+ * on incoming and outgoing packets, other than matching the packet's
420+ * and the socket's address and port. On a send operation, if the
421+ * packet's address is set and the packet's address and the socket's
422+ * address do not match, an {@code IllegalArgumentException} will be
423+ * thrown. A socket connected to a multicast address may only be used
424+ * to send packets.
425+ *
426+ * @param address the remote address for the socket
427+ *
428+ * @param port the remote port for the socket.
429+ *
430+ * @throws IllegalArgumentException
431+ * if the address is null, or the port is out of range.
432+ *
433+ * @throws SecurityException
434+ * if a security manager has been installed and it does
435+ * not permit access to the given remote address
436+ *
437+ * @see #disconnect
438+ */
439+ public void connect(InetAddress address, int port) {
440+ try {
441+ connectInternal(address, port);
442+ } catch (SocketException se) {
443+ throw new Error("connect failed", se);
444+ }
445+ }
446+
447+ /**
448+ * Connects this socket to a remote socket address (IP address + port number).
449+ *
450+ * <p> If given an {@link InetSocketAddress InetSocketAddress}, this method
451+ * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)}
452+ * with the the given socket addresses IP address and port number.
453+ *
454+ * @param addr The remote address.
455+ *
456+ * @throws SocketException
457+ * if the connect fails
458+ *
459+ * @throws IllegalArgumentException
460+ * if {@code addr} is {@code null}, or {@code addr} is a SocketAddress
461+ * subclass not supported by this socket
462+ *
463+ * @throws SecurityException
464+ * if a security manager has been installed and it does
465+ * not permit access to the given remote address
466+ *
467+ * @since 1.4
468+ */
469+ public void connect(SocketAddress addr) throws SocketException {
470+ if (addr == null)
471+ throw new IllegalArgumentException("Address can't be null");
472+ if (!(addr instanceof InetSocketAddress))
473+ throw new IllegalArgumentException("Unsupported address type");
474+ InetSocketAddress epoint = (InetSocketAddress) addr;
475+ if (epoint.isUnresolved())
476+ throw new SocketException("Unresolved address");
477+ connectInternal(epoint.getAddress(), epoint.getPort());
478+ }
479+
480+ /**
481+ * Disconnects the socket. If the socket is closed or not connected,
482+ * then this method has no effect.
483+ *
484+ * @see #connect
485+ */
486+ public void disconnect() {
487+ synchronized (this) {
488+ if (isClosed())
489+ return;
490+ if (connectState == ST_CONNECTED) {
491+ impl.disconnect ();
492+ }
493+ connectedAddress = null;
494+ connectedPort = -1;
495+ connectState = ST_NOT_CONNECTED;
496+ }
497+ }
498+
499+ /**
500+ * Returns the binding state of the socket.
501+ * <p>
502+ * If the socket was bound prior to being {@link #close closed},
503+ * then this method will continue to return <code>true</code>
504+ * after the socket is closed.
505+ *
506+ * @return true if the socket successfully bound to an address
507+ * @since 1.4
508+ */
509+ public boolean isBound() {
510+ return bound;
511+ }
512+
513+ /**
514+ * Returns the connection state of the socket.
515+ * <p>
516+ * If the socket was connected prior to being {@link #close closed},
517+ * then this method will continue to return <code>true</code>
518+ * after the socket is closed.
519+ *
520+ * @return true if the socket successfully connected to a server
521+ * @since 1.4
522+ */
523+ public boolean isConnected() {
524+ return connectState != ST_NOT_CONNECTED;
525+ }
526+
527+ /**
528+ * Returns the address to which this socket is connected. Returns
529+ * <code>null</code> if the socket is not connected.
530+ * <p>
531+ * If the socket was connected prior to being {@link #close closed},
532+ * then this method will continue to return the connected address
533+ * after the socket is closed.
534+ *
535+ * @return the address to which this socket is connected.
536+ */
537+ public InetAddress getInetAddress() {
538+ return connectedAddress;
539+ }
540+
541+ /**
542+ * Returns the port number to which this socket is connected.
543+ * Returns <code>-1</code> if the socket is not connected.
544+ * <p>
545+ * If the socket was connected prior to being {@link #close closed},
546+ * then this method will continue to return the connected port number
547+ * after the socket is closed.
548+ *
549+ * @return the port number to which this socket is connected.
550+ */
551+ public int getPort() {
552+ return connectedPort;
553+ }
554+
555+ /**
556+ * Returns the address of the endpoint this socket is connected to, or
557+ * <code>null</code> if it is unconnected.
558+ * <p>
559+ * If the socket was connected prior to being {@link #close closed},
560+ * then this method will continue to return the connected address
561+ * after the socket is closed.
562+ *
563+ * @return a <code>SocketAddress</code> representing the remote
564+ * endpoint of this socket, or <code>null</code> if it is
565+ * not connected yet.
566+ * @see #getInetAddress()
567+ * @see #getPort()
568+ * @see #connect(SocketAddress)
569+ * @since 1.4
570+ */
571+ public SocketAddress getRemoteSocketAddress() {
572+ if (!isConnected())
573+ return null;
574+ return new InetSocketAddress(getInetAddress(), getPort());
575+ }
576+
577+ /**
578+ * Returns the address of the endpoint this socket is bound to.
579+ *
580+ * @return a <code>SocketAddress</code> representing the local endpoint of this
581+ * socket, or <code>null</code> if it is closed or not bound yet.
582+ * @see #getLocalAddress()
583+ * @see #getLocalPort()
584+ * @see #bind(SocketAddress)
585+ * @since 1.4
586+ */
587+
588+ public SocketAddress getLocalSocketAddress() {
589+ if (isClosed())
590+ return null;
591+ if (!isBound())
592+ return null;
593+ return new InetSocketAddress(getLocalAddress(), getLocalPort());
594+ }
595+
596+ /**
597+ * Sends a datagram packet from this socket. The
598+ * <code>DatagramPacket</code> includes information indicating the
599+ * data to be sent, its length, the IP address of the remote host,
600+ * and the port number on the remote host.
601+ *
602+ * <p>If there is a security manager, and the socket is not currently
603+ * connected to a remote address, this method first performs some
604+ * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
605+ * is true, this method calls the
606+ * security manager's <code>checkMulticast</code> method
607+ * with <code>p.getAddress()</code> as its argument.
608+ * If the evaluation of that expression is false,
609+ * this method instead calls the security manager's
610+ * <code>checkConnect</code> method with arguments
611+ * <code>p.getAddress().getHostAddress()</code> and
612+ * <code>p.getPort()</code>. Each call to a security manager method
613+ * could result in a SecurityException if the operation is not allowed.
614+ *
615+ * @param p the <code>DatagramPacket</code> to be sent.
616+ *
617+ * @exception IOException if an I/O error occurs.
618+ * @exception SecurityException if a security manager exists and its
619+ * <code>checkMulticast</code> or <code>checkConnect</code>
620+ * method doesn't allow the send.
621+ * @exception PortUnreachableException may be thrown if the socket is connected
622+ * to a currently unreachable destination. Note, there is no
623+ * guarantee that the exception will be thrown.
624+ * @exception java.nio.channels.IllegalBlockingModeException
625+ * if this socket has an associated channel,
626+ * and the channel is in non-blocking mode.
627+ * @exception IllegalArgumentException if the socket is connected,
628+ * and connected address and packet address differ.
629+ *
630+ * @see java.net.DatagramPacket
631+ * @see SecurityManager#checkMulticast(InetAddress)
632+ * @see SecurityManager#checkConnect
633+ * @revised 1.4
634+ * @spec JSR-51
635+ */
636+ public void send(DatagramPacket p) throws IOException {
637+ InetAddress packetAddress = null;
638+ synchronized (p) {
639+ if (isClosed())
640+ throw new SocketException("Socket is closed");
641+ checkAddress (p.getAddress(), "send");
642+ if (connectState == ST_NOT_CONNECTED) {
643+ // check the address is ok wiht the security manager on every send.
644+ SecurityManager security = System.getSecurityManager();
645+
646+ // The reason you want to synchronize on datagram packet
647+ // is because you dont want an applet to change the address
648+ // while you are trying to send the packet for example
649+ // after the security check but before the send.
650+ if (security != null) {
651+ if (p.getAddress().isMulticastAddress()) {
652+ security.checkMulticast(p.getAddress());
653+ } else {
654+ security.checkConnect(p.getAddress().getHostAddress(),
655+ p.getPort());
656+ }
657+ }
658+ } else {
659+ // we're connected
660+ packetAddress = p.getAddress();
661+ if (packetAddress == null) {
662+ p.setAddress(connectedAddress);
663+ p.setPort(connectedPort);
664+ } else if ((!packetAddress.equals(connectedAddress)) ||
665+ p.getPort() != connectedPort) {
666+ throw new IllegalArgumentException("connected address " +
667+ "and packet address" +
668+ " differ");
669+ }
670+ }
671+ // Check whether the socket is bound
672+ if (!isBound())
673+ bind(new InetSocketAddress(0));
674+ // call the method to send
675+ getImpl().send(p);
676+ }
677+ }
678+
679+ /**
680+ * Receives a datagram packet from this socket. When this method
681+ * returns, the <code>DatagramPacket</code>'s buffer is filled with
682+ * the data received. The datagram packet also contains the sender's
683+ * IP address, and the port number on the sender's machine.
684+ * <p>
685+ * This method blocks until a datagram is received. The
686+ * <code>length</code> field of the datagram packet object contains
687+ * the length of the received message. If the message is longer than
688+ * the packet's length, the message is truncated.
689+ * <p>
690+ * If there is a security manager, a packet cannot be received if the
691+ * security manager's <code>checkAccept</code> method
692+ * does not allow it.
693+ *
694+ * @param p the <code>DatagramPacket</code> into which to place
695+ * the incoming data.
696+ * @exception IOException if an I/O error occurs.
697+ * @exception SocketTimeoutException if setSoTimeout was previously called
698+ * and the timeout has expired.
699+ * @exception PortUnreachableException may be thrown if the socket is connected
700+ * to a currently unreachable destination. Note, there is no guarantee that the
701+ * exception will be thrown.
702+ * @exception java.nio.channels.IllegalBlockingModeException
703+ * if this socket has an associated channel,
704+ * and the channel is in non-blocking mode.
705+ * @see java.net.DatagramPacket
706+ * @see java.net.DatagramSocket
707+ * @revised 1.4
708+ * @spec JSR-51
709+ */
710+ public synchronized void receive(DatagramPacket p) throws IOException {
711+ synchronized (p) {
712+ if (!isBound())
713+ bind(new InetSocketAddress(0));
714+ if (connectState == ST_NOT_CONNECTED) {
715+ // check the address is ok with the security manager before every recv.
716+ SecurityManager security = System.getSecurityManager();
717+ if (security != null) {
718+ while(true) {
719+ String peekAd = null;
720+ int peekPort = 0;
721+ // peek at the packet to see who it is from.
722+ if (!oldImpl) {
723+ // We can use the new peekData() API
724+ DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
725+ peekPort = getImpl().peekData(peekPacket);
726+ peekAd = peekPacket.getAddress().getHostAddress();
727+ } else {
728+ InetAddress adr = new InetAddress();
729+ peekPort = getImpl().peek(adr);
730+ peekAd = adr.getHostAddress();
731+ }
732+ try {
733+ security.checkAccept(peekAd, peekPort);
734+ // security check succeeded - so now break
735+ // and recv the packet.
736+ break;
737+ } catch (SecurityException se) {
738+ // Throw away the offending packet by consuming
739+ // it in a tmp buffer.
740+ DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
741+ getImpl().receive(tmp);
742+
743+ // silently discard the offending packet
744+ // and continue: unknown/malicious
745+ // entities on nets should not make
746+ // runtime throw security exception and
747+ // disrupt the applet by sending random
748+ // datagram packets.
749+ continue;
750+ }
751+ } // end of while
752+ }
753+ }
754+ if (connectState == ST_CONNECTED_NO_IMPL) {
755+ // We have to do the filtering the old fashioned way since
756+ // the native impl doesn't support connect or the connect
757+ // via the impl failed.
758+ boolean stop = false;
759+ while (!stop) {
760+ // peek at the packet to see who it is from.
761+ InetAddress peekAddress = new InetAddress();
762+ int peekPort = getImpl().peek(peekAddress);
763+ if ((!connectedAddress.equals(peekAddress)) ||
764+ (connectedPort != peekPort)) {
765+ // throw the packet away and silently continue
766+ DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
767+ getImpl().receive(tmp);
768+ } else {
769+ stop = true;
770+ }
771+ }
772+ }
773+ // If the security check succeeds, or the datagram is
774+ // connected then receive the packet
775+ getImpl().receive(p);
776+ }
777+ }
778+
779+ /**
780+ * Gets the local address to which the socket is bound.
781+ *
782+ * <p>If there is a security manager, its
783+ * <code>checkConnect</code> method is first called
784+ * with the host address and <code>-1</code>
785+ * as its arguments to see if the operation is allowed.
786+ *
787+ * @see SecurityManager#checkConnect
788+ * @return the local address to which the socket is bound,
789+ * <code>null</code> if the socket is closed, or
790+ * an <code>InetAddress</code> representing
791+ * {@link InetAddress#isAnyLocalAddress wildcard}
792+ * address if either the socket is not bound, or
793+ * the security manager <code>checkConnect</code>
794+ * method does not allow the operation
795+ * @since 1.1
796+ */
797+ public InetAddress getLocalAddress() {
798+ if (isClosed())
799+ return null;
800+ InetAddress in = null;
801+ try {
802+ in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
803+ if (in.isAnyLocalAddress()) {
804+ in = InetAddress.anyLocalAddress();
805+ }
806+ SecurityManager s = System.getSecurityManager();
807+ if (s != null) {
808+ s.checkConnect(in.getHostAddress(), -1);
809+ }
810+ } catch (Exception e) {
811+ in = InetAddress.anyLocalAddress(); // "0.0.0.0"
812+ }
813+ return in;
814+ }
815+
816+ /**
817+ * Returns the port number on the local host to which this socket
818+ * is bound.
819+ *
820+ * @return the port number on the local host to which this socket is bound,
821+ <code>-1</code> if the socket is closed, or
822+ <code>0</code> if it is not bound yet.
823+ */
824+ public int getLocalPort() {
825+ if (isClosed())
826+ return -1;
827+ try {
828+ return getImpl().getLocalPort();
829+ } catch (Exception e) {
830+ return 0;
831+ }
832+ }
833+
834+ /** Enable/disable SO_TIMEOUT with the specified timeout, in
835+ * milliseconds. With this option set to a non-zero timeout,
836+ * a call to receive() for this DatagramSocket
837+ * will block for only this amount of time. If the timeout expires,
838+ * a <B>java.net.SocketTimeoutException</B> is raised, though the
839+ * DatagramSocket is still valid. The option <B>must</B> be enabled
840+ * prior to entering the blocking operation to have effect. The
841+ * timeout must be > 0.
842+ * A timeout of zero is interpreted as an infinite timeout.
843+ *
844+ * @param timeout the specified timeout in milliseconds.
845+ * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
846+ * @since JDK1.1
847+ * @see #getSoTimeout()
848+ */
849+ public synchronized void setSoTimeout(int timeout) throws SocketException {
850+ if (isClosed())
851+ throw new SocketException("Socket is closed");
852+ getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
853+ }
854+
855+ /**
856+ * Retrieve setting for SO_TIMEOUT. 0 returns implies that the
857+ * option is disabled (i.e., timeout of infinity).
858+ *
859+ * @return the setting for SO_TIMEOUT
860+ * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
861+ * @since JDK1.1
862+ * @see #setSoTimeout(int)
863+ */
864+ public synchronized int getSoTimeout() throws SocketException {
865+ if (isClosed())
866+ throw new SocketException("Socket is closed");
867+ if (getImpl() == null)
868+ return 0;
869+ Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
870+ /* extra type safety */
871+ if (o instanceof Integer) {
872+ return ((Integer) o).intValue();
873+ } else {
874+ return 0;
875+ }
876+ }
877+
878+ /**
879+ * Sets the SO_SNDBUF option to the specified value for this
880+ * <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the
881+ * network implementation as a hint to size the underlying
882+ * network I/O buffers. The SO_SNDBUF setting may also be used
883+ * by the network implementation to determine the maximum size
884+ * of the packet that can be sent on this socket.
885+ * <p>
886+ * As SO_SNDBUF is a hint, applications that want to verify
887+ * what size the buffer is should call {@link #getSendBufferSize()}.
888+ * <p>
889+ * Increasing the buffer size may allow multiple outgoing packets
890+ * to be queued by the network implementation when the send rate
891+ * is high.
892+ * <p>
893+ * Note: If {@link #send(DatagramPacket)} is used to send a
894+ * <code>DatagramPacket</code> that is larger than the setting
895+ * of SO_SNDBUF then it is implementation specific if the
896+ * packet is sent or discarded.
897+ *
898+ * @param size the size to which to set the send buffer
899+ * size. This value must be greater than 0.
900+ *
901+ * @exception SocketException if there is an error
902+ * in the underlying protocol, such as an UDP error.
903+ * @exception IllegalArgumentException if the value is 0 or is
904+ * negative.
905+ * @see #getSendBufferSize()
906+ */
907+ public synchronized void setSendBufferSize(int size)
908+ throws SocketException{
909+ if (!(size > 0)) {
910+ throw new IllegalArgumentException("negative send size");
911+ }
912+ if (isClosed())
913+ throw new SocketException("Socket is closed");
914+ getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
915+ }
916+
917+ /**
918+ * Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that is the
919+ * buffer size used by the platform for output on this <tt>DatagramSocket</tt>.
920+ *
921+ * @return the value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>
922+ * @exception SocketException if there is an error in
923+ * the underlying protocol, such as an UDP error.
924+ * @see #setSendBufferSize
925+ */
926+ public synchronized int getSendBufferSize() throws SocketException {
927+ if (isClosed())
928+ throw new SocketException("Socket is closed");
929+ int result = 0;
930+ Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
931+ if (o instanceof Integer) {
932+ result = ((Integer)o).intValue();
933+ }
934+ return result;
935+ }
936+
937+ /**
938+ * Sets the SO_RCVBUF option to the specified value for this
939+ * <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the
940+ * the network implementation as a hint to size the underlying
941+ * network I/O buffers. The SO_RCVBUF setting may also be used
942+ * by the network implementation to determine the maximum size
943+ * of the packet that can be received on this socket.
944+ * <p>
945+ * Because SO_RCVBUF is a hint, applications that want to
946+ * verify what size the buffers were set to should call
947+ * {@link #getReceiveBufferSize()}.
948+ * <p>
949+ * Increasing SO_RCVBUF may allow the network implementation
950+ * to buffer multiple packets when packets arrive faster than
951+ * are being received using {@link #receive(DatagramPacket)}.
952+ * <p>
953+ * Note: It is implementation specific if a packet larger
954+ * than SO_RCVBUF can be received.
955+ *
956+ * @param size the size to which to set the receive buffer
957+ * size. This value must be greater than 0.
958+ *
959+ * @exception SocketException if there is an error in
960+ * the underlying protocol, such as an UDP error.
961+ * @exception IllegalArgumentException if the value is 0 or is
962+ * negative.
963+ * @see #getReceiveBufferSize()
964+ */
965+ public synchronized void setReceiveBufferSize(int size)
966+ throws SocketException{
967+ if (size <= 0) {
968+ throw new IllegalArgumentException("invalid receive size");
969+ }
970+ if (isClosed())
971+ throw new SocketException("Socket is closed");
972+ getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
973+ }
974+
975+ /**
976+ * Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that is the
977+ * buffer size used by the platform for input on this <tt>DatagramSocket</tt>.
978+ *
979+ * @return the value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>
980+ * @exception SocketException if there is an error in the underlying protocol, such as an UDP error.
981+ * @see #setReceiveBufferSize(int)
982+ */
983+ public synchronized int getReceiveBufferSize()
984+ throws SocketException{
985+ if (isClosed())
986+ throw new SocketException("Socket is closed");
987+ int result = 0;
988+ Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
989+ if (o instanceof Integer) {
990+ result = ((Integer)o).intValue();
991+ }
992+ return result;
993+ }
994+
995+ /**
996+ * Enable/disable the SO_REUSEADDR socket option.
997+ * <p>
998+ * For UDP sockets it may be necessary to bind more than one
999+ * socket to the same socket address. This is typically for the
1000+ * purpose of receiving multicast packets
1001+ * (See {@link java.net.MulticastSocket}). The
1002+ * <tt>SO_REUSEADDR</tt> socket option allows multiple
1003+ * sockets to be bound to the same socket address if the
1004+ * <tt>SO_REUSEADDR</tt> socket option is enabled prior
1005+ * to binding the socket using {@link #bind(SocketAddress)}.
1006+ * <p>
1007+ * Note: This functionality is not supported by all existing platforms,
1008+ * so it is implementation specific whether this option will be ignored
1009+ * or not. However, if it is not supported then
1010+ * {@link #getReuseAddress()} will always return <code>false</code>.
1011+ * <p>
1012+ * When a <tt>DatagramSocket</tt> is created the initial setting
1013+ * of <tt>SO_REUSEADDR</tt> is disabled.
1014+ * <p>
1015+ * The behaviour when <tt>SO_REUSEADDR</tt> is enabled or
1016+ * disabled after a socket is bound (See {@link #isBound()})
1017+ * is not defined.
1018+ *
1019+ * @param on whether to enable or disable the
1020+ * @exception SocketException if an error occurs enabling or
1021+ * disabling the <tt>SO_RESUEADDR</tt> socket option,
1022+ * or the socket is closed.
1023+ * @since 1.4
1024+ * @see #getReuseAddress()
1025+ * @see #bind(SocketAddress)
1026+ * @see #isBound()
1027+ * @see #isClosed()
1028+ */
1029+ public synchronized void setReuseAddress(boolean on) throws SocketException {
1030+ if (isClosed())
1031+ throw new SocketException("Socket is closed");
1032+ // Integer instead of Boolean for compatibility with older DatagramSocketImpl
1033+ if (oldImpl)
1034+ getImpl().setOption(SocketOptions.SO_REUSEADDR, new Integer(on?-1:0));
1035+ else
1036+ getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
1037+ }
1038+
1039+ /**
1040+ * Tests if SO_REUSEADDR is enabled.
1041+ *
1042+ * @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is enabled.
1043+ * @exception SocketException if there is an error
1044+ * in the underlying protocol, such as an UDP error.
1045+ * @since 1.4
1046+ * @see #setReuseAddress(boolean)
1047+ */
1048+ public synchronized boolean getReuseAddress() throws SocketException {
1049+ if (isClosed())
1050+ throw new SocketException("Socket is closed");
1051+ Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1052+ return ((Boolean)o).booleanValue();
1053+ }
1054+
1055+ /**
1056+ * Enable/disable SO_BROADCAST.
1057+ *
1058+ * <p> Some operating systems may require that the Java virtual machine be
1059+ * started with implementation specific privileges to enable this option or
1060+ * send broadcast datagrams.
1061+ *
1062+ * @param on
1063+ * whether or not to have broadcast turned on.
1064+ *
1065+ * @throws SocketException
1066+ * if there is an error in the underlying protocol, such as an UDP
1067+ * error.
1068+ *
1069+ * @since 1.4
1070+ * @see #getBroadcast()
1071+ */
1072+ public synchronized void setBroadcast(boolean on) throws SocketException {
1073+ if (isClosed())
1074+ throw new SocketException("Socket is closed");
1075+ getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on));
1076+ }
1077+
1078+ /**
1079+ * Tests if SO_BROADCAST is enabled.
1080+ * @return a <code>boolean</code> indicating whether or not SO_BROADCAST is enabled.
1081+ * @exception SocketException if there is an error
1082+ * in the underlying protocol, such as an UDP error.
1083+ * @since 1.4
1084+ * @see #setBroadcast(boolean)
1085+ */
1086+ public synchronized boolean getBroadcast() throws SocketException {
1087+ if (isClosed())
1088+ throw new SocketException("Socket is closed");
1089+ return ((Boolean)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue();
1090+ }
1091+
1092+ /**
1093+ * Sets traffic class or type-of-service octet in the IP
1094+ * datagram header for datagrams sent from this DatagramSocket.
1095+ * As the underlying network implementation may ignore this
1096+ * value applications should consider it a hint.
1097+ *
1098+ * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
1099+ * 255</code> or an IllegalArgumentException will be thrown.
1100+ * <p>Notes:
1101+ * <p>For Internet Protocol v4 the value consists of an
1102+ * <code>integer</code>, the least significant 8 bits of which
1103+ * represent the value of the TOS octet in IP packets sent by
1104+ * the socket.
1105+ * RFC 1349 defines the TOS values as follows:
1106+ * <p>
1107+ * <UL>
1108+ * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
1109+ * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
1110+ * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
1111+ * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
1112+ * </UL>
1113+ * The last low order bit is always ignored as this
1114+ * corresponds to the MBZ (must be zero) bit.
1115+ * <p>
1116+ * Setting bits in the precedence field may result in a
1117+ * SocketException indicating that the operation is not
1118+ * permitted.
1119+ * <p>
1120+ * for Internet Protocol v6 <code>tc</code> is the value that
1121+ * would be placed into the sin6_flowinfo field of the IP header.
1122+ *
1123+ * @param tc an <code>int</code> value for the bitset.
1124+ * @throws SocketException if there is an error setting the
1125+ * traffic class or type-of-service
1126+ * @since 1.4
1127+ * @see #getTrafficClass
1128+ */
1129+ public synchronized void setTrafficClass(int tc) throws SocketException {
1130+ if (tc < 0 || tc > 255)
1131+ throw new IllegalArgumentException("tc is not in range 0 -- 255");
1132+
1133+ if (isClosed())
1134+ throw new SocketException("Socket is closed");
1135+ getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
1136+ }
1137+
1138+ /**
1139+ * Gets traffic class or type-of-service in the IP datagram
1140+ * header for packets sent from this DatagramSocket.
1141+ * <p>
1142+ * As the underlying network implementation may ignore the
1143+ * traffic class or type-of-service set using {@link #setTrafficClass(int)}
1144+ * this method may return a different value than was previously
1145+ * set using the {@link #setTrafficClass(int)} method on this
1146+ * DatagramSocket.
1147+ *
1148+ * @return the traffic class or type-of-service already set
1149+ * @throws SocketException if there is an error obtaining the
1150+ * traffic class or type-of-service value.
1151+ * @since 1.4
1152+ * @see #setTrafficClass(int)
1153+ */
1154+ public synchronized int getTrafficClass() throws SocketException {
1155+ if (isClosed())
1156+ throw new SocketException("Socket is closed");
1157+ return ((Integer)(getImpl().getOption(SocketOptions.IP_TOS))).intValue();
1158+ }
1159+
1160+ /**
1161+ * Closes this datagram socket.
1162+ * <p>
1163+ * Any thread currently blocked in {@link #receive} upon this socket
1164+ * will throw a {@link SocketException}.
1165+ *
1166+ * <p> If this socket has an associated channel then the channel is closed
1167+ * as well.
1168+ *
1169+ * @revised 1.4
1170+ * @spec JSR-51
1171+ */
1172+ public void close() {
1173+ synchronized(closeLock) {
1174+ if (isClosed())
1175+ return;
1176+ impl.close();
1177+ closed = true;
1178+ }
1179+ }
1180+
1181+ /**
1182+ * Returns whether the socket is closed or not.
1183+ *
1184+ * @return true if the socket has been closed
1185+ * @since 1.4
1186+ */
1187+ public boolean isClosed() {
1188+ synchronized(closeLock) {
1189+ return closed;
1190+ }
1191+ }
1192+
1193+ /**
1194+ * Returns the unique {@link java.nio.channels.DatagramChannel} object
1195+ * associated with this datagram socket, if any.
1196+ *
1197+ * <p> A datagram socket will have a channel if, and only if, the channel
1198+ * itself was created via the {@link java.nio.channels.DatagramChannel#open
1199+ * DatagramChannel.open} method.
1200+ *
1201+ * @return the datagram channel associated with this datagram socket,
1202+ * or <tt>null</tt> if this socket was not created for a channel
1203+ *
1204+ * @since 1.4
1205+ * @spec JSR-51
1206+ */
1207+ public DatagramChannel getChannel() {
1208+ return null;
1209+ }
1210+
1211+ /**
1212+ * User defined factory for all datagram sockets.
1213+ */
1214+ static DatagramSocketImplFactory factory;
1215+
1216+ /**
1217+ * Sets the datagram socket implementation factory for the
1218+ * application. The factory can be specified only once.
1219+ * <p>
1220+ * When an application creates a new datagram socket, the socket
1221+ * implementation factory's <code>createDatagramSocketImpl</code> method is
1222+ * called to create the actual datagram socket implementation.
1223+ * <p>
1224+ * Passing <code>null</code> to the method is a no-op unless the factory
1225+ * was already set.
1226+ *
1227+ * <p>If there is a security manager, this method first calls
1228+ * the security manager's <code>checkSetFactory</code> method
1229+ * to ensure the operation is allowed.
1230+ * This could result in a SecurityException.
1231+ *
1232+ * @param fac the desired factory.
1233+ * @exception IOException if an I/O error occurs when setting the
1234+ * datagram socket factory.
1235+ * @exception SocketException if the factory is already defined.
1236+ * @exception SecurityException if a security manager exists and its
1237+ * <code>checkSetFactory</code> method doesn't allow the
1238+ operation.
1239+ * @see
1240+ java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
1241+ * @see SecurityManager#checkSetFactory
1242+ * @since 1.3
1243+ */
1244+ public static synchronized void
1245+ setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
1246+ throws IOException
1247+ {
1248+ if (factory != null) {
1249+ throw new SocketException("factory already defined");
1250+ }
1251+ SecurityManager security = System.getSecurityManager();
1252+ if (security != null) {
1253+ security.checkSetFactory();
1254+ }
1255+ factory = fac;
1256+ }
1257+}