1 /* 2 * Copyright (c) 1996, 2011, 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 package java.net; 26 27 import java.io.FileDescriptor; 28 import java.io.IOException; 29 import java.io.InterruptedIOException; 30 import java.util.Enumeration; 31 import sun.net.ResourceManager; 32 33 /** 34 * Abstract datagram and multicast socket implementation base class. 35 * Note: This is not a public class, so that applets cannot call 36 * into the implementation directly and hence cannot bypass the 37 * security checks present in the DatagramSocket and MulticastSocket 38 * classes. 39 * 40 * @author Pavani Diwanji 41 */ 42 43 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl 44 { 45 /* timeout value for receive() */ 46 int timeout = 0; 47 boolean connected = false; 48 private int trafficClass = 0; 49 private InetAddress connectedAddress = null; 50 private int connectedPort = -1; 51 52 /* cached socket options */ 53 private int multicastInterface = 0; 54 private boolean loopbackMode = true; 55 private int ttl = -1; 56 57 /** 58 * Load net library into runtime. 59 */ 60 static { 61 java.security.AccessController.doPrivileged( 62 new sun.security.action.LoadLibraryAction("net")); 63 } 64 65 /** 66 * Creates a datagram socket 67 */ 68 protected synchronized void create() throws SocketException { 69 fd = new FileDescriptor(); 70 ResourceManager.beforeUdpCreate(); 71 try { 72 datagramSocketCreate(); 73 } catch (SocketException ioe) { 74 ResourceManager.afterUdpClose(); 75 fd = null; 76 throw ioe; 77 } 78 } 79 80 /** 81 * Binds a datagram socket to a local port. 82 */ 83 protected synchronized void bind(int lport, InetAddress laddr) 84 throws SocketException { 85 bind0(lport, laddr); 86 } 87 88 protected abstract void bind0(int lport, InetAddress laddr) 89 throws SocketException; 90 91 /** 92 * Sends a datagram packet. The packet contains the data and the 93 * destination address to send the packet to. 94 * @param packet to be sent. 95 */ 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. 102 * @param address the remote InetAddress to connect to 103 * @param port the remote port number 104 */ 105 protected void connect(InetAddress address, int port) throws SocketException { 106 connect0(address, port); 107 connectedAddress = address; 108 connectedPort = port; 109 connected = true; 110 } 111 112 /** 113 * Disconnects a previously connected socket. Does nothing if the socket was 114 * not connected already. 115 */ 116 protected void disconnect() { 117 disconnect0(connectedAddress.family); 118 connected = false; 119 connectedAddress = null; 120 connectedPort = -1; 121 } 122 123 /** 124 * Peek at the packet to see who it is from. 125 * @param return the address which the packet came from. 126 */ 127 protected abstract int peek(InetAddress i) throws IOException; 128 protected abstract int peekData(DatagramPacket p) throws IOException; 129 /** 130 * Receive the datagram packet. 131 * @param Packet Received. 132 */ 133 protected synchronized void receive(DatagramPacket p) 134 throws IOException { 135 receive0(p); 136 } 137 138 protected abstract void receive0(DatagramPacket p) 139 throws IOException; 140 141 /** 142 * Set the TTL (time-to-live) option. 143 * @param TTL to be set. 144 */ 145 protected abstract void setTimeToLive(int ttl) throws IOException; 146 147 /** 148 * Get the TTL (time-to-live) option. 149 */ 150 protected abstract int getTimeToLive() throws IOException; 151 152 /** 153 * Set the TTL (time-to-live) option. 154 * @param TTL to be set. 155 */ 156 protected abstract void setTTL(byte ttl) throws IOException; 157 158 /** 159 * Get the TTL (time-to-live) option. 160 */ 161 protected abstract byte getTTL() throws IOException; 162 163 /** 164 * Join the multicast group. 165 * @param multicast address to join. 166 */ 167 protected void join(InetAddress inetaddr) throws IOException { 168 join(inetaddr, null); 169 } 170 171 /** 172 * Leave the multicast group. 173 * @param multicast address to leave. 174 */ 175 protected void leave(InetAddress inetaddr) throws IOException { 176 leave(inetaddr, null); 177 } 178 /** 179 * Join the multicast group. 180 * @param multicast address to join. 181 * @param netIf specifies the local interface to receive multicast 182 * datagram packets 183 * @throws IllegalArgumentException if mcastaddr is null or is a 184 * SocketAddress subclass not supported by this socket 185 * @since 1.4 186 */ 187 188 protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) 189 throws IOException { 190 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) 191 throw new IllegalArgumentException("Unsupported address type"); 192 join(((InetSocketAddress)mcastaddr).getAddress(), netIf); 193 } 194 195 protected abstract void join(InetAddress inetaddr, NetworkInterface netIf) 196 throws IOException; 197 198 /** 199 * Leave the multicast group. 200 * @param multicast address to leave. 201 * @param netIf specified the local interface to leave the group at 202 * @throws IllegalArgumentException if mcastaddr is null or is a 203 * SocketAddress subclass not supported by this socket 204 * @since 1.4 205 */ 206 protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) 207 throws IOException { 208 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) 209 throw new IllegalArgumentException("Unsupported address type"); 210 leave(((InetSocketAddress)mcastaddr).getAddress(), netIf); 211 } 212 213 protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf) 214 throws IOException; 215 216 /** 217 * Close the socket. 218 */ 219 protected void close() { 220 if (fd != null) { 221 datagramSocketClose(); 222 ResourceManager.afterUdpClose(); 223 fd = null; 224 } 225 } 226 227 protected boolean isClosed() { 228 return (fd == null) ? true : false; 229 } 230 231 protected void finalize() { 232 close(); 233 } 234 235 /** 236 * set a value - since we only support (setting) binary options 237 * here, o must be a Boolean 238 */ 239 240 public void setOption(int optID, Object o) throws SocketException { 241 if (isClosed()) { 242 throw new SocketException("Socket Closed"); 243 } 244 switch (optID) { 245 /* check type safety b4 going native. These should never 246 * fail, since only java.Socket* has access to 247 * PlainSocketImpl.setOption(). 248 */ 249 case SO_TIMEOUT: 250 if (o == null || !(o instanceof Integer)) { 251 throw new SocketException("bad argument for SO_TIMEOUT"); 252 } 253 int tmp = ((Integer) o).intValue(); 254 if (tmp < 0) 255 throw new IllegalArgumentException("timeout < 0"); 256 timeout = tmp; 257 return; 258 case IP_TOS: 259 if (o == null || !(o instanceof Integer)) { 260 throw new SocketException("bad argument for IP_TOS"); 261 } 262 trafficClass = ((Integer)o).intValue(); 263 break; 264 case SO_REUSEADDR: 265 if (o == null || !(o instanceof Boolean)) { 266 throw new SocketException("bad argument for SO_REUSEADDR"); 267 } 268 break; 269 case SO_BROADCAST: 270 if (o == null || !(o instanceof Boolean)) { 271 throw new SocketException("bad argument for SO_BROADCAST"); 272 } 273 break; 274 case SO_BINDADDR: 275 throw new SocketException("Cannot re-bind Socket"); 276 case SO_RCVBUF: 277 case SO_SNDBUF: 278 if (o == null || !(o instanceof Integer) || 279 ((Integer)o).intValue() < 0) { 280 throw new SocketException("bad argument for SO_SNDBUF or " + 281 "SO_RCVBUF"); 282 } 283 break; 284 case IP_MULTICAST_IF: 285 if (o == null || !(o instanceof InetAddress)) 286 throw new SocketException("bad argument for IP_MULTICAST_IF"); 287 break; 288 case IP_MULTICAST_IF2: 289 if (o == null || !(o instanceof NetworkInterface)) 290 throw new SocketException("bad argument for IP_MULTICAST_IF2"); 291 break; 292 case IP_MULTICAST_LOOP: 293 if (o == null || !(o instanceof Boolean)) 294 throw new SocketException("bad argument for IP_MULTICAST_LOOP"); 295 break; 296 default: 297 throw new SocketException("invalid option: " + optID); 298 } 299 socketSetOption(optID, o); 300 } 301 302 /* 303 * get option's state - set or not 304 */ 305 306 public Object getOption(int optID) throws SocketException { 307 if (isClosed()) { 308 throw new SocketException("Socket Closed"); 309 } 310 311 Object result; 312 313 switch (optID) { 314 case SO_TIMEOUT: 315 result = new Integer(timeout); 316 break; 317 318 case IP_TOS: 319 result = socketGetOption(optID); 320 if ( ((Integer)result).intValue() == -1) { 321 result = new Integer(trafficClass); 322 } 323 break; 324 325 case SO_BINDADDR: 326 case IP_MULTICAST_IF: 327 case IP_MULTICAST_IF2: 328 case SO_RCVBUF: 329 case SO_SNDBUF: 330 case IP_MULTICAST_LOOP: 331 case SO_REUSEADDR: 332 case SO_BROADCAST: 333 result = socketGetOption(optID); 334 break; 335 336 default: 337 throw new SocketException("invalid option: " + optID); 338 } 339 340 return result; 341 } 342 343 protected abstract void datagramSocketCreate() throws SocketException; 344 protected abstract void datagramSocketClose(); 345 protected abstract void socketSetOption(int opt, Object val) 346 throws SocketException; 347 protected abstract Object socketGetOption(int opt) throws SocketException; 348 349 protected abstract void connect0(InetAddress address, int port) throws SocketException; 350 protected abstract void disconnect0(int family); 351 352 }