author | michaelm |
Wed, 26 Feb 2014 16:18:08 +0000 | |
changeset 23023 | c1aebf9d16a9 |
parent 23015 | 73b21ab36615 |
child 23564 | 62146f638e22 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
22069
diff
changeset
|
2 |
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
#include <windows.h> |
|
26 |
#include <winsock2.h> |
|
27 |
#include "jni.h" |
|
28 |
#include "net_util.h" |
|
29 |
#include "java_net_DualStackPlainDatagramSocketImpl.h" |
|
30 |
||
31 |
/* |
|
32 |
* This function "purges" all outstanding ICMP port unreachable packets |
|
33 |
* outstanding on a socket and returns JNI_TRUE if any ICMP messages |
|
34 |
* have been purged. The rational for purging is to emulate normal BSD |
|
35 |
* behaviour whereby receiving a "connection reset" status resets the |
|
36 |
* socket. |
|
37 |
*/ |
|
38 |
static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd) |
|
39 |
{ |
|
40 |
jboolean got_icmp = JNI_FALSE; |
|
41 |
char buf[1]; |
|
42 |
fd_set tbl; |
|
43 |
struct timeval t = { 0, 0 }; |
|
22069
d55e36f6c0c9
7102702: java/net/PortUnreachableException/OneExceptionOnly.java failing
msheppar
parents:
18253
diff
changeset
|
44 |
SOCKETADDRESS rmtaddr; |
2 | 45 |
int addrlen = sizeof(rmtaddr); |
46 |
||
47 |
/* |
|
48 |
* Peek at the queue to see if there is an ICMP port unreachable. If there |
|
49 |
* is then receive it. |
|
50 |
*/ |
|
51 |
FD_ZERO(&tbl); |
|
52 |
FD_SET(fd, &tbl); |
|
53 |
while(1) { |
|
54 |
if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) { |
|
55 |
break; |
|
56 |
} |
|
57 |
if (recvfrom(fd, buf, 1, MSG_PEEK, |
|
23015
73b21ab36615
8034174: Remove use of JVM_* functions from java.net code
chegar
parents:
23010
diff
changeset
|
58 |
(struct sockaddr *)&rmtaddr, &addrlen) != SOCKET_ERROR) { |
2 | 59 |
break; |
60 |
} |
|
61 |
if (WSAGetLastError() != WSAECONNRESET) { |
|
62 |
/* some other error - we don't care here */ |
|
63 |
break; |
|
64 |
} |
|
65 |
||
66 |
recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen); |
|
67 |
got_icmp = JNI_TRUE; |
|
68 |
} |
|
69 |
||
70 |
return got_icmp; |
|
71 |
} |
|
72 |
||
73 |
/* |
|
74 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
23023 | 75 |
* Method: initIDs |
76 |
* Signature: ()V |
|
77 |
*/ |
|
78 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_initIDs |
|
79 |
(JNIEnv *env, jclass clazz) |
|
80 |
{ |
|
81 |
initInetAddressIDs(env); |
|
82 |
} |
|
83 |
||
84 |
/* |
|
85 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
2 | 86 |
* Method: socketCreate |
87 |
* Signature: (Z)I |
|
88 |
*/ |
|
89 |
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate |
|
90 |
(JNIEnv *env, jclass clazz, jboolean v6Only /*unused*/) { |
|
91 |
int fd, rv, opt=0, t=TRUE; |
|
92 |
DWORD x1, x2; /* ignored result codes */ |
|
93 |
||
94 |
fd = (int) socket(AF_INET6, SOCK_DGRAM, 0); |
|
95 |
if (fd == INVALID_SOCKET) { |
|
96 |
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); |
|
97 |
return -1; |
|
98 |
} |
|
99 |
||
100 |
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); |
|
101 |
if (rv == SOCKET_ERROR) { |
|
102 |
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); |
|
16054
a7cdb40ea8e8
8008804: file descriptor leak in src/windows/native/java/net/DualStackPlainSocketImpl.c
jzavgren
parents:
14342
diff
changeset
|
103 |
closesocket(fd); |
2 | 104 |
return -1; |
105 |
} |
|
106 |
||
107 |
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); |
|
108 |
NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); |
|
109 |
||
110 |
/* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which |
|
111 |
* returns connection reset errors on unconnected UDP sockets (as well |
|
112 |
* as connected sockets). The solution is to only enable this feature |
|
113 |
* when the socket is connected. |
|
114 |
*/ |
|
115 |
t = FALSE; |
|
116 |
WSAIoctl(fd ,SIO_UDP_CONNRESET ,&t ,sizeof(t) ,&x1 ,sizeof(x1) ,&x2 ,0 ,0); |
|
117 |
||
118 |
return fd; |
|
119 |
} |
|
120 |
||
121 |
/* |
|
122 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
123 |
* Method: socketBind |
|
124 |
* Signature: (ILjava/net/InetAddress;I)V |
|
125 |
*/ |
|
126 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind |
|
18192 | 127 |
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) { |
2 | 128 |
SOCKETADDRESS sa; |
129 |
int rv; |
|
130 |
int sa_len = sizeof(sa); |
|
131 |
||
132 |
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, |
|
133 |
&sa_len, JNI_TRUE) != 0) { |
|
134 |
return; |
|
135 |
} |
|
18192 | 136 |
rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind); |
2 | 137 |
|
138 |
if (rv == SOCKET_ERROR) { |
|
139 |
if (WSAGetLastError() == WSAEACCES) { |
|
140 |
WSASetLastError(WSAEADDRINUSE); |
|
141 |
} |
|
142 |
NET_ThrowNew(env, WSAGetLastError(), "Cannot bind"); |
|
143 |
} |
|
144 |
} |
|
145 |
||
146 |
/* |
|
147 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
148 |
* Method: socketConnect |
|
149 |
* Signature: (ILjava/net/InetAddress;I)V |
|
150 |
*/ |
|
151 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect |
|
152 |
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { |
|
153 |
SOCKETADDRESS sa; |
|
154 |
int rv; |
|
155 |
int sa_len = sizeof(sa); |
|
156 |
DWORD x1, x2; /* ignored result codes */ |
|
157 |
int t = TRUE; |
|
158 |
||
159 |
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, |
|
160 |
&sa_len, JNI_TRUE) != 0) { |
|
161 |
return; |
|
162 |
} |
|
163 |
||
164 |
rv = connect(fd, (struct sockaddr *)&sa, sa_len); |
|
165 |
if (rv == SOCKET_ERROR) { |
|
166 |
NET_ThrowNew(env, WSAGetLastError(), "connect"); |
|
167 |
return; |
|
168 |
} |
|
169 |
||
170 |
/* see comment in socketCreate */ |
|
171 |
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0); |
|
172 |
} |
|
173 |
||
174 |
/* |
|
175 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
176 |
* Method: socketDisconnect |
|
177 |
* Signature: (I)V |
|
178 |
*/ |
|
179 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketDisconnect |
|
180 |
(JNIEnv *env, jclass clazz, jint fd ) { |
|
181 |
SOCKETADDRESS sa; |
|
182 |
int sa_len = sizeof(sa); |
|
183 |
DWORD x1, x2; /* ignored result codes */ |
|
184 |
int t = FALSE; |
|
185 |
||
186 |
memset(&sa, 0, sa_len); |
|
187 |
connect(fd, (struct sockaddr *)&sa, sa_len); |
|
188 |
||
189 |
/* see comment in socketCreate */ |
|
190 |
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0); |
|
191 |
} |
|
192 |
||
193 |
/* |
|
194 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
195 |
* Method: socketClose |
|
196 |
* Signature: (I)V |
|
197 |
*/ |
|
198 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClose |
|
199 |
(JNIEnv *env, jclass clazz , jint fd) { |
|
200 |
NET_SocketClose(fd); |
|
201 |
} |
|
202 |
||
203 |
||
204 |
/* |
|
205 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
206 |
* Method: socketLocalPort |
|
207 |
* Signature: (I)I |
|
208 |
*/ |
|
209 |
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalPort |
|
210 |
(JNIEnv *env, jclass clazz, jint fd) { |
|
211 |
SOCKETADDRESS sa; |
|
212 |
int len = sizeof(sa); |
|
213 |
||
214 |
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { |
|
23015
73b21ab36615
8034174: Remove use of JVM_* functions from java.net code
chegar
parents:
23010
diff
changeset
|
215 |
NET_ThrowNew(env, WSAGetLastError(), "getsockname"); |
2 | 216 |
return -1; |
217 |
} |
|
218 |
return (int) ntohs((u_short)GET_PORT(&sa)); |
|
219 |
} |
|
220 |
||
221 |
/* |
|
222 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
223 |
* Method: socketLocalAddress |
|
224 |
* Signature: (I)Ljava/lang/Object; |
|
225 |
*/ |
|
226 |
JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress |
|
227 |
(JNIEnv *env , jclass clazz, jint fd) { |
|
228 |
SOCKETADDRESS sa; |
|
229 |
int len = sizeof(sa); |
|
230 |
jobject iaObj; |
|
231 |
int port; |
|
232 |
||
233 |
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { |
|
234 |
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); |
|
235 |
return NULL; |
|
236 |
} |
|
237 |
||
238 |
iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); |
|
239 |
return iaObj; |
|
240 |
} |
|
241 |
||
242 |
/* |
|
243 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
244 |
* Method: socketReceiveOrPeekData |
|
245 |
* Signature: (ILjava/net/DatagramPacket;IZZ)I |
|
246 |
*/ |
|
247 |
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketReceiveOrPeekData |
|
248 |
(JNIEnv *env, jclass clazz, jint fd, jobject dpObj, |
|
249 |
jint timeout, jboolean connected, jboolean peek) { |
|
250 |
SOCKETADDRESS sa; |
|
251 |
int sa_len = sizeof(sa); |
|
252 |
int port, rv, flags=0; |
|
253 |
char BUF[MAX_BUFFER_LEN]; |
|
254 |
char *fullPacket; |
|
255 |
BOOL retry; |
|
256 |
jlong prevTime = 0; |
|
257 |
||
258 |
jint packetBufferOffset, packetBufferLen; |
|
259 |
jbyteArray packetBuffer; |
|
260 |
||
261 |
/* if we are only peeking. Called from peekData */ |
|
262 |
if (peek) { |
|
263 |
flags = MSG_PEEK; |
|
264 |
} |
|
265 |
||
266 |
packetBuffer = (*env)->GetObjectField(env, dpObj, dp_bufID); |
|
267 |
packetBufferOffset = (*env)->GetIntField(env, dpObj, dp_offsetID); |
|
268 |
packetBufferLen = (*env)->GetIntField(env, dpObj, dp_bufLengthID); |
|
17925
e8d88b57f82e
8008972: Memory leak: Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0 [parfait]
jzavgren
parents:
16054
diff
changeset
|
269 |
/* Note: the buffer needn't be greater than 65,536 (0xFFFF) |
e8d88b57f82e
8008972: Memory leak: Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0 [parfait]
jzavgren
parents:
16054
diff
changeset
|
270 |
* the max size of an IP packet. Anything bigger is truncated anyway. |
e8d88b57f82e
8008972: Memory leak: Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0 [parfait]
jzavgren
parents:
16054
diff
changeset
|
271 |
*/ |
e8d88b57f82e
8008972: Memory leak: Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0 [parfait]
jzavgren
parents:
16054
diff
changeset
|
272 |
if (packetBufferLen > MAX_PACKET_LEN) { |
e8d88b57f82e
8008972: Memory leak: Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0 [parfait]
jzavgren
parents:
16054
diff
changeset
|
273 |
packetBufferLen = MAX_PACKET_LEN; |
e8d88b57f82e
8008972: Memory leak: Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0 [parfait]
jzavgren
parents:
16054
diff
changeset
|
274 |
} |
2 | 275 |
|
276 |
if (packetBufferLen > MAX_BUFFER_LEN) { |
|
277 |
fullPacket = (char *)malloc(packetBufferLen); |
|
278 |
if (!fullPacket) { |
|
13245
7ab3ef5b9520
7181353: Update error message to distinguish native OOM and java OOM in net
zhouyx
parents:
5506
diff
changeset
|
279 |
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); |
2 | 280 |
return -1; |
281 |
} |
|
282 |
} else { |
|
283 |
fullPacket = &(BUF[0]); |
|
284 |
} |
|
285 |
||
286 |
do { |
|
287 |
retry = FALSE; |
|
288 |
||
289 |
if (timeout) { |
|
290 |
if (prevTime == 0) { |
|
291 |
prevTime = JVM_CurrentTimeMillis(env, 0); |
|
292 |
} |
|
293 |
rv = NET_Timeout(fd, timeout); |
|
294 |
if (rv <= 0) { |
|
295 |
if (rv == 0) { |
|
296 |
JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", |
|
297 |
"Receive timed out"); |
|
23015
73b21ab36615
8034174: Remove use of JVM_* functions from java.net code
chegar
parents:
23010
diff
changeset
|
298 |
} else if (rv == -1) { |
2 | 299 |
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
300 |
"Socket closed"); |
|
301 |
} |
|
302 |
if (packetBufferLen > MAX_BUFFER_LEN) { |
|
303 |
free(fullPacket); |
|
304 |
} |
|
305 |
return -1; |
|
306 |
} |
|
307 |
} |
|
308 |
||
309 |
/* receive the packet */ |
|
310 |
rv = recvfrom(fd, fullPacket, packetBufferLen, flags, |
|
311 |
(struct sockaddr *)&sa, &sa_len); |
|
312 |
||
313 |
if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) { |
|
314 |
/* An icmp port unreachable - we must receive this as Windows |
|
315 |
* does not reset the state of the socket until this has been |
|
316 |
* received. |
|
317 |
*/ |
|
318 |
purgeOutstandingICMP(env, fd); |
|
319 |
||
320 |
if (connected) { |
|
321 |
JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", |
|
322 |
"ICMP Port Unreachable"); |
|
323 |
if (packetBufferLen > MAX_BUFFER_LEN) |
|
324 |
free(fullPacket); |
|
325 |
return -1; |
|
326 |
} else if (timeout) { |
|
327 |
/* Adjust timeout */ |
|
328 |
jlong newTime = JVM_CurrentTimeMillis(env, 0); |
|
329 |
timeout -= (jint)(newTime - prevTime); |
|
330 |
if (timeout <= 0) { |
|
331 |
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", |
|
332 |
"Receive timed out"); |
|
333 |
if (packetBufferLen > MAX_BUFFER_LEN) |
|
334 |
free(fullPacket); |
|
335 |
return -1; |
|
336 |
} |
|
337 |
prevTime = newTime; |
|
338 |
} |
|
339 |
retry = TRUE; |
|
340 |
} |
|
341 |
} while (retry); |
|
342 |
||
343 |
port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&sa)); |
|
344 |
||
345 |
/* truncate the data if the packet's length is too small */ |
|
346 |
if (rv > packetBufferLen) { |
|
347 |
rv = packetBufferLen; |
|
348 |
} |
|
349 |
if (rv < 0) { |
|
350 |
if (WSAGetLastError() == WSAEMSGSIZE) { |
|
351 |
/* it is because the buffer is too small. It's UDP, it's |
|
352 |
* unreliable, it's all good. discard the rest of the |
|
353 |
* data.. |
|
354 |
*/ |
|
355 |
rv = packetBufferLen; |
|
356 |
} else { |
|
357 |
/* failure */ |
|
358 |
(*env)->SetIntField(env, dpObj, dp_lengthID, 0); |
|
359 |
} |
|
360 |
} |
|
361 |
||
362 |
if (rv == -1) { |
|
363 |
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); |
|
364 |
} else if (rv == -2) { |
|
365 |
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", |
|
366 |
"operation interrupted"); |
|
367 |
} else if (rv < 0) { |
|
368 |
NET_ThrowCurrent(env, "Datagram receive failed"); |
|
369 |
} else { |
|
370 |
jobject packetAddress; |
|
371 |
/* |
|
372 |
* Check if there is an InetAddress already associated with this |
|
373 |
* packet. If so, we check if it is the same source address. We |
|
374 |
* can't update any existing InetAddress because it is immutable |
|
375 |
*/ |
|
376 |
packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID); |
|
377 |
if (packetAddress != NULL) { |
|
378 |
if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa, |
|
379 |
packetAddress)) { |
|
380 |
/* force a new InetAddress to be created */ |
|
381 |
packetAddress = NULL; |
|
382 |
} |
|
383 |
} |
|
384 |
if (packetAddress == NULL) { |
|
385 |
packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, |
|
386 |
&port); |
|
387 |
/* stuff the new Inetaddress into the packet */ |
|
388 |
(*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress); |
|
389 |
} |
|
390 |
||
391 |
/* populate the packet */ |
|
392 |
(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, rv, |
|
393 |
(jbyte *)fullPacket); |
|
394 |
(*env)->SetIntField(env, dpObj, dp_portID, port); |
|
395 |
(*env)->SetIntField(env, dpObj, dp_lengthID, rv); |
|
396 |
} |
|
397 |
||
398 |
if (packetBufferLen > MAX_BUFFER_LEN) { |
|
399 |
free(fullPacket); |
|
400 |
} |
|
401 |
return port; |
|
402 |
} |
|
403 |
||
404 |
/* |
|
405 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
406 |
* Method: socketSend |
|
407 |
* Signature: (I[BIILjava/net/InetAddress;IZ)V |
|
408 |
*/ |
|
409 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend |
|
410 |
(JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length, |
|
411 |
jobject iaObj, jint port, jboolean connected) { |
|
412 |
SOCKETADDRESS sa; |
|
413 |
int sa_len = sizeof(sa); |
|
414 |
SOCKETADDRESS *sap = &sa; |
|
415 |
char BUF[MAX_BUFFER_LEN]; |
|
416 |
char *fullPacket; |
|
417 |
int rv; |
|
418 |
||
419 |
if (connected) { |
|
23015
73b21ab36615
8034174: Remove use of JVM_* functions from java.net code
chegar
parents:
23010
diff
changeset
|
420 |
sap = 0; /* arg to sendto () null in this case */ |
2 | 421 |
sa_len = 0; |
422 |
} else { |
|
423 |
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, |
|
424 |
&sa_len, JNI_TRUE) != 0) { |
|
425 |
return; |
|
426 |
} |
|
427 |
} |
|
428 |
||
429 |
if (length > MAX_BUFFER_LEN) { |
|
430 |
/* Note: the buffer needn't be greater than 65,536 (0xFFFF) |
|
431 |
* the max size of an IP packet. Anything bigger is truncated anyway. |
|
432 |
*/ |
|
433 |
if (length > MAX_PACKET_LEN) { |
|
434 |
length = MAX_PACKET_LEN; |
|
435 |
} |
|
436 |
fullPacket = (char *)malloc(length); |
|
437 |
if (!fullPacket) { |
|
13245
7ab3ef5b9520
7181353: Update error message to distinguish native OOM and java OOM in net
zhouyx
parents:
5506
diff
changeset
|
438 |
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); |
2 | 439 |
return; |
440 |
} |
|
441 |
} else { |
|
442 |
fullPacket = &(BUF[0]); |
|
443 |
} |
|
444 |
||
445 |
(*env)->GetByteArrayRegion(env, data, offset, length, |
|
446 |
(jbyte *)fullPacket); |
|
447 |
rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len); |
|
448 |
if (rv == SOCKET_ERROR) { |
|
23015
73b21ab36615
8034174: Remove use of JVM_* functions from java.net code
chegar
parents:
23010
diff
changeset
|
449 |
if (rv == -1) { |
2 | 450 |
NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed"); |
451 |
} |
|
452 |
} |
|
453 |
||
454 |
if (length > MAX_BUFFER_LEN) { |
|
455 |
free(fullPacket); |
|
456 |
} |
|
457 |
} |
|
458 |
||
459 |
/* |
|
460 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
461 |
* Method: socketSetIntOption |
|
462 |
* Signature: (III)V |
|
463 |
*/ |
|
464 |
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption |
|
465 |
(JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) { |
|
466 |
int level, opt; |
|
467 |
||
468 |
if (NET_MapSocketOption(cmd, &level, &opt) < 0) { |
|
469 |
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", |
|
470 |
"Invalid option"); |
|
471 |
return; |
|
472 |
} |
|
473 |
||
474 |
if (NET_SetSockOpt(fd, level, opt, (char *)&value, sizeof(value)) < 0) { |
|
475 |
NET_ThrowNew(env, WSAGetLastError(), "setsockopt"); |
|
476 |
} |
|
477 |
} |
|
478 |
||
479 |
/* |
|
480 |
* Class: java_net_DualStackPlainDatagramSocketImpl |
|
481 |
* Method: socketGetIntOption |
|
482 |
* Signature: (II)I |
|
483 |
*/ |
|
484 |
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption |
|
485 |
(JNIEnv *env, jclass clazz, jint fd, jint cmd) { |
|
486 |
int level, opt, result=0; |
|
487 |
int result_len = sizeof(result); |
|
488 |
||
489 |
if (NET_MapSocketOption(cmd, &level, &opt) < 0) { |
|
490 |
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", |
|
491 |
"Invalid option"); |
|
492 |
return -1; |
|
493 |
} |
|
494 |
||
495 |
if (NET_GetSockOpt(fd, level, opt, (void *)&result, &result_len) < 0) { |
|
496 |
NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); |
|
497 |
return -1; |
|
498 |
} |
|
499 |
||
500 |
return result; |
|
501 |
} |