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