1 /*
2  * Copyright (c) 2002, 2018, 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
Java_sun_nio_ch_DatagramDispatcher_read0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len)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
Java_sun_nio_ch_DatagramDispatcher_readv0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len)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     if (bufs == NULL) {
99         JNU_ThrowOutOfMemoryError(env, NULL);
100         return IOS_THROWN;
101     }
102 
103     /* copy iovec into WSABUF */
104     for(i=0; i<len; i++) {
105         bufs[i].buf = (char *)iovp[i].iov_base;
106         bufs[i].len = (u_long)iovp[i].iov_len;
107     }
108 
109     /* read into the buffers */
110     i = WSARecv((SOCKET)fd, /* Socket */
111             bufs,           /* pointers to the buffers */
112             (DWORD)len,     /* number of buffers to process */
113             &read,          /* receives number of bytes read */
114             &flags,         /* no flags */
115             0,              /* no overlapped sockets */
116             0);             /* no completion routine */
117 
118     /* clean up */
119     free(bufs);
120 
121     if (i != 0) {
122         int theErr = (jint)WSAGetLastError();
123         if (theErr == WSAEWOULDBLOCK) {
124             return IOS_UNAVAILABLE;
125         }
126         if (theErr == WSAECONNRESET) {
127             purgeOutstandingICMP(env, clazz, fd);
128             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
129             return IOS_THROWN;
130         }
131         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
132         return IOS_THROWN;
133     }
134 
135     return convertLongReturnVal(env, (jlong)read, JNI_TRUE);
136 }
137 
138 
139 JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramDispatcher_write0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len)140 Java_sun_nio_ch_DatagramDispatcher_write0(JNIEnv *env, jclass clazz,
141                                           jobject fdo, jlong address, jint len)
142 {
143     /* set up */
144     int i = 0;
145     DWORD written = 0;
146     jint fd = fdval(env, fdo);
147     WSABUF buf;
148 
149     /* copy iovec into WSABUF */
150     buf.buf = (char *)address;
151     buf.len = (u_long)len;
152 
153     /* read into the buffers */
154     i = WSASend((SOCKET)fd, /* Socket */
155             &buf,           /* pointers to the buffers */
156             (DWORD)1,       /* number of buffers to process */
157             &written,       /* receives number of bytes written */
158             0,              /* no flags */
159             0,              /* no overlapped sockets */
160             0);             /* no completion routine */
161 
162     if (i == SOCKET_ERROR) {
163         int theErr = (jint)WSAGetLastError();
164         if (theErr == WSAEWOULDBLOCK) {
165             return IOS_UNAVAILABLE;
166         }
167         if (theErr == WSAECONNRESET) {
168             purgeOutstandingICMP(env, clazz, fd);
169             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
170             return IOS_THROWN;
171         }
172         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
173         return IOS_THROWN;
174     }
175 
176     return convertReturnVal(env, (jint)written, JNI_FALSE);
177 }
178 
179 JNIEXPORT jlong JNICALL
Java_sun_nio_ch_DatagramDispatcher_writev0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len)180 Java_sun_nio_ch_DatagramDispatcher_writev0(JNIEnv *env, jclass clazz,
181                                          jobject fdo, jlong address, jint len)
182 {
183     /* set up */
184     int i = 0;
185     DWORD written = 0;
186     jint fd = fdval(env, fdo);
187     struct iovec *iovp = (struct iovec *)address;
188     WSABUF *bufs = malloc(len * sizeof(WSABUF));
189     if (bufs == NULL) {
190         JNU_ThrowOutOfMemoryError(env, NULL);
191         return IOS_THROWN;
192     }
193 
194     /* copy iovec into WSABUF */
195     for(i=0; i<len; i++) {
196         bufs[i].buf = (char *)iovp[i].iov_base;
197         bufs[i].len = (u_long)iovp[i].iov_len;
198     }
199 
200     /* read into the buffers */
201     i = WSASend((SOCKET)fd, /* Socket */
202             bufs,           /* pointers to the buffers */
203             (DWORD)len,     /* number of buffers to process */
204             &written,       /* receives number of bytes written */
205             0,              /* no flags */
206             0,              /* no overlapped sockets */
207             0);             /* no completion routine */
208 
209     /* clean up */
210     free(bufs);
211 
212     if (i != 0) {
213         int theErr = (jint)WSAGetLastError();
214         if (theErr == WSAEWOULDBLOCK) {
215             return IOS_UNAVAILABLE;
216         }
217         if (theErr == WSAECONNRESET) {
218             purgeOutstandingICMP(env, clazz, fd);
219             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
220             return IOS_THROWN;
221         }
222         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
223         return IOS_THROWN;
224     }
225 
226     return convertLongReturnVal(env, (jlong)written, JNI_FALSE);
227 }
228