File: | jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c |
Warning: | line 735, column 10 Although the value stored to 'rv' is used in the enclosing expression, the value is never actually read from 'rv' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2009, 2021, 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 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <dlfcn.h> |
29 | |
30 | #include "Sctp.h" |
31 | #include "jni.h" |
32 | #include "jni_util.h" |
33 | #include "nio_util.h" |
34 | #include "nio.h" |
35 | #include "net_util.h" |
36 | #include "net_util_md.h" |
37 | #include "sun_nio_ch_sctp_SctpNet.h" |
38 | #include "sun_nio_ch_sctp_SctpStdSocketOption.h" |
39 | |
40 | static jclass isaCls = 0; |
41 | static jmethodID isaCtrID = 0; |
42 | |
43 | static const char* nativeSctpLib = "libsctp.so.1"; |
44 | static jboolean funcsLoaded = JNI_FALSE0; |
45 | |
46 | sctp_getladdrs_func* nio_sctp_getladdrs; |
47 | sctp_freeladdrs_func* nio_sctp_freeladdrs; |
48 | sctp_getpaddrs_func* nio_sctp_getpaddrs; |
49 | sctp_freepaddrs_func* nio_sctp_freepaddrs; |
50 | sctp_bindx_func* nio_sctp_bindx; |
51 | sctp_peeloff_func* nio_sctp_peeloff; |
52 | |
53 | JNIEXPORT__attribute__((visibility("default"))) jint JNICALL DEF_JNI_OnLoadJNI_OnLoad |
54 | (JavaVM *vm, void *reserved) { |
55 | return JNI_VERSION_1_20x00010002; |
56 | } |
57 | |
58 | static int preCloseFD = -1; /* File descriptor to which we dup other fd's |
59 | before closing them for real */ |
60 | |
61 | /** |
62 | * Loads the native sctp library that contains the socket extension |
63 | * functions, as well as locating the individual functions. |
64 | * There will be a pending exception if this method returns false. |
65 | */ |
66 | jboolean loadSocketExtensionFuncs |
67 | (JNIEnv* env) { |
68 | if (dlopen(nativeSctpLib, RTLD_GLOBAL0x00100 | RTLD_LAZY0x00001) == NULL((void*)0)) { |
69 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
70 | dlerror()); |
71 | return JNI_FALSE0; |
72 | } |
73 | |
74 | if ((nio_sctp_getladdrs = (sctp_getladdrs_func*) |
75 | dlsym(RTLD_DEFAULT((void *) 0), "sctp_getladdrs")) == NULL((void*)0)) { |
76 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
77 | dlerror()); |
78 | return JNI_FALSE0; |
79 | } |
80 | |
81 | if ((nio_sctp_freeladdrs = (sctp_freeladdrs_func*) |
82 | dlsym(RTLD_DEFAULT((void *) 0), "sctp_freeladdrs")) == NULL((void*)0)) { |
83 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
84 | dlerror()); |
85 | return JNI_FALSE0; |
86 | } |
87 | |
88 | if ((nio_sctp_getpaddrs = (sctp_getpaddrs_func*) |
89 | dlsym(RTLD_DEFAULT((void *) 0), "sctp_getpaddrs")) == NULL((void*)0)) { |
90 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
91 | dlerror()); |
92 | return JNI_FALSE0; |
93 | } |
94 | |
95 | if ((nio_sctp_freepaddrs = (sctp_freepaddrs_func*) |
96 | dlsym(RTLD_DEFAULT((void *) 0), "sctp_freepaddrs")) == NULL((void*)0)) { |
97 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
98 | dlerror()); |
99 | return JNI_FALSE0; |
100 | } |
101 | |
102 | if ((nio_sctp_bindx = (sctp_bindx_func*) |
103 | dlsym(RTLD_DEFAULT((void *) 0), "sctp_bindx")) == NULL((void*)0)) { |
104 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
105 | dlerror()); |
106 | return JNI_FALSE0; |
107 | } |
108 | |
109 | if ((nio_sctp_peeloff = (sctp_peeloff_func*) |
110 | dlsym(RTLD_DEFAULT((void *) 0), "sctp_peeloff")) == NULL((void*)0)) { |
111 | JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", |
112 | dlerror()); |
113 | return JNI_FALSE0; |
114 | } |
115 | |
116 | funcsLoaded = JNI_TRUE1; |
117 | return JNI_TRUE1; |
118 | } |
119 | |
120 | jint |
121 | handleSocketError(JNIEnv *env, jint errorValue) |
122 | { |
123 | char *xn; |
124 | switch (errorValue) { |
125 | case EINPROGRESS115: /* Non-blocking connect */ |
126 | return 0; |
127 | case EPROTO71: |
128 | xn= JNU_JAVANETPKG"java/net/" "ProtocolException"; |
129 | break; |
130 | case ECONNREFUSED111: |
131 | xn = JNU_JAVANETPKG"java/net/" "ConnectException"; |
132 | break; |
133 | case ETIMEDOUT110: |
134 | xn = JNU_JAVANETPKG"java/net/" "ConnectException"; |
135 | break; |
136 | case EHOSTUNREACH113: |
137 | xn = JNU_JAVANETPKG"java/net/" "NoRouteToHostException"; |
138 | break; |
139 | case EADDRINUSE98: /* Fall through */ |
140 | case EADDRNOTAVAIL99: |
141 | xn = JNU_JAVANETPKG"java/net/" "BindException"; |
142 | break; |
143 | default: |
144 | xn = JNU_JAVANETPKG"java/net/" "SocketException"; |
145 | break; |
146 | } |
147 | errno(*__errno_location ()) = errorValue; |
148 | JNU_ThrowByNameWithLastError(env, xn, "NioSocketError"); |
149 | return IOS_THROWN(-5L); |
150 | } |
151 | |
152 | /* |
153 | * Class: sun_nio_ch_sctp_SctpNet |
154 | * Method: init |
155 | * Signature: ()V |
156 | */ |
157 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL |
158 | Java_sun_nio_ch_sctp_SctpNet_init |
159 | (JNIEnv *env, jclass cl) { |
160 | int sp[2]; |
161 | if (socketpair(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0, sp) < 0) { |
162 | JNU_ThrowIOExceptionWithLastError(env, "socketpair failed"); |
163 | return; |
164 | } |
165 | preCloseFD = sp[0]; |
166 | close(sp[1]); |
167 | initInetAddressIDs(env); |
168 | } |
169 | |
170 | /* |
171 | * Class: sun_nio_ch_sctp_SctpNet |
172 | * Method: socket0 |
173 | * Signature: (Z)I |
174 | */ |
175 | JNIEXPORT__attribute__((visibility("default"))) jint JNICALL Java_sun_nio_ch_sctp_SctpNet_socket0 |
176 | (JNIEnv *env, jclass klass, jboolean oneToOne) { |
177 | int fd; |
178 | struct sctp_event_subscribe event; |
179 | #ifdef AF_INET610 |
180 | int domain = ipv6_available() ? AF_INET610 : AF_INET2; |
181 | #else |
182 | int domain = AF_INET2; |
183 | #endif |
184 | |
185 | /* Try to load the socket API extension functions */ |
186 | if (!funcsLoaded && !loadSocketExtensionFuncs(env)) { |
187 | return 0; |
188 | } |
189 | |
190 | fd = socket(domain, (oneToOne ? SOCK_STREAMSOCK_STREAM : SOCK_SEQPACKETSOCK_SEQPACKET), IPPROTO_SCTPIPPROTO_SCTP); |
191 | |
192 | if (fd < 0) { |
193 | if (errno(*__errno_location ()) == EPROTONOSUPPORT93 || errno(*__errno_location ()) == ESOCKTNOSUPPORT94) { |
194 | JNU_ThrowByNameWithLastError(env, "java/lang/UnsupportedOperationException", |
195 | "Protocol not supported"); |
196 | return IOS_THROWN(-5L); |
197 | } else { |
198 | return handleSocketError(env, errno(*__errno_location ())); |
199 | } |
200 | } |
201 | |
202 | /* Enable events */ |
203 | memset(&event, 0, sizeof(event)); |
204 | event.sctp_data_io_event = 1; |
205 | event.sctp_association_event = 1; |
206 | event.sctp_address_event = 1; |
207 | event.sctp_send_failure_event = 1; |
208 | //event.sctp_peer_error_event = 1; |
209 | event.sctp_shutdown_event = 1; |
210 | //event.sctp_partial_delivery_event = 1; |
211 | //event.sctp_adaptation_layer_event = 1; |
212 | if (setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTSSCTP_EVENTS, &event, sizeof(event)) != 0) { |
213 | handleSocketError(env, errno(*__errno_location ())); |
214 | } |
215 | return fd; |
216 | } |
217 | |
218 | /* |
219 | * Class: sun_nio_ch_sctp_SctpNet |
220 | * Method: bindx |
221 | * Signature: (I[Ljava/net/InetAddress;IIZ)V |
222 | */ |
223 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_bindx |
224 | (JNIEnv *env, jclass klass, jint fd, jobjectArray addrs, jint port, |
225 | jint addrsLength, jboolean add, jboolean preferIPv6) { |
226 | SOCKETADDRESS *sap, *tmpSap; |
227 | int i; |
228 | jobject ia; |
229 | |
230 | if (addrsLength < 1) |
231 | return; |
232 | |
233 | if ((sap = calloc(addrsLength, sizeof(SOCKETADDRESS))) == NULL((void*)0)) { |
234 | JNU_ThrowOutOfMemoryError(env, "heap allocation failure"); |
235 | return; |
236 | } |
237 | |
238 | tmpSap = sap; |
239 | for (i = 0; i < addrsLength; i++) { |
240 | ia = (*env)->GetObjectArrayElement(env, addrs, i); |
241 | if (NET_InetAddressToSockaddr(env, ia, port, tmpSap, NULL((void*)0), |
242 | preferIPv6) != 0) { |
243 | free(sap); |
244 | return; |
245 | } |
246 | tmpSap++; |
247 | } |
248 | |
249 | if (nio_sctp_bindx(fd, (void *)sap, addrsLength, add ? SCTP_BINDX_ADD_ADDR0x01 : |
250 | SCTP_BINDX_REM_ADDR0x02) != 0) { |
251 | handleSocketError(env, errno(*__errno_location ())); |
252 | } |
253 | |
254 | free(sap); |
255 | } |
256 | |
257 | /* |
258 | * Class: sun_nio_ch_sctp_SctpNet |
259 | * Method: listen0 |
260 | * Signature: (II)V |
261 | */ |
262 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL |
263 | Java_sun_nio_ch_sctp_SctpNet_listen0 |
264 | (JNIEnv *env, jclass cl, jint fd, jint backlog) { |
265 | if (listen(fd, backlog) < 0) |
266 | handleSocketError(env, errno(*__errno_location ())); |
267 | } |
268 | |
269 | /* |
270 | * Class: sun_nio_ch_sctp_SctpNet |
271 | * Method: connect0 |
272 | * Signature: (ILjava/net/InetAddress;I)I |
273 | */ |
274 | JNIEXPORT__attribute__((visibility("default"))) jint JNICALL |
275 | Java_sun_nio_ch_sctp_SctpNet_connect0 |
276 | (JNIEnv *env, jclass clazz, int fd, jobject iao, jint port) { |
277 | SOCKETADDRESS sa; |
278 | int sa_len = 0; |
279 | int rv; |
280 | |
281 | if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, |
282 | JNI_TRUE1) != 0) { |
283 | return IOS_THROWN(-5L); |
284 | } |
285 | |
286 | rv = connect(fd, &sa.sa, sa_len); |
287 | if (rv != 0) { |
288 | if (errno(*__errno_location ()) == EINPROGRESS115) { |
289 | return IOS_UNAVAILABLE(-2L); |
290 | } else if (errno(*__errno_location ()) == EINTR4) { |
291 | return IOS_INTERRUPTED(-3L); |
292 | } |
293 | return handleSocketError(env, errno(*__errno_location ())); |
294 | } |
295 | return 1; |
296 | } |
297 | |
298 | /* |
299 | * Class: sun_nio_ch_sctp_SctpNet |
300 | * Method: close0 |
301 | * Signature: (I)V |
302 | */ |
303 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL |
304 | Java_sun_nio_ch_sctp_SctpNet_close0 |
305 | (JNIEnv *env, jclass clazz, jint fd) { |
306 | if (fd != -1) { |
307 | int rv = close(fd); |
308 | if (rv < 0) |
309 | JNU_ThrowIOExceptionWithLastError(env, "Close failed"); |
310 | } |
311 | } |
312 | |
313 | /* |
314 | * Class: sun_nio_ch_sctp_SctpNet |
315 | * Method: preClose0 |
316 | * Signature: (I)V |
317 | */ |
318 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL |
319 | Java_sun_nio_ch_sctp_SctpNet_preClose0 |
320 | (JNIEnv *env, jclass clazz, jint fd) { |
321 | if (preCloseFD >= 0) { |
322 | if (dup2(preCloseFD, fd) < 0) |
323 | JNU_ThrowIOExceptionWithLastError(env, "dup2 failed"); |
324 | } |
325 | } |
326 | |
327 | void initializeISA(JNIEnv* env) { |
328 | if (isaCls == 0) { |
329 | jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress"); |
330 | CHECK_NULL(c)do { if ((c) == ((void*)0)) { return; } } while (0); |
331 | isaCtrID = (*env)->GetMethodID(env, c, "<init>", |
332 | "(Ljava/net/InetAddress;I)V"); |
333 | CHECK_NULL(isaCtrID)do { if ((isaCtrID) == ((void*)0)) { return; } } while (0); |
334 | isaCls = (*env)->NewGlobalRef(env, c); |
335 | CHECK_NULL(isaCls)do { if ((isaCls) == ((void*)0)) { return; } } while (0); |
336 | (*env)->DeleteLocalRef(env, c); |
337 | } |
338 | } |
339 | |
340 | jobject SockAddrToInetSocketAddress(JNIEnv *env, SOCKETADDRESS *sap) { |
341 | int port = 0; |
342 | |
343 | jobject ia = NET_SockaddrToInetAddress(env, sap, &port); |
344 | if (ia == NULL((void*)0)) |
345 | return NULL((void*)0); |
346 | |
347 | if (isaCls == 0) { |
348 | initializeISA(env); |
349 | CHECK_NULL_RETURN(isaCls, NULL)do { if ((isaCls) == ((void*)0)) { return (((void*)0)); } } while (0); |
350 | } |
351 | |
352 | return (*env)->NewObject(env, isaCls, isaCtrID, ia, port); |
353 | } |
354 | |
355 | /* |
356 | * Class: sun_nio_ch_sctp_SctpNet |
357 | * Method: getLocalAddresses0 |
358 | * Signature: (I)[Ljava/net/SocketAddress; |
359 | */ |
360 | JNIEXPORT__attribute__((visibility("default"))) jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0 |
361 | (JNIEnv *env, jclass klass, jint fd) |
362 | { |
363 | void *addr_buf, *laddr; |
364 | int i, addrCount; |
365 | jobjectArray isaa; |
366 | |
367 | if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) { |
368 | handleSocketError(env, errno(*__errno_location ())); |
369 | return NULL((void*)0); |
370 | } |
371 | |
372 | if (addrCount < 1) |
373 | return NULL((void*)0); |
374 | |
375 | if (isaCls == 0) { |
376 | initializeISA(env); |
377 | CHECK_NULL_RETURN(isaCls, NULL)do { if ((isaCls) == ((void*)0)) { return (((void*)0)); } } while (0); |
378 | } |
379 | |
380 | isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL((void*)0)); |
381 | if (isaa == NULL((void*)0)) { |
382 | nio_sctp_freeladdrs(addr_buf); |
383 | return NULL((void*)0); |
384 | } |
385 | |
386 | laddr = addr_buf; |
387 | for (i = 0; i < addrCount; i++) { |
388 | int port = 0; |
389 | jobject ia, isa = NULL((void*)0); |
390 | ia = NET_SockaddrToInetAddress(env, (SOCKETADDRESS *)addr_buf, &port); |
391 | if (ia != NULL((void*)0)) |
392 | isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port); |
393 | if (isa == NULL((void*)0)) |
394 | break; |
395 | (*env)->SetObjectArrayElement(env, isaa, i, isa); |
396 | |
397 | if (((struct sockaddr *)addr_buf)->sa_family == AF_INET2) |
398 | addr_buf = ((struct sockaddr_in *)addr_buf) + 1; |
399 | else |
400 | addr_buf = ((struct sockaddr_in6 *)addr_buf) + 1; |
401 | } |
402 | |
403 | nio_sctp_freeladdrs(laddr); |
404 | return isaa; |
405 | } |
406 | |
407 | jobjectArray getRemoteAddresses(JNIEnv *env, jint fd, sctp_assoc_t id) { |
408 | void *addr_buf, *paddr; |
409 | int i, addrCount; |
410 | jobjectArray isaa; |
411 | |
412 | if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr **)&addr_buf)) == -1) { |
413 | handleSocketError(env, errno(*__errno_location ())); |
414 | return NULL((void*)0); |
415 | } |
416 | |
417 | if (addrCount < 1) |
418 | return NULL((void*)0); |
419 | |
420 | if (isaCls == 0) { |
421 | initializeISA(env); |
422 | CHECK_NULL_RETURN(isaCls, NULL)do { if ((isaCls) == ((void*)0)) { return (((void*)0)); } } while (0); |
423 | } |
424 | |
425 | isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL((void*)0)); |
426 | if (isaa == NULL((void*)0)) { |
427 | nio_sctp_freepaddrs(addr_buf); |
428 | return NULL((void*)0); |
429 | } |
430 | |
431 | paddr = addr_buf; |
432 | for (i = 0; i < addrCount; i++) { |
433 | int port = 0; |
434 | jobject ia, isa = NULL((void*)0); |
435 | ia = NET_SockaddrToInetAddress(env, (SOCKETADDRESS *)addr_buf, &port); |
436 | if (ia != NULL((void*)0)) |
437 | isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port); |
438 | if (isa == NULL((void*)0)) |
439 | break; |
440 | (*env)->SetObjectArrayElement(env, isaa, i, isa); |
441 | |
442 | if (((struct sockaddr *)addr_buf)->sa_family == AF_INET2) |
443 | addr_buf = ((struct sockaddr_in *)addr_buf) + 1; |
444 | else |
445 | addr_buf = ((struct sockaddr_in6 *)addr_buf) + 1; |
446 | } |
447 | |
448 | nio_sctp_freepaddrs(paddr); |
449 | return isaa; |
450 | } |
451 | |
452 | /* |
453 | * Class: sun_nio_ch_sctp_SctpNet |
454 | * Method: getRemoteAddresses0 |
455 | * Signature: (II)[Ljava/net/SocketAddress; |
456 | */ |
457 | JNIEXPORT__attribute__((visibility("default"))) jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getRemoteAddresses0 |
458 | (JNIEnv *env, jclass klass, jint fd, jint assocId) { |
459 | return getRemoteAddresses(env, fd, assocId); |
460 | } |
461 | |
462 | /* Map the Java level option to the native level */ |
463 | int mapSocketOption |
464 | (jint cmd, int *level, int *optname) { |
465 | static struct { |
466 | jint cmd; |
467 | int level; |
468 | int optname; |
469 | } const opts[] = { |
470 | { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_DISABLE_FRAGMENTS1L, IPPROTO_SCTPIPPROTO_SCTP, SCTP_DISABLE_FRAGMENTSSCTP_DISABLE_FRAGMENTS }, |
471 | { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_EXPLICIT_COMPLETE2L, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EXPLICIT_EOR-1 }, |
472 | { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_FRAGMENT_INTERLEAVE3L, IPPROTO_SCTPIPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVESCTP_FRAGMENT_INTERLEAVE }, |
473 | { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_NODELAY4L, IPPROTO_SCTPIPPROTO_SCTP, SCTP_NODELAYSCTP_NODELAY }, |
474 | { sun_nio_ch_sctp_SctpStdSocketOption_SO_SNDBUF5L, SOL_SOCKET1, SO_SNDBUF7 }, |
475 | { sun_nio_ch_sctp_SctpStdSocketOption_SO_RCVBUF6L, SOL_SOCKET1, SO_RCVBUF8 }, |
476 | { sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER7L, SOL_SOCKET1, SO_LINGER13 } }; |
477 | |
478 | int i; |
479 | for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) { |
480 | if (cmd == opts[i].cmd) { |
481 | *level = opts[i].level; |
482 | *optname = opts[i].optname; |
483 | return 0; |
484 | } |
485 | } |
486 | |
487 | /* not found */ |
488 | return -1; |
489 | } |
490 | |
491 | /* |
492 | * Class: sun_nio_ch_sctp_SctpNet |
493 | * Method: setIntOption0 |
494 | * Signature: (III)V |
495 | */ |
496 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_setIntOption0 |
497 | (JNIEnv *env, jclass klass, jint fd, jint opt, int arg) { |
498 | int klevel, kopt; |
499 | int result; |
500 | struct linger linger; |
501 | void *parg; |
502 | int arglen; |
503 | |
504 | if (mapSocketOption(opt, &klevel, &kopt) < 0) { |
505 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
506 | "Unsupported socket option"); |
507 | return; |
508 | } |
509 | |
510 | if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER7L) { |
511 | parg = (void *)&linger; |
512 | arglen = sizeof(linger); |
513 | if (arg >= 0) { |
514 | linger.l_onoff = 1; |
515 | linger.l_linger = arg; |
516 | } else { |
517 | linger.l_onoff = 0; |
518 | linger.l_linger = 0; |
519 | } |
520 | } else { |
521 | parg = (void *)&arg; |
522 | arglen = sizeof(arg); |
523 | } |
524 | |
525 | if (NET_SetSockOpt(fd, klevel, kopt, parg, arglen) < 0) { |
526 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
527 | "sun_nio_ch_sctp_SctpNet.setIntOption0"); |
528 | } |
529 | } |
530 | |
531 | /* |
532 | * Class: sun_nio_ch_sctp_SctpNet |
533 | * Method: getIntOption0 |
534 | * Signature: (II)I |
535 | */ |
536 | JNIEXPORT__attribute__((visibility("default"))) int JNICALL Java_sun_nio_ch_sctp_SctpNet_getIntOption0 |
537 | (JNIEnv *env, jclass klass, jint fd, jint opt) { |
538 | int klevel, kopt; |
539 | int result; |
540 | struct linger linger; |
541 | void *arg; |
542 | int arglen; |
543 | |
544 | memset((char *) &linger, 0, sizeof(linger)); |
545 | if (mapSocketOption(opt, &klevel, &kopt) < 0) { |
546 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
547 | "Unsupported socket option"); |
548 | return -1; |
549 | } |
550 | |
551 | if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER7L) { |
552 | arg = (void *)&linger; |
553 | arglen = sizeof(linger); |
554 | } else { |
555 | arg = (void *)&result; |
556 | arglen = sizeof(result); |
557 | } |
558 | |
559 | if (NET_GetSockOpt(fd, klevel, kopt, arg, &arglen) < 0) { |
560 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
561 | "sun.nio.ch.Net.getIntOption"); |
562 | return -1; |
563 | } |
564 | |
565 | if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER7L) |
566 | return linger.l_onoff ? linger.l_linger : -1; |
567 | else |
568 | return result; |
569 | } |
570 | |
571 | /* |
572 | * Class: sun_nio_ch_sctp_SctpNet |
573 | * Method: getPrimAddrOption0 |
574 | * Signature: (II)Ljava/net/SocketAddress; |
575 | */ |
576 | JNIEXPORT__attribute__((visibility("default"))) jobject JNICALL Java_sun_nio_ch_sctp_SctpNet_getPrimAddrOption0 |
577 | (JNIEnv *env, jclass klass, jint fd, jint assocId) { |
578 | struct sctp_setprim prim; |
579 | unsigned int prim_len = sizeof(prim); |
580 | |
581 | prim.ssp_assoc_id = assocId; |
582 | |
583 | if (getsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_PRIMARY_ADDRSCTP_PRIMARY_ADDR, &prim, &prim_len) < 0) { |
584 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
585 | "sun.nio.ch.SctpNet.getPrimAddrOption0"); |
586 | return NULL((void*)0); |
587 | } |
588 | |
589 | return SockAddrToInetSocketAddress(env, (SOCKETADDRESS *)&prim.ssp_addr); |
590 | } |
591 | |
592 | /* |
593 | * Class: sun_nio_ch_sctp_SctpNet |
594 | * Method: setPrimAddrOption0 |
595 | * Signature: (IILjava/net/InetAddress;I)V |
596 | */ |
597 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_setPrimAddrOption0 |
598 | (JNIEnv *env, jclass klass, jint fd, jint assocId, jobject iaObj, jint port) { |
599 | struct sctp_setprim prim; |
600 | |
601 | if (NET_InetAddressToSockaddr(env, iaObj, port, |
602 | (SOCKETADDRESS *)&prim.ssp_addr, |
603 | NULL((void*)0), JNI_TRUE1) != 0) { |
604 | return; |
605 | } |
606 | |
607 | prim.ssp_assoc_id = assocId; |
608 | |
609 | if (setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_PRIMARY_ADDRSCTP_PRIMARY_ADDR, &prim, sizeof(prim)) < 0) { |
610 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
611 | "sun.nio.ch.SctpNet.setPrimAddrOption0"); |
612 | } |
613 | } |
614 | |
615 | /* |
616 | * Class: sun_nio_ch_sctp_SctpNet |
617 | * Method: setPeerPrimAddrOption0 |
618 | * Signature: (IILjava/net/InetAddress;I)V |
619 | */ |
620 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_setPeerPrimAddrOption0 |
621 | (JNIEnv *env, jclass klass, jint fd, jint assocId, |
622 | jobject iaObj, jint port, jboolean preferIPv6) { |
623 | struct sctp_setpeerprim prim; |
624 | |
625 | if (NET_InetAddressToSockaddr(env, iaObj, port, |
626 | (SOCKETADDRESS *)&prim.sspp_addr, |
627 | NULL((void*)0), preferIPv6) != 0) { |
628 | return; |
629 | } |
630 | |
631 | prim.sspp_assoc_id = assocId; |
632 | |
633 | if (setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDRSCTP_SET_PEER_PRIMARY_ADDR, &prim, |
634 | sizeof(prim)) < 0) { |
635 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
636 | "sun.nio.ch.SctpNet.setPeerPrimAddrOption0"); |
637 | } |
638 | } |
639 | |
640 | /* |
641 | * Class: sun_nio_ch_sctp_SctpNet |
642 | * Method: getInitMsgOption0 |
643 | * Signature: (I[I)V |
644 | */ |
645 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_getInitMsgOption0 |
646 | (JNIEnv *env, jclass klass, jint fd, jintArray retVal) { |
647 | struct sctp_initmsg sctp_initmsg; |
648 | unsigned int sim_len = sizeof(sctp_initmsg); |
649 | int vals[2]; |
650 | |
651 | if (getsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_INITMSGSCTP_INITMSG, &sctp_initmsg, |
652 | &sim_len) < 0) { |
653 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
654 | "sun.nio.ch.SctpNet.getInitMsgOption0"); |
655 | return; |
656 | } |
657 | |
658 | vals[0] = sctp_initmsg.sinit_max_instreams; |
659 | vals[1] = sctp_initmsg.sinit_num_ostreams; |
660 | (*env)->SetIntArrayRegion(env, retVal, 0, 2, vals); |
661 | } |
662 | |
663 | /* |
664 | * Class: sun_nio_ch_sctp_SctpNet |
665 | * Method: setInitMsgOption0 |
666 | * Signature: (III)V |
667 | */ |
668 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_setInitMsgOption0 |
669 | (JNIEnv *env, jclass klass, jint fd, jint inArg, jint outArg) { |
670 | struct sctp_initmsg sctp_initmsg; |
671 | |
672 | sctp_initmsg.sinit_max_instreams = (unsigned int)inArg; |
673 | sctp_initmsg.sinit_num_ostreams = (unsigned int)outArg; |
674 | sctp_initmsg.sinit_max_attempts = 0; // default |
675 | sctp_initmsg.sinit_max_init_timeo = 0; // default |
676 | |
677 | if (setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_INITMSGSCTP_INITMSG, &sctp_initmsg, |
678 | sizeof(sctp_initmsg)) < 0) { |
679 | JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG"java/net/" "SocketException", |
680 | "sun.nio.ch.SctpNet.setInitMsgOption0"); |
681 | } |
682 | } |
683 | |
684 | /* |
685 | * Class: sun_nio_ch_sctp_SctpNet |
686 | * Method: shutdown0 |
687 | * Signature: (II)V |
688 | */ |
689 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL Java_sun_nio_ch_sctp_SctpNet_shutdown0 |
690 | (JNIEnv *env, jclass klass, jint fd, jint assocId) { |
691 | int rv; |
692 | struct msghdr msg[1]; |
693 | struct iovec iov[1]; |
694 | int cbuf_size = CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))((((sizeof (struct sctp_sndrcvinfo)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr )) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1 ))); |
695 | char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))((((sizeof (struct sctp_sndrcvinfo)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr )) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1 )))]; |
696 | struct cmsghdr* cmsg; |
697 | struct sctp_sndrcvinfo *sri; |
698 | |
699 | /* SctpSocketChannel */ |
700 | if (assocId < 0) { |
701 | shutdown(fd, SHUT_WRSHUT_WR); |
702 | return; |
703 | } |
704 | |
705 | memset(msg, 0, sizeof (*msg)); |
706 | memset(cbuf, 0, cbuf_size); |
707 | msg->msg_name = NULL((void*)0); |
708 | msg->msg_namelen = 0; |
709 | iov->iov_base = NULL((void*)0); |
710 | iov->iov_len = 0; |
711 | msg->msg_iov = iov; |
712 | msg->msg_iovlen = 1; |
713 | msg->msg_control = cbuf; |
714 | msg->msg_controllen = cbuf_size; |
715 | msg->msg_flags = 0; |
716 | |
717 | cmsg = CMSG_FIRSTHDR(msg)((size_t) (msg)->msg_controllen >= sizeof (struct cmsghdr ) ? (struct cmsghdr *) (msg)->msg_control : (struct cmsghdr *) 0); |
718 | cmsg->cmsg_level = IPPROTO_SCTPIPPROTO_SCTP; |
719 | cmsg->cmsg_type = SCTP_SNDRCVSCTP_SNDRCV; |
720 | cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (sizeof(struct sctp_sndrcvinfo))); |
721 | |
722 | /* Initialize the payload: */ |
723 | sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg)((cmsg)->__cmsg_data); |
724 | memset(sri, 0, sizeof (*sri)); |
725 | |
726 | if (assocId > 0) { |
727 | sri->sinfo_assoc_id = assocId; |
728 | } |
729 | |
730 | sri->sinfo_flags = sri->sinfo_flags | SCTP_EOF; |
731 | |
732 | /* Sum of the length of all control messages in the buffer. */ |
733 | msg->msg_controllen = cmsg->cmsg_len; |
734 | |
735 | if ((rv = sendmsg(fd, msg, 0)) < 0) { |
Although the value stored to 'rv' is used in the enclosing expression, the value is never actually read from 'rv' | |
736 | handleSocketError(env, errno(*__errno_location ())); |
737 | } |
738 | } |
739 | |
740 | /* |
741 | * Class: sun_nio_ch_sctp_SctpNet |
742 | * Method: branch |
743 | * Signature: (II)I |
744 | */ |
745 | JNIEXPORT__attribute__((visibility("default"))) int JNICALL Java_sun_nio_ch_sctp_SctpNet_branch0 |
746 | (JNIEnv *env, jclass klass, jint fd, jint assocId) { |
747 | int newfd = 0; |
748 | if ((newfd = nio_sctp_peeloff(fd, assocId)) < 0) { |
749 | handleSocketError(env, errno(*__errno_location ())); |
750 | } |
751 | |
752 | return newfd; |
753 | } |