35 |
obligated to do so. If you do not wish to do so, delete this |
obligated to do so. If you do not wish to do so, delete this |
36 |
exception statement from your version. */ |
exception statement from your version. */ |
37 |
|
|
38 |
|
/* do not move; needed here because of some macro definitions */ |
39 |
|
#include <config.h> |
40 |
|
|
|
#include <stdio.h> |
|
41 |
#include <stdlib.h> |
#include <stdlib.h> |
42 |
|
#include <stdio.h> |
43 |
#include <string.h> |
#include <string.h> |
44 |
#include <errno.h> |
#include <assert.h> |
|
#include <unistd.h> |
|
|
#include <sys/types.h> |
|
|
#include <sys/socket.h> |
|
|
#include <netinet/in.h> |
|
|
#include <netinet/tcp.h> |
|
45 |
|
|
46 |
#include <jni.h> |
#include <jni.h> |
47 |
#include <jcl.h> |
#include <jcl.h> |
48 |
|
|
49 |
#include "javanet.h" |
#include "javanet.h" |
50 |
|
|
51 |
|
#include "target_native.h" |
52 |
|
#ifndef WITHOUT_NETWORK |
53 |
|
#include "target_native_network.h" |
54 |
|
#endif /* WITHOUT_NETWORK */ |
55 |
|
|
56 |
|
#ifndef WITHOUT_NETWORK |
57 |
/* Need to have some value for SO_TIMEOUT */ |
/* Need to have some value for SO_TIMEOUT */ |
58 |
#ifndef SO_TIMEOUT |
#ifndef SO_TIMEOUT |
59 |
#ifndef SO_RCVTIMEO |
#ifndef SO_RCVTIMEO |
63 |
#define SO_TIMEOUT SO_RCVTIMEO |
#define SO_TIMEOUT SO_RCVTIMEO |
64 |
#endif /* not SO_RCVTIMEO */ |
#endif /* not SO_RCVTIMEO */ |
65 |
#endif /* not SO_TIMEOUT */ |
#endif /* not SO_TIMEOUT */ |
66 |
|
#endif /* WITHOUT_NETWORK */ |
67 |
|
|
68 |
/*************************************************************************/ |
/*************************************************************************/ |
69 |
|
|
74 |
_javanet_set_int_field(JNIEnv *env, jobject obj, char *class, char *field, |
_javanet_set_int_field(JNIEnv *env, jobject obj, char *class, char *field, |
75 |
int val) |
int val) |
76 |
{ |
{ |
77 |
jclass cls; |
jclass cls; |
78 |
jfieldID fid; |
jfieldID fid; |
79 |
|
|
80 |
|
assert(env!=NULL); |
81 |
|
assert((*env)!=NULL); |
82 |
|
|
83 |
cls = (*env)->FindClass(env, class); |
cls = (*env)->FindClass(env, class); |
84 |
if (cls == NULL) |
if (cls == NULL) |
85 |
return; |
return; |
106 |
jfieldID fid; |
jfieldID fid; |
107 |
int fd; |
int fd; |
108 |
|
|
109 |
|
assert(env!=NULL); |
110 |
|
assert((*env)!=NULL); |
111 |
|
|
112 |
DBG("_javanet_get_int_field(): Entered _javanet_get_int_field\n"); |
DBG("_javanet_get_int_field(): Entered _javanet_get_int_field\n"); |
113 |
|
|
114 |
cls = (*env)->GetObjectClass(env, obj); |
cls = (*env)->GetObjectClass(env, obj); |
135 |
static void |
static void |
136 |
_javanet_create_localfd(JNIEnv *env, jobject this) |
_javanet_create_localfd(JNIEnv *env, jobject this) |
137 |
{ |
{ |
138 |
jclass this_cls, fd_cls; |
jclass this_cls, fd_cls; |
139 |
jfieldID fid; |
jfieldID fid; |
140 |
jmethodID mid; |
jmethodID mid; |
141 |
jobject fd_obj; |
jobject fd_obj; |
142 |
|
|
143 |
|
assert(env!=NULL); |
144 |
|
assert((*env)!=NULL); |
145 |
|
|
146 |
DBG("_javanet_create_localfd(): Entered _javanet_create_localfd\n"); |
DBG("_javanet_create_localfd(): Entered _javanet_create_localfd\n"); |
147 |
|
|
190 |
static jobject |
static jobject |
191 |
_javanet_create_boolean(JNIEnv *env, jboolean val) |
_javanet_create_boolean(JNIEnv *env, jboolean val) |
192 |
{ |
{ |
193 |
jclass cls; |
jclass cls; |
194 |
jmethodID mid; |
jmethodID mid; |
195 |
jobject obj; |
jobject obj; |
196 |
|
|
197 |
|
assert(env!=NULL); |
198 |
|
assert((*env)!=NULL); |
199 |
|
|
200 |
cls = (*env)->FindClass(env, "java/lang/Boolean"); |
cls = (*env)->FindClass(env, "java/lang/Boolean"); |
201 |
if (cls == NULL) |
if (cls == NULL) |
224 |
jmethodID mid; |
jmethodID mid; |
225 |
jobject obj; |
jobject obj; |
226 |
|
|
227 |
|
assert(env!=NULL); |
228 |
|
assert((*env)!=NULL); |
229 |
|
|
230 |
cls = (*env)->FindClass(env, "java/lang/Integer"); |
cls = (*env)->FindClass(env, "java/lang/Integer"); |
231 |
if (cls == NULL) |
if (cls == NULL) |
232 |
return NULL; |
return NULL; |
250 |
static jobject |
static jobject |
251 |
_javanet_create_inetaddress(JNIEnv *env, int netaddr) |
_javanet_create_inetaddress(JNIEnv *env, int netaddr) |
252 |
{ |
{ |
253 |
char buf[16]; |
#ifndef WITHOUT_NETWORK |
254 |
jclass ia_cls; |
unsigned char octets[4]; |
255 |
jmethodID mid; |
char buf[16]; |
256 |
jstring ip_str; |
jclass ia_cls; |
257 |
jobject ia; |
jmethodID mid; |
258 |
|
jstring ip_str; |
259 |
|
jobject ia; |
260 |
|
|
261 |
|
assert(env!=NULL); |
262 |
|
assert((*env)!=NULL); |
263 |
|
|
264 |
/* Build a string IP address */ |
/* Build a string IP address */ |
265 |
sprintf(buf, "%d.%d.%d.%d", ((netaddr & 0xFF000000) >> 24), |
TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES(netaddr, |
266 |
((netaddr & 0x00FF0000) >> 16), ((netaddr &0x0000FF00) >> 8), |
octets[0], |
267 |
(netaddr & 0x000000FF)); |
octets[1], |
268 |
|
octets[2], |
269 |
|
octets[3] |
270 |
|
); |
271 |
|
sprintf(buf, "%d.%d.%d.%d", |
272 |
|
octets[0], |
273 |
|
octets[1], |
274 |
|
octets[2], |
275 |
|
octets[3] |
276 |
|
); |
277 |
DBG("_javanet_create_inetaddress(): Created ip addr string\n"); |
DBG("_javanet_create_inetaddress(): Created ip addr string\n"); |
278 |
|
|
279 |
/* Get an InetAddress object for this IP */ |
/* Get an InetAddress object for this IP */ |
280 |
ia_cls = (*env)->FindClass(env, "java/net/InetAddress"); |
ia_cls = (*env)->FindClass(env, "java/net/InetAddress"); |
281 |
if (ia_cls == NULL) |
if (ia_cls == NULL) |
282 |
return NULL; |
{ |
283 |
|
return NULL; |
284 |
|
} |
285 |
|
|
286 |
DBG("_javanet_create_inetaddress(): Found InetAddress class\n"); |
DBG("_javanet_create_inetaddress(): Found InetAddress class\n"); |
287 |
|
|
288 |
mid = (*env)->GetStaticMethodID(env, ia_cls, "getByName", |
mid = (*env)->GetStaticMethodID(env, ia_cls, "getByName", |
289 |
"(Ljava/lang/String;)Ljava/net/InetAddress;"); |
"(Ljava/lang/String;)Ljava/net/InetAddress;"); |
290 |
if (mid == NULL) |
if (mid == NULL) |
291 |
return NULL; |
{ |
292 |
|
return NULL; |
293 |
|
} |
294 |
|
|
295 |
DBG("_javanet_create_inetaddress(): Found getByName method\n"); |
DBG("_javanet_create_inetaddress(): Found getByName method\n"); |
296 |
|
|
297 |
ip_str = (*env)->NewStringUTF(env, buf); |
ip_str = (*env)->NewStringUTF(env, buf); |
298 |
if (ip_str == NULL) |
if (ip_str == NULL) |
299 |
return NULL; |
{ |
300 |
|
return NULL; |
301 |
|
} |
302 |
|
|
303 |
ia = (*env)->CallStaticObjectMethod(env, ia_cls, mid, ip_str); |
ia = (*env)->CallStaticObjectMethod(env, ia_cls, mid, ip_str); |
304 |
if (ia == NULL) |
if (ia == NULL) |
305 |
return NULL; |
{ |
306 |
|
return NULL; |
307 |
|
} |
308 |
|
|
309 |
DBG("_javanet_create_inetaddress(): Called getByName method\n"); |
DBG("_javanet_create_inetaddress(): Called getByName method\n"); |
310 |
|
|
311 |
return ia; |
return ia; |
312 |
|
#else /* not WITHOUT_NETWORK */ |
313 |
|
return NULL; |
314 |
|
#endif /* not WITHOUT_NETWORK */ |
315 |
} |
} |
316 |
|
|
317 |
/*************************************************************************/ |
/*************************************************************************/ |
318 |
|
|
319 |
static void _javanet_set_remhost_addr(JNIEnv*, jobject, jobject); |
static void |
320 |
|
_javanet_set_remhost_addr(JNIEnv *env, jobject this, jobject ia) |
321 |
|
{ |
322 |
|
jclass this_cls; |
323 |
|
jfieldID fid; |
324 |
|
|
325 |
|
assert(env!=NULL); |
326 |
|
assert((*env)!=NULL); |
327 |
|
|
328 |
|
/* Set the variable in the object */ |
329 |
|
this_cls = (*env)->FindClass(env, "java/net/SocketImpl"); |
330 |
|
if (this_cls == NULL) |
331 |
|
return; |
332 |
|
|
333 |
|
fid = (*env)->GetFieldID(env, this_cls, "address", "Ljava/net/InetAddress;"); |
334 |
|
if (fid == NULL) |
335 |
|
return; |
336 |
|
|
337 |
|
DBG("_javanet_set_remhost_addr(): Found address field\n"); |
338 |
|
|
339 |
|
(*env)->SetObjectField(env, this, fid, ia); |
340 |
|
DBG("_javanet_set_remhost_addr(): Set field\n"); |
341 |
|
} |
342 |
|
|
343 |
/* |
/* |
344 |
* Set's the value of the "addr" field in PlainSocketImpl with a new |
* Set's the value of the "addr" field in PlainSocketImpl with a new |
349 |
{ |
{ |
350 |
jobject ia; |
jobject ia; |
351 |
|
|
352 |
|
assert(env!=NULL); |
353 |
|
assert((*env)!=NULL); |
354 |
|
|
355 |
DBG("_javanet_set_remhost(): Entered _javanet_set_remhost\n"); |
DBG("_javanet_set_remhost(): Entered _javanet_set_remhost\n"); |
356 |
|
|
357 |
/* Get an InetAddress object */ |
/* Get an InetAddress object */ |
362 |
_javanet_set_remhost_addr(env, this, ia); |
_javanet_set_remhost_addr(env, this, ia); |
363 |
} |
} |
364 |
|
|
|
static void |
|
|
_javanet_set_remhost_addr(JNIEnv *env, jobject this, jobject ia) |
|
|
{ |
|
|
jclass this_cls; |
|
|
jfieldID fid; |
|
|
|
|
|
/* Set the variable in the object */ |
|
|
this_cls = (*env)->FindClass(env, "java/net/SocketImpl"); |
|
|
if (this_cls == NULL) |
|
|
return; |
|
|
|
|
|
fid = (*env)->GetFieldID(env, this_cls, "address", "Ljava/net/InetAddress;"); |
|
|
if (fid == NULL) |
|
|
return; |
|
|
|
|
|
DBG("_javanet_set_remhost_addr(): Found address field\n"); |
|
|
|
|
|
(*env)->SetObjectField(env, this, fid, ia); |
|
|
DBG("_javanet_set_remhost_addr(): Set field\n"); |
|
|
} |
|
365 |
|
|
366 |
/*************************************************************************/ |
/*************************************************************************/ |
367 |
|
|
371 |
int |
int |
372 |
_javanet_get_netaddr(JNIEnv *env, jobject addr) |
_javanet_get_netaddr(JNIEnv *env, jobject addr) |
373 |
{ |
{ |
374 |
jclass cls = 0; |
#ifndef WITHOUT_NETWORK |
375 |
|
jclass cls = 0; |
376 |
jmethodID mid; |
jmethodID mid; |
377 |
jarray arr = 0; |
jarray arr = 0; |
378 |
jbyte *octets; |
jbyte *octets; |
379 |
int netaddr, len; |
int netaddr, len; |
380 |
|
|
381 |
|
assert(env!=NULL); |
382 |
|
assert((*env)!=NULL); |
383 |
|
|
384 |
DBG("_javanet_get_netaddr(): Entered _javanet_get_netaddr\n"); |
DBG("_javanet_get_netaddr(): Entered _javanet_get_netaddr\n"); |
385 |
|
|
415 |
|
|
416 |
DBG("_javanet_get_netaddr(): Grabbed bytes\n"); |
DBG("_javanet_get_netaddr(): Grabbed bytes\n"); |
417 |
|
|
418 |
netaddr = (((unsigned char)octets[0]) << 24) + |
TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT(octets[0], |
419 |
(((unsigned char)octets[1]) << 16) + |
octets[1], |
420 |
(((unsigned char)octets[2]) << 8) + |
octets[2], |
421 |
((unsigned char)octets[3]); |
octets[3], |
422 |
|
netaddr |
423 |
netaddr = htonl(netaddr); |
); |
424 |
|
|
425 |
(*env)->ReleaseByteArrayElements(env, arr, octets, 0); |
(*env)->ReleaseByteArrayElements(env, arr, octets, 0); |
426 |
DBG("_javanet_get_netaddr(): Done getting addr\n"); |
DBG("_javanet_get_netaddr(): Done getting addr\n"); |
427 |
|
|
428 |
return netaddr; |
return netaddr; |
429 |
|
#else /* not WITHOUT_NETWORK */ |
430 |
|
#endif /* not WITHOUT_NETWORK */ |
431 |
} |
} |
432 |
|
|
433 |
/*************************************************************************/ |
/*************************************************************************/ |
438 |
void |
void |
439 |
_javanet_create(JNIEnv *env, jobject this, jboolean stream) |
_javanet_create(JNIEnv *env, jobject this, jboolean stream) |
440 |
{ |
{ |
441 |
|
#ifndef WITHOUT_NETWORK |
442 |
int fd; |
int fd; |
443 |
|
int result; |
444 |
|
|
445 |
|
assert(env!=NULL); |
446 |
|
assert((*env)!=NULL); |
447 |
|
|
448 |
if (stream) |
if (stream) |
449 |
fd = socket(AF_INET, SOCK_STREAM, 0); |
TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM(fd,result); |
450 |
else |
else |
451 |
fd = socket(AF_INET, SOCK_DGRAM, 0); |
TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM(fd,result); |
452 |
|
|
453 |
if (fd == -1) |
if (result != TARGET_NATIVE_OK) |
454 |
{ JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); return; } |
{ |
455 |
|
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
456 |
|
return; |
457 |
|
} |
458 |
|
|
459 |
if (stream) |
if (stream) |
460 |
_javanet_set_int_field(env, this, "java/net/PlainSocketImpl", |
_javanet_set_int_field(env, this, "java/net/PlainSocketImpl", |
462 |
else |
else |
463 |
_javanet_set_int_field(env, this, "java/net/PlainDatagramSocketImpl", |
_javanet_set_int_field(env, this, "java/net/PlainDatagramSocketImpl", |
464 |
"native_fd", fd); |
"native_fd", fd); |
465 |
|
#else /* not WITHOUT_NETWORK */ |
466 |
|
#endif /* not WITHOUT_NETWORK */ |
467 |
} |
} |
468 |
|
|
469 |
/*************************************************************************/ |
/*************************************************************************/ |
475 |
void |
void |
476 |
_javanet_close(JNIEnv *env, jobject this, int stream) |
_javanet_close(JNIEnv *env, jobject this, int stream) |
477 |
{ |
{ |
478 |
int fd = -1; |
#ifndef WITHOUT_NETWORK |
479 |
|
int fd; |
480 |
|
int result; |
481 |
|
|
482 |
|
assert(env!=NULL); |
483 |
|
assert((*env)!=NULL); |
484 |
|
|
485 |
fd = _javanet_get_int_field(env, this, "native_fd"); |
fd = _javanet_get_int_field(env, this, "native_fd"); |
486 |
if (fd == -1) |
if (fd == -1) |
487 |
return; |
return; |
488 |
|
|
489 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
490 |
|
|
491 |
if (stream) |
if (stream) |
492 |
_javanet_set_int_field(env, this, "java/net/PlainSocketImpl", |
_javanet_set_int_field(env, this, "java/net/PlainSocketImpl", |
494 |
else |
else |
495 |
_javanet_set_int_field(env, this, "java/net/PlainDatagramSocketImpl", |
_javanet_set_int_field(env, this, "java/net/PlainDatagramSocketImpl", |
496 |
"native_fd", -1); |
"native_fd", -1); |
497 |
|
#else /* not WITHOUT_NETWORK */ |
498 |
|
#endif /* not WITHOUT_NETWORK */ |
499 |
} |
} |
500 |
|
|
501 |
/*************************************************************************/ |
/*************************************************************************/ |
506 |
void |
void |
507 |
_javanet_connect(JNIEnv *env, jobject this, jobject addr, jint port) |
_javanet_connect(JNIEnv *env, jobject this, jobject addr, jint port) |
508 |
{ |
{ |
509 |
int netaddr, fd = -1, rc, addrlen; |
#ifndef WITHOUT_NETWORK |
510 |
struct sockaddr_in si; |
int netaddr, fd; |
511 |
|
int result; |
512 |
|
int local_address,local_port; |
513 |
|
int remote_address,remote_port; |
514 |
|
|
515 |
|
assert(env!=NULL); |
516 |
|
assert((*env)!=NULL); |
517 |
|
|
518 |
DBG("_javanet_connect(): Entered _javanet_connect\n"); |
DBG("_javanet_connect(): Entered _javanet_connect\n"); |
519 |
|
|
537 |
DBG("_javanet_connect(): Got native fd\n"); |
DBG("_javanet_connect(): Got native fd\n"); |
538 |
|
|
539 |
/* Connect up */ |
/* Connect up */ |
540 |
memset(&si, 0, sizeof(struct sockaddr_in)); |
TARGET_NATIVE_NETWORK_SOCKET_CONNECT(fd,netaddr,port,result); |
541 |
si.sin_family = AF_INET; |
if (result != TARGET_NATIVE_OK) |
542 |
si.sin_addr.s_addr = netaddr; |
{ |
543 |
si.sin_port = htons(((short)port)); |
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
544 |
|
return; |
545 |
rc = connect(fd, (struct sockaddr *) &si, sizeof(struct sockaddr_in)); |
} |
|
if (rc == -1) |
|
|
{ JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); return; } |
|
546 |
DBG("_javanet_connect(): Connected successfully\n"); |
DBG("_javanet_connect(): Connected successfully\n"); |
547 |
|
|
548 |
/* Populate instance variables */ |
/* Populate instance variables */ |
549 |
addrlen = sizeof(struct sockaddr_in); |
TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO(fd,local_address,local_port,result); |
550 |
rc = getsockname(fd, (struct sockaddr *) &si, &addrlen); |
if (result != TARGET_NATIVE_OK) |
|
if (rc == -1) |
|
551 |
{ |
{ |
552 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
553 |
JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
554 |
return; |
return; |
555 |
} |
} |
556 |
|
|
557 |
_javanet_create_localfd(env, this); |
_javanet_create_localfd(env, this); |
558 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
559 |
{ |
{ |
560 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
561 |
return; |
return; |
562 |
} |
} |
563 |
DBG("_javanet_connect(): Created fd\n"); |
DBG("_javanet_connect(): Created fd\n"); |
564 |
|
|
565 |
_javanet_set_int_field(env, this, "java/net/SocketImpl", "localport", |
_javanet_set_int_field(env, this, "java/net/SocketImpl", "localport", |
566 |
ntohs(si.sin_port)); |
local_port); |
567 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
568 |
{ |
{ |
569 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
570 |
return; |
return; |
571 |
} |
} |
572 |
DBG("_javanet_connect(): Set the local port\n"); |
DBG("_javanet_connect(): Set the local port\n"); |
573 |
|
|
574 |
addrlen = sizeof(struct sockaddr_in); |
TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO(fd,remote_address,remote_port,result); |
575 |
rc = getpeername(fd, (struct sockaddr *) &si, &addrlen); |
if (result != TARGET_NATIVE_OK) |
|
if (rc == -1) |
|
576 |
{ |
{ |
577 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
578 |
JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
579 |
return; |
return; |
580 |
} |
} |
581 |
|
|
582 |
_javanet_set_remhost_addr(env, this, addr); |
_javanet_set_remhost(env, this, remote_address); |
583 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
584 |
{ |
{ |
585 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
586 |
return; |
return; |
587 |
} |
} |
588 |
DBG("_javanet_connect(): Set the remote host\n"); |
DBG("_javanet_connect(): Set the remote host\n"); |
589 |
|
|
590 |
_javanet_set_int_field(env, this, "java/net/SocketImpl", "port", |
_javanet_set_int_field(env, this, "java/net/SocketImpl", "port", |
591 |
ntohs(si.sin_port)); |
remote_port); |
592 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
593 |
{ |
{ |
594 |
close(fd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
595 |
return; |
return; |
596 |
} |
} |
597 |
DBG("_javanet_connect(): Set the remote port\n"); |
DBG("_javanet_connect(): Set the remote port\n"); |
598 |
|
#else /* not WITHOUT_NETWORK */ |
599 |
|
#endif /* not WITHOUT_NETWORK */ |
600 |
} |
} |
601 |
|
|
602 |
/*************************************************************************/ |
/*************************************************************************/ |
609 |
void |
void |
610 |
_javanet_bind(JNIEnv *env, jobject this, jobject addr, jint port, int stream) |
_javanet_bind(JNIEnv *env, jobject this, jobject addr, jint port, int stream) |
611 |
{ |
{ |
612 |
jclass cls; |
#ifndef WITHOUT_NETWORK |
613 |
jmethodID mid; |
jclass cls; |
614 |
|
jmethodID mid; |
615 |
jbyteArray arr = 0; |
jbyteArray arr = 0; |
616 |
jbyte *octets; |
jbyte *octets; |
617 |
jint fd; |
jint fd; |
618 |
struct sockaddr_in si; |
int tmpaddr; |
619 |
int namelen; |
int result; |
620 |
|
int local_address,local_port; |
621 |
|
|
622 |
|
assert(env!=NULL); |
623 |
|
assert((*env)!=NULL); |
624 |
|
|
625 |
DBG("_javanet_bind(): Entering native bind()\n"); |
DBG("_javanet_bind(): Entering native bind()\n"); |
626 |
|
|
658 |
} |
} |
659 |
DBG("_javanet_bind(): Past native_fd lookup\n"); |
DBG("_javanet_bind(): Past native_fd lookup\n"); |
660 |
|
|
661 |
|
// NYI ??? |
662 |
_javanet_set_option (env, this, SOCKOPT_SO_REUSEADDR, |
_javanet_set_option (env, this, SOCKOPT_SO_REUSEADDR, |
663 |
_javanet_create_boolean (env, JNI_TRUE)); |
_javanet_create_boolean (env, JNI_TRUE)); |
664 |
|
|
665 |
|
|
666 |
/* Bind the socket */ |
/* Bind the socket */ |
667 |
memset(&si, 0, sizeof(struct sockaddr_in)); |
TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT(octets[0], |
668 |
|
octets[1], |
669 |
si.sin_family = AF_INET; |
octets[2], |
670 |
si.sin_addr.s_addr = *(int *)octets; /* Already in network byte order */ |
octets[3], |
671 |
if (port == -1) |
tmpaddr |
672 |
si.sin_port = 0; |
); |
673 |
else |
TARGET_NATIVE_NETWORK_SOCKET_BIND(fd,tmpaddr,port,result); |
|
si.sin_port = htons(port); |
|
674 |
|
|
675 |
(*env)->ReleaseByteArrayElements(env, arr, octets, 0); |
(*env)->ReleaseByteArrayElements(env, arr, octets, 0); |
676 |
|
|
677 |
if (bind(fd, (struct sockaddr *) &si, sizeof(struct sockaddr_in)) == -1) |
if (result != TARGET_NATIVE_OK) |
678 |
{ JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); return; } |
{ |
679 |
|
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
680 |
|
return; |
681 |
|
} |
682 |
DBG("_javanet_bind(): Past bind\n"); |
DBG("_javanet_bind(): Past bind\n"); |
683 |
|
|
684 |
/* Update instance variables, specifically the local port number */ |
/* Update instance variables, specifically the local port number */ |
685 |
namelen = sizeof(struct sockaddr_in); |
TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO(fd,local_address,local_port,result); |
686 |
getsockname(fd, (struct sockaddr *) &si, &namelen); |
if (result != TARGET_NATIVE_OK) |
687 |
|
{ |
688 |
|
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
689 |
|
return; |
690 |
|
} |
691 |
|
|
692 |
if (stream) |
if (stream) |
693 |
_javanet_set_int_field(env, this, "java/net/SocketImpl", |
_javanet_set_int_field(env, this, "java/net/SocketImpl", |
694 |
"localport", ntohs(si.sin_port)); |
"localport", local_port); |
695 |
else |
else |
696 |
_javanet_set_int_field(env, this, "java/net/DatagramSocketImpl", |
_javanet_set_int_field(env, this, "java/net/DatagramSocketImpl", |
697 |
"localPort", ntohs(si.sin_port)); |
"localPort", local_port); |
698 |
DBG("_javanet_bind(): Past update port number\n"); |
DBG("_javanet_bind(): Past update port number\n"); |
699 |
|
|
700 |
return; |
return; |
701 |
|
#else /* not WITHOUT_NETWORK */ |
702 |
|
#endif /* not WITHOUT_NETWORK */ |
703 |
} |
} |
704 |
|
|
705 |
/*************************************************************************/ |
/*************************************************************************/ |
711 |
void |
void |
712 |
_javanet_listen(JNIEnv *env, jobject this, jint queuelen) |
_javanet_listen(JNIEnv *env, jobject this, jint queuelen) |
713 |
{ |
{ |
714 |
int fd = -1, rc; |
#ifndef WITHOUT_NETWORK |
715 |
|
int fd; |
716 |
|
int result; |
717 |
|
|
718 |
|
assert(env!=NULL); |
719 |
|
assert((*env)!=NULL); |
720 |
|
|
721 |
/* Get the real file descriptor */ |
/* Get the real file descriptor */ |
722 |
fd = _javanet_get_int_field(env, this, "native_fd"); |
fd = _javanet_get_int_field(env, this, "native_fd"); |
728 |
} |
} |
729 |
|
|
730 |
/* Start listening */ |
/* Start listening */ |
731 |
rc = listen(fd, queuelen); |
TARGET_NATIVE_NETWORK_SOCKET_LISTEN(fd,queuelen,result); |
732 |
if (rc == -1) |
if (result!=TARGET_NATIVE_OK) |
733 |
{ JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); return; } |
{ |
734 |
|
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
735 |
return; |
return; |
736 |
|
} |
737 |
|
#else /* not WITHOUT_NETWORK */ |
738 |
|
#endif /* not WITHOUT_NETWORK */ |
739 |
} |
} |
740 |
|
|
741 |
/*************************************************************************/ |
/*************************************************************************/ |
747 |
void |
void |
748 |
_javanet_accept(JNIEnv *env, jobject this, jobject impl) |
_javanet_accept(JNIEnv *env, jobject this, jobject impl) |
749 |
{ |
{ |
750 |
int fd = -1, newfd, addrlen, rc; |
#ifndef WITHOUT_NETWORK |
751 |
struct sockaddr_in si; |
int fd, newfd; |
752 |
|
int result; |
753 |
|
int local_address,local_port; |
754 |
|
int remote_address,remote_port; |
755 |
|
|
756 |
|
assert(env!=NULL); |
757 |
|
assert((*env)!=NULL); |
758 |
|
|
759 |
/* Get the real file descriptor */ |
/* Get the real file descriptor */ |
760 |
fd = _javanet_get_int_field(env, this, "native_fd"); |
fd = _javanet_get_int_field(env, this, "native_fd"); |
766 |
} |
} |
767 |
|
|
768 |
/* Accept the connection */ |
/* Accept the connection */ |
|
addrlen = sizeof(struct sockaddr_in); |
|
|
memset(&si, 0, addrlen); |
|
|
|
|
769 |
/******* Do we need to look for EINTR? */ |
/******* Do we need to look for EINTR? */ |
770 |
newfd = accept(fd, (struct sockaddr *) &si, &addrlen); |
TARGET_NATIVE_NETWORK_SOCKET_ACCEPT(fd,newfd,result); |
771 |
if (newfd == -1) |
if (result != TARGET_NATIVE_OK) |
772 |
{ JCL_ThrowException(env, IO_EXCEPTION, "Internal error: _javanet_accept(): "); return; } |
{ |
773 |
|
JCL_ThrowException(env, IO_EXCEPTION, "Internal error: _javanet_accept(): "); |
774 |
|
return; |
775 |
|
} |
776 |
|
|
777 |
/* Populate instance variables */ |
/* Populate instance variables */ |
778 |
_javanet_set_int_field(env, impl, "java/net/PlainSocketImpl", "native_fd", |
_javanet_set_int_field(env, impl, "java/net/PlainSocketImpl", "native_fd", |
780 |
|
|
781 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
782 |
{ |
{ |
783 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
784 |
return; |
return; |
785 |
} |
} |
786 |
|
|
787 |
rc = getsockname(newfd, (struct sockaddr *) &si, &addrlen); |
TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO(newfd,local_address,local_port,result); |
788 |
if (rc == -1) |
if (result!=TARGET_NATIVE_OK) |
789 |
{ |
{ |
790 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
791 |
JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
792 |
return; |
return; |
793 |
} |
} |
794 |
|
|
795 |
_javanet_create_localfd(env, impl); |
_javanet_create_localfd(env, impl); |
796 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
797 |
{ |
{ |
798 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
799 |
return; |
return; |
800 |
} |
} |
801 |
|
|
802 |
_javanet_set_int_field(env, impl, "java/net/SocketImpl", "localport", |
_javanet_set_int_field(env, impl, "java/net/SocketImpl", "localport", |
803 |
ntohs(si.sin_port)); |
local_port); |
804 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
805 |
{ |
{ |
806 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
807 |
return; |
return; |
808 |
} |
} |
809 |
|
|
810 |
addrlen = sizeof(struct sockaddr_in); |
TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO(newfd,remote_address,remote_port,result); |
811 |
rc = getpeername(newfd, (struct sockaddr *) &si, &addrlen); |
if (result!=TARGET_NATIVE_OK) |
|
if (rc == -1) |
|
812 |
{ |
{ |
813 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
814 |
JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
815 |
return; |
return; |
816 |
} |
} |
817 |
|
|
818 |
_javanet_set_remhost(env, impl, ntohl(si.sin_addr.s_addr)); |
_javanet_set_remhost(env, impl, remote_address); |
819 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
820 |
{ |
{ |
821 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
822 |
return; |
return; |
823 |
} |
} |
824 |
|
|
825 |
_javanet_set_int_field(env, impl, "java/net/SocketImpl", "port", |
_javanet_set_int_field(env, impl, "java/net/SocketImpl", "port", |
826 |
ntohs(si.sin_port)); |
remote_port); |
827 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
828 |
{ |
{ |
829 |
close(newfd); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(newfd,result); |
830 |
return; |
return; |
831 |
} |
} |
832 |
|
#else /* not WITHOUT_NETWORK */ |
833 |
|
#endif /* not WITHOUT_NETWORK */ |
834 |
} |
} |
835 |
|
|
836 |
/*************************************************************************/ |
/*************************************************************************/ |
853 |
_javanet_recvfrom(JNIEnv *env, jobject this, jarray buf, int offset, int len, |
_javanet_recvfrom(JNIEnv *env, jobject this, jarray buf, int offset, int len, |
854 |
int *addr, int *port) |
int *addr, int *port) |
855 |
{ |
{ |
856 |
int fd, rc, si_len; |
#ifndef WITHOUT_NETWORK |
857 |
|
int fd; |
858 |
jbyte *p; |
jbyte *p; |
859 |
struct sockaddr_in si; |
int from_address,from_port; |
860 |
|
int received_bytes; |
861 |
|
|
862 |
|
assert(env!=NULL); |
863 |
|
assert((*env)!=NULL); |
864 |
|
|
865 |
DBG("_javanet_recvfrom(): Entered _javanet_recvfrom\n"); |
DBG("_javanet_recvfrom(): Entered _javanet_recvfrom\n"); |
866 |
|
|
882 |
DBG("_javanet_recvfrom(): Got buffer\n"); |
DBG("_javanet_recvfrom(): Got buffer\n"); |
883 |
|
|
884 |
/* Read the data */ |
/* Read the data */ |
885 |
for (;;) |
from_address = 0; |
886 |
{ |
from_port = 0; |
887 |
if (addr == NULL) |
do { |
888 |
rc = recv(fd, p + offset, len, 0); |
if (addr != NULL) |
889 |
else |
{ |
890 |
{ |
TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT(fd,p+offset,len,from_address,from_port,received_bytes); |
891 |
memset(&si, 0, sizeof(struct sockaddr_in)); |
} |
892 |
si_len = sizeof(struct sockaddr_in); |
else |
893 |
rc = recvfrom(fd, p + offset, len, 0, (struct sockaddr *) &si, &si_len); |
{ |
894 |
} |
TARGET_NATIVE_NETWORK_SOCKET_RECEIVE(fd,p+offset,len,received_bytes); |
895 |
|
} |
896 |
if ((rc == -1) && (errno == EINTR)) |
} while ((received_bytes == -1) && |
897 |
continue; |
(TARGET_NATIVE_LAST_ERROR() == TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL) |
898 |
|
); |
|
break; |
|
|
} |
|
899 |
|
|
900 |
(*env)->ReleaseByteArrayElements(env, buf, p, 0); |
(*env)->ReleaseByteArrayElements(env, buf, p, 0); |
901 |
|
|
902 |
if (rc == -1) |
if (received_bytes == -1) |
903 |
{ JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); return 0; } |
{ |
904 |
|
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
905 |
|
return 0; |
906 |
|
} |
907 |
|
|
908 |
/* Handle return addr case */ |
/* Handle return addr case */ |
909 |
if (addr) |
if (addr != NULL) |
910 |
{ |
{ |
911 |
*addr = si.sin_addr.s_addr; |
(*addr) = from_address; |
912 |
if (port) |
if (port != NULL) |
913 |
*port = si.sin_port; |
(*port) = from_port; |
914 |
} |
} |
915 |
|
|
916 |
return(rc); |
return(received_bytes); |
917 |
|
#else /* not WITHOUT_NETWORK */ |
918 |
|
#endif /* not WITHOUT_NETWORK */ |
919 |
} |
} |
920 |
|
|
921 |
/*************************************************************************/ |
/*************************************************************************/ |
933 |
_javanet_sendto(JNIEnv *env, jobject this, jarray buf, int offset, int len, |
_javanet_sendto(JNIEnv *env, jobject this, jarray buf, int offset, int len, |
934 |
int addr, int port) |
int addr, int port) |
935 |
{ |
{ |
936 |
int fd, rc; |
#ifndef WITHOUT_NETWORK |
937 |
|
int fd; |
938 |
jbyte *p; |
jbyte *p; |
939 |
struct sockaddr_in si; |
int bytes_sent; |
940 |
|
|
941 |
|
assert(env!=NULL); |
942 |
|
assert((*env)!=NULL); |
943 |
|
|
944 |
/* Get the real file descriptor */ |
/* Get the real file descriptor */ |
945 |
fd = _javanet_get_int_field(env, this, "native_fd"); |
fd = _javanet_get_int_field(env, this, "native_fd"); |
959 |
if (addr == 0) |
if (addr == 0) |
960 |
{ |
{ |
961 |
DBG("_javanet_sendto(): Sending....\n"); |
DBG("_javanet_sendto(): Sending....\n"); |
962 |
rc = send(fd, p + offset, len, 0); |
TARGET_NATIVE_NETWORK_SOCKET_SEND(fd,p+offset,len,bytes_sent); |
963 |
} |
} |
964 |
else |
else |
965 |
{ |
{ |
|
memset(&si, 0, sizeof(struct sockaddr_in)); |
|
|
si.sin_family = AF_INET; |
|
|
si.sin_addr.s_addr = addr; |
|
|
si.sin_port = (unsigned short)port; |
|
|
|
|
966 |
DBG("_javanet_sendto(): Sending....\n"); |
DBG("_javanet_sendto(): Sending....\n"); |
967 |
rc = sendto(fd, p + offset, len, 0, (struct sockaddr *) &si, sizeof(struct sockaddr_in)); |
TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT(fd,p+offset,len,addr,port,bytes_sent); |
968 |
} |
} |
969 |
|
|
970 |
(*env)->ReleaseByteArrayElements(env, buf, p, 0); |
(*env)->ReleaseByteArrayElements(env, buf, p, 0); |
971 |
|
|
972 |
/***** Do we need to check EINTR? */ |
/***** Do we need to check EINTR? */ |
973 |
if (rc == -1) |
if (bytes_sent<0) |
974 |
{ JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); return; } |
{ |
975 |
|
JCL_ThrowException(env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
976 |
return; |
return; |
977 |
|
} |
978 |
|
#else /* not WITHOUT_NETWORK */ |
979 |
|
#endif /* not WITHOUT_NETWORK */ |
980 |
} |
} |
981 |
|
|
982 |
/*************************************************************************/ |
/*************************************************************************/ |
987 |
void |
void |
988 |
_javanet_set_option(JNIEnv *env, jobject this, jint option_id, jobject val) |
_javanet_set_option(JNIEnv *env, jobject this, jint option_id, jobject val) |
989 |
{ |
{ |
990 |
int fd = -1, rc; |
#ifndef WITHOUT_NETWORK |
991 |
int optval, sockopt; |
int fd; |
992 |
jclass cls; |
int optval; |
993 |
|
jclass cls; |
994 |
jmethodID mid; |
jmethodID mid; |
995 |
struct linger linger; |
int address; |
996 |
struct sockaddr_in si; |
int result; |
997 |
|
|
998 |
|
assert(env!=NULL); |
999 |
|
assert((*env)!=NULL); |
1000 |
|
|
1001 |
/* Get the real file descriptor */ |
/* Get the real file descriptor */ |
1002 |
fd = _javanet_get_int_field(env, this, "native_fd"); |
fd = _javanet_get_int_field(env, this, "native_fd"); |
1013 |
return; |
return; |
1014 |
|
|
1015 |
/* Process the option request */ |
/* Process the option request */ |
1016 |
|
result = TARGET_NATIVE_ERROR; |
1017 |
switch (option_id) |
switch (option_id) |
1018 |
{ |
{ |
1019 |
/* TCP_NODELAY case. val is a Boolean that tells us what to do */ |
/* TCP_NODELAY case. val is a Boolean that tells us what to do */ |
1028 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1029 |
return; |
return; |
1030 |
|
|
1031 |
rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)); |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY(fd,optval,result); |
1032 |
break; |
break; |
1033 |
|
|
1034 |
/* SO_LINGER case. If val is a boolean, then it will always be set |
/* SO_LINGER case. If val is a boolean, then it will always be set |
1035 |
to false indicating disable linger, otherwise it will be an |
to false indicating disable linger, otherwise it will be an |
1036 |
integer that contains the linger value */ |
integer that contains the linger value */ |
1037 |
case SOCKOPT_SO_LINGER: |
case SOCKOPT_SO_LINGER: |
|
memset(&linger, 0, sizeof(struct linger)); |
|
|
|
|
1038 |
mid = (*env)->GetMethodID(env, cls, "booleanValue", "()Z"); |
mid = (*env)->GetMethodID(env, cls, "booleanValue", "()Z"); |
1039 |
if (mid) |
if (mid) |
1040 |
{ |
{ |
1041 |
/* We are disabling linger */ |
/* We are disabling linger */ |
1042 |
linger.l_onoff = 0; |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER(fd,1,0,result); |
1043 |
} |
} |
1044 |
else |
else |
1045 |
{ |
{ |
1053 |
{ JCL_ThrowException(env, IO_EXCEPTION, |
{ JCL_ThrowException(env, IO_EXCEPTION, |
1054 |
"Internal error: _javanet_set_option()"); return; } |
"Internal error: _javanet_set_option()"); return; } |
1055 |
|
|
1056 |
linger.l_linger = (*env)->CallIntMethod(env, val, mid); |
optval= (*env)->CallIntMethod(env, val, mid); |
1057 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1058 |
return; |
return; |
1059 |
|
|
1060 |
linger.l_onoff = 1; |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER(fd,0,optval,result); |
1061 |
} |
} |
|
rc = setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, |
|
|
sizeof(struct linger)); |
|
1062 |
break; |
break; |
1063 |
|
|
1064 |
/* SO_TIMEOUT case. Val will be an integer with the new value */ |
/* SO_TIMEOUT case. Val will be an integer with the new value */ |
1074 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1075 |
return; |
return; |
1076 |
|
|
1077 |
rc = setsockopt(fd, SOL_SOCKET, SO_TIMEOUT, &optval, sizeof(int)); |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT(fd,optval,result); |
1078 |
#endif |
#endif |
1079 |
return; // ignore errors and do not throw an exception |
return; // ignore errors and do not throw an exception |
1080 |
break; |
break; |
1091 |
return; |
return; |
1092 |
|
|
1093 |
if (option_id == SOCKOPT_SO_SNDBUF) |
if (option_id == SOCKOPT_SO_SNDBUF) |
1094 |
sockopt = SO_SNDBUF; |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF(fd,optval,result); |
1095 |
else |
else |
1096 |
sockopt = SO_RCVBUF; |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF(fd,optval,result); |
|
|
|
|
rc = setsockopt(fd, SOL_SOCKET, sockopt, &optval, sizeof(int)); |
|
1097 |
break; |
break; |
1098 |
|
|
1099 |
/* TTL case. Val with be an Integer with the new time to live value */ |
/* TTL case. Val with be an Integer with the new time to live value */ |
1107 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1108 |
return; |
return; |
1109 |
|
|
1110 |
rc = setsockopt(fd, IPPROTO_IP, IP_TTL, &optval, sizeof(int)); |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL(fd,optval,result); |
1111 |
break; |
break; |
1112 |
|
|
1113 |
/* Multicast Interface case - val is InetAddress object */ |
/* Multicast Interface case - val is InetAddress object */ |
1114 |
case SOCKOPT_IP_MULTICAST_IF: |
case SOCKOPT_IP_MULTICAST_IF: |
1115 |
memset(&si, 0, sizeof(struct sockaddr_in)); |
address = _javanet_get_netaddr(env, val); |
|
si.sin_family = AF_INET; |
|
|
si.sin_addr.s_addr = _javanet_get_netaddr(env, val); |
|
1116 |
|
|
1117 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1118 |
return; |
return; |
1119 |
|
|
1120 |
rc = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &si, |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF(fd,address,result); |
|
sizeof(struct sockaddr_in)); |
|
1121 |
break; |
break; |
1122 |
|
|
1123 |
case SOCKOPT_SO_REUSEADDR: |
case SOCKOPT_SO_REUSEADDR: |
1131 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1132 |
return; |
return; |
1133 |
|
|
1134 |
rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS(fd,optval,result); |
|
sizeof(int)); |
|
1135 |
break; |
break; |
1136 |
|
|
1137 |
case SOCKOPT_SO_KEEPALIVE: |
case SOCKOPT_SO_KEEPALIVE: |
1145 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred(env)) |
1146 |
return; |
return; |
1147 |
|
|
1148 |
rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE(fd,optval,result); |
|
sizeof(int)); |
|
1149 |
break; |
break; |
1150 |
|
|
1151 |
case SOCKOPT_SO_BINDADDR: |
case SOCKOPT_SO_BINDADDR: |
1158 |
} |
} |
1159 |
|
|
1160 |
/* Check to see if above operations succeeded */ |
/* Check to see if above operations succeeded */ |
1161 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
1162 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
{ |
1163 |
|
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1164 |
return; |
return; |
1165 |
|
} |
1166 |
|
#else /* not WITHOUT_NETWORK */ |
1167 |
|
#endif /* not WITHOUT_NETWORK */ |
1168 |
} |
} |
1169 |
|
|
1170 |
/*************************************************************************/ |
/*************************************************************************/ |
1175 |
jobject |
jobject |
1176 |
_javanet_get_option(JNIEnv *env, jobject this, jint option_id) |
_javanet_get_option(JNIEnv *env, jobject this, jint option_id) |
1177 |
{ |
{ |
1178 |
int fd = -1, rc; |
#ifndef WITHOUT_NETWORK |
1179 |
int optval, optlen, sockopt; |
int fd; |
1180 |
struct linger linger; |
int flag,optval; |
1181 |
struct sockaddr_in si; |
int address; |
1182 |
|
int result; |
1183 |
|
|
1184 |
|
assert(env!=NULL); |
1185 |
|
assert((*env)!=NULL); |
1186 |
|
|
1187 |
/* Get the real file descriptor */ |
/* Get the real file descriptor */ |
1188 |
fd = _javanet_get_int_field(env, this, "native_fd"); |
fd = _javanet_get_int_field(env, this, "native_fd"); |
1198 |
{ |
{ |
1199 |
/* TCP_NODELAY case. Return a Boolean indicating on or off */ |
/* TCP_NODELAY case. Return a Boolean indicating on or off */ |
1200 |
case SOCKOPT_TCP_NODELAY: |
case SOCKOPT_TCP_NODELAY: |
1201 |
optlen = sizeof(optval); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY(fd,optval,result); |
1202 |
rc = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, &optlen); |
if (result != TARGET_NATIVE_OK) |
|
if (rc == -1) |
|
1203 |
{ |
{ |
1204 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1205 |
return(0); |
return(0); |
1206 |
} |
} |
1207 |
|
|
1215 |
/* SO_LINGER case. If disabled, return a Boolean object that represents |
/* SO_LINGER case. If disabled, return a Boolean object that represents |
1216 |
false, else return an Integer that is the value of SO_LINGER */ |
false, else return an Integer that is the value of SO_LINGER */ |
1217 |
case SOCKOPT_SO_LINGER: |
case SOCKOPT_SO_LINGER: |
1218 |
memset(&linger, 0, sizeof(struct linger)); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER(fd,flag,optval,result); |
1219 |
optlen = sizeof(struct linger); |
if (result != TARGET_NATIVE_OK) |
|
|
|
|
rc = getsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, &optlen); |
|
|
if (rc == -1) |
|
1220 |
{ |
{ |
1221 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1222 |
return(0); |
return(0); |
1223 |
} |
} |
1224 |
|
|
1225 |
if (linger.l_onoff) |
if (optval) |
1226 |
return(_javanet_create_integer(env, linger.l_linger)); |
return(_javanet_create_integer(env, JNI_TRUE)); |
1227 |
else |
else |
1228 |
return(_javanet_create_boolean(env, JNI_FALSE)); |
return(_javanet_create_boolean(env, JNI_FALSE)); |
1229 |
|
|
1232 |
/* SO_TIMEOUT case. Return an Integer object with the timeout value */ |
/* SO_TIMEOUT case. Return an Integer object with the timeout value */ |
1233 |
case SOCKOPT_SO_TIMEOUT: |
case SOCKOPT_SO_TIMEOUT: |
1234 |
#ifdef SO_TIMEOUT |
#ifdef SO_TIMEOUT |
1235 |
optlen = sizeof(int); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT(fd,optval,result); |
1236 |
|
if (result != TARGET_NATIVE_OK) |
|
rc = getsockopt(fd, SOL_SOCKET, SO_TIMEOUT, &optval, &optlen); |
|
|
#else |
|
|
JCL_ThrowException(env, SOCKET_EXCEPTION, |
|
|
"SO_TIMEOUT not supported on this platform"); |
|
|
return(0); |
|
|
#endif /* not SO_TIMEOUT */ |
|
|
|
|
|
if (rc == -1) |
|
1237 |
{ |
{ |
1238 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1239 |
return(0); |
return(0); |
1240 |
} |
} |
1241 |
|
|
1242 |
return(_javanet_create_integer(env, optval)); |
return(_javanet_create_integer(env, optval)); |
1243 |
|
#else |
1244 |
|
JCL_ThrowException(env, SOCKET_EXCEPTION, |
1245 |
|
"SO_TIMEOUT not supported on this platform"); |
1246 |
|
return(0); |
1247 |
|
#endif /* not SO_TIMEOUT */ |
1248 |
break; |
break; |
1249 |
|
|
1250 |
case SOCKOPT_SO_SNDBUF: |
case SOCKOPT_SO_SNDBUF: |
1251 |
case SOCKOPT_SO_RCVBUF: |
case SOCKOPT_SO_RCVBUF: |
|
optlen = sizeof(int); |
|
1252 |
if (option_id == SOCKOPT_SO_SNDBUF) |
if (option_id == SOCKOPT_SO_SNDBUF) |
1253 |
sockopt = SO_SNDBUF; |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF(fd,optval,result); |
1254 |
else |
else |
1255 |
sockopt = SO_RCVBUF; |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF(fd,optval,result); |
1256 |
|
if (result != TARGET_NATIVE_OK) |
|
rc = getsockopt(fd, SOL_SOCKET, sockopt, &optval, &optlen); |
|
|
|
|
|
if (rc == -1) |
|
1257 |
{ |
{ |
1258 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1259 |
return(0); |
return(0); |
1260 |
} |
} |
1261 |
|
|
1264 |
|
|
1265 |
/* The TTL case. Return an Integer with the Time to Live value */ |
/* The TTL case. Return an Integer with the Time to Live value */ |
1266 |
case SOCKOPT_IP_TTL: |
case SOCKOPT_IP_TTL: |
1267 |
optlen = sizeof(int); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL(fd,optval,result); |
1268 |
|
if (result != TARGET_NATIVE_OK) |
|
rc = getsockopt(fd, IPPROTO_IP, IP_TTL, &optval, &optlen); |
|
|
if (rc == -1) |
|
1269 |
{ |
{ |
1270 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1271 |
return(0); |
return(0); |
1272 |
} |
} |
1273 |
|
|
1276 |
|
|
1277 |
/* Multicast interface case */ |
/* Multicast interface case */ |
1278 |
case SOCKOPT_IP_MULTICAST_IF: |
case SOCKOPT_IP_MULTICAST_IF: |
1279 |
memset(&si, 0, sizeof(struct sockaddr_in)); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF(fd,address,result); |
1280 |
optlen = sizeof(struct sockaddr_in); |
if (result != TARGET_NATIVE_OK) |
1281 |
|
{ |
1282 |
rc = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &si, &optlen); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1283 |
if (rc == -1) |
return(0); |
1284 |
{ |
} |
|
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
|
|
return(0); |
|
|
} |
|
1285 |
|
|
1286 |
return(_javanet_create_inetaddress(env, ntohl(si.sin_addr.s_addr))); |
return(_javanet_create_inetaddress(env, address)); |
1287 |
break; |
break; |
1288 |
|
|
1289 |
case SOCKOPT_SO_BINDADDR: |
case SOCKOPT_SO_BINDADDR: |
1290 |
memset(&si, 0, sizeof(struct sockaddr_in)); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS(fd,address,result); |
1291 |
optlen = sizeof(struct sockaddr_in); |
if (result != TARGET_NATIVE_OK) |
|
rc = getsockname(fd, (struct sockaddr *) &si, &optlen); |
|
|
if (rc == -1) |
|
1292 |
{ |
{ |
1293 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1294 |
return(0); |
return(0); |
1295 |
} |
} |
1296 |
|
|
1297 |
return(_javanet_create_inetaddress(env, ntohl(si.sin_addr.s_addr))); |
return(_javanet_create_inetaddress(env, address)); |
1298 |
break; |
break; |
1299 |
|
|
1300 |
case SOCKOPT_SO_REUSEADDR: |
case SOCKOPT_SO_REUSEADDR: |
1301 |
optlen = sizeof(int); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS(fd,optval,result); |
1302 |
rc = getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, &optlen); |
if (result != TARGET_NATIVE_OK) |
|
if (rc == -1) |
|
1303 |
{ |
{ |
1304 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1305 |
return(0); |
return(0); |
1306 |
} |
} |
1307 |
|
|
1313 |
break; |
break; |
1314 |
|
|
1315 |
case SOCKOPT_SO_KEEPALIVE: |
case SOCKOPT_SO_KEEPALIVE: |
1316 |
optlen = sizeof(int); |
TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE(fd,optval,result); |
1317 |
rc = getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, &optlen); |
if (result != TARGET_NATIVE_OK) |
|
if (rc == -1) |
|
1318 |
{ |
{ |
1319 |
JCL_ThrowException(env, SOCKET_EXCEPTION, strerror(errno)); |
JCL_ThrowException(env, SOCKET_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING()); |
1320 |
return(0); |
return(0); |
1321 |
} |
} |
1322 |
|
|
1333 |
} |
} |
1334 |
|
|
1335 |
return(0); |
return(0); |
1336 |
|
#else /* not WITHOUT_NETWORK */ |
1337 |
|
#endif /* not WITHOUT_NETWORK */ |
1338 |
} |
} |
1339 |
|
|
1340 |
|
/* end of file */ |