001: /*
002: * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package java.net;
026:
027: import java.io.IOException;
028: import java.io.FileDescriptor;
029:
030: /*
031: * This class defines the plain SocketImpl that is used for all
032: * Windows version lower than Vista. It adds support for IPv6 on
033: * these platforms where available.
034: *
035: * For backward compatibility Windows platforms that do not have IPv6
036: * support also use this implementation, and fd1 gets set to null
037: * during socket creation.
038: *
039: * @version 1.2, 06/11/07
040: * @author Chris Hegarty
041: */
042:
043: class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl {
044: /* second fd, used for ipv6 on windows only.
045: * fd1 is used for listeners and for client sockets at initialization
046: * until the socket is connected. Up to this point fd always refers
047: * to the ipv4 socket and fd1 to the ipv6 socket. After the socket
048: * becomes connected, fd always refers to the connected socket
049: * (either v4 or v6) and fd1 is closed.
050: *
051: * For ServerSockets, fd always refers to the v4 listener and
052: * fd1 the v6 listener.
053: */
054: private FileDescriptor fd1;
055:
056: /*
057: * Needed for ipv6 on windows because we need to know
058: * if the socket is bound to ::0 or 0.0.0.0, when a caller
059: * asks for it. Otherwise we don't know which socket to ask.
060: */
061: private InetAddress anyLocalBoundAddr = null;
062:
063: /* to prevent starvation when listening on two sockets, this is
064: * is used to hold the id of the last socket we accepted on.
065: */
066: private int lastfd = -1;
067:
068: static {
069: initProto();
070: }
071:
072: public TwoStacksPlainSocketImpl() {
073: }
074:
075: public TwoStacksPlainSocketImpl(FileDescriptor fd) {
076: this .fd = fd;
077: }
078:
079: /**
080: * Creates a socket with a boolean that specifies whether this
081: * is a stream socket (true) or an unconnected UDP socket (false).
082: */
083: protected synchronized void create(boolean stream)
084: throws IOException {
085: fd1 = new FileDescriptor();
086: super .create(stream);
087: }
088:
089: /**
090: * Binds the socket to the specified address of the specified local port.
091: * @param address the address
092: * @param port the port
093: */
094: protected synchronized void bind(InetAddress address, int lport)
095: throws IOException {
096: super .bind(address, lport);
097: if (address.isAnyLocalAddress()) {
098: anyLocalBoundAddr = address;
099: }
100: }
101:
102: public Object getOption(int opt) throws SocketException {
103: if (isClosedOrPending()) {
104: throw new SocketException("Socket Closed");
105: }
106: if (opt == SO_BINDADDR) {
107: if (fd != null && fd1 != null) {
108: /* must be unbound or else bound to anyLocal */
109: return anyLocalBoundAddr;
110: }
111: InetAddressContainer in = new InetAddressContainer();
112: socketGetOption(opt, in);
113: return in.addr;
114: } else
115: return super .getOption(opt);
116: }
117:
118: /**
119: * Closes the socket.
120: */
121: protected void close() throws IOException {
122: synchronized (fdLock) {
123: if (fd != null || fd1 != null) {
124: if (fdUseCount == 0) {
125: if (closePending) {
126: return;
127: }
128: closePending = true;
129: socketClose();
130: fd = null;
131: fd1 = null;
132: return;
133: } else {
134: /*
135: * If a thread has acquired the fd and a close
136: * isn't pending then use a deferred close.
137: * Also decrement fdUseCount to signal the last
138: * thread that releases the fd to close it.
139: */
140: if (!closePending) {
141: closePending = true;
142: fdUseCount--;
143: socketClose();
144: }
145: }
146: }
147: }
148: }
149:
150: void reset() throws IOException {
151: if (fd != null || fd1 != null) {
152: socketClose();
153: }
154: fd = null;
155: fd1 = null;
156: super .reset();
157: }
158:
159: /*
160: * Return true if already closed or close is pending
161: */
162: public boolean isClosedOrPending() {
163: /*
164: * Lock on fdLock to ensure that we wait if a
165: * close is in progress.
166: */
167: synchronized (fdLock) {
168: if (closePending || (fd == null && fd1 == null)) {
169: return true;
170: } else {
171: return false;
172: }
173: }
174: }
175:
176: /* Native methods */
177:
178: static native void initProto();
179:
180: native void socketCreate(boolean isServer) throws IOException;
181:
182: native void socketConnect(InetAddress address, int port, int timeout)
183: throws IOException;
184:
185: native void socketBind(InetAddress address, int port)
186: throws IOException;
187:
188: native void socketListen(int count) throws IOException;
189:
190: native void socketAccept(SocketImpl s) throws IOException;
191:
192: native int socketAvailable() throws IOException;
193:
194: native void socketClose0(boolean useDeferredClose)
195: throws IOException;
196:
197: native void socketShutdown(int howto) throws IOException;
198:
199: native void socketSetOption(int cmd, boolean on, Object value)
200: throws SocketException;
201:
202: native int socketGetOption(int opt, Object iaContainerObj)
203: throws SocketException;
204:
205: native int socketGetOption1(int opt, Object iaContainerObj,
206: FileDescriptor fd) throws SocketException;
207:
208: native void socketSendUrgentData(int data) throws IOException;
209: }
|