blob: 9475bd3f7a10e17ed845d2b7df49599e04344c35 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package java.net;
26
27import java.io.IOException;
28import java.io.FileDescriptor;
29
30/*
31 * This class defines the plain SocketImpl that is used for all
32 * Windows version lower than Vista. It adds support for IPv6 on
33 * these platforms where available.
34 *
35 * For backward compatibility Windows platforms that do not have IPv6
36 * support also use this implementation, and fd1 gets set to null
37 * during socket creation.
38 *
39 * @author Chris Hegarty
40 */
41
42class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
43{
44 /* second fd, used for ipv6 on windows only.
45 * fd1 is used for listeners and for client sockets at initialization
46 * until the socket is connected. Up to this point fd always refers
47 * to the ipv4 socket and fd1 to the ipv6 socket. After the socket
48 * becomes connected, fd always refers to the connected socket
49 * (either v4 or v6) and fd1 is closed.
50 *
51 * For ServerSockets, fd always refers to the v4 listener and
52 * fd1 the v6 listener.
53 */
54 private FileDescriptor fd1;
55
56 /*
57 * Needed for ipv6 on windows because we need to know
58 * if the socket is bound to ::0 or 0.0.0.0, when a caller
59 * asks for it. Otherwise we don't know which socket to ask.
60 */
61 private InetAddress anyLocalBoundAddr = null;
62
63 /* to prevent starvation when listening on two sockets, this is
64 * is used to hold the id of the last socket we accepted on.
65 */
66 private int lastfd = -1;
67
68 static {
69 initProto();
70 }
71
72 public TwoStacksPlainSocketImpl() {}
73
74 public TwoStacksPlainSocketImpl(FileDescriptor fd) {
75 this.fd = fd;
76 }
77
78 /**
79 * Creates a socket with a boolean that specifies whether this
80 * is a stream socket (true) or an unconnected UDP socket (false).
81 */
82 protected synchronized void create(boolean stream) throws IOException {
83 fd1 = new FileDescriptor();
84 super.create(stream);
85 }
86
87 /**
88 * Binds the socket to the specified address of the specified local port.
89 * @param address the address
90 * @param port the port
91 */
92 protected synchronized void bind(InetAddress address, int lport)
93 throws IOException
94 {
95 super.bind(address, lport);
96 if (address.isAnyLocalAddress()) {
97 anyLocalBoundAddr = address;
98 }
99 }
100
101 public Object getOption(int opt) throws SocketException {
102 if (isClosedOrPending()) {
103 throw new SocketException("Socket Closed");
104 }
105 if (opt == SO_BINDADDR) {
106 if (fd != null && fd1 != null ) {
107 /* must be unbound or else bound to anyLocal */
108 return anyLocalBoundAddr;
109 }
110 InetAddressContainer in = new InetAddressContainer();
111 socketGetOption(opt, in);
112 return in.addr;
113 } else
114 return super.getOption(opt);
115 }
116
117 /**
118 * Closes the socket.
119 */
120 protected void close() throws IOException {
121 synchronized(fdLock) {
122 if (fd != null || fd1 != null) {
123 if (fdUseCount == 0) {
124 if (closePending) {
125 return;
126 }
127 closePending = true;
128 socketClose();
129 fd = null;
130 fd1 = null;
131 return;
132 } else {
133 /*
134 * If a thread has acquired the fd and a close
135 * isn't pending then use a deferred close.
136 * Also decrement fdUseCount to signal the last
137 * thread that releases the fd to close it.
138 */
139 if (!closePending) {
140 closePending = true;
141 fdUseCount--;
142 socketClose();
143 }
144 }
145 }
146 }
147 }
148
149 void reset() throws IOException {
150 if (fd != null || fd1 != null) {
151 socketClose();
152 }
153 fd = null;
154 fd1 = null;
155 super.reset();
156 }
157
158 /*
159 * Return true if already closed or close is pending
160 */
161 public boolean isClosedOrPending() {
162 /*
163 * Lock on fdLock to ensure that we wait if a
164 * close is in progress.
165 */
166 synchronized (fdLock) {
167 if (closePending || (fd == null && fd1 == null)) {
168 return true;
169 } else {
170 return false;
171 }
172 }
173 }
174
175 /* Native methods */
176
177 static native void initProto();
178
179 native void socketCreate(boolean isServer) throws IOException;
180
181 native void socketConnect(InetAddress address, int port, int timeout)
182 throws IOException;
183
184 native void socketBind(InetAddress address, int port)
185 throws IOException;
186
187 native void socketListen(int count) throws IOException;
188
189 native void socketAccept(SocketImpl s) throws IOException;
190
191 native int socketAvailable() throws IOException;
192
193 native void socketClose0(boolean useDeferredClose) throws IOException;
194
195 native void socketShutdown(int howto) throws IOException;
196
197 native void socketSetOption(int cmd, boolean on, Object value)
198 throws SocketException;
199
200 native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
201
202 native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd)
203 throws SocketException;
204
205 native void socketSendUrgentData(int data) throws IOException;
206}