1 /*
   2  * Copyright (c) 2002, 2003, 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 /*
  27  */
  28 
  29 #include <windows.h>
  30 #include <winsock2.h>
  31 #include <ctype.h>
  32 #include "jni.h"
  33 #include "jni_util.h"
  34 #include "jvm.h"
  35 #include "jlong.h"
  36 #include "sun_nio_ch_DatagramDispatcher.h"
  37 
  38 #include "nio.h"
  39 #include "nio_util.h"
  40 
  41 
  42 /**************************************************************
  43  * DatagramDispatcher.c
  44  */
  45 
  46 JNIEXPORT jint JNICALL
  47 Java_sun_nio_ch_DatagramDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo,
  48                                       jlong address, jint len)
  49 {
  50     /* set up */
  51     int i = 0;
  52     DWORD read = 0;
  53     DWORD flags = 0;
  54     jint fd = fdval(env, fdo);
  55     WSABUF buf;
  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         if (theErr == WSAECONNRESET) {
  76             purgeOutstandingICMP(env, clazz, fd);
  77             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
  78             return IOS_THROWN;
  79         }
  80         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
  81         return IOS_THROWN;
  82     }
  83 
  84     return convertReturnVal(env, (jint)read, JNI_TRUE);
  85 }
  86 
  87 JNIEXPORT jlong JNICALL
  88 Java_sun_nio_ch_DatagramDispatcher_readv0(JNIEnv *env, jclass clazz,
  89                                           jobject fdo, jlong address, jint len)
  90 {
  91     /* set up */
  92     int i = 0;
  93     DWORD read = 0;
  94     DWORD flags = 0;
  95     jint fd = fdval(env, fdo);
  96     struct iovec *iovp = (struct iovec *)address;
  97     WSABUF *bufs = malloc(len * sizeof(WSABUF));
  98 
  99     /* copy iovec into WSABUF */
 100     for(i=0; i<len; i++) {
 101         bufs[i].buf = (char *)iovp[i].iov_base;
 102         bufs[i].len = (u_long)iovp[i].iov_len;
 103     }
 104 
 105     /* read into the buffers */
 106     i = WSARecv((SOCKET)fd, /* Socket */
 107             bufs,           /* pointers to the buffers */
 108             (DWORD)len,     /* number of buffers to process */
 109             &read,          /* receives number of bytes read */
 110             &flags,         /* no flags */
 111             0,              /* no overlapped sockets */
 112             0);             /* no completion routine */
 113 
 114     /* clean up */
 115     free(bufs);
 116 
 117     if (i != 0) {
 118         int theErr = (jint)WSAGetLastError();
 119         if (theErr == WSAEWOULDBLOCK) {
 120             return IOS_UNAVAILABLE;
 121         }
 122         if (theErr == WSAECONNRESET) {
 123             purgeOutstandingICMP(env, clazz, fd);
 124             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
 125             return IOS_THROWN;
 126         }
 127         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
 128         return IOS_THROWN;
 129     }
 130 
 131     return convertLongReturnVal(env, (jlong)read, JNI_TRUE);
 132 }
 133 
 134 
 135 JNIEXPORT jint JNICALL
 136 Java_sun_nio_ch_DatagramDispatcher_write0(JNIEnv *env, jclass clazz,
 137                                           jobject fdo, jlong address, jint len)
 138 {
 139     /* set up */
 140     int i = 0;
 141     DWORD written = 0;
 142     jint fd = fdval(env, fdo);
 143     WSABUF buf;
 144 
 145     /* copy iovec into WSABUF */
 146     buf.buf = (char *)address;
 147     buf.len = (u_long)len;
 148 
 149     /* read into the buffers */
 150     i = WSASend((SOCKET)fd, /* Socket */
 151             &buf,           /* pointers to the buffers */
 152             (DWORD)1,       /* number of buffers to process */
 153             &written,       /* receives number of bytes written */
 154             0,              /* no flags */
 155             0,              /* no overlapped sockets */
 156             0);             /* no completion routine */
 157 
 158     if (i == SOCKET_ERROR) {
 159         int theErr = (jint)WSAGetLastError();
 160         if (theErr == WSAEWOULDBLOCK) {
 161             return IOS_UNAVAILABLE;
 162         }
 163         if (theErr == WSAECONNRESET) {
 164             purgeOutstandingICMP(env, clazz, fd);
 165             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
 166             return IOS_THROWN;
 167         }
 168         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
 169         return IOS_THROWN;
 170     }
 171 
 172     return convertReturnVal(env, (jint)written, JNI_FALSE);
 173 }
 174 
 175 JNIEXPORT jlong JNICALL
 176 Java_sun_nio_ch_DatagramDispatcher_writev0(JNIEnv *env, jclass clazz,
 177                                          jobject fdo, jlong address, jint len)
 178 {
 179     /* set up */
 180     int i = 0;
 181     DWORD written = 0;
 182     jint fd = fdval(env, fdo);
 183     struct iovec *iovp = (struct iovec *)address;
 184     WSABUF *bufs = malloc(len * sizeof(WSABUF));
 185 
 186     /* copy iovec into WSABUF */
 187     for(i=0; i<len; i++) {
 188         bufs[i].buf = (char *)iovp[i].iov_base;
 189         bufs[i].len = (u_long)iovp[i].iov_len;
 190     }
 191 
 192     /* read into the buffers */
 193     i = WSASend((SOCKET)fd, /* Socket */
 194             bufs,           /* pointers to the buffers */
 195             (DWORD)len,     /* number of buffers to process */
 196             &written,       /* receives number of bytes written */
 197             0,              /* no flags */
 198             0,              /* no overlapped sockets */
 199             0);             /* no completion routine */
 200 
 201     /* clean up */
 202     free(bufs);
 203 
 204     if (i != 0) {
 205         int theErr = (jint)WSAGetLastError();
 206         if (theErr == WSAEWOULDBLOCK) {
 207             return IOS_UNAVAILABLE;
 208         }
 209         if (theErr == WSAECONNRESET) {
 210             purgeOutstandingICMP(env, clazz, fd);
 211             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
 212             return IOS_THROWN;
 213         }
 214         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
 215         return IOS_THROWN;
 216     }
 217 
 218     return convertLongReturnVal(env, (jlong)written, JNI_FALSE);
 219 }