1 /* javanet.c - Common internal functions for the java.net package
2 Copyright (C) 1998, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 /* do not move; needed here because of some macro definitions */
50 #include "target_native.h"
51 #ifndef WITHOUT_NETWORK
52 #include "target_native_network.h"
53 #endif /* WITHOUT_NETWORK */
55 #ifndef WITHOUT_NETWORK
56 /* Need to have some value for SO_TIMEOUT */
59 #warning Neither SO_TIMEOUT or SO_RCVTIMEO are defined!
60 #warning This will cause all get/setOption calls with that value to throw an exception
62 #define SO_TIMEOUT SO_RCVTIMEO
63 #endif /* not SO_RCVTIMEO */
64 #endif /* not SO_TIMEOUT */
65 #endif /* WITHOUT_NETWORK */
67 /*************************************************************************/
70 * Sets an integer field in the specified object.
73 _javanet_set_int_field (JNIEnv
* env
, jobject obj
,
74 const char *class, const char *field
, int val
)
79 cls
= (*env
)->FindClass (env
, class);
83 fid
= (*env
)->GetFieldID (env
, cls
, field
, "I");
87 (*env
)->SetIntField (env
, obj
, fid
, val
);
92 /*************************************************************************/
95 * Returns the value of the specified integer instance variable field or
96 * -1 if an error occurs.
99 _javanet_get_int_field (JNIEnv
* env
, jobject obj
, const char *field
)
105 DBG ("_javanet_get_int_field(): Entered _javanet_get_int_field\n");
107 cls
= (*env
)->GetObjectClass (env
, obj
);
111 fid
= (*env
)->GetFieldID (env
, cls
, field
, "I");
114 DBG ("_javanet_get_int_field(): Found field id\n");
116 fd
= (*env
)->GetIntField (env
, obj
, fid
);
121 /*************************************************************************/
124 * Creates a FileDescriptor object in the parent class. It is not used
125 * by this implementation, but the docs list it as a variable, so we
126 * need to include it.
129 _javanet_create_localfd (JNIEnv
* env
, jobject
this, jboolean stream
)
131 jclass this_cls
, fd_cls
;
136 DBG ("_javanet_create_localfd(): Entered _javanet_create_localfd\n");
138 /* Look up the fd field */
140 this_cls
= (*env
)->FindClass(env
, "java/net/SocketImpl");
142 this_cls
= (*env
)->FindClass(env
, "java/net/DatagramSocketImpl");
143 if (this_cls
== NULL
)
146 fid
= (*env
)->GetFieldID (env
, this_cls
, "fd", "Ljava/io/FileDescriptor;");
150 DBG ("_javanet_create_localfd(): Found fd variable\n");
152 /* Create a FileDescriptor */
153 fd_cls
= (*env
)->FindClass (env
, "java/io/FileDescriptor");
157 DBG ("_javanet_create_localfd(): Found FileDescriptor class\n");
159 mid
= (*env
)->GetMethodID (env
, fd_cls
, "<init>", "()V");
163 DBG ("_javanet_create_localfd(): Found FileDescriptor constructor\n");
165 fd_obj
= (*env
)->NewObject (env
, fd_cls
, mid
);
169 DBG ("_javanet_create_localfd(): Created FileDescriptor\n");
171 /* Now set the pointer to the new FileDescriptor */
172 (*env
)->SetObjectField (env
, this, fid
, fd_obj
);
173 DBG ("_javanet_create_localfd(): Set fd field\n");
178 /*************************************************************************/
181 * Returns a Boolean object with the specfied value
184 _javanet_create_boolean (JNIEnv
* env
, jboolean val
)
190 cls
= (*env
)->FindClass (env
, "java/lang/Boolean");
194 mid
= (*env
)->GetMethodID (env
, cls
, "<init>", "(Z)V");
198 obj
= (*env
)->NewObject (env
, cls
, mid
, val
);
205 /*************************************************************************/
208 * Returns an Integer object with the specfied value
211 _javanet_create_integer (JNIEnv
* env
, jint val
)
217 cls
= (*env
)->FindClass (env
, "java/lang/Integer");
221 mid
= (*env
)->GetMethodID (env
, cls
, "<init>", "(I)V");
225 obj
= (*env
)->NewObject (env
, cls
, mid
, val
);
232 /*************************************************************************/
235 * Builds an InetAddress object from a 32 bit address in host byte order
238 _javanet_create_inetaddress (JNIEnv
* env
, int netaddr
)
240 #ifndef WITHOUT_NETWORK
241 unsigned char octets
[4];
248 /* Build a string IP address */
249 TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (netaddr
,
252 octets
[2], octets
[3]);
253 sprintf (buf
, "%d.%d.%d.%d", octets
[0], octets
[1], octets
[2], octets
[3]);
254 DBG ("_javanet_create_inetaddress(): Created ip addr string\n");
256 /* Get an InetAddress object for this IP */
257 ia_cls
= (*env
)->FindClass (env
, "java/net/InetAddress");
263 DBG ("_javanet_create_inetaddress(): Found InetAddress class\n");
265 mid
= (*env
)->GetStaticMethodID (env
, ia_cls
, "getByName",
266 "(Ljava/lang/String;)Ljava/net/InetAddress;");
272 DBG ("_javanet_create_inetaddress(): Found getByName method\n");
274 ip_str
= (*env
)->NewStringUTF (env
, buf
);
280 ia
= (*env
)->CallStaticObjectMethod (env
, ia_cls
, mid
, ip_str
);
286 DBG ("_javanet_create_inetaddress(): Called getByName method\n");
289 #else /* not WITHOUT_NETWORK */
291 #endif /* not WITHOUT_NETWORK */
294 /*************************************************************************/
297 _javanet_set_remhost_addr (JNIEnv
* env
, jobject
this, jobject ia
)
302 /* Set the variable in the object */
303 this_cls
= (*env
)->FindClass (env
, "java/net/SocketImpl");
304 if (this_cls
== NULL
)
308 (*env
)->GetFieldID (env
, this_cls
, "address", "Ljava/net/InetAddress;");
312 DBG ("_javanet_set_remhost_addr(): Found address field\n");
314 (*env
)->SetObjectField (env
, this, fid
, ia
);
315 DBG ("_javanet_set_remhost_addr(): Set field\n");
319 * Set's the value of the "addr" field in PlainSocketImpl with a new
320 * InetAddress for the specified addr
323 _javanet_set_remhost (JNIEnv
* env
, jobject
this, int netaddr
)
327 DBG ("_javanet_set_remhost(): Entered _javanet_set_remhost\n");
329 /* Get an InetAddress object */
330 ia
= _javanet_create_inetaddress (env
, netaddr
);
334 _javanet_set_remhost_addr (env
, this, ia
);
338 /*************************************************************************/
341 * Returns a 32 bit Internet address for the passed in InetAddress object
344 _javanet_get_netaddr (JNIEnv
* env
, jobject addr
)
346 #ifndef WITHOUT_NETWORK
353 DBG ("_javanet_get_netaddr(): Entered _javanet_get_netaddr\n");
357 JCL_ThrowException (env
, "java/lang/NullPointerException",
362 /* Call the getAddress method on the object to retrieve the IP address */
363 cls
= (*env
)->GetObjectClass (env
, addr
);
367 mid
= (*env
)->GetMethodID (env
, cls
, "getAddress", "()[B");
371 DBG ("_javanet_get_netaddr(): Got getAddress method\n");
373 arr
= (*env
)->CallObjectMethod (env
, addr
, mid
);
377 DBG ("_javanet_get_netaddr(): Got the address\n");
379 /* Turn the IP address into a 32 bit Internet address in network byte order */
380 len
= (*env
)->GetArrayLength (env
, arr
);
383 JCL_ThrowException (env
, IO_EXCEPTION
, "Internal Error");
386 DBG ("_javanet_get_netaddr(): Length ok\n");
388 octets
= (*env
)->GetByteArrayElements (env
, arr
, 0);
392 DBG ("_javanet_get_netaddr(): Grabbed bytes\n");
394 TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets
[0],
399 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
400 DBG ("_javanet_get_netaddr(): Done getting addr\n");
403 #else /* not WITHOUT_NETWORK */
404 #endif /* not WITHOUT_NETWORK */
407 /*************************************************************************/
410 * Creates a new stream or datagram socket
413 _javanet_create (JNIEnv
* env
, jobject
this, jboolean stream
)
415 #ifndef WITHOUT_NETWORK
421 /* create a stream socket */
422 TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM (fd
, result
);
423 if (result
!= TARGET_NATIVE_OK
)
425 JCL_ThrowException (env
, IO_EXCEPTION
,
426 TARGET_NATIVE_LAST_ERROR_STRING ());
432 /* create a datagram socket, set broadcast option */
433 TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM (fd
, result
);
434 if (result
!= TARGET_NATIVE_OK
)
436 JCL_ThrowException (env
, IO_EXCEPTION
,
437 TARGET_NATIVE_LAST_ERROR_STRING ());
440 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST (fd
, 1, result
);
441 if (result
!= TARGET_NATIVE_OK
)
443 JCL_ThrowException (env
, IO_EXCEPTION
,
444 TARGET_NATIVE_LAST_ERROR_STRING ());
450 _javanet_set_int_field (env
, this, "gnu/java/net/PlainSocketImpl",
453 _javanet_set_int_field (env
, this, "gnu/java/net/PlainDatagramSocketImpl",
456 if ((*env
)->ExceptionOccurred (env
))
458 /* Try to make sure we close the socket since close() won't work. */
461 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
462 if (result
!= TARGET_NATIVE_OK
463 && (TARGET_NATIVE_LAST_ERROR ()
464 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
467 while (result
!= TARGET_NATIVE_OK
);
471 #else /* not WITHOUT_NETWORK */
472 #endif /* not WITHOUT_NETWORK */
475 /*************************************************************************/
478 * Close the socket. Any underlying streams will be closed by this
482 _javanet_close (JNIEnv
* env
, jobject
this, int stream
)
484 #ifndef WITHOUT_NETWORK
489 fd
= _javanet_get_int_field (env
, this, "native_fd");
494 _javanet_set_int_field (env
, this, "gnu/java/net/PlainSocketImpl",
497 _javanet_set_int_field (env
, this, "gnu/java/net/PlainDatagramSocketImpl",
501 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
502 if (result
!= TARGET_NATIVE_OK
)
504 /* Only throw an error when a "real" error occurs. */
505 error
= TARGET_NATIVE_LAST_ERROR ();
506 if (error
!= TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
507 && error
!= ENOTCONN
&& error
!= ECONNRESET
&& error
!= EBADF
)
508 JCL_ThrowException (env
, IO_EXCEPTION
,
509 TARGET_NATIVE_LAST_ERROR_STRING ());
512 while (error
== TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
);
514 #else /* not WITHOUT_NETWORK */
515 #endif /* not WITHOUT_NETWORK */
518 /*************************************************************************/
521 * Connects to the specified destination.
524 _javanet_connect (JNIEnv
* env
, jobject
this, jobject addr
, jint port
,
527 #ifndef WITHOUT_NETWORK
530 int local_address
, local_port
;
531 int remote_address
, remote_port
;
533 DBG ("_javanet_connect(): Entered _javanet_connect\n");
535 /* Pre-process input variables */
536 netaddr
= _javanet_get_netaddr (env
, addr
);
537 if ((*env
)->ExceptionOccurred (env
))
542 DBG ("_javanet_connect(): Got network address\n");
544 /* Grab the real socket file descriptor */
545 fd
= _javanet_get_int_field (env
, this, "native_fd");
548 JCL_ThrowException (env
, IO_EXCEPTION
,
549 "Internal error: _javanet_connect(): no native file descriptor");
552 DBG ("_javanet_connect(): Got native fd\n");
557 TARGET_NATIVE_NETWORK_SOCKET_CONNECT (fd
, netaddr
, port
, result
);
558 if (result
!= TARGET_NATIVE_OK
559 && (TARGET_NATIVE_LAST_ERROR ()
560 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
562 JCL_ThrowException (env
, IO_EXCEPTION
,
563 TARGET_NATIVE_LAST_ERROR_STRING ());
567 while (result
!= TARGET_NATIVE_OK
);
569 DBG ("_javanet_connect(): Connected successfully\n");
571 /* Populate instance variables */
572 TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd
, local_address
, local_port
,
574 if (result
!= TARGET_NATIVE_OK
)
576 JCL_ThrowException (env
, IO_EXCEPTION
,
577 TARGET_NATIVE_LAST_ERROR_STRING ());
578 /* We don't care whether this succeeds. close() will cleanup later. */
579 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
583 _javanet_create_localfd (env
, this, stream
);
584 if ((*env
)->ExceptionOccurred (env
))
586 /* We don't care whether this succeeds. close() will cleanup later. */
587 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
590 DBG ("_javanet_connect(): Created fd\n");
593 _javanet_set_int_field (env
, this, "java/net/SocketImpl", "localport",
596 _javanet_set_int_field (env
, this, "java/net/DatagramSocketImpl",
597 "localPort", local_port
);
599 if ((*env
)->ExceptionOccurred (env
))
601 /* We don't care whether this succeeds. close() will cleanup later. */
602 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
605 DBG ("_javanet_connect(): Set the local port\n");
607 TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (fd
, remote_address
,
608 remote_port
, result
);
609 if (result
!= TARGET_NATIVE_OK
)
611 JCL_ThrowException (env
, IO_EXCEPTION
,
612 TARGET_NATIVE_LAST_ERROR_STRING ());
613 /* We don't care whether this succeeds. close() will cleanup later. */
614 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
620 if (remote_address
== netaddr
)
622 _javanet_set_remhost_addr (env
, this, addr
);
626 _javanet_set_remhost (env
, this, remote_address
);
628 if ((*env
)->ExceptionOccurred (env
))
630 /* We don't care whether this succeeds. close() will cleanup later.
632 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
635 DBG ("_javanet_connect(): Set the remote host\n");
637 _javanet_set_int_field (env
, this, "java/net/SocketImpl", "port",
639 if ((*env
)->ExceptionOccurred (env
))
641 /* We don't care whether this succeeds. close() will cleanup later.
643 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
646 DBG ("_javanet_connect(): Set the remote port\n");
648 #else /* not WITHOUT_NETWORK */
649 #endif /* not WITHOUT_NETWORK */
652 /*************************************************************************/
655 * This method binds the specified address to the specified local port.
656 * Note that we have to set the local address and local
657 * port public instance variables.
660 _javanet_bind (JNIEnv
* env
, jobject
this, jobject addr
, jint port
,
663 #ifndef WITHOUT_NETWORK
671 int local_address
, local_port
;
673 DBG ("_javanet_bind(): Entering native bind()\n");
675 /* Get the address to connect to */
676 cls
= (*env
)->GetObjectClass (env
, addr
);
680 mid
= (*env
)->GetMethodID (env
, cls
, "getAddress", "()[B");
684 DBG ("_javanet_bind(): Past getAddress method id\n");
686 arr
= (*env
)->CallObjectMethod (env
, addr
, mid
);
687 if ((arr
== NULL
) || (*env
)->ExceptionOccurred (env
))
689 JCL_ThrowException (env
, IO_EXCEPTION
,
690 "Internal error: _javanet_bind()");
694 DBG ("_javanet_bind(): Past call object method\n");
696 octets
= (*env
)->GetByteArrayElements (env
, arr
, 0);
700 DBG ("_javanet_bind(): Past grab array\n");
702 /* Get the native socket file descriptor */
703 fd
= _javanet_get_int_field (env
, this, "native_fd");
706 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
707 JCL_ThrowException (env
, IO_EXCEPTION
,
708 "Internal error: _javanet_bind(): no native file descriptor");
711 DBG ("_javanet_bind(): Past native_fd lookup\n");
714 _javanet_set_option (env
, this, SOCKOPT_SO_REUSEADDR
,
715 _javanet_create_boolean (env
, JNI_TRUE
));
718 /* Bind the socket */
719 TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets
[0],
723 TARGET_NATIVE_NETWORK_SOCKET_BIND (fd
, tmpaddr
, port
, result
);
725 if (result
!= TARGET_NATIVE_OK
)
727 char *errorstr
= TARGET_NATIVE_LAST_ERROR_STRING ();
728 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
730 JCL_ThrowException (env
, BIND_EXCEPTION
,
734 DBG ("_javanet_bind(): Past bind\n");
736 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
738 /* Update instance variables, specifically the local port number */
739 TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd
, local_address
, local_port
,
741 if (result
!= TARGET_NATIVE_OK
)
743 JCL_ThrowException (env
, IO_EXCEPTION
,
744 TARGET_NATIVE_LAST_ERROR_STRING ());
749 _javanet_set_int_field (env
, this, "java/net/SocketImpl",
750 "localport", local_port
);
752 _javanet_set_int_field (env
, this, "java/net/DatagramSocketImpl",
753 "localPort", local_port
);
754 DBG ("_javanet_bind(): Past update port number\n");
757 #else /* not WITHOUT_NETWORK */
758 #endif /* not WITHOUT_NETWORK */
761 /*************************************************************************/
764 * Starts listening on a socket with the specified number of pending
765 * connections allowed.
768 _javanet_listen (JNIEnv
* env
, jobject
this, jint queuelen
)
770 #ifndef WITHOUT_NETWORK
774 /* Get the real file descriptor */
775 fd
= _javanet_get_int_field (env
, this, "native_fd");
778 JCL_ThrowException (env
, IO_EXCEPTION
,
779 "Internal error: _javanet_listen(): no native file descriptor");
783 /* Start listening */
784 TARGET_NATIVE_NETWORK_SOCKET_LISTEN (fd
, queuelen
, result
);
785 if (result
!= TARGET_NATIVE_OK
)
787 JCL_ThrowException (env
, IO_EXCEPTION
,
788 TARGET_NATIVE_LAST_ERROR_STRING ());
791 #else /* not WITHOUT_NETWORK */
792 #endif /* not WITHOUT_NETWORK */
795 /*************************************************************************/
798 * Accepts a new connection and assigns it to the passed in SocketImpl
799 * object. Note that we assume this is a PlainSocketImpl just like us
802 _javanet_accept (JNIEnv
* env
, jobject
this, jobject impl
)
804 #ifndef WITHOUT_NETWORK
807 int local_address
, local_port
;
808 int remote_address
, remote_port
;
810 /* Get the real file descriptor */
811 fd
= _javanet_get_int_field (env
, this, "native_fd");
814 JCL_ThrowException (env
, IO_EXCEPTION
,
815 "Internal error: _javanet_accept(): no native file descriptor");
819 /* Accept the connection */
822 TARGET_NATIVE_NETWORK_SOCKET_ACCEPT (fd
, newfd
, result
);
823 if (result
!= TARGET_NATIVE_OK
824 && (TARGET_NATIVE_LAST_ERROR ()
825 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
827 if (TARGET_NATIVE_LAST_ERROR () == EAGAIN
)
828 JCL_ThrowException (env
, "java/net/SocketTimeoutException",
831 JCL_ThrowException (env
, IO_EXCEPTION
,
832 TARGET_NATIVE_LAST_ERROR_STRING ());
836 while (result
!= TARGET_NATIVE_OK
);
838 /* Populate instance variables */
839 _javanet_set_int_field (env
, impl
, "gnu/java/net/PlainSocketImpl",
842 if ((*env
)->ExceptionOccurred (env
))
844 /* Try to make sure we close the socket since close() won't work. */
847 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
848 if (result
!= TARGET_NATIVE_OK
849 && (TARGET_NATIVE_LAST_ERROR ()
850 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
853 while (result
!= TARGET_NATIVE_OK
);
857 TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (newfd
, local_address
,
859 if (result
!= TARGET_NATIVE_OK
)
861 /* We don't care whether this succeeds. close() will cleanup later. */
862 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
863 JCL_ThrowException (env
, IO_EXCEPTION
,
864 TARGET_NATIVE_LAST_ERROR_STRING ());
868 _javanet_create_localfd (env
, impl
, 1);
869 if ((*env
)->ExceptionOccurred (env
))
871 /* We don't care whether this succeeds. close() will cleanup later. */
872 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
876 _javanet_set_int_field (env
, impl
, "java/net/SocketImpl", "localport",
878 if ((*env
)->ExceptionOccurred (env
))
880 /* We don't care whether this succeeds. close() will cleanup later. */
881 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
885 TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (newfd
, remote_address
,
886 remote_port
, result
);
887 if (result
!= TARGET_NATIVE_OK
)
889 JCL_ThrowException (env
, IO_EXCEPTION
,
890 TARGET_NATIVE_LAST_ERROR_STRING ());
891 /* We don't care whether this succeeds. close() will cleanup later. */
892 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
896 _javanet_set_remhost (env
, impl
, remote_address
);
897 if ((*env
)->ExceptionOccurred (env
))
899 /* We don't care whether this succeeds. close() will cleanup later. */
900 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
904 _javanet_set_int_field (env
, impl
, "java/net/SocketImpl", "port",
906 if ((*env
)->ExceptionOccurred (env
))
908 /* We don't care whether this succeeds. close() will cleanup later. */
909 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
912 #else /* not WITHOUT_NETWORK */
913 #endif /* not WITHOUT_NETWORK */
916 /*************************************************************************/
919 * Receives a buffer from a remote host. The args are:
921 * buf - The byte array into which the data received will be written
922 * offset - Offset into the byte array to start writing
923 * len - The number of bytes to read.
924 * addr - Pointer to 32 bit net address of host to receive from. If null,
925 * this parm is ignored. If pointing to an address of 0, the
926 * actual address read is stored here
927 * port - Pointer to the port to receive from. If null, this parm is ignored.
928 * If it is 0, the actual remote port received from is stored here
930 * The actual number of bytes read is returned.
933 _javanet_recvfrom (JNIEnv
* env
, jobject
this, jarray buf
, int offset
,
934 int len
, int *addr
, int *port
)
936 #ifndef WITHOUT_NETWORK
939 int from_address
, from_port
;
942 DBG ("_javanet_recvfrom(): Entered _javanet_recvfrom\n");
944 /* Get the real file descriptor */
945 fd
= _javanet_get_int_field (env
, this, "native_fd");
948 JCL_ThrowException (env
, IO_EXCEPTION
,
949 "Internal error: _javanet_recvfrom(): no native file descriptor");
952 DBG ("_javanet_recvfrom(): Got native_fd\n");
954 /* Get a pointer to the buffer */
955 p
= (*env
)->GetByteArrayElements (env
, buf
, 0);
959 DBG ("_javanet_recvfrom(): Got buffer\n");
968 TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT (fd
,
977 TARGET_NATIVE_NETWORK_SOCKET_RECEIVE (fd
, p
+ offset
, len
,
981 while ((received_bytes
== -1) &&
982 (TARGET_NATIVE_LAST_ERROR () ==
983 TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
));
985 if (received_bytes
== -1)
987 if (TARGET_NATIVE_LAST_ERROR () == EAGAIN
)
988 JCL_ThrowException (env
, "java/net/SocketTimeoutException", "Timeout");
990 JCL_ThrowException (env
, IO_EXCEPTION
,
991 TARGET_NATIVE_LAST_ERROR_STRING ());
993 /* Cleanup and return. */
994 (*env
)->ReleaseByteArrayElements (env
, buf
, p
, 0);
998 (*env
)->ReleaseByteArrayElements (env
, buf
, p
, 0);
1000 /* Handle return addr case */
1003 (*addr
) = from_address
;
1005 (*port
) = from_port
;
1008 /* zero bytes received means recv() noticed the other side orderly
1009 closing the connection. */
1010 if (received_bytes
== 0)
1011 received_bytes
= -1;
1013 return (received_bytes
);
1014 #else /* not WITHOUT_NETWORK */
1015 #endif /* not WITHOUT_NETWORK */
1018 /*************************************************************************/
1021 * Sends a buffer to a remote host. The args are:
1023 * buf - A byte array
1024 * offset - Index into the byte array to start sendign
1025 * len - The number of bytes to write
1026 * addr - The 32bit address to send to (may be 0)
1027 * port - The port number to send to (may be 0)
1030 _javanet_sendto (JNIEnv
* env
, jobject
this, jarray buf
, int offset
, int len
,
1033 #ifndef WITHOUT_NETWORK
1038 /* Get the real file descriptor */
1039 fd
= _javanet_get_int_field (env
, this, "native_fd");
1042 JCL_ThrowException (env
, IO_EXCEPTION
,
1043 "Internal error: _javanet_sendto(): no native file descriptor");
1047 /* Get a pointer to the buffer */
1048 p
= (*env
)->GetByteArrayElements (env
, buf
, 0);
1052 /* We must send all the data, so repeat till done. */
1058 DBG ("_javanet_sendto(): Sending....\n");
1059 TARGET_NATIVE_NETWORK_SOCKET_SEND (fd
, p
+ offset
, len
, bytes_sent
);
1063 DBG ("_javanet_sendto(): Sending....\n");
1064 TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT (fd
, p
+ offset
,
1071 if (TARGET_NATIVE_LAST_ERROR ()
1072 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
)
1074 JCL_ThrowException (env
, IO_EXCEPTION
,
1075 TARGET_NATIVE_LAST_ERROR_STRING ());
1086 (*env
)->ReleaseByteArrayElements (env
, buf
, p
, 0);
1088 #else /* not WITHOUT_NETWORK */
1089 #endif /* not WITHOUT_NETWORK */
1092 /*************************************************************************/
1095 * Sets the specified option for a socket
1098 _javanet_set_option (JNIEnv
* env
, jobject
this, jint option_id
, jobject val
)
1100 #ifndef WITHOUT_NETWORK
1108 /* Get the real file descriptor */
1109 fd
= _javanet_get_int_field (env
, this, "native_fd");
1112 JCL_ThrowException (env
, IO_EXCEPTION
,
1113 "Internal error: _javanet_set_option(): no native file descriptor");
1117 /* We need a class object for all cases below */
1118 cls
= (*env
)->GetObjectClass (env
, val
);
1122 /* Process the option request */
1123 result
= TARGET_NATIVE_ERROR
;
1126 /* TCP_NODELAY case. val is a Boolean that tells us what to do */
1127 case SOCKOPT_TCP_NODELAY
:
1128 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1131 JCL_ThrowException (env
, IO_EXCEPTION
,
1132 "Internal error: _javanet_set_option()");
1136 /* Should be a 0 or a 1 */
1137 optval
= (*env
)->CallBooleanMethod (env
, val
, mid
);
1138 if ((*env
)->ExceptionOccurred (env
))
1141 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY (fd
, optval
,
1145 /* SO_LINGER case. If val is a boolean, then it will always be set
1146 to false indicating disable linger, otherwise it will be an
1147 integer that contains the linger value */
1148 case SOCKOPT_SO_LINGER
:
1149 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1152 /* We are disabling linger */
1153 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd
, 1, 0,
1158 /* Clear exception if thrown for failure to do method lookup
1160 if ((*env
)->ExceptionOccurred (env
))
1161 (*env
)->ExceptionClear (env
);
1163 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1166 JCL_ThrowException (env
, IO_EXCEPTION
,
1167 "Internal error: _javanet_set_option()");
1171 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1172 if ((*env
)->ExceptionOccurred (env
))
1175 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd
, 0, optval
,
1180 /* SO_TIMEOUT case. Val will be an integer with the new value */
1181 /* Not writable on Linux */
1182 case SOCKOPT_SO_TIMEOUT
:
1184 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1187 JCL_ThrowException (env
, IO_EXCEPTION
,
1188 "Internal error: _javanet_set_option()");
1192 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1193 if ((*env
)->ExceptionOccurred (env
))
1196 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT (fd
, optval
, result
);
1198 result
= TARGET_NATIVE_OK
;
1202 case SOCKOPT_SO_SNDBUF
:
1203 case SOCKOPT_SO_RCVBUF
:
1204 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1207 JCL_ThrowException (env
, IO_EXCEPTION
,
1208 "Internal error: _javanet_set_option()");
1213 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1214 if ((*env
)->ExceptionOccurred (env
))
1217 if (option_id
== SOCKOPT_SO_SNDBUF
)
1218 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF (fd
, optval
,
1221 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF (fd
, optval
,
1225 /* TTL case. Val with be an Integer with the new time to live value */
1226 case SOCKOPT_IP_TTL
:
1227 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1230 JCL_ThrowException (env
, IO_EXCEPTION
,
1231 "Internal error: _javanet_set_option()");
1235 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1236 if ((*env
)->ExceptionOccurred (env
))
1239 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL (fd
, optval
, result
);
1242 /* Multicast Interface case - val is InetAddress object */
1243 case SOCKOPT_IP_MULTICAST_IF
:
1244 address
= _javanet_get_netaddr (env
, val
);
1246 if ((*env
)->ExceptionOccurred (env
))
1249 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF (fd
, address
,
1253 case SOCKOPT_SO_REUSEADDR
:
1254 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1257 JCL_ThrowException (env
, IO_EXCEPTION
,
1258 "Internal error: _javanet_set_option()");
1262 /* Should be a 0 or a 1 */
1263 optval
= (*env
)->CallBooleanMethod (env
, val
, mid
);
1264 if ((*env
)->ExceptionOccurred (env
))
1267 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS (fd
, optval
,
1271 case SOCKOPT_SO_KEEPALIVE
:
1272 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1275 JCL_ThrowException (env
, IO_EXCEPTION
,
1276 "Internal error: _javanet_set_option()");
1280 /* Should be a 0 or a 1 */
1281 optval
= (*env
)->CallBooleanMethod (env
, val
, mid
);
1282 if ((*env
)->ExceptionOccurred (env
))
1285 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE (fd
, optval
, result
);
1288 case SOCKOPT_SO_BINDADDR
:
1289 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "This option cannot be set");
1293 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "Unrecognized option");
1297 /* Check to see if above operations succeeded */
1298 if (result
!= TARGET_NATIVE_OK
)
1300 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1301 TARGET_NATIVE_LAST_ERROR_STRING ());
1304 #else /* not WITHOUT_NETWORK */
1305 #endif /* not WITHOUT_NETWORK */
1308 /*************************************************************************/
1311 * Retrieves the specified option values for a socket
1314 _javanet_get_option (JNIEnv
* env
, jobject
this, jint option_id
)
1316 #ifndef WITHOUT_NETWORK
1322 /* Get the real file descriptor */
1323 fd
= _javanet_get_int_field (env
, this, "native_fd");
1326 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1327 "Internal error: _javanet_get_option(): no native file descriptor");
1331 /* Process the option requested */
1334 /* TCP_NODELAY case. Return a Boolean indicating on or off */
1335 case SOCKOPT_TCP_NODELAY
:
1336 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY (fd
, optval
,
1338 if (result
!= TARGET_NATIVE_OK
)
1340 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1341 TARGET_NATIVE_LAST_ERROR_STRING ());
1346 return (_javanet_create_boolean (env
, JNI_TRUE
));
1348 return (_javanet_create_boolean (env
, JNI_FALSE
));
1352 /* SO_LINGER case. If disabled, return a Boolean object that represents
1353 false, else return an Integer that is the value of SO_LINGER */
1354 case SOCKOPT_SO_LINGER
:
1355 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER (fd
, flag
, optval
,
1357 if (result
!= TARGET_NATIVE_OK
)
1359 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1360 TARGET_NATIVE_LAST_ERROR_STRING ());
1365 return (_javanet_create_integer (env
, JNI_TRUE
));
1367 return (_javanet_create_boolean (env
, JNI_FALSE
));
1371 /* SO_TIMEOUT case. Return an Integer object with the timeout value */
1372 case SOCKOPT_SO_TIMEOUT
:
1374 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT (fd
, optval
, result
);
1375 if (result
!= TARGET_NATIVE_OK
)
1377 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1378 TARGET_NATIVE_LAST_ERROR_STRING ());
1381 return (_javanet_create_integer (env
, optval
));
1383 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1384 "SO_TIMEOUT not supported on this platform");
1386 #endif /* not SO_TIMEOUT */
1389 case SOCKOPT_SO_SNDBUF
:
1390 case SOCKOPT_SO_RCVBUF
:
1391 if (option_id
== SOCKOPT_SO_SNDBUF
)
1392 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF (fd
, optval
,
1395 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF (fd
, optval
,
1397 if (result
!= TARGET_NATIVE_OK
)
1399 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1400 TARGET_NATIVE_LAST_ERROR_STRING ());
1404 return (_javanet_create_integer (env
, optval
));
1407 /* The TTL case. Return an Integer with the Time to Live value */
1408 case SOCKOPT_IP_TTL
:
1409 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL (fd
, optval
, result
);
1410 if (result
!= TARGET_NATIVE_OK
)
1412 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1413 TARGET_NATIVE_LAST_ERROR_STRING ());
1417 return (_javanet_create_integer (env
, optval
));
1420 /* Multicast interface case */
1421 case SOCKOPT_IP_MULTICAST_IF
:
1422 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF (fd
, address
,
1424 if (result
!= TARGET_NATIVE_OK
)
1426 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1427 TARGET_NATIVE_LAST_ERROR_STRING ());
1431 return (_javanet_create_inetaddress (env
, address
));
1434 case SOCKOPT_SO_BINDADDR
:
1435 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS (fd
, address
,
1437 if (result
!= TARGET_NATIVE_OK
)
1439 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1440 TARGET_NATIVE_LAST_ERROR_STRING ());
1444 return (_javanet_create_inetaddress (env
, address
));
1447 case SOCKOPT_SO_REUSEADDR
:
1448 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS (fd
, optval
,
1450 if (result
!= TARGET_NATIVE_OK
)
1452 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1453 TARGET_NATIVE_LAST_ERROR_STRING ());
1458 return (_javanet_create_boolean (env
, JNI_TRUE
));
1460 return (_javanet_create_boolean (env
, JNI_FALSE
));
1464 case SOCKOPT_SO_KEEPALIVE
:
1465 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE (fd
, optval
, result
);
1466 if (result
!= TARGET_NATIVE_OK
)
1468 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1469 TARGET_NATIVE_LAST_ERROR_STRING ());
1474 return (_javanet_create_boolean (env
, JNI_TRUE
));
1476 return (_javanet_create_boolean (env
, JNI_FALSE
));
1481 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "No such option");
1486 #else /* not WITHOUT_NETWORK */
1487 #endif /* not WITHOUT_NETWORK */
1491 _javanet_shutdownInput (JNIEnv
* env
, jobject
this)
1495 /* Get the real file descriptor. */
1496 fd
= _javanet_get_int_field (env
, this, "native_fd");
1499 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1500 "Internal error: _javanet_get_option(): no native file descriptor");
1504 /* Shutdown input stream of socket. */
1505 if (shutdown (fd
, SHUT_RD
) == -1)
1507 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1508 TARGET_NATIVE_LAST_ERROR_STRING());
1514 _javanet_shutdownOutput (JNIEnv
* env
, jobject
this)
1518 /* Get the real file descriptor. */
1519 fd
= _javanet_get_int_field (env
, this, "native_fd");
1522 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1523 "Internal error: _javanet_get_option(): no native file descriptor");
1527 /* Shutdown output stream of socket. */
1528 if (shutdown (fd
, SHUT_WR
) == -1)
1530 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1531 TARGET_NATIVE_LAST_ERROR_STRING());