Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/windows/native/java/net/TwoStacksPlainSocketImpl.c
+++ new/src/windows/native/java/net/TwoStacksPlainSocketImpl.c
1 1 /*
2 2 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Sun designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Sun in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 23 * have any questions.
24 24 */
25 25
26 26 #include <windows.h>
27 27 #include <winsock2.h>
28 28 #include <ctype.h>
29 29 #include <stdio.h>
30 30 #include <stdlib.h>
31 31 #include <malloc.h>
32 32 #include <sys/types.h>
33 33
34 34 #include "java_net_SocketOptions.h"
35 35 #include "java_net_TwoStacksPlainSocketImpl.h"
36 36 #include "java_net_SocketImpl.h"
37 37 #include "java_net_InetAddress.h"
38 38 #include "java_io_FileDescriptor.h"
39 39 #include "java_lang_Integer.h"
40 40
41 41 #include "jvm.h"
42 42 #include "net_util.h"
43 43 #include "jni_util.h"
44 44
45 45 /************************************************************************
46 46 * TwoStacksPlainSocketImpl
47 47 */
48 48
49 49 static jfieldID IO_fd_fdID;
50 50
51 51 jfieldID psi_fdID;
52 52 jfieldID psi_fd1ID;
53 53 jfieldID psi_addressID;
54 54 jfieldID psi_portID;
55 55 jfieldID psi_localportID;
56 56 jfieldID psi_timeoutID;
57 57 jfieldID psi_trafficClassID;
58 58 jfieldID psi_serverSocketID;
59 59 jfieldID psi_lastfdID;
60 60
61 61 /*
62 62 * the level of the TCP protocol for setsockopt and getsockopt
63 63 * we only want to look this up once, from the static initializer
64 64 * of TwoStacksPlainSocketImpl
65 65 */
66 66 static int tcp_level = -1;
67 67
68 68 static int getFD(JNIEnv *env, jobject this) {
69 69 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
70 70
71 71 if (fdObj == NULL) {
72 72 return -1;
73 73 }
74 74 return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
75 75 }
76 76
77 77 static int getFD1(JNIEnv *env, jobject this) {
78 78 jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID);
79 79
80 80 if (fdObj == NULL) {
81 81 return -1;
82 82 }
83 83 return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
84 84 }
85 85
86 86
87 87 /*
88 88 * The initProto function is called whenever TwoStacksPlainSocketImpl is
89 89 * loaded, to cache fieldIds for efficiency. This is called everytime
90 90 * the Java class is loaded.
91 91 *
92 92 * Class: java_net_TwoStacksPlainSocketImpl
93 93 * Method: initProto
94 94
95 95 * Signature: ()V
96 96 */
97 97 JNIEXPORT void JNICALL
98 98 Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
99 99
100 100 struct protoent *proto = getprotobyname("TCP");
101 101 tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
102 102
103 103 psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;");
104 104 CHECK_NULL(psi_fdID);
105 105 psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;");
106 106 CHECK_NULL(psi_fd1ID);
107 107 psi_addressID = (*env)->GetFieldID(env, cls, "address",
108 108 "Ljava/net/InetAddress;");
109 109 CHECK_NULL(psi_addressID);
110 110 psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
111 111 CHECK_NULL(psi_portID);
112 112 psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
113 113 CHECK_NULL(psi_portID);
114 114 psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
↓ open down ↓ |
114 lines elided |
↑ open up ↑ |
115 115 CHECK_NULL(psi_localportID);
116 116 psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
117 117 CHECK_NULL(psi_timeoutID);
118 118 psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
119 119 CHECK_NULL(psi_trafficClassID);
120 120 psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket",
121 121 "Ljava/net/ServerSocket;");
122 122 CHECK_NULL(psi_serverSocketID);
123 123 IO_fd_fdID = NET_GetFileDescriptorID(env);
124 124 CHECK_NULL(IO_fd_fdID);
125 +
126 + init(env);
125 127 }
126 128
127 129 /*
128 130 * Class: java_net_TwoStacksPlainSocketImpl
129 131 * Method: socketCreate
130 132 * Signature: (Z)V
131 133 */
132 134 JNIEXPORT void JNICALL
133 135 Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
134 136 jboolean stream) {
135 137 jobject fdObj, fd1Obj;
136 138 int fd, fd1;
137 139
138 140 fdObj = (*env)->GetObjectField(env, this, psi_fdID);
139 141
140 142 if (IS_NULL(fdObj)) {
141 143 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
142 144 "null fd object");
143 145 return;
144 146 }
145 - fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
147 + fd = (int)socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
146 148 if (fd == -1) {
147 149 NET_ThrowCurrent(env, "create");
148 150 return;
149 151 } else {
150 152 /* Set socket attribute so it is not passed to any child process */
151 153 SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
152 154 (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd);
153 155 }
154 156 if (ipv6_available()) {
155 157 fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
156 158
157 159 if (IS_NULL(fd1Obj)) {
158 160 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
159 161 "null fd1 object");
160 162 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
161 163 NET_SocketClose(fd);
162 164 return;
163 165 }
164 - fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
166 + fd1 = (int)socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
165 167 if (fd1 == -1) {
166 168 NET_ThrowCurrent(env, "create");
167 169 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
168 170 NET_SocketClose(fd);
169 171 return;
170 172 } else {
171 173 /* Set socket attribute so it is not passed to any child process */
172 174 SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE);
173 175 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
174 176 }
175 177 } else {
176 178 (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
177 179 }
178 180 }
179 181
180 182 /*
181 183 * inetAddress is the address object passed to the socket connect
182 184 * call.
183 185 *
184 186 * Class: java_net_TwoStacksPlainSocketImpl
185 187 * Method: socketConnect
186 188 * Signature: (Ljava/net/InetAddress;I)V
187 189 */
188 190 JNIEXPORT void JNICALL
189 191 Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
190 192 jobject iaObj, jint port,
191 193 jint timeout)
192 194 {
193 195 jint localport = (*env)->GetIntField(env, this, psi_localportID);
194 196
195 197 /* family and localport are int fields of iaObj */
196 198 int family;
197 199 jint fd, fd1=-1;
198 200 jint len;
199 201 int ipv6_supported = ipv6_available();
200 202
201 203 /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket
202 204 * If we want to connect to IPv6 then we swap the two sockets/objects
203 205 * This way, fd is always the connected socket, and fd1 always gets closed.
204 206 */
205 207 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
206 208 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
207 209
208 210 SOCKETADDRESS him;
209 211
210 212 /* The result of the connection */
211 213 int connect_res;
212 214
213 215 if (!IS_NULL(fdObj)) {
214 216 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
215 217 }
216 218
217 219 if (ipv6_supported && !IS_NULL(fd1Obj)) {
218 220 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
219 221 }
220 222
221 223 if (IS_NULL(iaObj)) {
222 224 JNU_ThrowNullPointerException(env, "inet address argument is null.");
223 225 return;
224 226 }
225 227
226 228 if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_FALSE) != 0) {
227 229 return;
228 230 }
229 231
230 232 family = him.him.sa_family;
231 233 if (family == AF_INET6) {
232 234 if (!ipv6_supported) {
233 235 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
234 236 "Protocol family not supported");
235 237 return;
236 238 } else {
237 239 if (fd1 == -1) {
238 240 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
239 241 "Destination unreachable");
240 242 return;
241 243 }
242 244 /* close the v4 socket, and set fd to be the v6 socket */
243 245 (*env)->SetObjectField(env, this, psi_fdID, fd1Obj);
244 246 (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
245 247 NET_SocketClose(fd);
246 248 fd = fd1; fdObj = fd1Obj;
247 249 }
248 250 } else {
249 251 if (fd1 != -1) {
250 252 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
251 253 NET_SocketClose(fd1);
252 254 }
253 255 if (fd == -1) {
254 256 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
255 257 "Destination unreachable");
256 258 return;
257 259 }
258 260 }
259 261 (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
260 262
261 263 if (timeout <= 0) {
262 264 connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him));
263 265 if (connect_res == SOCKET_ERROR) {
264 266 connect_res = WSAGetLastError();
265 267 }
266 268 } else {
267 269 int optval;
268 270 int optlen = sizeof(optval);
269 271
270 272 /* make socket non-blocking */
271 273 optval = 1;
272 274 ioctlsocket( fd, FIONBIO, &optval );
273 275
274 276 /* initiate the connect */
275 277 connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him));
276 278 if (connect_res == SOCKET_ERROR) {
277 279 if (WSAGetLastError() != WSAEWOULDBLOCK) {
278 280 connect_res = WSAGetLastError();
279 281 } else {
280 282 fd_set wr, ex;
281 283 struct timeval t;
282 284
283 285 FD_ZERO(&wr);
284 286 FD_ZERO(&ex);
285 287 FD_SET(fd, &wr);
286 288 FD_SET(fd, &ex);
287 289 t.tv_sec = timeout / 1000;
288 290 t.tv_usec = (timeout % 1000) * 1000;
289 291
290 292 /*
291 293 * Wait for timout, connection established or
292 294 * connection failed.
293 295 */
294 296 connect_res = select(fd+1, 0, &wr, &ex, &t);
295 297
296 298 /*
297 299 * Timeout before connection is established/failed so
298 300 * we throw exception and shutdown input/output to prevent
299 301 * socket from being used.
300 302 * The socket should be closed immediately by the caller.
301 303 */
302 304 if (connect_res == 0) {
303 305 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
304 306 "connect timed out");
305 307 shutdown( fd, SD_BOTH );
306 308
307 309 /* make socket blocking again - just in case */
308 310 optval = 0;
309 311 ioctlsocket( fd, FIONBIO, &optval );
310 312 return;
311 313 }
312 314
313 315 /*
314 316 * We must now determine if the connection has been established
315 317 * or if it has failed. The logic here is designed to work around
316 318 * bug on Windows NT whereby using getsockopt to obtain the
317 319 * last error (SO_ERROR) indicates there is no error. The workaround
318 320 * on NT is to allow winsock to be scheduled and this is done by
319 321 * yielding and retrying. As yielding is problematic in heavy
320 322 * load conditions we attempt up to 3 times to get the error reason.
321 323 */
322 324 if (!FD_ISSET(fd, &ex)) {
323 325 connect_res = 0;
324 326 } else {
325 327 int retry;
326 328 for (retry=0; retry<3; retry++) {
327 329 NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
328 330 (char*)&connect_res, &optlen);
329 331 if (connect_res) {
330 332 break;
331 333 }
332 334 Sleep(0);
333 335 }
334 336
335 337 if (connect_res == 0) {
336 338 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
337 339 "Unable to establish connection");
338 340 return;
339 341 }
340 342 }
341 343 }
342 344 }
343 345
344 346 /* make socket blocking again */
345 347 optval = 0;
346 348 ioctlsocket(fd, FIONBIO, &optval);
347 349 }
348 350
349 351 if (connect_res) {
350 352 if (connect_res == WSAEADDRNOTAVAIL) {
351 353 JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
352 354 "connect: Address is invalid on local machine, or port is not valid on remote machine");
353 355 } else {
354 356 NET_ThrowNew(env, connect_res, "connect");
355 357 }
356 358 return;
357 359 }
358 360
359 361 (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd);
360 362
361 363 /* set the remote peer address and port */
362 364 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
363 365 (*env)->SetIntField(env, this, psi_portID, port);
364 366
365 367 /*
366 368 * we need to initialize the local port field if bind was called
367 369 * previously to the connect (by the client) then localport field
368 370 * will already be initialized
369 371 */
370 372 if (localport == 0) {
371 373 /* Now that we're a connected socket, let's extract the port number
372 374 * that the system chose for us and store it in the Socket object.
373 375 */
374 376 u_short port;
375 377 int len = SOCKETADDRESS_LEN(&him);
376 378 if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
377 379
378 380 if (WSAGetLastError() == WSAENOTSOCK) {
379 381 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
380 382 "Socket closed");
381 383 } else {
382 384 NET_ThrowCurrent(env, "getsockname failed");
383 385 }
384 386 return;
385 387 }
386 388 port = ntohs ((u_short)GET_PORT(&him));
387 389 (*env)->SetIntField(env, this, psi_localportID, (int) port);
388 390 }
389 391 }
390 392
391 393 /*
392 394 * Class: java_net_TwoStacksPlainSocketImpl
393 395 * Method: socketBind
394 396 * Signature: (Ljava/net/InetAddress;I)V
395 397 */
396 398 JNIEXPORT void JNICALL
397 399 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
398 400 jobject iaObj, jint localport) {
399 401
400 402 /* fdObj is the FileDescriptor field on this */
401 403 jobject fdObj, fd1Obj;
402 404 /* fd is an int field on fdObj */
403 405 int fd, fd1, len;
404 406 int ipv6_supported = ipv6_available();
405 407
406 408 /* family is an int field of iaObj */
407 409 int family;
408 410 int rv;
409 411
410 412 SOCKETADDRESS him;
411 413
412 414 fdObj = (*env)->GetObjectField(env, this, psi_fdID);
413 415 fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
414 416
415 417 family = (*env)->GetIntField(env, iaObj, ia_familyID);
416 418
417 419 if (family == IPv6 && !ipv6_supported) {
418 420 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
419 421 "Protocol family not supported");
420 422 return;
421 423 }
422 424
423 425 if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {
424 426 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
425 427 "Socket closed");
426 428 return;
427 429 } else {
428 430 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
429 431 if (ipv6_supported) {
430 432 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
431 433 }
432 434 }
433 435 if (IS_NULL(iaObj)) {
434 436 JNU_ThrowNullPointerException(env, "inet address argument");
435 437 return;
436 438 }
437 439
438 440 if (NET_InetAddressToSockaddr(env, iaObj, localport,
439 441 (struct sockaddr *)&him, &len, JNI_FALSE) != 0) {
440 442 return;
441 443 }
↓ open down ↓ |
267 lines elided |
↑ open up ↑ |
442 444
443 445 if (ipv6_supported) {
444 446 struct ipv6bind v6bind;
445 447 v6bind.addr = &him;
446 448 v6bind.ipv4_fd = fd;
447 449 v6bind.ipv6_fd = fd1;
448 450 rv = NET_BindV6(&v6bind);
449 451 if (rv != -1) {
450 452 /* check if the fds have changed */
451 453 if (v6bind.ipv4_fd != fd) {
452 - fd = v6bind.ipv4_fd;
454 + fd = (int)v6bind.ipv4_fd;
453 455 if (fd == -1) {
454 456 /* socket is closed. */
455 457 (*env)->SetObjectField(env, this, psi_fdID, NULL);
456 458 } else {
457 459 /* socket was re-created */
458 460 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
459 461 }
460 462 }
461 463 if (v6bind.ipv6_fd != fd1) {
462 - fd1 = v6bind.ipv6_fd;
464 + fd1 = (int)v6bind.ipv6_fd;
463 465 if (fd1 == -1) {
464 466 /* socket is closed. */
465 467 (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
466 468 } else {
467 469 /* socket was re-created */
468 470 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
469 471 }
470 472 }
471 473 }
472 474 } else {
473 475 rv = NET_Bind(fd, (struct sockaddr *)&him, len);
474 476 }
475 477
476 478 if (rv == -1) {
477 479 NET_ThrowCurrent(env, "JVM_Bind");
478 480 return;
479 481 }
480 482
481 483 /* set the address */
482 484 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
483 485
484 486 /* intialize the local port */
485 487 if (localport == 0) {
486 488 /* Now that we're a bound socket, let's extract the port number
487 489 * that the system chose for us and store it in the Socket object.
488 490 */
489 491 int len = SOCKETADDRESS_LEN(&him);
490 492 u_short port;
491 493 fd = him.him.sa_family == AF_INET? fd: fd1;
492 494
493 495 if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
494 496 NET_ThrowCurrent(env, "getsockname in plain socketBind");
495 497 return;
496 498 }
497 499 port = ntohs ((u_short) GET_PORT (&him));
498 500
499 501 (*env)->SetIntField(env, this, psi_localportID, (int) port);
500 502 } else {
501 503 (*env)->SetIntField(env, this, psi_localportID, localport);
502 504 }
503 505 }
504 506
505 507 /*
506 508 * Class: java_net_TwoStacksPlainSocketImpl
507 509 * Method: socketListen
508 510 * Signature: (I)V
509 511 */
510 512 JNIEXPORT void JNICALL
511 513 Java_java_net_TwoStacksPlainSocketImpl_socketListen (JNIEnv *env, jobject this,
512 514 jint count)
513 515 {
514 516 /* this FileDescriptor fd field */
515 517 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
516 518 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
517 519 jobject address;
518 520 /* fdObj's int fd field */
519 521 int fd, fd1;
520 522 SOCKETADDRESS addr; int addrlen;
521 523
522 524 if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
523 525 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
524 526 "socket closed");
525 527 return;
526 528 }
527 529
528 530 if (!IS_NULL(fdObj)) {
529 531 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
530 532 }
531 533 /* Listen on V4 if address type is v4 or if v6 and address is ::0.
532 534 * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0.
533 535 * In cases, where we listen on one space only, we close the other socket.
534 536 */
535 537 address = (*env)->GetObjectField(env, this, psi_addressID);
536 538 if (IS_NULL(address)) {
537 539 JNU_ThrowNullPointerException(env, "socket address");
538 540 return;
539 541 }
540 542 if (NET_InetAddressToSockaddr(env, address, 0, (struct sockaddr *)&addr,
541 543 &addrlen, JNI_FALSE) != 0) {
542 544 return;
543 545 }
544 546
545 547 if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(&addr.him6)) {
546 548 /* listen on v4 */
547 549 if (listen(fd, count) == -1) {
548 550 NET_ThrowCurrent(env, "listen failed");
549 551 }
550 552 } else {
551 553 NET_SocketClose (fd);
552 554 (*env)->SetObjectField(env, this, psi_fdID, NULL);
553 555 }
554 556 if (ipv6_available() && !IS_NULL(fd1Obj)) {
555 557 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
556 558 if (addr.him.sa_family == AF_INET6 || addr.him4.sin_addr.s_addr == INADDR_ANY) {
557 559 /* listen on v6 */
558 560 if (listen(fd1, count) == -1) {
559 561 NET_ThrowCurrent(env, "listen failed");
560 562 }
561 563 } else {
562 564 NET_SocketClose (fd1);
563 565 (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
564 566 }
565 567 }
566 568 }
567 569
568 570 /*
569 571 * Class: java_net_TwoStacksPlainSocketImpl
570 572 * Method: socketAccept
571 573 * Signature: (Ljava/net/SocketImpl;)V
572 574 */
573 575 JNIEXPORT void JNICALL
574 576 Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
575 577 jobject socket)
↓ open down ↓ |
103 lines elided |
↑ open up ↑ |
576 578 {
577 579 /* fields on this */
578 580 jint port;
579 581 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
580 582 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
581 583 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
582 584
583 585 /* the FileDescriptor field on socket */
584 586 jobject socketFdObj;
585 587
586 - /* cache the Inet4/6Address classes */
587 - static jclass inet4Cls;
588 - static jclass inet6Cls;
589 -
590 588 /* the InetAddress field on socket */
591 589 jobject socketAddressObj;
592 590
593 591 /* the fd int field on fdObj */
594 592 jint fd=-1, fd1=-1;
595 593
596 594 SOCKETADDRESS him;
597 595 jint len;
598 596
599 597 if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
600 598 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
601 599 "Socket closed");
602 600 return;
603 601 }
604 602 if (!IS_NULL(fdObj)) {
605 603 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
606 604 }
607 605 if (!IS_NULL(fd1Obj)) {
608 606 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
609 607 }
610 608 if (IS_NULL(socket)) {
611 609 JNU_ThrowNullPointerException(env, "socket is null");
612 610 return;
613 611 } else {
614 612 socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
615 613 socketAddressObj = (*env)->GetObjectField(env, socket, psi_addressID);
616 614 }
617 615 if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) {
618 616 JNU_ThrowNullPointerException(env, "socket address or fd obj");
619 617 return;
620 618 }
621 619 if (fd != -1 && fd1 != -1) {
622 620 fd_set rfds;
623 621 struct timeval t, *tP=&t;
624 622 int lastfd, res, fd2;
625 623 FD_ZERO(&rfds);
626 624 FD_SET(fd,&rfds);
627 625 FD_SET(fd1,&rfds);
628 626 if (timeout) {
629 627 t.tv_sec = timeout/1000;
630 628 t.tv_usec = (timeout%1000)*1000;
631 629 } else {
632 630 tP = NULL;
633 631 }
634 632 res = select (fd, &rfds, NULL, NULL, tP);
635 633 if (res == 0) {
636 634 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
637 635 "Accept timed out");
638 636 return;
639 637 } else if (res == 1) {
640 638 fd2 = FD_ISSET(fd, &rfds)? fd: fd1;
641 639 } else if (res == 2) {
642 640 /* avoid starvation */
643 641 lastfd = (*env)->GetIntField(env, this, psi_lastfdID);
644 642 if (lastfd != -1) {
645 643 fd2 = lastfd==fd? fd1: fd;
646 644 } else {
647 645 fd2 = fd;
648 646 }
649 647 (*env)->SetIntField(env, this, psi_lastfdID, fd2);
650 648 } else {
651 649 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
652 650 "select failed");
653 651 return;
654 652 }
655 653 if (fd2 == fd) { /* v4 */
656 654 len = sizeof (struct sockaddr_in);
657 655 } else {
658 656 len = sizeof (struct SOCKADDR_IN6);
659 657 }
660 658 fd = fd2;
661 659 } else {
662 660 int ret;
663 661 if (fd1 != -1) {
664 662 fd = fd1;
665 663 len = sizeof (struct SOCKADDR_IN6);
666 664 } else {
667 665 len = sizeof (struct sockaddr_in);
668 666 }
669 667 if (timeout) {
670 668 ret = NET_Timeout(fd, timeout);
671 669 if (ret == 0) {
672 670 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
673 671 "Accept timed out");
674 672 return;
675 673 } else if (ret == -1) {
676 674 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
677 675 /* REMIND: SOCKET CLOSED PROBLEM */
678 676 /* NET_ThrowCurrent(env, "Accept failed"); */
679 677 return;
680 678 } else if (ret == -2) {
681 679 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
682 680 "operation interrupted");
683 681 return;
684 682 }
685 683 }
686 684 }
687 - fd = accept(fd, (struct sockaddr *)&him, &len);
685 + fd = (jint)accept(fd, (struct sockaddr *)&him, &len);
688 686 if (fd < 0) {
689 687 /* REMIND: SOCKET CLOSED PROBLEM */
690 688 if (fd == -2) {
691 689 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
692 690 "operation interrupted");
693 691 } else {
694 692 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
695 693 "socket closed");
696 694 }
697 695 return;
698 696 }
699 697 (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
700 698
701 699 if (him.him.sa_family == AF_INET) {
702 - if (inet4Cls == NULL) {
703 - jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
704 - if (c != NULL) {
705 - inet4Cls = (*env)->NewGlobalRef(env, c);
706 - (*env)->DeleteLocalRef(env, c);
707 - }
708 - }
709 -
710 700 /*
711 701 * fill up the remote peer port and address in the new socket structure
712 702 */
713 - if (inet4Cls != NULL) {
714 - socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
715 - } else {
716 - socketAddressObj = NULL;
717 - }
703 + socketAddressObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
704 +
718 705 if (socketAddressObj == NULL) {
719 706 /*
720 707 * FindClass or NewObject failed so close connection and
721 708 * exist (there will be a pending exception).
722 709 */
723 710 NET_SocketClose(fd);
724 711 return;
725 712 }
726 713
727 714 (*env)->SetIntField(env, socketAddressObj, ia_addressID,
728 715 ntohl(him.him4.sin_addr.s_addr));
729 716 (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv4);
730 717 (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
731 718 } else {
732 719 jbyteArray addr;
733 720 /* AF_INET6 -> Inet6Address */
734 - if (inet6Cls == 0) {
735 - jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
736 - if (c != NULL) {
737 - inet6Cls = (*env)->NewGlobalRef(env, c);
738 - (*env)->DeleteLocalRef(env, c);
739 - }
740 - }
721 + socketAddressObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
741 722
742 - if (inet6Cls != NULL) {
743 - socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
744 - } else {
745 - socketAddressObj = NULL;
746 - }
747 723 if (socketAddressObj == NULL) {
748 724 /*
749 725 * FindClass or NewObject failed so close connection and
750 726 * exist (there will be a pending exception).
751 727 */
752 728 NET_SocketClose(fd);
753 729 return;
754 730 }
755 731 addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID);
756 732 (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr);
757 733 (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6);
758 734 (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id);
759 735 }
760 736 /* fields common to AF_INET and AF_INET6 */
761 737
762 738 port = ntohs ((u_short) GET_PORT (&him));
763 739 (*env)->SetIntField(env, socket, psi_portID, (int)port);
764 740 port = (*env)->GetIntField(env, this, psi_localportID);
765 741 (*env)->SetIntField(env, socket, psi_localportID, port);
766 742 (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
767 743 }
768 744
769 745 /*
770 746 * Class: java_net_TwoStacksPlainSocketImpl
771 747 * Method: socketAvailable
772 748 * Signature: ()I
773 749 */
774 750 JNIEXPORT jint JNICALL
775 751 Java_java_net_TwoStacksPlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
776 752
777 753 jint available = -1;
778 754 jint res;
779 755 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
780 756 jint fd;
781 757
782 758 if (IS_NULL(fdObj)) {
783 759 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
784 760 return -1;
785 761 } else {
786 762 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
787 763 }
788 764 res = ioctlsocket(fd, FIONREAD, &available);
789 765 /* if result isn't 0, it means an error */
790 766 if (res != 0) {
791 767 NET_ThrowNew(env, res, "socket available");
792 768 }
793 769 return available;
794 770 }
795 771
796 772 /*
797 773 * Class: java_net_TwoStacksPlainSocketImpl
798 774 * Method: socketClose
799 775 * Signature: ()V
800 776 */
801 777 JNIEXPORT void JNICALL
802 778 Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
803 779 jboolean useDeferredClose) {
804 780
805 781 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
806 782 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
807 783 jint fd=-1, fd1=-1;
808 784
809 785 if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
810 786 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
811 787 "socket already closed");
812 788 return;
813 789 }
814 790 if (!IS_NULL(fdObj)) {
815 791 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
816 792 }
817 793 if (!IS_NULL(fd1Obj)) {
818 794 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
819 795 }
820 796 if (fd != -1) {
821 797 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
822 798 NET_SocketClose(fd);
823 799 }
824 800 if (fd1 != -1) {
825 801 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
826 802 NET_SocketClose(fd1);
827 803 }
828 804 }
829 805
830 806 /*
831 807 * Socket options for plainsocketImpl
832 808 *
833 809 *
834 810 * Class: java_net_TwoStacksPlainSocketImpl
835 811 * Method: socketSetOption
836 812 * Signature: (IZLjava/lang/Object;)V
837 813 */
838 814 JNIEXPORT void JNICALL
839 815 Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this,
840 816 jint cmd, jboolean on,
841 817 jobject value) {
842 818 int fd, fd1;
843 819 int level, optname, optlen;
844 820 union {
845 821 int i;
846 822 struct linger ling;
847 823 } optval;
848 824
849 825 /*
850 826 * Get SOCKET and check that it hasn't been closed
851 827 */
852 828 fd = getFD(env, this);
853 829 fd1 = getFD1(env, this);
854 830 if (fd < 0 && fd1 < 0) {
855 831 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
856 832 return;
857 833 }
858 834
859 835 /*
860 836 * SO_TIMEOUT is the socket option used to specify the timeout
861 837 * for ServerSocket.accept and Socket.getInputStream().read.
862 838 * It does not typically map to a native level socket option.
863 839 * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
864 840 * socket option to specify a receive timeout on the socket. This
865 841 * receive timeout is applicable to Socket only and the socket
866 842 * option should not be set on ServerSocket.
867 843 */
868 844 if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
869 845
870 846 /*
871 847 * Don't enable the socket option on ServerSocket as it's
872 848 * meaningless (we don't receive on a ServerSocket).
873 849 */
874 850 jobject ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
875 851 if (ssObj != NULL) {
876 852 return;
877 853 }
878 854
879 855 /*
880 856 * SO_RCVTIMEO is only supported on Microsoft's implementation
881 857 * of Windows Sockets so if WSAENOPROTOOPT returned then
882 858 * reset flag and timeout will be implemented using
883 859 * select() -- see SocketInputStream.socketRead.
884 860 */
885 861 if (isRcvTimeoutSupported) {
886 862 jclass iCls = (*env)->FindClass(env, "java/lang/Integer");
887 863 jfieldID i_valueID;
888 864 jint timeout;
889 865
890 866 CHECK_NULL(iCls);
891 867 i_valueID = (*env)->GetFieldID(env, iCls, "value", "I");
892 868 CHECK_NULL(i_valueID);
893 869 timeout = (*env)->GetIntField(env, value, i_valueID);
894 870
895 871 /*
896 872 * Disable SO_RCVTIMEO if timeout is <= 5 second.
897 873 */
898 874 if (timeout <= 5000) {
899 875 timeout = 0;
900 876 }
901 877
902 878 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
903 879 sizeof(timeout)) < 0) {
904 880 if (WSAGetLastError() == WSAENOPROTOOPT) {
905 881 isRcvTimeoutSupported = JNI_FALSE;
906 882 } else {
907 883 NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
908 884 }
909 885 }
910 886 if (fd1 != -1) {
911 887 if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
912 888 sizeof(timeout)) < 0) {
913 889 NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
914 890 }
915 891 }
916 892 }
917 893 return;
918 894 }
919 895
920 896 /*
921 897 * Map the Java level socket option to the platform specific
922 898 * level
923 899 */
924 900 if (NET_MapSocketOption(cmd, &level, &optname)) {
925 901 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
926 902 "Invalid option");
927 903 return;
928 904 }
929 905
930 906 switch (cmd) {
931 907
932 908 case java_net_SocketOptions_TCP_NODELAY :
933 909 case java_net_SocketOptions_SO_OOBINLINE :
934 910 case java_net_SocketOptions_SO_KEEPALIVE :
935 911 case java_net_SocketOptions_SO_REUSEADDR :
936 912 optval.i = (on ? 1 : 0);
937 913 optlen = sizeof(optval.i);
938 914 break;
939 915
940 916 case java_net_SocketOptions_SO_SNDBUF :
941 917 case java_net_SocketOptions_SO_RCVBUF :
942 918 case java_net_SocketOptions_IP_TOS :
943 919 {
944 920 jclass cls;
945 921 jfieldID fid;
946 922
947 923 cls = (*env)->FindClass(env, "java/lang/Integer");
948 924 CHECK_NULL(cls);
949 925 fid = (*env)->GetFieldID(env, cls, "value", "I");
950 926 CHECK_NULL(fid);
951 927
952 928 optval.i = (*env)->GetIntField(env, value, fid);
953 929 optlen = sizeof(optval.i);
954 930 }
955 931 break;
956 932
957 933 case java_net_SocketOptions_SO_LINGER :
958 934 {
959 935 jclass cls;
960 936 jfieldID fid;
961 937
962 938 cls = (*env)->FindClass(env, "java/lang/Integer");
963 939 CHECK_NULL(cls);
964 940 fid = (*env)->GetFieldID(env, cls, "value", "I");
965 941 CHECK_NULL(fid);
966 942
967 943 if (on) {
968 944 optval.ling.l_onoff = 1;
969 945 optval.ling.l_linger =
970 946 (unsigned short)(*env)->GetIntField(env, value, fid);
971 947 } else {
972 948 optval.ling.l_onoff = 0;
973 949 optval.ling.l_linger = 0;
974 950 }
975 951 optlen = sizeof(optval.ling);
976 952 }
977 953 break;
978 954
979 955 default: /* shouldn't get here */
980 956 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
981 957 "Option not supported by TwoStacksPlainSocketImpl");
982 958 return;
983 959 }
984 960
985 961 if (fd != -1) {
986 962 if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) {
987 963 NET_ThrowCurrent(env, "setsockopt");
988 964 }
989 965 }
990 966
991 967 if (fd1 != -1) {
992 968 if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) {
993 969 NET_ThrowCurrent(env, "setsockopt");
994 970 }
995 971 }
996 972 }
997 973
998 974
999 975 /*
1000 976 * Class: java_net_TwoStacksPlainSocketImpl
1001 977 * Method: socketGetOption
1002 978 * Signature: (I)I
1003 979 */
1004 980 JNIEXPORT jint JNICALL
1005 981 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
1006 982 jint opt, jobject iaContainerObj) {
1007 983
1008 984 int fd, fd1;
1009 985 int level, optname, optlen;
1010 986 union {
1011 987 int i;
1012 988 struct linger ling;
1013 989 } optval;
1014 990
1015 991 /*
1016 992 * Get SOCKET and check it hasn't been closed
1017 993 */
1018 994 fd = getFD(env, this);
1019 995 fd1 = getFD1(env, this);
1020 996
1021 997 if (fd < 0 && fd1 < 0) {
1022 998 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
1023 999 return -1;
1024 1000 }
1025 1001 if (fd < 0) {
1026 1002 fd = fd1;
1027 1003 }
1028 1004
1029 1005 /* For IPv6, we assume both sockets have the same setting always */
1030 1006
1031 1007 /*
1032 1008 * SO_BINDADDR isn't a socket option
1033 1009 */
1034 1010 if (opt == java_net_SocketOptions_SO_BINDADDR) {
1035 1011 SOCKET_ADDRESS him;
1036 1012 int len;
1037 1013 int port;
1038 1014 jobject iaObj;
1039 1015 jclass iaCntrClass;
1040 1016 jfieldID iaFieldID;
1041 1017
1042 1018 len = sizeof(struct sockaddr_in);
1043 1019
1044 1020 if (fd == -1) {
1045 1021 /* must be an IPV6 only socket. Case where both sockets are != -1
1046 1022 * is handled in java
1047 1023 */
1048 1024 fd = getFD1 (env, this);
1049 1025 len = sizeof(struct SOCKADDR_IN6);
1050 1026 }
1051 1027
1052 1028 if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
1053 1029 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1054 1030 "Error getting socket name");
1055 1031 return -1;
1056 1032 }
1057 1033 iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
1058 1034 CHECK_NULL_RETURN(iaObj, -1);
1059 1035
1060 1036 iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
1061 1037 iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
1062 1038 CHECK_NULL_RETURN(iaFieldID, -1);
1063 1039 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
1064 1040 return 0; /* notice change from before */
1065 1041 }
1066 1042
1067 1043 /*
1068 1044 * Map the Java level socket option to the platform specific
1069 1045 * level and option name.
1070 1046 */
1071 1047 if (NET_MapSocketOption(opt, &level, &optname)) {
1072 1048 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1073 1049 return -1;
1074 1050 }
1075 1051
1076 1052 /*
1077 1053 * Args are int except for SO_LINGER
1078 1054 */
1079 1055 if (opt == java_net_SocketOptions_SO_LINGER) {
1080 1056 optlen = sizeof(optval.ling);
1081 1057 } else {
1082 1058 optlen = sizeof(optval.i);
1083 1059 optval.i = 0;
1084 1060 }
1085 1061
1086 1062 if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
1087 1063 NET_ThrowCurrent(env, "getsockopt");
1088 1064 return -1;
1089 1065 }
1090 1066
1091 1067 switch (opt) {
1092 1068 case java_net_SocketOptions_SO_LINGER:
1093 1069 return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
1094 1070
1095 1071 case java_net_SocketOptions_SO_SNDBUF:
1096 1072 case java_net_SocketOptions_SO_RCVBUF:
1097 1073 case java_net_SocketOptions_IP_TOS:
1098 1074 return optval.i;
1099 1075
1100 1076 case java_net_SocketOptions_TCP_NODELAY :
1101 1077 case java_net_SocketOptions_SO_OOBINLINE :
1102 1078 case java_net_SocketOptions_SO_KEEPALIVE :
1103 1079 case java_net_SocketOptions_SO_REUSEADDR :
1104 1080 return (optval.i == 0) ? -1 : 1;
1105 1081
1106 1082 default: /* shouldn't get here */
1107 1083 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1108 1084 "Option not supported by TwoStacksPlainSocketImpl");
1109 1085 return -1;
1110 1086 }
1111 1087 }
1112 1088
1113 1089 /*
1114 1090 * Class: java_net_TwoStacksPlainSocketImpl
1115 1091 * Method: socketShutdown
1116 1092 * Signature: (I)V
1117 1093 */
1118 1094 JNIEXPORT void JNICALL
1119 1095 Java_java_net_TwoStacksPlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
1120 1096 jint howto)
1121 1097 {
1122 1098
1123 1099 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1124 1100 jint fd;
1125 1101
1126 1102 /*
1127 1103 * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
1128 1104 * -1 already?
1129 1105 */
1130 1106 if (IS_NULL(fdObj)) {
1131 1107 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1132 1108 "socket already closed");
1133 1109 return;
1134 1110 } else {
1135 1111 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1136 1112 }
1137 1113 shutdown(fd, howto);
1138 1114 }
1139 1115
1140 1116 /*
↓ open down ↓ |
384 lines elided |
↑ open up ↑ |
1141 1117 * Class: java_net_TwoStacksPlainSocketImpl
1142 1118 * Method: socketSendUrgentData
1143 1119 * Signature: (B)V
1144 1120 */
1145 1121 JNIEXPORT void JNICALL
1146 1122 Java_java_net_TwoStacksPlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this,
1147 1123 jint data) {
1148 1124 /* The fd field */
1149 1125 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1150 1126 int n, fd;
1151 - unsigned char d = data & 0xff;
1127 + unsigned char d = (unsigned char)data & 0xff;
1152 1128
1153 1129 if (IS_NULL(fdObj)) {
1154 1130 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1155 1131 return;
1156 1132 } else {
1157 1133 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1158 1134 /* Bug 4086704 - If the Socket associated with this file descriptor
1159 1135 * was closed (sysCloseFD), the the file descriptor is set to -1.
1160 1136 */
1161 1137 if (fd == -1) {
1162 1138 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1163 1139 return;
1164 1140 }
1165 1141
1166 1142 }
1167 1143 n = send(fd, (char *)&data, 1, MSG_OOB);
1168 1144 if (n == JVM_IO_ERR) {
1169 1145 NET_ThrowCurrent(env, "send");
1170 1146 return;
1171 1147 }
1172 1148 if (n == JVM_IO_INTR) {
1173 1149 JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
1174 1150 return;
1175 1151 }
1176 1152 }
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX