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
46JNIEXPORT jint JNICALL
47Java_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
87JNIEXPORT jlong JNICALL
88Java_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
135JNIEXPORT jint JNICALL
136Java_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
175JNIEXPORT jlong JNICALL
176Java_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}
220