249 } else {
250 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
251 }
252 if (IS_NULL(iaObj)) {
253 JNU_ThrowNullPointerException(env, "inet address argument null.");
254 return;
255 }
256
257 /* connect */
258 if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
259 JNI_TRUE) != 0) {
260 return;
261 }
262
263 if (trafficClass != 0 && ipv6_available()) {
264 NET_SetTrafficClass(&sa, trafficClass);
265 }
266
267 if (timeout <= 0) {
268 connect_rv = NET_Connect(fd, &sa.sa, len);
269 #ifdef __solaris__
270 if (connect_rv == -1 && errno == EINPROGRESS ) {
271
272 /* This can happen if a blocking connect is interrupted by a signal.
273 * See 6343810.
274 */
275 while (1) {
276 struct pollfd pfd;
277 pfd.fd = fd;
278 pfd.events = POLLOUT;
279
280 connect_rv = NET_Poll(&pfd, 1, -1);
281
282 if (connect_rv == -1) {
283 if (errno == EINTR) {
284 continue;
285 } else {
286 break;
287 }
288 }
289 if (connect_rv > 0) {
290 socklen_t optlen;
291 /* has connection been established */
292 optlen = sizeof(connect_rv);
293 if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
294 (void*)&connect_rv, &optlen) <0) {
295 connect_rv = errno;
296 }
297
298 if (connect_rv != 0) {
299 /* restore errno */
300 errno = connect_rv;
301 connect_rv = -1;
302 }
303 break;
304 }
305 }
306 }
307 #endif
308 } else {
309 /*
310 * A timeout was specified. We put the socket into non-blocking
311 * mode, connect, and then wait for the connection to be
312 * established, fail, or timeout.
313 */
314 SET_NONBLOCKING(fd);
315
316 /* no need to use NET_Connect as non-blocking */
317 connect_rv = connect(fd, &sa.sa, len);
318
319 /* connection not established immediately */
320 if (connect_rv != 0) {
321 socklen_t optlen;
322 jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
323 jlong prevNanoTime = JVM_NanoTime(env, 0);
324
325 if (errno != EINPROGRESS) {
326 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
327 "connect failed");
876 optval.ling.l_onoff = 0;
877 optval.ling.l_linger = 0;
878 }
879 optlen = sizeof(optval.ling);
880 } else {
881 optval.i = (*env)->GetIntField(env, value, fid);
882 optlen = sizeof(optval.i);
883 }
884
885 break;
886 }
887
888 /* Boolean -> int */
889 default :
890 optval.i = (on ? 1 : 0);
891 optlen = sizeof(optval.i);
892
893 }
894
895 if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
896 #if defined(__solaris__) || defined(_AIX)
897 if (errno == EINVAL) {
898 // On Solaris setsockopt will set errno to EINVAL if the socket
899 // is closed. The default error message is then confusing
900 char fullMsg[128];
901 jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
902 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
903 return;
904 }
905 #endif /* __solaris__ */
906 JNU_ThrowByNameWithMessageAndLastError
907 (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
908 }
909 }
910
911 /*
912 * Class: java_net_PlainSocketImpl
913 * Method: socketGetOption
914 * Signature: (ILjava/lang/Object;)I
915 */
916 JNIEXPORT jint JNICALL
917 Java_java_net_PlainSocketImpl_socketGetOption
918 (JNIEnv *env, jobject this, jint cmd, jobject iaContainerObj)
919 {
920 int fd;
921 int level, optname, optlen;
922 union {
923 int i;
924 struct linger ling;
925 } optval;
|
249 } else {
250 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
251 }
252 if (IS_NULL(iaObj)) {
253 JNU_ThrowNullPointerException(env, "inet address argument null.");
254 return;
255 }
256
257 /* connect */
258 if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
259 JNI_TRUE) != 0) {
260 return;
261 }
262
263 if (trafficClass != 0 && ipv6_available()) {
264 NET_SetTrafficClass(&sa, trafficClass);
265 }
266
267 if (timeout <= 0) {
268 connect_rv = NET_Connect(fd, &sa.sa, len);
269 } else {
270 /*
271 * A timeout was specified. We put the socket into non-blocking
272 * mode, connect, and then wait for the connection to be
273 * established, fail, or timeout.
274 */
275 SET_NONBLOCKING(fd);
276
277 /* no need to use NET_Connect as non-blocking */
278 connect_rv = connect(fd, &sa.sa, len);
279
280 /* connection not established immediately */
281 if (connect_rv != 0) {
282 socklen_t optlen;
283 jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
284 jlong prevNanoTime = JVM_NanoTime(env, 0);
285
286 if (errno != EINPROGRESS) {
287 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
288 "connect failed");
837 optval.ling.l_onoff = 0;
838 optval.ling.l_linger = 0;
839 }
840 optlen = sizeof(optval.ling);
841 } else {
842 optval.i = (*env)->GetIntField(env, value, fid);
843 optlen = sizeof(optval.i);
844 }
845
846 break;
847 }
848
849 /* Boolean -> int */
850 default :
851 optval.i = (on ? 1 : 0);
852 optlen = sizeof(optval.i);
853
854 }
855
856 if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
857 #if defined(_AIX)
858 if (errno == EINVAL) {
859 // On Solaris setsockopt will set errno to EINVAL if the socket
860 // is closed. The default error message is then confusing
861 char fullMsg[128];
862 jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
863 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
864 return;
865 }
866 #endif /* _AIX */
867 JNU_ThrowByNameWithMessageAndLastError
868 (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
869 }
870 }
871
872 /*
873 * Class: java_net_PlainSocketImpl
874 * Method: socketGetOption
875 * Signature: (ILjava/lang/Object;)I
876 */
877 JNIEXPORT jint JNICALL
878 Java_java_net_PlainSocketImpl_socketGetOption
879 (JNIEnv *env, jobject this, jint cmd, jobject iaContainerObj)
880 {
881 int fd;
882 int level, optname, optlen;
883 union {
884 int i;
885 struct linger ling;
886 } optval;
|