Path: blob/master/src/java.base/windows/native/libnio/ch/SocketDispatcher.c
41134 views
/*1* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <windows.h>26#include <winsock2.h>27#include <ctype.h>28#include "jni.h"29#include "jni_util.h"30#include "jvm.h"31#include "jlong.h"32#include "sun_nio_ch_SocketDispatcher.h"33#include "nio.h"34#include "nio_util.h"353637/**************************************************************38* SocketDispatcher.c39*/4041JNIEXPORT jint JNICALL42Java_sun_nio_ch_SocketDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo,43jlong address, jint len)44{45/* set up */46int i = 0;47DWORD read = 0;48DWORD flags = 0;49jint fd = fdval(env, fdo);50WSABUF buf;5152/* limit size */53if (len > MAX_BUFFER_SIZE)54len = MAX_BUFFER_SIZE;5556/* destination buffer and size */57buf.buf = (char *)address;58buf.len = (u_long)len;5960/* read into the buffers */61i = WSARecv((SOCKET)fd, /* Socket */62&buf, /* pointers to the buffers */63(DWORD)1, /* number of buffers to process */64&read, /* receives number of bytes read */65&flags, /* no flags */660, /* no overlapped sockets */670); /* no completion routine */6869if (i == SOCKET_ERROR) {70int theErr = (jint)WSAGetLastError();71if (theErr == WSAEWOULDBLOCK) {72return IOS_UNAVAILABLE;73}74if (theErr == WSAECONNRESET) {75JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");76} else {77JNU_ThrowIOExceptionWithLastError(env, "Read failed");78}79return IOS_THROWN;80}8182return convertReturnVal(env, (jint)read, JNI_TRUE);83}8485JNIEXPORT jlong JNICALL86Java_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo,87jlong address, jint len)88{89/* set up */90int i = 0;91DWORD read = 0;92DWORD flags = 0;93jint fd = fdval(env, fdo);94struct iovec *iovp = (struct iovec *)address;95WSABUF *bufs = malloc(len * sizeof(WSABUF));96jint rem = MAX_BUFFER_SIZE;9798if (bufs == 0) {99JNU_ThrowOutOfMemoryError(env, 0);100return IOS_THROWN;101}102103/* copy iovec into WSABUF */104for(i=0; i<len; i++) {105jint iov_len = iovp[i].iov_len;106if (iov_len > rem)107iov_len = rem;108bufs[i].buf = (char *)iovp[i].iov_base;109bufs[i].len = (u_long)iov_len;110rem -= iov_len;111if (rem == 0) {112len = i+1;113break;114}115}116117/* read into the buffers */118i = WSARecv((SOCKET)fd, /* Socket */119bufs, /* pointers to the buffers */120(DWORD)len, /* number of buffers to process */121&read, /* receives number of bytes read */122&flags, /* no flags */1230, /* no overlapped sockets */1240); /* no completion routine */125126/* clean up */127free(bufs);128129if (i != 0) {130int theErr = (jint)WSAGetLastError();131if (theErr == WSAEWOULDBLOCK) {132return IOS_UNAVAILABLE;133}134if (theErr == WSAECONNRESET) {135JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");136} else {137JNU_ThrowIOExceptionWithLastError(env, "Vector read failed");138}139return IOS_THROWN;140}141142return convertLongReturnVal(env, (jlong)read, JNI_TRUE);143}144145JNIEXPORT jint JNICALL146Java_sun_nio_ch_SocketDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo,147jlong address, jint total)148{149/* set up */150int i = 0;151DWORD written = 0;152jint count = 0;153jint fd = fdval(env, fdo);154WSABUF buf;155156do {157/* limit size */158jint len = total - count;159if (len > MAX_BUFFER_SIZE)160len = MAX_BUFFER_SIZE;161162/* copy iovec into WSABUF */163buf.buf = (char *)address;164buf.len = (u_long)len;165166/* write from the buffer */167i = WSASend((SOCKET)fd, /* Socket */168&buf, /* pointers to the buffers */169(DWORD)1, /* number of buffers to process */170&written, /* receives number of bytes written */1710, /* no flags */1720, /* no overlapped sockets */1730); /* no completion routine */174175if (i == SOCKET_ERROR) {176if (count > 0) {177/* can't throw exception when some bytes have been written */178break;179} else {180int theErr = (jint)WSAGetLastError();181if (theErr == WSAEWOULDBLOCK) {182return IOS_UNAVAILABLE;183}184if (theErr == WSAECONNRESET) {185JNU_ThrowIOException(env, "Connection reset by peer");186} else {187JNU_ThrowIOExceptionWithLastError(env, "Write failed");188}189return IOS_THROWN;190}191}192193count += (jint)written;194address += written;195196} while ((count < total) && (written == MAX_BUFFER_SIZE));197198return count;199}200201JNIEXPORT jlong JNICALL202Java_sun_nio_ch_SocketDispatcher_writev0(JNIEnv *env, jclass clazz,203jobject fdo, jlong address, jint len)204{205/* set up */206int next_index, next_offset, ret=0;207DWORD written = 0;208jint fd = fdval(env, fdo);209struct iovec *iovp = (struct iovec *)address;210WSABUF *bufs = malloc(len * sizeof(WSABUF));211jlong count = 0;212213if (bufs == 0) {214JNU_ThrowOutOfMemoryError(env, 0);215return IOS_THROWN;216}217218// next buffer and offset to consume219next_index = 0;220next_offset = 0;221222while (next_index < len) {223DWORD buf_count = 0;224225/* Prepare the WSABUF array to a maximum total size of MAX_BUFFER_SIZE */226jint rem = MAX_BUFFER_SIZE;227while (next_index < len && rem > 0) {228jint iov_len = iovp[next_index].iov_len - next_offset;229char* ptr = (char *)iovp[next_index].iov_base;230ptr += next_offset;231if (iov_len > rem) {232iov_len = rem;233next_offset += rem;234} else {235next_index ++;236next_offset = 0;237}238239bufs[buf_count].buf = ptr;240bufs[buf_count].len = (u_long)iov_len;241buf_count++;242243rem -= iov_len;244}245246/* write the buffers */247ret = WSASend((SOCKET)fd, /* Socket */248bufs, /* pointers to the buffers */249buf_count, /* number of buffers to process */250&written, /* receives number of bytes written */2510, /* no flags */2520, /* no overlapped sockets */2530); /* no completion routine */254255if (ret == SOCKET_ERROR) {256break;257}258259count += written;260}261262/* clean up */263free(bufs);264265if (ret == SOCKET_ERROR && count == 0) {266int theErr = (jint)WSAGetLastError();267if (theErr == WSAEWOULDBLOCK) {268return IOS_UNAVAILABLE;269}270if (theErr == WSAECONNRESET) {271JNU_ThrowIOException(env, "Connection reset by peer");272} else {273JNU_ThrowIOExceptionWithLastError(env, "Vector write failed");274}275return IOS_THROWN;276}277278return convertLongReturnVal(env, count, JNI_FALSE);279}280281JNIEXPORT void JNICALL282Java_sun_nio_ch_SocketDispatcher_close0(JNIEnv *env, jclass clazz, jint fd)283{284if (closesocket(fd) == SOCKET_ERROR) {285JNU_ThrowIOExceptionWithLastError(env, "Socket close failed");286}287}288289290