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 }