TwoStacksPlainDatagramSocketImpl.java revision 12745:f068a4ffddd2
1/* 2 * Copyright (c) 2007, 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.IOException; 28import java.io.FileDescriptor; 29import sun.net.ResourceManager; 30 31/** 32 * This class defines the plain DatagramSocketImpl that is used for all 33 * Windows versions lower than Vista. It adds support for IPv6 on 34 * these platforms where available. 35 * 36 * For backward compatibility windows platforms that do not have IPv6 37 * support also use this implementation, and fd1 gets set to null 38 * during socket creation. 39 * 40 * @author Chris Hegarty 41 */ 42 43class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl 44{ 45 /* Used for IPv6 on Windows only */ 46 private FileDescriptor fd1; 47 48 /* 49 * Needed for ipv6 on windows because we need to know 50 * if the socket was bound to ::0 or 0.0.0.0, when a caller 51 * asks for it. In this case, both sockets are used, but we 52 * don't know whether the caller requested ::0 or 0.0.0.0 53 * and need to remember it here. 54 */ 55 private InetAddress anyLocalBoundAddr=null; 56 57 private int fduse=-1; /* saved between peek() and receive() calls */ 58 59 /* saved between successive calls to receive, if data is detected 60 * on both sockets at same time. To ensure that one socket is not 61 * starved, they rotate using this field 62 */ 63 private int lastfd=-1; 64 65 static { 66 init(); 67 } 68 69 // true if this socket is exclusively bound 70 private final boolean exclusiveBind; 71 72 /* 73 * Set to true if SO_REUSEADDR is set after the socket is bound to 74 * indicate SO_REUSEADDR is being emulated 75 */ 76 private boolean reuseAddressEmulated; 77 78 // emulates SO_REUSEADDR when exclusiveBind is true and socket is bound 79 private boolean isReuseAddress; 80 81 TwoStacksPlainDatagramSocketImpl(boolean exclBind) { 82 exclusiveBind = exclBind; 83 } 84 85 protected synchronized void create() throws SocketException { 86 fd1 = new FileDescriptor(); 87 try { 88 super.create(); 89 } catch (SocketException e) { 90 fd1 = null; 91 throw e; 92 } 93 } 94 95 protected synchronized void bind(int lport, InetAddress laddr) 96 throws SocketException { 97 super.bind(lport, laddr); 98 if (laddr.isAnyLocalAddress()) { 99 anyLocalBoundAddr = laddr; 100 } 101 } 102 103 @Override 104 protected synchronized void bind0(int lport, InetAddress laddr) 105 throws SocketException 106 { 107 bind0(lport, laddr, exclusiveBind); 108 109 } 110 111 protected synchronized void receive(DatagramPacket p) 112 throws IOException { 113 try { 114 receive0(p); 115 } finally { 116 fduse = -1; 117 } 118 } 119 120 public Object getOption(int optID) throws SocketException { 121 if (isClosed()) { 122 throw new SocketException("Socket Closed"); 123 } 124 125 if (optID == SO_BINDADDR) { 126 if ((fd != null && fd1 != null) && !connected) { 127 return anyLocalBoundAddr; 128 } 129 int family = connectedAddress == null ? -1 : connectedAddress.holder().getFamily(); 130 return socketLocalAddress(family); 131 } else if (optID == SO_REUSEADDR && reuseAddressEmulated) { 132 return isReuseAddress; 133 } else { 134 return super.getOption(optID); 135 } 136 } 137 138 protected void socketSetOption(int opt, Object val) 139 throws SocketException 140 { 141 if (opt == SO_REUSEADDR && exclusiveBind && localPort != 0) { 142 // socket already bound, emulate 143 reuseAddressEmulated = true; 144 isReuseAddress = (Boolean)val; 145 } else { 146 socketNativeSetOption(opt, val); 147 } 148 149 } 150 151 protected boolean isClosed() { 152 return (fd == null && fd1 == null) ? true : false; 153 } 154 155 protected void close() { 156 if (fd != null || fd1 != null) { 157 datagramSocketClose(); 158 ResourceManager.afterUdpClose(); 159 fd = null; 160 fd1 = null; 161 } 162 } 163 164 /* Native methods */ 165 166 protected synchronized native void bind0(int lport, InetAddress laddr, 167 boolean exclBind) 168 throws SocketException; 169 170 protected native void send(DatagramPacket p) throws IOException; 171 172 protected synchronized native int peek(InetAddress i) throws IOException; 173 174 protected synchronized native int peekData(DatagramPacket p) throws IOException; 175 176 protected synchronized native void receive0(DatagramPacket p) 177 throws IOException; 178 179 protected native void setTimeToLive(int ttl) throws IOException; 180 181 protected native int getTimeToLive() throws IOException; 182 183 @Deprecated 184 protected native void setTTL(byte ttl) throws IOException; 185 186 @Deprecated 187 protected native byte getTTL() throws IOException; 188 189 protected native void join(InetAddress inetaddr, NetworkInterface netIf) 190 throws IOException; 191 192 protected native void leave(InetAddress inetaddr, NetworkInterface netIf) 193 throws IOException; 194 195 protected native void datagramSocketCreate() throws SocketException; 196 197 protected native void datagramSocketClose(); 198 199 protected native void socketNativeSetOption(int opt, Object val) 200 throws SocketException; 201 202 protected native Object socketGetOption(int opt) throws SocketException; 203 204 protected native void connect0(InetAddress address, int port) throws SocketException; 205 206 protected native Object socketLocalAddress(int family) throws SocketException; 207 208 protected native void disconnect0(int family); 209 210 native int dataAvailable(); 211 212 /** 213 * Perform class load-time initializations. 214 */ 215 private static native void init(); 216} 217