1 /* 2 * Copyright (c) 2000, 2010, 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 if ((isNT() == JNI_FALSE) && (len > 16)) { 101 len = 16; 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 return convertLongReturnVal(env, (jlong)read, JNI_TRUE); 140 } 141 142 JNIEXPORT jint JNICALL 143 Java_sun_nio_ch_SocketDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, 144 jlong address, jint len) 145 { 146 /* set up */ 147 int i = 0; 148 DWORD written = 0; 149 jint fd = fdval(env, fdo); 150 WSABUF buf; 151 152 /* limit size */ 153 if (len > MAX_BUFFER_SIZE) 154 len = MAX_BUFFER_SIZE; 155 156 /* copy iovec into WSABUF */ 157 buf.buf = (char *)address; 158 buf.len = (u_long)len; 159 160 /* read into the buffers */ 161 i = WSASend((SOCKET)fd, /* Socket */ 162 &buf, /* pointers to the buffers */ 163 (DWORD)1, /* number of buffers to process */ 164 &written, /* receives number of bytes written */ 165 0, /* no flags */ 166 0, /* no overlapped sockets */ 167 0); /* no completion routine */ 168 169 if (i == SOCKET_ERROR) { 170 int theErr = (jint)WSAGetLastError(); 171 if (theErr == WSAEWOULDBLOCK) { 172 return IOS_UNAVAILABLE; 173 } 174 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 175 return IOS_THROWN; 176 } 177 178 return convertReturnVal(env, (jint)written, JNI_FALSE); 179 } 180 181 JNIEXPORT jlong JNICALL 182 Java_sun_nio_ch_SocketDispatcher_writev0(JNIEnv *env, jclass clazz, 183 jobject fdo, jlong address, jint len) 184 { 185 /* set up */ 186 int i = 0; 187 DWORD written = 0; 188 jint fd = fdval(env, fdo); 189 struct iovec *iovp = (struct iovec *)address; 190 WSABUF *bufs = malloc(len * sizeof(WSABUF)); 191 jint rem = MAX_BUFFER_SIZE; 192 193 if (bufs == 0) { 194 JNU_ThrowOutOfMemoryError(env, 0); 195 return IOS_THROWN; 196 } 197 198 if ((isNT() == JNI_FALSE) && (len > 16)) { 199 len = 16; 200 } 201 202 /* copy iovec into WSABUF */ 203 for(i=0; i<len; i++) { 204 jint iov_len = iovp[i].iov_len; 205 if (iov_len > rem) 206 iov_len = rem; 207 bufs[i].buf = (char *)iovp[i].iov_base; 208 bufs[i].len = (u_long)iov_len; 209 rem -= iov_len; 210 if (rem == 0) { 211 len = i+1; 212 break; 213 } 214 } 215 216 /* read into the buffers */ 217 i = WSASend((SOCKET)fd, /* Socket */ 218 bufs, /* pointers to the buffers */ 219 (DWORD)len, /* number of buffers to process */ 220 &written, /* receives number of bytes written */ 221 0, /* no flags */ 222 0, /* no overlapped sockets */ 223 0); /* no completion routine */ 224 225 /* clean up */ 226 free(bufs); 227 228 if (i != 0) { 229 int theErr = (jint)WSAGetLastError(); 230 if (theErr == WSAEWOULDBLOCK) { 231 return IOS_UNAVAILABLE; 232 } 233 JNU_ThrowIOExceptionWithLastError(env, "Vector write failed"); 234 return IOS_THROWN; 235 } 236 237 return convertLongReturnVal(env, (jlong)written, JNI_FALSE); 238 } 239 240 JNIEXPORT void JNICALL 241 Java_sun_nio_ch_SocketDispatcher_close0(JNIEnv *env, jclass clazz, 242 jobject fdo) 243 { 244 jint fd = fdval(env, fdo); 245 struct linger l; 246 int len = sizeof(l); 247 248 if (fd != -1) { 249 int result = 0; 250 if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) { 251 if (l.l_onoff == 0) { 252 WSASendDisconnect(fd, NULL); 253 } 254 } 255 result = closesocket(fd); 256 if (result == SOCKET_ERROR) { 257 JNU_ThrowIOExceptionWithLastError(env, "Socket close failed"); 258 } 259 } 260 }