1 /* 2 * Copyright (c) 1996, 2013, 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 32 /** 33 * Abstract datagram and multicast socket implementation base class. 34 * @author Pavani Diwanji 35 * @since JDK1.1 36 */ 37 38 public abstract class DatagramSocketImpl implements SocketOptions { 39 40 /** 41 * The local port number. 42 */ 43 protected int localPort; 44 45 /** 46 * The file descriptor object. 47 */ 48 protected FileDescriptor fd; 49 dataAvailable()50 int dataAvailable() { 51 // default impl returns zero, which disables the calling 52 // functionality 53 return 0; 54 } 55 56 /** 57 * The DatagramSocket or MulticastSocket 58 * that owns this impl 59 */ 60 DatagramSocket socket; 61 setDatagramSocket(DatagramSocket socket)62 void setDatagramSocket(DatagramSocket socket) { 63 this.socket = socket; 64 } 65 getDatagramSocket()66 DatagramSocket getDatagramSocket() { 67 return socket; 68 } 69 70 /** 71 * Creates a datagram socket. 72 * @exception SocketException if there is an error in the 73 * underlying protocol, such as a TCP error. 74 */ create()75 protected abstract void create() throws SocketException; 76 77 /** 78 * Binds a datagram socket to a local port and address. 79 * @param lport the local port 80 * @param laddr the local address 81 * @exception SocketException if there is an error in the 82 * underlying protocol, such as a TCP error. 83 */ bind(int lport, InetAddress laddr)84 protected abstract void bind(int lport, InetAddress laddr) throws SocketException; 85 86 /** 87 * Sends a datagram packet. The packet contains the data and the 88 * destination address to send the packet to. 89 * @param p the packet to be sent. 90 * @exception IOException if an I/O exception occurs while sending the 91 * datagram packet. 92 * @exception PortUnreachableException may be thrown if the socket is connected 93 * to a currently unreachable destination. Note, there is no guarantee that 94 * the exception will be thrown. 95 */ send(DatagramPacket p)96 protected abstract void send(DatagramPacket p) throws IOException; 97 98 /** 99 * Connects a datagram socket to a remote destination. This associates the remote 100 * address with the local socket so that datagrams may only be sent to this destination 101 * and received from this destination. This may be overridden to call a native 102 * system connect. 103 * 104 * <p>If the remote destination to which the socket is connected does not 105 * exist, or is otherwise unreachable, and if an ICMP destination unreachable 106 * packet has been received for that address, then a subsequent call to 107 * send or receive may throw a PortUnreachableException. 108 * Note, there is no guarantee that the exception will be thrown. 109 * @param address the remote InetAddress to connect to 110 * @param port the remote port number 111 * @exception SocketException may be thrown if the socket cannot be 112 * connected to the remote destination 113 * @since 1.4 114 */ connect(InetAddress address, int port)115 protected void connect(InetAddress address, int port) throws SocketException {} 116 117 /** 118 * Disconnects a datagram socket from its remote destination. 119 * @since 1.4 120 */ disconnect()121 protected void disconnect() {} 122 123 /** 124 * Peek at the packet to see who it is from. Updates the specified {@code InetAddress} 125 * to the address which the packet came from. 126 * @param i an InetAddress object 127 * @return the port number which the packet came from. 128 * @exception IOException if an I/O exception occurs 129 * @exception PortUnreachableException may be thrown if the socket is connected 130 * to a currently unreachable destination. Note, there is no guarantee that the 131 * exception will be thrown. 132 */ peek(InetAddress i)133 protected abstract int peek(InetAddress i) throws IOException; 134 135 /** 136 * Peek at the packet to see who it is from. The data is copied into the specified 137 * {@code DatagramPacket}. The data is returned, 138 * but not consumed, so that a subsequent peekData/receive operation 139 * will see the same data. 140 * @param p the Packet Received. 141 * @return the port number which the packet came from. 142 * @exception IOException if an I/O exception occurs 143 * @exception PortUnreachableException may be thrown if the socket is connected 144 * to a currently unreachable destination. Note, there is no guarantee that the 145 * exception will be thrown. 146 * @since 1.4 147 */ peekData(DatagramPacket p)148 protected abstract int peekData(DatagramPacket p) throws IOException; 149 /** 150 * Receive the datagram packet. 151 * @param p the Packet Received. 152 * @exception IOException if an I/O exception occurs 153 * while receiving the datagram packet. 154 * @exception PortUnreachableException may be thrown if the socket is connected 155 * to a currently unreachable destination. Note, there is no guarantee that the 156 * exception will be thrown. 157 */ receive(DatagramPacket p)158 protected abstract void receive(DatagramPacket p) throws IOException; 159 160 /** 161 * Set the TTL (time-to-live) option. 162 * @param ttl a byte specifying the TTL value 163 * 164 * @deprecated use setTimeToLive instead. 165 * @exception IOException if an I/O exception occurs while setting 166 * the time-to-live option. 167 * @see #getTTL() 168 */ 169 @Deprecated setTTL(byte ttl)170 protected abstract void setTTL(byte ttl) throws IOException; 171 172 /** 173 * Retrieve the TTL (time-to-live) option. 174 * 175 * @exception IOException if an I/O exception occurs 176 * while retrieving the time-to-live option 177 * @deprecated use getTimeToLive instead. 178 * @return a byte representing the TTL value 179 * @see #setTTL(byte) 180 */ 181 @Deprecated getTTL()182 protected abstract byte getTTL() throws IOException; 183 184 /** 185 * Set the TTL (time-to-live) option. 186 * @param ttl an {@code int} specifying the time-to-live value 187 * @exception IOException if an I/O exception occurs 188 * while setting the time-to-live option. 189 * @see #getTimeToLive() 190 */ setTimeToLive(int ttl)191 protected abstract void setTimeToLive(int ttl) throws IOException; 192 193 /** 194 * Retrieve the TTL (time-to-live) option. 195 * @exception IOException if an I/O exception occurs 196 * while retrieving the time-to-live option 197 * @return an {@code int} representing the time-to-live value 198 * @see #setTimeToLive(int) 199 */ getTimeToLive()200 protected abstract int getTimeToLive() throws IOException; 201 202 /** 203 * Join the multicast group. 204 * @param inetaddr multicast address to join. 205 * @exception IOException if an I/O exception occurs 206 * while joining the multicast group. 207 */ join(InetAddress inetaddr)208 protected abstract void join(InetAddress inetaddr) throws IOException; 209 210 /** 211 * Leave the multicast group. 212 * @param inetaddr multicast address to leave. 213 * @exception IOException if an I/O exception occurs 214 * while leaving the multicast group. 215 */ leave(InetAddress inetaddr)216 protected abstract void leave(InetAddress inetaddr) throws IOException; 217 218 /** 219 * Join the multicast group. 220 * @param mcastaddr address to join. 221 * @param netIf specifies the local interface to receive multicast 222 * datagram packets 223 * @throws IOException if an I/O exception occurs while joining 224 * the multicast group 225 * @since 1.4 226 */ joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)227 protected abstract void joinGroup(SocketAddress mcastaddr, 228 NetworkInterface netIf) 229 throws IOException; 230 231 /** 232 * Leave the multicast group. 233 * @param mcastaddr address to leave. 234 * @param netIf specified the local interface to leave the group at 235 * @throws IOException if an I/O exception occurs while leaving 236 * the multicast group 237 * @since 1.4 238 */ leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)239 protected abstract void leaveGroup(SocketAddress mcastaddr, 240 NetworkInterface netIf) 241 throws IOException; 242 243 /** 244 * Close the socket. 245 */ close()246 protected abstract void close(); 247 248 /** 249 * Gets the local port. 250 * @return an {@code int} representing the local port value 251 */ getLocalPort()252 protected int getLocalPort() { 253 return localPort; 254 } 255 setOption(SocketOption<T> name, T value)256 <T> void setOption(SocketOption<T> name, T value) throws IOException { 257 if (name == StandardSocketOptions.SO_SNDBUF) { 258 setOption(SocketOptions.SO_SNDBUF, value); 259 } else if (name == StandardSocketOptions.SO_RCVBUF) { 260 setOption(SocketOptions.SO_RCVBUF, value); 261 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 262 setOption(SocketOptions.SO_REUSEADDR, value); 263 } else if (name == StandardSocketOptions.IP_TOS) { 264 setOption(SocketOptions.IP_TOS, value); 265 } else if (name == StandardSocketOptions.IP_MULTICAST_IF && 266 (getDatagramSocket() instanceof MulticastSocket)) { 267 setOption(SocketOptions.IP_MULTICAST_IF2, value); 268 } else if (name == StandardSocketOptions.IP_MULTICAST_TTL && 269 (getDatagramSocket() instanceof MulticastSocket)) { 270 if (! (value instanceof Integer)) { 271 throw new IllegalArgumentException("not an integer"); 272 } 273 setTimeToLive((Integer)value); 274 } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP && 275 (getDatagramSocket() instanceof MulticastSocket)) { 276 setOption(SocketOptions.IP_MULTICAST_LOOP, value); 277 } else { 278 throw new UnsupportedOperationException("unsupported option"); 279 } 280 } 281 getOption(SocketOption<T> name)282 <T> T getOption(SocketOption<T> name) throws IOException { 283 if (name == StandardSocketOptions.SO_SNDBUF) { 284 return (T) getOption(SocketOptions.SO_SNDBUF); 285 } else if (name == StandardSocketOptions.SO_RCVBUF) { 286 return (T) getOption(SocketOptions.SO_RCVBUF); 287 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 288 return (T) getOption(SocketOptions.SO_REUSEADDR); 289 } else if (name == StandardSocketOptions.IP_TOS) { 290 return (T) getOption(SocketOptions.IP_TOS); 291 } else if (name == StandardSocketOptions.IP_MULTICAST_IF && 292 (getDatagramSocket() instanceof MulticastSocket)) { 293 return (T) getOption(SocketOptions.IP_MULTICAST_IF2); 294 } else if (name == StandardSocketOptions.IP_MULTICAST_TTL && 295 (getDatagramSocket() instanceof MulticastSocket)) { 296 Integer ttl = getTimeToLive(); 297 return (T)ttl; 298 } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP && 299 (getDatagramSocket() instanceof MulticastSocket)) { 300 return (T) getOption(SocketOptions.IP_MULTICAST_LOOP); 301 } else { 302 throw new UnsupportedOperationException("unsupported option"); 303 } 304 } 305 306 /** 307 * Gets the datagram socket file descriptor. 308 * @return a {@code FileDescriptor} object representing the datagram socket 309 * file descriptor 310 */ getFileDescriptor()311 protected FileDescriptor getFileDescriptor() { 312 return fd; 313 } 314 } 315