1 /* 2 * Copyright (c) 2000, 2012, 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 23 * questions. 24 */ 25 26 #include <windows.h> 27 #include <winsock2.h> 28 #include <io.h> 29 #include "jni.h" 30 #include "jni_util.h" 31 #include "jvm.h" 32 #include "jlong.h" 33 34 #include "nio.h" 35 #include "nio_util.h" 36 #include "net_util.h" 37 #include "sun_nio_ch_IOUtil.h" 38 39 /* field id for jlong 'handle' in java.io.FileDescriptor used for file fds */ 40 static jfieldID handle_fdID; 41 42 /* field id for jint 'fd' in java.io.FileDescriptor used for socket fds */ 43 static jfieldID fd_fdID; 44 45 JNIEXPORT jboolean JNICALL 46 Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed 47 (JNIEnv *env, jclass clazz, jbyteArray randArray); 48 49 /************************************************************** 50 * static method to store field IDs in initializers 51 */ 52 53 JNIEXPORT void JNICALL 54 Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) 55 { 56 CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); 57 CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); 58 CHECK_NULL(handle_fdID = (*env)->GetFieldID(env, clazz, "handle", "J")); 59 initInetAddressIDs(env); 60 } 61 62 /************************************************************** 63 * IOUtil.c 64 */ 65 JNIEXPORT jboolean JNICALL 66 Java_sun_nio_ch_IOUtil_randomBytes(JNIEnv *env, jclass clazz, 67 jbyteArray randArray) 68 { 69 return 70 Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed(env, 71 clazz, 72 randArray); 73 } 74 75 JNIEXPORT jint JNICALL 76 Java_sun_nio_ch_IOUtil_iovMax(JNIEnv *env, jclass this) 77 { 78 return 16; 79 } 80 81 82 jint 83 convertReturnVal(JNIEnv *env, jint n, jboolean reading) 84 { 85 if (n > 0) /* Number of bytes written */ 86 return n; 87 if (n == 0) { 88 if (reading) { 89 return IOS_EOF; /* EOF is -1 in javaland */ 90 } else { 91 return 0; 92 } 93 } 94 JNU_ThrowIOExceptionWithLastError(env, "Read/write failed"); 95 return IOS_THROWN; 96 } 97 98 jlong 99 convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading) 100 { 101 if (n > 0) /* Number of bytes written */ 102 return n; 103 if (n == 0) { 104 if (reading) { 105 return IOS_EOF; /* EOF is -1 in javaland */ 106 } else { 107 return 0; 108 } 109 } 110 JNU_ThrowIOExceptionWithLastError(env, "Read/write failed"); 111 return IOS_THROWN; 112 } 113 114 JNIEXPORT jint JNICALL 115 Java_sun_nio_ch_IOUtil_fdVal(JNIEnv *env, jclass clazz, jobject fdo) 116 { 117 return fdval(env, fdo); 118 } 119 120 JNIEXPORT void JNICALL 121 Java_sun_nio_ch_IOUtil_setfdVal(JNIEnv *env, jclass clazz, jobject fdo, jint val) 122 { 123 (*env)->SetIntField(env, fdo, fd_fdID, val); 124 } 125 126 127 #define SET_BLOCKING 0 128 #define SET_NONBLOCKING 1 129 130 JNIEXPORT void JNICALL 131 Java_sun_nio_ch_IOUtil_configureBlocking(JNIEnv *env, jclass clazz, 132 jobject fdo, jboolean blocking) 133 { 134 u_long argp; 135 int result = 0; 136 jint fd = fdval(env, fdo); 137 138 if (blocking == JNI_FALSE) { 139 argp = SET_NONBLOCKING; 140 } else { 141 argp = SET_BLOCKING; 142 /* Blocking fd cannot be registered with EventSelect */ 143 WSAEventSelect(fd, NULL, 0); 144 } 145 result = ioctlsocket(fd, FIONBIO, &argp); 146 if (result == SOCKET_ERROR) { 147 int error = WSAGetLastError(); 148 handleSocketError(env, (jint)error); 149 } 150 } 151 152 /* Note: Drain uses the int fd value. It is currently not called 153 on windows. 154 */ 155 JNIEXPORT jboolean JNICALL 156 Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd) 157 { 158 DWORD read = 0; 159 int totalRead = 0; 160 BOOL result = 0; 161 HANDLE h = (HANDLE)_get_osfhandle(fd); 162 char buf[128]; 163 164 if (h == INVALID_HANDLE_VALUE) { 165 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 166 return JNI_FALSE; 167 } 168 169 for (;;) { 170 result = ReadFile(h, /* File handle to read */ 171 (LPVOID)&buf, /* address to put data */ 172 128, /* number of bytes to read */ 173 &read, /* number of bytes read */ 174 NULL); /* no overlapped struct */ 175 176 if (result == 0) { 177 int error = GetLastError(); 178 if (error == ERROR_NO_DATA) { 179 return (totalRead > 0) ? JNI_TRUE : JNI_FALSE; 180 } 181 JNU_ThrowIOExceptionWithLastError(env, "Drain"); 182 return JNI_FALSE; 183 } 184 if (read > 0) { 185 totalRead += read; 186 } else { 187 break; 188 } 189 } 190 return (totalRead > 0) ? JNI_TRUE : JNI_FALSE; 191 } 192 193 /* Note: This function returns the int fd value from file descriptor. 194 It is mostly used for sockets which should use the int fd value. 195 */ 196 jint 197 fdval(JNIEnv *env, jobject fdo) 198 { 199 return (*env)->GetIntField(env, fdo, fd_fdID); 200 } 201 202 jlong 203 handleval(JNIEnv *env, jobject fdo) 204 { 205 return (*env)->GetLongField(env, fdo, handle_fdID); 206 }