1 /* 2 * Copyright (c) 2000, 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 23 * questions. 24 */ 25 26 #include <windows.h> 27 #include <winsock2.h> 28 #include <ctype.h> 29 #include "jni.h" 30 #include "jni_util.h" 31 #include "jvm.h" 32 #include "jlong.h" 33 #include "sun_nio_ch_SocketDispatcher.h" 34 #include "nio.h" 35 #include "nio_util.h" 36 37 38 /************************************************************** 39 * SocketDispatcher.c 40 */ 41 42 JNIEXPORT jint JNICALL 43 Java_sun_nio_ch_SocketDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo, 44 jlong address, jint len) 45 { 46 /* set up */ 47 int i = 0; 48 DWORD read = 0; 49 DWORD flags = 0; 50 jint fd = fdval(env, fdo); 51 WSABUF buf; 52 53 /* limit size */ 54 if (len > MAX_BUFFER_SIZE) 55 len = MAX_BUFFER_SIZE; 56 57 /* destination buffer and size */ 58 buf.buf = (char *)address; 59 buf.len = (u_long)len; 60 61 /* read into the buffers */ 62 i = WSARecv((SOCKET)fd, /* Socket */ 63 &buf, /* pointers to the buffers */ 64 (DWORD)1, /* number of buffers to process */ 65 &read, /* receives number of bytes read */ 66 &flags, /* no flags */ 67 0, /* no overlapped sockets */ 68 0); /* no completion routine */ 69 70 if (i == SOCKET_ERROR) { 71 int theErr = (jint)WSAGetLastError(); 72 if (theErr == WSAEWOULDBLOCK) { 73 return IOS_UNAVAILABLE; 74 } 75 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 76 return IOS_THROWN; 77 } 78 79 if (read > 0) { 80 JVM_callNetworkReadBytes(env, (jint) read); 81 } 82 83 return convertReturnVal(env, (jint)read, JNI_TRUE); 84 } 85 86 JNIEXPORT jlong JNICALL 87 Java_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo, 88 jlong address, jint len) 89 { 90 /* set up */ 91 int i = 0; 92 DWORD read = 0; 93 DWORD flags = 0; 94 jint fd = fdval(env, fdo); 95 struct iovec *iovp = (struct iovec *)address; 96 WSABUF *bufs = malloc(len * sizeof(WSABUF)); 97 jint rem = MAX_BUFFER_SIZE; 98 99 if (bufs == 0) { 100 JNU_ThrowOutOfMemoryError(env, 0); 101 return IOS_THROWN; 102 } 103 104 /* copy iovec into WSABUF */ 105 for(i=0; i<len; i++) { 106 jint iov_len = iovp[i].iov_len; 107 if (iov_len > rem) 108 iov_len = rem; 109 bufs[i].buf = (char *)iovp[i].iov_base; 110 bufs[i].len = (u_long)iov_len; 111 rem -= iov_len; 112 if (rem == 0) { 113 len = i+1; 114 break; 115 } 116 } 117 118 /* read into the buffers */ 119 i = WSARecv((SOCKET)fd, /* Socket */ 120 bufs, /* pointers to the buffers */ 121 (DWORD)len, /* number of buffers to process */ 122 &read, /* receives number of bytes read */ 123 &flags, /* no flags */ 124 0, /* no overlapped sockets */ 125 0); /* no completion routine */ 126 127 /* clean up */ 128 free(bufs); 129 130 if (i != 0) { 131 int theErr = (jint)WSAGetLastError(); 132 if (theErr == WSAEWOULDBLOCK) { 133 return IOS_UNAVAILABLE; 134 } 135 JNU_ThrowIOExceptionWithLastError(env, "Vector read failed"); 136 return IOS_THROWN; 137 } 138 139 if (read > 0) { 140 JVM_callNetworkReadBytes(env, (jint) read); 141 } 142 143 return convertLongReturnVal(env, (jlong)read, JNI_TRUE); 144 } 145 146 JNIEXPORT jint JNICALL 147 Java_sun_nio_ch_SocketDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, 148 jlong address, jint total) 149 { 150 /* set up */ 151 int i = 0; 152 DWORD written = 0; 153 jint count = 0; 154 jint fd = fdval(env, fdo); 155 WSABUF buf; 156 157 do { 158 /* limit size */ 159 jint len = total - count; 160 if (len > MAX_BUFFER_SIZE) 161 len = MAX_BUFFER_SIZE; 162 163 /* copy iovec into WSABUF */ 164 buf.buf = (char *)address; 165 buf.len = (u_long)len; 166 167 /* write from the buffer */ 168 i = WSASend((SOCKET)fd, /* Socket */ 169 &buf, /* pointers to the buffers */ 170 (DWORD)1, /* number of buffers to process */ 171 &written, /* receives number of bytes written */ 172 0, /* no flags */ 173 0, /* no overlapped sockets */ 174 0); /* no completion routine */ 175 176 if (i == SOCKET_ERROR) { 177 if (count > 0) { 178 /* can't throw exception when some bytes have been written */ 179 break; 180 } else { 181 int theErr = (jint)WSAGetLastError(); 182 if (theErr == WSAEWOULDBLOCK) { 183 return IOS_UNAVAILABLE; 184 } 185 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 186 return IOS_THROWN; 187 } 188 } 189 190 if (written > 0) { 191 JVM_callFileWriteBytes(env, written); 192 } 193 194 count += (jint)written; 195 address += written; 196 197 } while ((count < total) && (written == MAX_BUFFER_SIZE)); 198 199 return count; 200 } 201 202 JNIEXPORT jlong JNICALL 203 Java_sun_nio_ch_SocketDispatcher_writev0(JNIEnv *env, jclass clazz, 204 jobject fdo, jlong address, jint len) 205 { 206 /* set up */ 207 int next_index, next_offset, ret=0; 208 DWORD written = 0; 209 jint fd = fdval(env, fdo); 210 struct iovec *iovp = (struct iovec *)address; 211 WSABUF *bufs = malloc(len * sizeof(WSABUF)); 212 jlong count = 0; 213 214 if (bufs == 0) { 215 JNU_ThrowOutOfMemoryError(env, 0); 216 return IOS_THROWN; 217 } 218 219 // next buffer and offset to consume 220 next_index = 0; 221 next_offset = 0; 222 223 while (next_index < len) { 224 DWORD buf_count = 0; 225 226 /* Prepare the WSABUF array to a maximum total size of MAX_BUFFER_SIZE */ 227 jint rem = MAX_BUFFER_SIZE; 228 while (next_index < len && rem > 0) { 229 jint iov_len = iovp[next_index].iov_len - next_offset; 230 char* ptr = (char *)iovp[next_index].iov_base; 231 ptr += next_offset; 232 if (iov_len > rem) { 233 iov_len = rem; 234 next_offset += rem; 235 } else { 236 next_index ++; 237 next_offset = 0; 238 } 239 240 bufs[buf_count].buf = ptr; 241 bufs[buf_count].len = (u_long)iov_len; 242 buf_count++; 243 244 rem -= iov_len; 245 } 246 247 /* write the buffers */ 248 ret = WSASend((SOCKET)fd, /* Socket */ 249 bufs, /* pointers to the buffers */ 250 buf_count, /* number of buffers to process */ 251 &written, /* receives number of bytes written */ 252 0, /* no flags */ 253 0, /* no overlapped sockets */ 254 0); /* no completion routine */ 255 256 if (ret == SOCKET_ERROR) { 257 break; 258 } 259 260 count += written; 261 } 262 263 /* clean up */ 264 free(bufs); 265 266 if (ret == SOCKET_ERROR && count == 0) { 267 int theErr = (jint)WSAGetLastError(); 268 if (theErr == WSAEWOULDBLOCK) { 269 return IOS_UNAVAILABLE; 270 } 271 JNU_ThrowIOExceptionWithLastError(env, "Vector write failed"); 272 return IOS_THROWN; 273 } 274 275 if (count > 0) { 276 JVM_callFileWriteBytes(env, (jint) count); 277 } 278 279 return convertLongReturnVal(env, count, JNI_FALSE); 280 } 281 282 JNIEXPORT void JNICALL 283 Java_sun_nio_ch_SocketDispatcher_preClose0(JNIEnv *env, jclass clazz, 284 jobject fdo) 285 { 286 jint fd = fdval(env, fdo); 287 struct linger l; 288 int len = sizeof(l); 289 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) { 290 if (l.l_onoff == 0) { 291 shutdown(fd, SD_SEND); 292 } 293 } 294 } 295 296 JNIEXPORT void JNICALL 297 Java_sun_nio_ch_SocketDispatcher_close0(JNIEnv *env, jclass clazz, 298 jobject fdo) 299 { 300 jint fd = fdval(env, fdo); 301 if (closesocket(fd) == SOCKET_ERROR) { 302 JNU_ThrowIOExceptionWithLastError(env, "Socket close failed"); 303 } 304 }