34 #include "nio_util.h" |
34 #include "nio_util.h" |
35 #include "net_util.h" |
35 #include "net_util.h" |
36 |
36 |
37 #include "sun_nio_ch_Net.h" |
37 #include "sun_nio_ch_Net.h" |
38 |
38 |
39 |
39 /** |
40 static jfieldID ia_addrID; |
40 * Definitions to allow for building with older SDK include files. |
41 static jclass ia_class; |
|
42 static jmethodID ia_ctorID; |
|
43 static jfieldID ia_famID; |
|
44 |
|
45 /************************************************************** |
|
46 * static method to store field IDs in initializers |
|
47 */ |
41 */ |
48 |
42 |
|
43 #ifndef MCAST_BLOCK_SOURCE |
|
44 |
|
45 #define MCAST_BLOCK_SOURCE 43 |
|
46 #define MCAST_UNBLOCK_SOURCE 44 |
|
47 #define MCAST_JOIN_SOURCE_GROUP 45 |
|
48 #define MCAST_LEAVE_SOURCE_GROUP 46 |
|
49 |
|
50 #endif /* MCAST_BLOCK_SOURCE */ |
|
51 |
|
52 typedef struct my_ip_mreq_source { |
|
53 IN_ADDR imr_multiaddr; |
|
54 IN_ADDR imr_sourceaddr; |
|
55 IN_ADDR imr_interface; |
|
56 }; |
|
57 |
|
58 typedef struct my_group_source_req { |
|
59 ULONG gsr_interface; |
|
60 SOCKADDR_STORAGE gsr_group; |
|
61 SOCKADDR_STORAGE gsr_source; |
|
62 }; |
|
63 |
|
64 /** |
|
65 * Copy IPv6 address as jbytearray to target |
|
66 */ |
|
67 #define COPY_INET6_ADDRESS(env, source, target) \ |
|
68 (*env)->GetByteArrayRegion(env, source, 0, 16, target) |
|
69 |
|
70 |
|
71 |
49 JNIEXPORT void JNICALL |
72 JNIEXPORT void JNICALL |
50 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) |
73 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) |
51 { |
74 { |
52 clazz = (*env)->FindClass(env, "java/net/Inet4Address"); |
75 /* nothing to do */ |
53 ia_class = (*env)->NewGlobalRef(env, clazz); |
76 } |
54 ia_addrID = (*env)->GetFieldID(env, clazz, "address", "I"); |
77 |
55 ia_famID = (*env)->GetFieldID(env, clazz, "family", "I"); |
78 JNIEXPORT jboolean JNICALL |
56 ia_ctorID = (*env)->GetMethodID(env, clazz, "<init>", "()V"); |
79 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) |
57 } |
80 { |
58 |
81 /* |
59 |
82 * Return true if Windows Vista or newer, and IPv6 is configured |
60 JNIEXPORT jint JNICALL |
83 */ |
61 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream, |
84 OSVERSIONINFO ver; |
62 jboolean reuse) |
85 ver.dwOSVersionInfoSize = sizeof(ver); |
|
86 GetVersionEx(&ver); |
|
87 if ((ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && |
|
88 (ver.dwMajorVersion >= 6) && ipv6_available()) |
|
89 { |
|
90 return JNI_TRUE; |
|
91 } |
|
92 return JNI_FALSE; |
|
93 } |
|
94 |
|
95 JNIEXPORT jint JNICALL |
|
96 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, |
|
97 jboolean stream, jboolean reuse) |
63 { |
98 { |
64 SOCKET s; |
99 SOCKET s; |
65 |
100 int domain = (preferIPv6) ? AF_INET6 : AF_INET; |
66 s = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0); |
101 |
|
102 s = socket(domain, (stream ? SOCK_STREAM : SOCK_DGRAM), 0); |
67 if (s != INVALID_SOCKET) { |
103 if (s != INVALID_SOCKET) { |
68 SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0); |
104 SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0); |
|
105 |
|
106 /* IPV6_V6ONLY is true by default */ |
|
107 if (domain == AF_INET6) { |
|
108 int opt = 0; |
|
109 setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, |
|
110 (const char *)&opt, sizeof(opt)); |
|
111 } |
69 } else { |
112 } else { |
70 NET_ThrowNew(env, WSAGetLastError(), "socket"); |
113 NET_ThrowNew(env, WSAGetLastError(), "socket"); |
71 } |
114 } |
|
115 |
72 return (jint)s; |
116 return (jint)s; |
73 } |
117 } |
74 |
118 |
75 JNIEXPORT void JNICALL |
119 JNIEXPORT void JNICALL |
76 Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, |
120 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6, |
77 jobject fdo, jobject iao, jint port) |
121 jobject fdo, jobject iao, jint port) |
78 { |
122 { |
79 SOCKETADDRESS sa; |
123 SOCKETADDRESS sa; |
80 int rv; |
124 int rv; |
81 int sa_len = sizeof(sa); |
125 int sa_len; |
82 |
126 |
83 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) { |
127 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { |
84 return; |
128 return; |
85 } |
129 } |
86 |
130 |
87 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); |
131 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); |
88 if (rv == SOCKET_ERROR) |
132 if (rv == SOCKET_ERROR) |
89 NET_ThrowNew(env, WSAGetLastError(), "bind"); |
133 NET_ThrowNew(env, WSAGetLastError(), "bind"); |
90 } |
134 } |
91 |
135 |
92 JNIEXPORT jint JNICALL |
136 JNIEXPORT void JNICALL |
93 Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, jobject fdo, jobject iao, |
137 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog) |
94 jint port, jint trafficClass) |
138 { |
|
139 if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) { |
|
140 NET_ThrowNew(env, WSAGetLastError(), "listen"); |
|
141 } |
|
142 } |
|
143 |
|
144 |
|
145 JNIEXPORT jint JNICALL |
|
146 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo, |
|
147 jobject iao, jint port) |
95 { |
148 { |
96 SOCKETADDRESS sa; |
149 SOCKETADDRESS sa; |
97 int rv; |
150 int rv; |
98 int sa_len = sizeof(sa); |
151 int sa_len; |
99 |
152 |
100 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) { |
153 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { |
101 return IOS_THROWN; |
154 return IOS_THROWN; |
102 } |
155 } |
103 |
156 |
104 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); |
157 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); |
105 if (rv != 0) { |
158 if (rv != 0) { |
106 int err = WSAGetLastError(); |
159 int err = WSAGetLastError(); |
114 } |
167 } |
115 |
168 |
116 JNIEXPORT jint JNICALL |
169 JNIEXPORT jint JNICALL |
117 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo) |
170 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo) |
118 { |
171 { |
119 struct sockaddr_in sa; |
172 SOCKETADDRESS sa; |
120 int sa_len = sizeof(sa); |
173 int sa_len = sizeof(sa); |
121 |
174 |
122 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { |
175 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { |
123 int error = WSAGetLastError(); |
176 int error = WSAGetLastError(); |
124 if (error == WSAEINVAL) { |
177 if (error == WSAEINVAL) { |
125 return 0; |
178 return 0; |
126 } |
179 } |
127 NET_ThrowNew(env, error, "getsockname"); |
180 NET_ThrowNew(env, error, "getsockname"); |
128 return IOS_THROWN; |
181 return IOS_THROWN; |
129 } |
182 } |
130 return (jint)ntohs(sa.sin_port); |
183 return NET_GetPortFromSockaddr((struct sockaddr *)&sa); |
131 } |
184 } |
132 |
185 |
133 JNIEXPORT jobject JNICALL |
186 JNIEXPORT jobject JNICALL |
134 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo) |
187 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo) |
135 { |
188 { |
136 struct sockaddr_in sa; |
189 SOCKETADDRESS sa; |
137 int sa_len = sizeof(sa); |
190 int sa_len = sizeof(sa); |
138 jobject iao; |
191 int port; |
139 |
192 |
140 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { |
193 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { |
141 NET_ThrowNew(env, WSAGetLastError(), "getsockname"); |
194 NET_ThrowNew(env, WSAGetLastError(), "getsockname"); |
142 return NULL; |
195 return NULL; |
143 } |
196 } |
144 |
197 return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); |
145 iao = (*env)->NewObject(env, ia_class, ia_ctorID); |
198 } |
146 if (iao == NULL) { |
199 |
147 JNU_ThrowOutOfMemoryError(env, "heap allocation failure"); |
200 JNIEXPORT jint JNICALL |
148 } else { |
201 Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo) |
149 (*env)->SetIntField(env, iao, ia_addrID, ntohl(sa.sin_addr.s_addr)); |
202 { |
150 } |
203 SOCKETADDRESS sa; |
151 |
204 int sa_len = sizeof(sa); |
152 return iao; |
205 |
153 } |
206 if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { |
154 |
207 int error = WSAGetLastError(); |
155 |
208 if (error == WSAEINVAL) { |
156 JNIEXPORT jint JNICALL |
209 return 0; |
157 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, |
210 } |
158 jobject fdo, jint opt) |
211 NET_ThrowNew(env, error, "getsockname"); |
159 { |
212 return IOS_THROWN; |
160 int klevel, kopt; |
213 } |
161 int result; |
214 return NET_GetPortFromSockaddr((struct sockaddr *)&sa); |
|
215 } |
|
216 |
|
217 JNIEXPORT jobject JNICALL |
|
218 Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo) |
|
219 { |
|
220 SOCKETADDRESS sa; |
|
221 int sa_len = sizeof(sa); |
|
222 int port; |
|
223 |
|
224 if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { |
|
225 NET_ThrowNew(env, WSAGetLastError(), "getsockname"); |
|
226 return NULL; |
|
227 } |
|
228 return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); |
|
229 } |
|
230 |
|
231 JNIEXPORT jint JNICALL |
|
232 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, |
|
233 jboolean mayNeedConversion, jint level, jint opt) |
|
234 { |
|
235 int result = 0; |
162 struct linger linger; |
236 struct linger linger; |
163 char *arg; |
237 char *arg; |
164 int arglen; |
238 int arglen, n; |
165 |
239 |
166 if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) { |
240 if (level == SOL_SOCKET && opt == SO_LINGER) { |
167 JNU_ThrowByNameWithLastError(env, |
|
168 JNU_JAVANETPKG "SocketException", |
|
169 "Unsupported socket option"); |
|
170 return IOS_THROWN; |
|
171 } |
|
172 |
|
173 if (opt == java_net_SocketOptions_SO_LINGER) { |
|
174 arg = (char *)&linger; |
241 arg = (char *)&linger; |
175 arglen = sizeof(linger); |
242 arglen = sizeof(linger); |
176 } else { |
243 } else { |
177 arg = (char *)&result; |
244 arg = (char *)&result; |
178 arglen = sizeof(result); |
245 arglen = sizeof(result); |
179 } |
246 } |
180 |
247 |
181 if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) { |
248 /** |
182 NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption"); |
249 * HACK: IP_TOS is deprecated on Windows and querying the option |
183 return IOS_THROWN; |
250 * returns a protocol error. NET_GetSockOpt handles this and uses |
184 } |
251 * a fallback mechanism. |
185 |
252 */ |
186 if (opt == java_net_SocketOptions_SO_LINGER) |
253 if (level == IPPROTO_IP && opt == IP_TOS) { |
|
254 mayNeedConversion = JNI_TRUE; |
|
255 } |
|
256 |
|
257 if (mayNeedConversion) { |
|
258 n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen); |
|
259 } else { |
|
260 n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen); |
|
261 } |
|
262 if (n < 0) { |
|
263 handleSocketError(env, WSAGetLastError()); |
|
264 return IOS_THROWN; |
|
265 } |
|
266 |
|
267 if (level == SOL_SOCKET && opt == SO_LINGER) |
187 return linger.l_onoff ? linger.l_linger : -1; |
268 return linger.l_onoff ? linger.l_linger : -1; |
188 else |
269 else |
189 return result; |
270 return result; |
190 } |
271 } |
191 |
272 |
192 JNIEXPORT void JNICALL |
273 JNIEXPORT void JNICALL |
193 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, |
274 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, |
194 jobject fdo, jint opt, jint arg) |
275 jboolean mayNeedConversion, jint level, jint opt, jint arg) |
195 { |
276 { |
196 int klevel, kopt; |
|
197 struct linger linger; |
277 struct linger linger; |
198 char *parg; |
278 char *parg; |
199 int arglen; |
279 int arglen, n; |
200 |
280 |
201 if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) { |
281 if (level == SOL_SOCKET && opt == SO_LINGER) { |
202 JNU_ThrowByNameWithLastError(env, |
|
203 JNU_JAVANETPKG "SocketException", |
|
204 "Unsupported socket option"); |
|
205 return; |
|
206 } |
|
207 |
|
208 if (opt == java_net_SocketOptions_SO_LINGER) { |
|
209 parg = (char *)&linger; |
282 parg = (char *)&linger; |
210 arglen = sizeof(linger); |
283 arglen = sizeof(linger); |
211 if (arg >= 0) { |
284 if (arg >= 0) { |
212 linger.l_onoff = 1; |
285 linger.l_onoff = 1; |
213 linger.l_linger = (unsigned short)arg; |
286 linger.l_linger = (unsigned short)arg; |
218 } else { |
291 } else { |
219 parg = (char *)&arg; |
292 parg = (char *)&arg; |
220 arglen = sizeof(arg); |
293 arglen = sizeof(arg); |
221 } |
294 } |
222 |
295 |
223 if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) { |
296 if (mayNeedConversion) { |
224 NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption"); |
297 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen); |
225 } |
298 } else { |
226 } |
299 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen); |
|
300 } |
|
301 if (n < 0) |
|
302 handleSocketError(env, WSAGetLastError()); |
|
303 } |
|
304 |
|
305 JNIEXPORT jint JNICALL |
|
306 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo, |
|
307 jint group, jint interf, jint source) |
|
308 { |
|
309 struct ip_mreq mreq; |
|
310 struct my_ip_mreq_source mreq_source; |
|
311 int opt, n, optlen; |
|
312 void* optval; |
|
313 |
|
314 if (source == 0) { |
|
315 mreq.imr_multiaddr.s_addr = htonl(group); |
|
316 mreq.imr_interface.s_addr = htonl(interf); |
|
317 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; |
|
318 optval = (void*)&mreq; |
|
319 optlen = sizeof(mreq); |
|
320 } else { |
|
321 mreq_source.imr_multiaddr.s_addr = htonl(group); |
|
322 mreq_source.imr_sourceaddr.s_addr = htonl(source); |
|
323 mreq_source.imr_interface.s_addr = htonl(interf); |
|
324 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP; |
|
325 optval = (void*)&mreq_source; |
|
326 optlen = sizeof(mreq_source); |
|
327 } |
|
328 |
|
329 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen); |
|
330 if (n < 0) { |
|
331 if (join && (WSAGetLastError() == WSAENOPROTOOPT)) |
|
332 return IOS_UNAVAILABLE; |
|
333 handleSocketError(env, WSAGetLastError()); |
|
334 } |
|
335 return 0; |
|
336 } |
|
337 |
|
338 JNIEXPORT jint JNICALL |
|
339 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo, |
|
340 jint group, jint interf, jint source) |
|
341 { |
|
342 struct my_ip_mreq_source mreq_source; |
|
343 int n; |
|
344 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE; |
|
345 |
|
346 mreq_source.imr_multiaddr.s_addr = htonl(group); |
|
347 mreq_source.imr_sourceaddr.s_addr = htonl(source); |
|
348 mreq_source.imr_interface.s_addr = htonl(interf); |
|
349 |
|
350 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, |
|
351 (void*)&mreq_source, sizeof(mreq_source)); |
|
352 if (n < 0) { |
|
353 if (block && (WSAGetLastError() == WSAENOPROTOOPT)) |
|
354 return IOS_UNAVAILABLE; |
|
355 handleSocketError(env, WSAGetLastError()); |
|
356 } |
|
357 return 0; |
|
358 } |
|
359 |
|
360 /** |
|
361 * Call setsockopt with a IPPROTO_IPV6 level socket option |
|
362 * and a group_source_req structure as the option value. The |
|
363 * given IPv6 group, interface index, and IPv6 source address |
|
364 * are copied into the structure. |
|
365 */ |
|
366 static int setGroupSourceReqOption(JNIEnv* env, |
|
367 jobject fdo, |
|
368 int opt, |
|
369 jbyteArray group, |
|
370 jint index, |
|
371 jbyteArray source) |
|
372 { |
|
373 struct my_group_source_req req; |
|
374 struct sockaddr_in6* sin6; |
|
375 |
|
376 req.gsr_interface = (ULONG)index; |
|
377 |
|
378 sin6 = (struct sockaddr_in6*)&(req.gsr_group); |
|
379 sin6->sin6_family = AF_INET6; |
|
380 COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr)); |
|
381 |
|
382 sin6 = (struct sockaddr_in6*)&(req.gsr_source); |
|
383 sin6->sin6_family = AF_INET6; |
|
384 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr)); |
|
385 |
|
386 return setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, (void*)&req, sizeof(req)); |
|
387 } |
|
388 |
|
389 JNIEXPORT jint JNICALL |
|
390 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo, |
|
391 jbyteArray group, jint index, jbyteArray source) |
|
392 { |
|
393 struct ipv6_mreq mreq6; |
|
394 int n; |
|
395 |
|
396 if (source == NULL) { |
|
397 int opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP; |
|
398 COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr)); |
|
399 mreq6.ipv6mr_interface = (int)index; |
|
400 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, |
|
401 (void*)&mreq6, sizeof(mreq6)); |
|
402 } else { |
|
403 int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP; |
|
404 n = setGroupSourceReqOption(env, fdo, opt, group, index, source); |
|
405 } |
|
406 |
|
407 if (n < 0) { |
|
408 handleSocketError(env, errno); |
|
409 } |
|
410 return 0; |
|
411 } |
|
412 |
|
413 JNIEXPORT jint JNICALL |
|
414 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo, |
|
415 jbyteArray group, jint index, jbyteArray source) |
|
416 { |
|
417 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE; |
|
418 int n = setGroupSourceReqOption(env, fdo, opt, group, index, source); |
|
419 if (n < 0) { |
|
420 handleSocketError(env, errno); |
|
421 } |
|
422 return 0; |
|
423 } |
|
424 |
|
425 JNIEXPORT void JNICALL |
|
426 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf) |
|
427 { |
|
428 struct in_addr in; |
|
429 int arglen = sizeof(struct in_addr); |
|
430 int n; |
|
431 |
|
432 in.s_addr = htonl(interf); |
|
433 |
|
434 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, |
|
435 (void*)&(in.s_addr), arglen); |
|
436 if (n < 0) { |
|
437 handleSocketError(env, WSAGetLastError()); |
|
438 } |
|
439 } |
|
440 |
|
441 JNIEXPORT jint JNICALL |
|
442 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo) |
|
443 { |
|
444 struct in_addr in; |
|
445 int arglen = sizeof(struct in_addr); |
|
446 int n; |
|
447 |
|
448 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen); |
|
449 if (n < 0) { |
|
450 handleSocketError(env, WSAGetLastError()); |
|
451 return IOS_THROWN; |
|
452 } |
|
453 return ntohl(in.s_addr); |
|
454 } |
|
455 |
|
456 JNIEXPORT void JNICALL |
|
457 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index) |
|
458 { |
|
459 int value = (jint)index; |
|
460 int arglen = sizeof(value); |
|
461 int n; |
|
462 |
|
463 n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, |
|
464 (void*)&(index), arglen); |
|
465 if (n < 0) { |
|
466 handleSocketError(env, errno); |
|
467 } |
|
468 } |
|
469 |
|
470 JNIEXPORT jint JNICALL |
|
471 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo) |
|
472 { |
|
473 int index; |
|
474 int arglen = sizeof(index); |
|
475 int n; |
|
476 |
|
477 n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen); |
|
478 if (n < 0) { |
|
479 handleSocketError(env, errno); |
|
480 return -1; |
|
481 } |
|
482 return (jint)index; |
|
483 } |
|
484 |
|
485 JNIEXPORT void JNICALL |
|
486 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow) { |
|
487 int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SD_RECEIVE : |
|
488 (jhow == sun_nio_ch_Net_SHUT_WR) ? SD_SEND : SD_BOTH; |
|
489 if (shutdown(fdval(env, fdo), how) == SOCKET_ERROR) { |
|
490 NET_ThrowNew(env, WSAGetLastError(), "shutdown"); |
|
491 } |
|
492 } |