0N/A/*
3261N/A * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <windows.h>
0N/A#include <winsock2.h>
0N/A#include <ctype.h>
0N/A#include "jni.h"
0N/A#include "jni_util.h"
0N/A#include "jvm.h"
0N/A#include "jlong.h"
0N/A#include "sun_nio_ch_SocketDispatcher.h"
0N/A#include "nio.h"
0N/A#include "nio_util.h"
0N/A
0N/A
0N/A/**************************************************************
0N/A * SocketDispatcher.c
0N/A */
0N/A
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_nio_ch_SocketDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo,
0N/A jlong address, jint len)
0N/A{
0N/A /* set up */
0N/A int i = 0;
0N/A DWORD read = 0;
0N/A DWORD flags = 0;
0N/A jint fd = fdval(env, fdo);
0N/A WSABUF buf;
0N/A
2491N/A /* limit size */
2491N/A if (len > MAX_BUFFER_SIZE)
2491N/A len = MAX_BUFFER_SIZE;
2491N/A
0N/A /* destination buffer and size */
0N/A buf.buf = (char *)address;
0N/A buf.len = (u_long)len;
0N/A
0N/A /* read into the buffers */
0N/A i = WSARecv((SOCKET)fd, /* Socket */
0N/A &buf, /* pointers to the buffers */
0N/A (DWORD)1, /* number of buffers to process */
0N/A &read, /* receives number of bytes read */
0N/A &flags, /* no flags */
0N/A 0, /* no overlapped sockets */
0N/A 0); /* no completion routine */
0N/A
0N/A if (i == SOCKET_ERROR) {
0N/A int theErr = (jint)WSAGetLastError();
0N/A if (theErr == WSAEWOULDBLOCK) {
0N/A return IOS_UNAVAILABLE;
0N/A }
0N/A JNU_ThrowIOExceptionWithLastError(env, "Read failed");
0N/A return IOS_THROWN;
0N/A }
0N/A
0N/A return convertReturnVal(env, (jint)read, JNI_TRUE);
0N/A}
0N/A
0N/AJNIEXPORT jlong JNICALL
0N/AJava_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo,
0N/A jlong address, jint len)
0N/A{
0N/A /* set up */
0N/A int i = 0;
0N/A DWORD read = 0;
0N/A DWORD flags = 0;
0N/A jint fd = fdval(env, fdo);
0N/A struct iovec *iovp = (struct iovec *)address;
0N/A WSABUF *bufs = malloc(len * sizeof(WSABUF));
2491N/A jint rem = MAX_BUFFER_SIZE;
0N/A
0N/A if (bufs == 0) {
0N/A JNU_ThrowOutOfMemoryError(env, 0);
0N/A return IOS_THROWN;
0N/A }
0N/A
0N/A /* copy iovec into WSABUF */
0N/A for(i=0; i<len; i++) {
2491N/A jint iov_len = iovp[i].iov_len;
2491N/A if (iov_len > rem)
2491N/A iov_len = rem;
0N/A bufs[i].buf = (char *)iovp[i].iov_base;
2491N/A bufs[i].len = (u_long)iov_len;
2491N/A rem -= iov_len;
2491N/A if (rem == 0) {
2491N/A len = i+1;
2491N/A break;
2491N/A }
0N/A }
0N/A
0N/A /* read into the buffers */
0N/A i = WSARecv((SOCKET)fd, /* Socket */
0N/A bufs, /* pointers to the buffers */
0N/A (DWORD)len, /* number of buffers to process */
0N/A &read, /* receives number of bytes read */
0N/A &flags, /* no flags */
0N/A 0, /* no overlapped sockets */
0N/A 0); /* no completion routine */
0N/A
0N/A /* clean up */
0N/A free(bufs);
0N/A
0N/A if (i != 0) {
0N/A int theErr = (jint)WSAGetLastError();
0N/A if (theErr == WSAEWOULDBLOCK) {
0N/A return IOS_UNAVAILABLE;
0N/A }
0N/A JNU_ThrowIOExceptionWithLastError(env, "Vector read failed");
0N/A return IOS_THROWN;
0N/A }
0N/A
0N/A return convertLongReturnVal(env, (jlong)read, JNI_TRUE);
0N/A}
0N/A
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_nio_ch_SocketDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo,
5154N/A jlong address, jint total)
0N/A{
0N/A /* set up */
0N/A int i = 0;
0N/A DWORD written = 0;
5154N/A jint count = 0;
0N/A jint fd = fdval(env, fdo);
0N/A WSABUF buf;
0N/A
5154N/A do {
5154N/A /* limit size */
5154N/A jint len = total - count;
5154N/A if (len > MAX_BUFFER_SIZE)
5154N/A len = MAX_BUFFER_SIZE;
2491N/A
5154N/A /* copy iovec into WSABUF */
5154N/A buf.buf = (char *)address;
5154N/A buf.len = (u_long)len;
5154N/A
5154N/A /* write from the buffer */
5154N/A i = WSASend((SOCKET)fd, /* Socket */
5154N/A &buf, /* pointers to the buffers */
5154N/A (DWORD)1, /* number of buffers to process */
5154N/A &written, /* receives number of bytes written */
5154N/A 0, /* no flags */
5154N/A 0, /* no overlapped sockets */
5154N/A 0); /* no completion routine */
0N/A
5154N/A if (i == SOCKET_ERROR) {
5154N/A if (count > 0) {
5154N/A /* can't throw exception when some bytes have been written */
5154N/A break;
5154N/A } else {
5154N/A int theErr = (jint)WSAGetLastError();
5154N/A if (theErr == WSAEWOULDBLOCK) {
5154N/A return IOS_UNAVAILABLE;
5154N/A }
5154N/A JNU_ThrowIOExceptionWithLastError(env, "Write failed");
5154N/A return IOS_THROWN;
5154N/A }
5154N/A }
0N/A
5154N/A count += written;
5154N/A address += written;
0N/A
5154N/A } while ((count < total) && (written == MAX_BUFFER_SIZE));
5154N/A
5154N/A return count;
0N/A}
0N/A
0N/AJNIEXPORT jlong JNICALL
0N/AJava_sun_nio_ch_SocketDispatcher_writev0(JNIEnv *env, jclass clazz,
0N/A jobject fdo, jlong address, jint len)
0N/A{
0N/A /* set up */
0N/A int i = 0;
0N/A DWORD written = 0;
0N/A jint fd = fdval(env, fdo);
0N/A struct iovec *iovp = (struct iovec *)address;
0N/A WSABUF *bufs = malloc(len * sizeof(WSABUF));
2491N/A jint rem = MAX_BUFFER_SIZE;
0N/A
0N/A if (bufs == 0) {
0N/A JNU_ThrowOutOfMemoryError(env, 0);
0N/A return IOS_THROWN;
0N/A }
0N/A
0N/A /* copy iovec into WSABUF */
0N/A for(i=0; i<len; i++) {
2491N/A jint iov_len = iovp[i].iov_len;
2491N/A if (iov_len > rem)
2491N/A iov_len = rem;
0N/A bufs[i].buf = (char *)iovp[i].iov_base;
2491N/A bufs[i].len = (u_long)iov_len;
2491N/A rem -= iov_len;
2491N/A if (rem == 0) {
2491N/A len = i+1;
2491N/A break;
2491N/A }
0N/A }
0N/A
0N/A /* read into the buffers */
0N/A i = WSASend((SOCKET)fd, /* Socket */
0N/A bufs, /* pointers to the buffers */
0N/A (DWORD)len, /* number of buffers to process */
0N/A &written, /* receives number of bytes written */
0N/A 0, /* no flags */
0N/A 0, /* no overlapped sockets */
0N/A 0); /* no completion routine */
0N/A
0N/A /* clean up */
0N/A free(bufs);
0N/A
0N/A if (i != 0) {
0N/A int theErr = (jint)WSAGetLastError();
0N/A if (theErr == WSAEWOULDBLOCK) {
0N/A return IOS_UNAVAILABLE;
0N/A }
0N/A JNU_ThrowIOExceptionWithLastError(env, "Vector write failed");
0N/A return IOS_THROWN;
0N/A }
0N/A
0N/A return convertLongReturnVal(env, (jlong)written, JNI_FALSE);
0N/A}
0N/A
0N/AJNIEXPORT void JNICALL
5028N/AJava_sun_nio_ch_SocketDispatcher_preClose0(JNIEnv *env, jclass clazz,
5028N/A jobject fdo)
0N/A{
0N/A jint fd = fdval(env, fdo);
0N/A struct linger l;
0N/A int len = sizeof(l);
5028N/A if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) {
5028N/A if (l.l_onoff == 0) {
5028N/A WSASendDisconnect(fd, NULL);
0N/A }
0N/A }
0N/A}
5028N/A
5028N/AJNIEXPORT void JNICALL
5028N/AJava_sun_nio_ch_SocketDispatcher_close0(JNIEnv *env, jclass clazz,
5028N/A jobject fdo)
5028N/A{
5028N/A jint fd = fdval(env, fdo);
5028N/A if (closesocket(fd) == SOCKET_ERROR) {
5028N/A JNU_ThrowIOExceptionWithLastError(env, "Socket close failed");
5028N/A }
5028N/A}