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: import sun.misc.SharedSecrets;
030: import sun.misc.JavaIOFileDescriptorAccess;
031:
032: /**
033: * This class defines the plain SocketImpl that is used on Windows platforms
034: * greater or equal to Windows Vista. These platforms have a dual
035: * layer TCP/IP stack and can handle both IPv4 and IPV6 through a
036: * single file descriptor.
037: *
038: * @version 1.2, 06/11/07
039: * @author Chris Hegarty
040: */
041:
042: class DualStackPlainSocketImpl extends AbstractPlainSocketImpl {
043: static JavaIOFileDescriptorAccess fdAccess = SharedSecrets
044: .getJavaIOFileDescriptorAccess();
045:
046: public DualStackPlainSocketImpl() {
047: }
048:
049: public DualStackPlainSocketImpl(FileDescriptor fd) {
050: this .fd = fd;
051: }
052:
053: void socketCreate(boolean stream) throws IOException {
054: if (fd == null)
055: throw new SocketException("Socket closed");
056:
057: int newfd = socket0(stream, false /*v6 Only*/);
058:
059: fdAccess.set(fd, newfd);
060: }
061:
062: void socketConnect(InetAddress address, int port, int timeout)
063: throws IOException {
064: int nativefd = checkAndReturnNativeFD();
065:
066: if (address == null)
067: throw new NullPointerException(
068: "inet address argument is null.");
069:
070: int connectResult;
071: if (timeout <= 0) {
072: connectResult = connect0(nativefd, address, port);
073: } else {
074: configureBlocking(nativefd, false);
075: try {
076: connectResult = connect0(nativefd, address, port);
077: if (connectResult == WOULDBLOCK) {
078: waitForConnect(nativefd, timeout);
079: }
080: } finally {
081: configureBlocking(nativefd, true);
082: }
083: }
084: /*
085: * We need to set the local port field. If bind was called
086: * previous to the connect (by the client) then localport field
087: * will already be set.
088: */
089: if (localport == 0)
090: localport = localPort0(nativefd);
091: }
092:
093: void socketBind(InetAddress address, int port) throws IOException {
094: int nativefd = checkAndReturnNativeFD();
095:
096: if (address == null)
097: throw new NullPointerException(
098: "inet address argument is null.");
099:
100: bind0(nativefd, address, port);
101: if (port == 0) {
102: localport = localPort0(nativefd);
103: } else {
104: localport = port;
105: }
106:
107: this .address = address;
108: }
109:
110: void socketListen(int backlog) throws IOException {
111: int nativefd = checkAndReturnNativeFD();
112:
113: listen0(nativefd, backlog);
114: }
115:
116: void socketAccept(SocketImpl s) throws IOException {
117: int nativefd = checkAndReturnNativeFD();
118:
119: if (s == null)
120: throw new NullPointerException("socket is null");
121:
122: int newfd = -1;
123: InetSocketAddress[] isaa = new InetSocketAddress[1];
124: if (timeout <= 0) {
125: newfd = accept0(nativefd, isaa);
126: } else {
127: configureBlocking(nativefd, false);
128: try {
129: waitForNewConnection(nativefd, timeout);
130: newfd = accept0(nativefd, isaa);
131: if (newfd != -1) {
132: configureBlocking(newfd, true);
133: }
134: } finally {
135: configureBlocking(nativefd, true);
136: }
137: }
138: /* Update (SocketImpl)s' fd */
139: fdAccess.set(s.fd, newfd);
140: /* Update socketImpls remote port, address and localport */
141: InetSocketAddress isa = isaa[0];
142: s.port = isa.getPort();
143: s.address = isa.getAddress();
144: s.localport = localport;
145: }
146:
147: int socketAvailable() throws IOException {
148: int nativefd = checkAndReturnNativeFD();
149: return available0(nativefd);
150: }
151:
152: void socketClose0(boolean useDeferredClose/*unused*/)
153: throws IOException {
154: if (fd == null)
155: throw new SocketException("Socket closed");
156:
157: if (!fd.valid())
158: return;
159:
160: close0(fdAccess.get(fd));
161: fdAccess.set(fd, -1);
162: }
163:
164: void socketShutdown(int howto) throws IOException {
165: int nativefd = checkAndReturnNativeFD();
166: shutdown0(nativefd, howto);
167: }
168:
169: void socketSetOption(int opt, boolean on, Object value)
170: throws SocketException {
171: int nativefd = checkAndReturnNativeFD();
172:
173: if (opt == SO_TIMEOUT) { // timeout implemented through select.
174: return;
175: }
176:
177: int optionValue = 0;
178:
179: switch (opt) {
180: case TCP_NODELAY:
181: case SO_OOBINLINE:
182: case SO_KEEPALIVE:
183: case SO_REUSEADDR:
184: optionValue = on ? 1 : 0;
185: break;
186: case SO_SNDBUF:
187: case SO_RCVBUF:
188: case IP_TOS:
189: optionValue = ((Integer) value).intValue();
190: break;
191: case SO_LINGER:
192: if (on) {
193: optionValue = ((Integer) value).intValue();
194: } else {
195: optionValue = -1;
196: }
197: break;
198: default:/* shouldn't get here */
199: throw new SocketException("Option not supported");
200: }
201:
202: setIntOption(nativefd, opt, optionValue);
203: }
204:
205: int socketGetOption(int opt, Object iaContainerObj)
206: throws SocketException {
207: int nativefd = checkAndReturnNativeFD();
208:
209: // SO_BINDADDR is not a socket option.
210: if (opt == SO_BINDADDR) {
211: localAddress(nativefd,
212: (InetAddressContainer) iaContainerObj);
213: return 0; // return value doesn't matter.
214: }
215:
216: int value = getIntOption(nativefd, opt);
217:
218: switch (opt) {
219: case TCP_NODELAY:
220: case SO_OOBINLINE:
221: case SO_KEEPALIVE:
222: case SO_REUSEADDR:
223: return (value == 0) ? -1 : 1;
224: }
225: return value;
226: }
227:
228: int socketGetOption1(int opt, Object iaContainerObj,
229: FileDescriptor fd) throws SocketException {
230: return 0;
231: } // un-implemented REMOVE
232:
233: void socketSendUrgentData(int data) throws IOException {
234: int nativefd = checkAndReturnNativeFD();
235: sendOOB(nativefd, data);
236: }
237:
238: private int checkAndReturnNativeFD() throws SocketException {
239: if (fd == null || !fd.valid())
240: throw new SocketException("Socket closed");
241:
242: return fdAccess.get(fd);
243: }
244:
245: static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
246:
247: static {
248: initIDs();
249: }
250:
251: /* Native methods */
252:
253: static native void initIDs();
254:
255: static native int socket0(boolean stream, boolean v6Only)
256: throws IOException;
257:
258: static native void bind0(int fd, InetAddress localAddress,
259: int localport) throws IOException;
260:
261: static native int connect0(int fd, InetAddress remote,
262: int remotePort) throws IOException;
263:
264: static native void waitForConnect(int fd, int timeout)
265: throws IOException;
266:
267: static native int localPort0(int fd) throws IOException;
268:
269: static native void localAddress(int fd, InetAddressContainer in)
270: throws SocketException;
271:
272: static native void listen0(int fd, int backlog) throws IOException;
273:
274: static native int accept0(int fd, InetSocketAddress[] isaa)
275: throws IOException;
276:
277: static native void waitForNewConnection(int fd, int timeout)
278: throws IOException;
279:
280: static native int available0(int fd) throws IOException;
281:
282: static native void close0(int fd) throws IOException;
283:
284: static native void shutdown0(int fd, int howto) throws IOException;
285:
286: static native void setIntOption(int fd, int cmd, int optionValue)
287: throws SocketException;
288:
289: static native int getIntOption(int fd, int cmd)
290: throws SocketException;
291:
292: static native void sendOOB(int fd, int data) throws IOException;
293:
294: static native void configureBlocking(int fd, boolean blocking)
295: throws IOException;
296: }
|