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