1 /* 2 * Copyright (c) 2000, 2017, 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 return convertReturnVal(env, (jint)read, JNI_TRUE); 80 } 81 82 JNIEXPORT jlong JNICALL 83 Java_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo, 84 jlong address, jint len) 85 { 86 /* set up */ 87 int i = 0; 88 DWORD read = 0; 89 DWORD flags = 0; 90 jint fd = fdval(env, fdo); 91 struct iovec *iovp = (struct iovec *)address; 92 WSABUF *bufs = malloc(len * sizeof(WSABUF)); 93 jint rem = MAX_BUFFER_SIZE; 94 95 if (bufs == 0) { 96 JNU_ThrowOutOfMemoryError(env, 0); 97 return IOS_THROWN; 98 } 99 100 /* copy iovec into WSABUF */ 101 for(i=0; i<len; i++) { 102 jint iov_len = iovp[i].iov_len; 103 if (iov_len > rem) 104 iov_len = rem; 105 bufs[i].buf = (char *)iovp[i].iov_base; 106 bufs[i].len = (u_long)iov_len; 107 rem -= iov_len; 108 if (rem == 0) { 109 len = i+1; 110 break; 111 } 112 } 113 114 /* read into the buffers */ 115 i = WSARecv((SOCKET)fd, /* Socket */ 116 bufs, /* pointers to the buffers */ 117 (DWORD)len, /* number of buffers to process */ 118 &read, /* receives number of bytes read */ 119 &flags, /* no flags */ 120 0, /* no overlapped sockets */ 121 0); /* no completion routine */ 122 123 /* clean up */ 124 free(bufs); 125 126 if (i != 0) { 127 int theErr = (jint)WSAGetLastError(); 128 if (theErr == WSAEWOULDBLOCK) { 129 return IOS_UNAVAILABLE; 130 } 131 JNU_ThrowIOExceptionWithLastError(env, "Vector read failed"); 132 return IOS_THROWN; 133 } 134 135 return convertLongReturnVal(env, (jlong)read, JNI_TRUE); 136 } 137 138 JNIEXPORT jint JNICALL 139 Java_sun_nio_ch_SocketDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, 140 jlong address, jint total) 141 { 142 /* set up */ 143 int i = 0; 144 DWORD written = 0; 145 jint count = 0; 146 jint fd = fdval(env, fdo); 147 WSABUF buf; 148 149 do { 150 /* limit size */ 151 jint len = total - count; 152 if (len > MAX_BUFFER_SIZE) 153 len = MAX_BUFFER_SIZE; 154 155 /* copy iovec into WSABUF */ 156 buf.buf = (char *)address; 157 buf.len = (u_long)len; 158 159 /* write from the buffer */ 160 i = WSASend((SOCKET)fd, /* Socket */ 161 &buf, /* pointers to the buffers */ 162 (DWORD)1, /* number of buffers to process */ 163 &written, /* receives number of bytes written */ 164 0, /* no flags */ 165 0, /* no overlapped sockets */ 166 0); /* no completion routine */ 167 168 if (i == SOCKET_ERROR) { 169 if (count > 0) { 170 /* can't throw exception when some bytes have been written */ 171 break; 172 } else { 173 int theErr = (jint)WSAGetLastError(); 174 if (theErr == WSAEWOULDBLOCK) { 175 return IOS_UNAVAILABLE; 176 } 177 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 178 return IOS_THROWN; 179 } 180 } 181 182 count += (jint)written; 183 address += written; 184 185 } while ((count < total) && (written == MAX_BUFFER_SIZE)); 186 187 return count; 188 } 189 190 JNIEXPORT jlong JNICALL 191 Java_sun_nio_ch_SocketDispatcher_writev0(JNIEnv *env, jclass clazz, 192 jobject fdo, jlong address, jint len) 193 { 194 /* set up */ 195 int next_index, next_offset, ret=0; 196 DWORD written = 0; 197 jint fd = fdval(env, fdo); 198 struct iovec *iovp = (struct iovec *)address; 199 WSABUF *bufs = malloc(len * sizeof(WSABUF)); 200 jlong count = 0; 201 202 if (bufs == 0) { 203 JNU_ThrowOutOfMemoryError(env, 0); 204 return IOS_THROWN; 205 } 206 207 // next buffer and offset to consume 208 next_index = 0; 209 next_offset = 0; 210 211 while (next_index < len) { 212 DWORD buf_count = 0; 213 214 /* Prepare the WSABUF array to a maximum total size of MAX_BUFFER_SIZE */ 215 jint rem = MAX_BUFFER_SIZE; 216 while (next_index < len && rem > 0) { 217 jint iov_len = iovp[next_index].iov_len - next_offset; 218 char* ptr = (char *)iovp[next_index].iov_base; 219 ptr += next_offset; 220 if (iov_len > rem) { 221 iov_len = rem; 222 next_offset += rem; 223 } else { 224 next_index ++; 225 next_offset = 0; 226 } 227 228 bufs[buf_count].buf = ptr; 229 bufs[buf_count].len = (u_long)iov_len; 230 buf_count++; 231 232 rem -= iov_len; 233 } 234 235 /* write the buffers */ 236 ret = WSASend((SOCKET)fd, /* Socket */ 237 bufs, /* pointers to the buffers */ 238 buf_count, /* number of buffers to process */ 239 &written, /* receives number of bytes written */ 240 0, /* no flags */ 241 0, /* no overlapped sockets */ 242 0); /* no completion routine */ 243 244 if (ret == SOCKET_ERROR) { 245 break; 246 } 247 248 count += written; 249 } 250 251 /* clean up */ 252 free(bufs); 253 254 if (ret == SOCKET_ERROR && count == 0) { 255 int theErr = (jint)WSAGetLastError(); 256 if (theErr == WSAEWOULDBLOCK) { 257 return IOS_UNAVAILABLE; 258 } 259 JNU_ThrowIOExceptionWithLastError(env, "Vector write failed"); 260 return IOS_THROWN; 261 } 262 263 return convertLongReturnVal(env, count, JNI_FALSE); 264 } 265 266 JNIEXPORT void JNICALL 267 Java_sun_nio_ch_SocketDispatcher_preClose0(JNIEnv *env, jclass clazz, 268 jobject fdo) 269 { 270 jint fd = fdval(env, fdo); 271 struct linger l; 272 int len = sizeof(l); 273 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) { 274 if (l.l_onoff == 0) { 275 WSASendDisconnect(fd, NULL); 276 } 277 } 278 } 279 280 JNIEXPORT void JNICALL 281 Java_sun_nio_ch_SocketDispatcher_close0(JNIEnv *env, jclass clazz, 282 jobject fdo) 283 { 284 jint fd = fdval(env, fdo); 285 if (closesocket(fd) == SOCKET_ERROR) { 286 JNU_ThrowIOExceptionWithLastError(env, "Socket close failed"); 287 } 288 }