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