blob: 116046603f8592cdb676615b6e78a4d94c6293fd [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;
29import sun.misc.SharedSecrets;
30import sun.misc.JavaIOFileDescriptorAccess;
31
32/**
33 * This class defines the plain SocketImpl that is used on Windows platforms
34 * greater or equal to Windows Vista. These platforms have a dual
35 * layer TCP/IP stack and can handle both IPv4 and IPV6 through a
36 * single file descriptor.
37 *
38 * @author Chris Hegarty
39 */
40
41class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
42{
43 static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
44
45 public DualStackPlainSocketImpl() {}
46
47 public DualStackPlainSocketImpl(FileDescriptor fd) {
48 this.fd = fd;
49 }
50
51 void socketCreate(boolean stream) throws IOException {
52 if (fd == null)
53 throw new SocketException("Socket closed");
54
55 int newfd = socket0(stream, false /*v6 Only*/);
56
57 fdAccess.set(fd, newfd);
58 }
59
60 void socketConnect(InetAddress address, int port, int timeout)
61 throws IOException {
62 int nativefd = checkAndReturnNativeFD();
63
64 if (address == null)
65 throw new NullPointerException("inet address argument is null.");
66
67 int connectResult;
68 if (timeout <= 0) {
69 connectResult = connect0(nativefd, address, port);
70 } else {
71 configureBlocking(nativefd, false);
72 try {
73 connectResult = connect0(nativefd, address, port);
74 if (connectResult == WOULDBLOCK) {
75 waitForConnect(nativefd, timeout);
76 }
77 } finally {
78 configureBlocking(nativefd, true);
79 }
80 }
81 /*
82 * We need to set the local port field. If bind was called
83 * previous to the connect (by the client) then localport field
84 * will already be set.
85 */
86 if (localport == 0)
87 localport = localPort0(nativefd);
88 }
89
90 void socketBind(InetAddress address, int port) throws IOException {
91 int nativefd = checkAndReturnNativeFD();
92
93 if (address == null)
94 throw new NullPointerException("inet address argument is null.");
95
96 bind0(nativefd, address, port);
97 if (port == 0) {
98 localport = localPort0(nativefd);
99 } else {
100 localport = port;
101 }
102
103 this.address = address;
104 }
105
106 void socketListen(int backlog) throws IOException {
107 int nativefd = checkAndReturnNativeFD();
108
109 listen0(nativefd, backlog);
110 }
111
112 void socketAccept(SocketImpl s) throws IOException {
113 int nativefd = checkAndReturnNativeFD();
114
115 if (s == null)
116 throw new NullPointerException("socket is null");
117
118 int newfd = -1;
119 InetSocketAddress[] isaa = new InetSocketAddress[1];
120 if (timeout <= 0) {
121 newfd = accept0(nativefd, isaa);
122 } else {
123 configureBlocking(nativefd, false);
124 try {
125 waitForNewConnection(nativefd, timeout);
126 newfd = accept0(nativefd, isaa);
127 if (newfd != -1) {
128 configureBlocking(newfd, true);
129 }
130 } finally {
131 configureBlocking(nativefd, true);
132 }
133 }
134 /* Update (SocketImpl)s' fd */
135 fdAccess.set(s.fd, newfd);
136 /* Update socketImpls remote port, address and localport */
137 InetSocketAddress isa = isaa[0];
138 s.port = isa.getPort();
139 s.address = isa.getAddress();
140 s.localport = localport;
141 }
142
143 int socketAvailable() throws IOException {
144 int nativefd = checkAndReturnNativeFD();
145 return available0(nativefd);
146 }
147
148 void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
149 if (fd == null)
150 throw new SocketException("Socket closed");
151
152 if (!fd.valid())
153 return;
154
155 close0(fdAccess.get(fd));
156 fdAccess.set(fd, -1);
157 }
158
159 void socketShutdown(int howto) throws IOException {
160 int nativefd = checkAndReturnNativeFD();
161 shutdown0(nativefd, howto);
162 }
163
164 void socketSetOption(int opt, boolean on, Object value)
165 throws SocketException {
166 int nativefd = checkAndReturnNativeFD();
167
168 if (opt == SO_TIMEOUT) { // timeout implemented through select.
169 return;
170 }
171
172 int optionValue = 0;
173
174 switch(opt) {
175 case TCP_NODELAY :
176 case SO_OOBINLINE :
177 case SO_KEEPALIVE :
178 case SO_REUSEADDR :
179 optionValue = on ? 1 : 0;
180 break;
181 case SO_SNDBUF :
182 case SO_RCVBUF :
183 case IP_TOS :
184 optionValue = ((Integer)value).intValue();
185 break;
186 case SO_LINGER :
187 if (on) {
188 optionValue = ((Integer)value).intValue();
189 } else {
190 optionValue = -1;
191 }
192 break;
193 default :/* shouldn't get here */
194 throw new SocketException("Option not supported");
195 }
196
197 setIntOption(nativefd, opt, optionValue);
198 }
199
200 int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
201 int nativefd = checkAndReturnNativeFD();
202
203 // SO_BINDADDR is not a socket option.
204 if (opt == SO_BINDADDR) {
205 localAddress(nativefd, (InetAddressContainer)iaContainerObj);
206 return 0; // return value doesn't matter.
207 }
208
209 int value = getIntOption(nativefd, opt);
210
211 switch (opt) {
212 case TCP_NODELAY :
213 case SO_OOBINLINE :
214 case SO_KEEPALIVE :
215 case SO_REUSEADDR :
216 return (value == 0) ? -1 : 1;
217 }
218 return value;
219 }
220
221 int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd)
222 throws SocketException {return 0;} // un-implemented REMOVE
223
224 void socketSendUrgentData(int data) throws IOException {
225 int nativefd = checkAndReturnNativeFD();
226 sendOOB(nativefd, data);
227 }
228
229 private int checkAndReturnNativeFD() throws SocketException {
230 if (fd == null || !fd.valid())
231 throw new SocketException("Socket closed");
232
233 return fdAccess.get(fd);
234 }
235
236 static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
237
238 static {
239 initIDs();
240 }
241
242 /* Native methods */
243
244 static native void initIDs();
245
246 static native int socket0(boolean stream, boolean v6Only) throws IOException;
247
248 static native void bind0(int fd, InetAddress localAddress, int localport)
249 throws IOException;
250
251 static native int connect0(int fd, InetAddress remote, int remotePort)
252 throws IOException;
253
254 static native void waitForConnect(int fd, int timeout) throws IOException;
255
256 static native int localPort0(int fd) throws IOException;
257
258 static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
259
260 static native void listen0(int fd, int backlog) throws IOException;
261
262 static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
263
264 static native void waitForNewConnection(int fd, int timeout) throws IOException;
265
266 static native int available0(int fd) throws IOException;
267
268 static native void close0(int fd) throws IOException;
269
270 static native void shutdown0(int fd, int howto) throws IOException;
271
272 static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
273
274 static native int getIntOption(int fd, int cmd) throws SocketException;
275
276 static native void sendOOB(int fd, int data) throws IOException;
277
278 static native void configureBlocking(int fd, boolean blocking) throws IOException;
279}