1 /* javanet.c - Common internal functions for the java.net package
2 Copyright (C) 1998, 2002, 2004, 2005 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 */
51 #include "target_native.h"
52 #ifndef WITHOUT_NETWORK
53 #include "target_native_network.h"
54 #endif /* WITHOUT_NETWORK */
56 #ifndef WITHOUT_NETWORK
57 /* Need to have some value for SO_TIMEOUT */
60 #warning Neither SO_TIMEOUT or SO_RCVTIMEO are defined!
61 #warning This will cause all get/setOption calls with that value to throw an exception
63 #define SO_TIMEOUT SO_RCVTIMEO
64 #endif /* not SO_RCVTIMEO */
65 #endif /* not SO_TIMEOUT */
66 #endif /* WITHOUT_NETWORK */
68 /*************************************************************************/
71 * Sets an integer field in the specified object.
74 _javanet_set_int_field (JNIEnv
* env
, jobject obj
,
75 const char *class, const char *field
, int val
)
81 assert ((*env
) != NULL
);
83 cls
= (*env
)->FindClass (env
, class);
87 fid
= (*env
)->GetFieldID (env
, cls
, field
, "I");
91 (*env
)->SetIntField (env
, obj
, fid
, val
);
96 /*************************************************************************/
99 * Returns the value of the specified integer instance variable field or
100 * -1 if an error occurs.
103 _javanet_get_int_field (JNIEnv
* env
, jobject obj
, const char *field
)
109 assert (env
!= NULL
);
110 assert ((*env
) != NULL
);
112 DBG ("_javanet_get_int_field(): Entered _javanet_get_int_field\n");
114 cls
= (*env
)->GetObjectClass (env
, obj
);
118 fid
= (*env
)->GetFieldID (env
, cls
, field
, "I");
121 DBG ("_javanet_get_int_field(): Found field id\n");
123 fd
= (*env
)->GetIntField (env
, obj
, fid
);
128 /*************************************************************************/
131 * Creates a FileDescriptor object in the parent class. It is not used
132 * by this implementation, but the docs list it as a variable, so we
133 * need to include it.
136 _javanet_create_localfd (JNIEnv
* env
, jobject
this)
138 jclass this_cls
, fd_cls
;
143 assert (env
!= NULL
);
144 assert ((*env
) != NULL
);
146 DBG ("_javanet_create_localfd(): Entered _javanet_create_localfd\n");
148 /* Look up the fd field */
149 this_cls
= (*env
)->FindClass (env
, "java/net/SocketImpl");
150 if (this_cls
== NULL
)
153 fid
= (*env
)->GetFieldID (env
, this_cls
, "fd", "Ljava/io/FileDescriptor;");
157 DBG ("_javanet_create_localfd(): Found fd variable\n");
159 /* Create a FileDescriptor */
160 fd_cls
= (*env
)->FindClass (env
, "java/io/FileDescriptor");
164 DBG ("_javanet_create_localfd(): Found FileDescriptor class\n");
166 mid
= (*env
)->GetMethodID (env
, fd_cls
, "<init>", "()V");
170 DBG ("_javanet_create_localfd(): Found FileDescriptor constructor\n");
172 fd_obj
= (*env
)->NewObject (env
, fd_cls
, mid
);
176 DBG ("_javanet_create_localfd(): Created FileDescriptor\n");
178 /* Now set the pointer to the new FileDescriptor */
179 (*env
)->SetObjectField (env
, this, fid
, fd_obj
);
180 DBG ("_javanet_create_localfd(): Set fd field\n");
185 /*************************************************************************/
188 * Returns a Boolean object with the specfied value
191 _javanet_create_boolean (JNIEnv
* env
, jboolean val
)
197 assert (env
!= NULL
);
198 assert ((*env
) != NULL
);
200 cls
= (*env
)->FindClass (env
, "java/lang/Boolean");
204 mid
= (*env
)->GetMethodID (env
, cls
, "<init>", "(Z)V");
208 obj
= (*env
)->NewObject (env
, cls
, mid
, val
);
215 /*************************************************************************/
218 * Returns an Integer object with the specfied value
221 _javanet_create_integer (JNIEnv
* env
, jint val
)
227 assert (env
!= NULL
);
228 assert ((*env
) != NULL
);
230 cls
= (*env
)->FindClass (env
, "java/lang/Integer");
234 mid
= (*env
)->GetMethodID (env
, cls
, "<init>", "(I)V");
238 obj
= (*env
)->NewObject (env
, cls
, mid
, val
);
245 /*************************************************************************/
248 * Builds an InetAddress object from a 32 bit address in host byte order
251 _javanet_create_inetaddress (JNIEnv
* env
, int netaddr
)
253 #ifndef WITHOUT_NETWORK
254 unsigned char octets
[4];
261 assert (env
!= NULL
);
262 assert ((*env
) != NULL
);
264 /* Build a string IP address */
265 TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (netaddr
,
268 octets
[2], octets
[3]);
269 sprintf (buf
, "%d.%d.%d.%d", octets
[0], octets
[1], octets
[2], octets
[3]);
270 DBG ("_javanet_create_inetaddress(): Created ip addr string\n");
272 /* Get an InetAddress object for this IP */
273 ia_cls
= (*env
)->FindClass (env
, "java/net/InetAddress");
279 DBG ("_javanet_create_inetaddress(): Found InetAddress class\n");
281 mid
= (*env
)->GetStaticMethodID (env
, ia_cls
, "getByName",
282 "(Ljava/lang/String;)Ljava/net/InetAddress;");
288 DBG ("_javanet_create_inetaddress(): Found getByName method\n");
290 ip_str
= (*env
)->NewStringUTF (env
, buf
);
296 ia
= (*env
)->CallStaticObjectMethod (env
, ia_cls
, mid
, ip_str
);
302 DBG ("_javanet_create_inetaddress(): Called getByName method\n");
305 #else /* not WITHOUT_NETWORK */
307 #endif /* not WITHOUT_NETWORK */
310 /*************************************************************************/
313 _javanet_set_remhost_addr (JNIEnv
* env
, jobject
this, jobject ia
)
318 assert (env
!= NULL
);
319 assert ((*env
) != NULL
);
321 /* Set the variable in the object */
322 this_cls
= (*env
)->FindClass (env
, "java/net/SocketImpl");
323 if (this_cls
== NULL
)
327 (*env
)->GetFieldID (env
, this_cls
, "address", "Ljava/net/InetAddress;");
331 DBG ("_javanet_set_remhost_addr(): Found address field\n");
333 (*env
)->SetObjectField (env
, this, fid
, ia
);
334 DBG ("_javanet_set_remhost_addr(): Set field\n");
338 * Set's the value of the "addr" field in PlainSocketImpl with a new
339 * InetAddress for the specified addr
342 _javanet_set_remhost (JNIEnv
* env
, jobject
this, int netaddr
)
346 assert (env
!= NULL
);
347 assert ((*env
) != NULL
);
349 DBG ("_javanet_set_remhost(): Entered _javanet_set_remhost\n");
351 /* Get an InetAddress object */
352 ia
= _javanet_create_inetaddress (env
, netaddr
);
356 _javanet_set_remhost_addr (env
, this, ia
);
360 /*************************************************************************/
363 * Returns a 32 bit Internet address for the passed in InetAddress object
366 _javanet_get_netaddr (JNIEnv
* env
, jobject addr
)
368 #ifndef WITHOUT_NETWORK
375 assert (env
!= NULL
);
376 assert ((*env
) != NULL
);
378 DBG ("_javanet_get_netaddr(): Entered _javanet_get_netaddr\n");
382 JCL_ThrowException (env
, "java/lang/NullPointerException",
387 /* Call the getAddress method on the object to retrieve the IP address */
388 cls
= (*env
)->GetObjectClass (env
, addr
);
392 mid
= (*env
)->GetMethodID (env
, cls
, "getAddress", "()[B");
396 DBG ("_javanet_get_netaddr(): Got getAddress method\n");
398 arr
= (*env
)->CallObjectMethod (env
, addr
, mid
);
402 DBG ("_javanet_get_netaddr(): Got the address\n");
404 /* Turn the IP address into a 32 bit Internet address in network byte order */
405 len
= (*env
)->GetArrayLength (env
, arr
);
408 JCL_ThrowException (env
, IO_EXCEPTION
, "Internal Error");
411 DBG ("_javanet_get_netaddr(): Length ok\n");
413 octets
= (*env
)->GetByteArrayElements (env
, arr
, 0);
417 DBG ("_javanet_get_netaddr(): Grabbed bytes\n");
419 TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets
[0],
424 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
425 DBG ("_javanet_get_netaddr(): Done getting addr\n");
428 #else /* not WITHOUT_NETWORK */
429 #endif /* not WITHOUT_NETWORK */
432 /*************************************************************************/
435 * Creates a new stream or datagram socket
438 _javanet_create (JNIEnv
* env
, jobject
this, jboolean stream
)
440 #ifndef WITHOUT_NETWORK
444 assert (env
!= NULL
);
445 assert ((*env
) != NULL
);
449 /* create a stream socket */
450 TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM (fd
, result
);
451 if (result
!= TARGET_NATIVE_OK
)
453 JCL_ThrowException (env
, IO_EXCEPTION
,
454 TARGET_NATIVE_LAST_ERROR_STRING ());
460 /* create a datagram socket, set broadcast option */
461 TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM (fd
, result
);
462 if (result
!= TARGET_NATIVE_OK
)
464 JCL_ThrowException (env
, IO_EXCEPTION
,
465 TARGET_NATIVE_LAST_ERROR_STRING ());
468 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST (fd
, 1, result
);
469 if (result
!= TARGET_NATIVE_OK
)
471 JCL_ThrowException (env
, IO_EXCEPTION
,
472 TARGET_NATIVE_LAST_ERROR_STRING ());
478 _javanet_set_int_field (env
, this, "gnu/java/net/PlainSocketImpl",
481 _javanet_set_int_field (env
, this, "gnu/java/net/PlainDatagramSocketImpl",
484 if ((*env
)->ExceptionOccurred (env
))
486 /* Try to make sure we close the socket since close() won't work. */
489 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
490 if (result
!= TARGET_NATIVE_OK
491 && (TARGET_NATIVE_LAST_ERROR ()
492 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
495 while (result
!= TARGET_NATIVE_OK
);
499 #else /* not WITHOUT_NETWORK */
500 #endif /* not WITHOUT_NETWORK */
503 /*************************************************************************/
506 * Close the socket. Any underlying streams will be closed by this
510 _javanet_close (JNIEnv
* env
, jobject
this, int stream
)
512 #ifndef WITHOUT_NETWORK
517 assert (env
!= NULL
);
518 assert ((*env
) != NULL
);
520 fd
= _javanet_get_int_field (env
, this, "native_fd");
525 _javanet_set_int_field (env
, this, "gnu/java/net/PlainSocketImpl",
528 _javanet_set_int_field (env
, this, "gnu/java/net/PlainDatagramSocketImpl",
532 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
533 if (result
!= TARGET_NATIVE_OK
)
535 /* Only throw an error when a "real" error occurs. */
536 error
= TARGET_NATIVE_LAST_ERROR ();
537 if (error
!= TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
538 && error
!= ENOTCONN
&& error
!= ECONNRESET
&& error
!= EBADF
)
539 JCL_ThrowException (env
, IO_EXCEPTION
,
540 TARGET_NATIVE_LAST_ERROR_STRING ());
543 while (error
== TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
);
545 #else /* not WITHOUT_NETWORK */
546 #endif /* not WITHOUT_NETWORK */
549 /*************************************************************************/
552 * Connects to the specified destination.
555 _javanet_connect (JNIEnv
* env
, jobject
this, jobject addr
, jint port
)
557 #ifndef WITHOUT_NETWORK
560 int local_address
, local_port
;
561 int remote_address
, remote_port
;
563 assert (env
!= NULL
);
564 assert ((*env
) != NULL
);
566 DBG ("_javanet_connect(): Entered _javanet_connect\n");
568 /* Pre-process input variables */
569 netaddr
= _javanet_get_netaddr (env
, addr
);
570 if ((*env
)->ExceptionOccurred (env
))
575 DBG ("_javanet_connect(): Got network address\n");
577 /* Grab the real socket file descriptor */
578 fd
= _javanet_get_int_field (env
, this, "native_fd");
581 JCL_ThrowException (env
, IO_EXCEPTION
,
582 "Internal error: _javanet_connect(): no native file descriptor");
585 DBG ("_javanet_connect(): Got native fd\n");
590 TARGET_NATIVE_NETWORK_SOCKET_CONNECT (fd
, netaddr
, port
, result
);
591 if (result
!= TARGET_NATIVE_OK
592 && (TARGET_NATIVE_LAST_ERROR ()
593 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
595 JCL_ThrowException (env
, IO_EXCEPTION
,
596 TARGET_NATIVE_LAST_ERROR_STRING ());
600 while (result
!= TARGET_NATIVE_OK
);
602 DBG ("_javanet_connect(): Connected successfully\n");
604 /* Populate instance variables */
605 TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd
, local_address
, local_port
,
607 if (result
!= TARGET_NATIVE_OK
)
609 JCL_ThrowException (env
, IO_EXCEPTION
,
610 TARGET_NATIVE_LAST_ERROR_STRING ());
611 /* We don't care whether this succeeds. close() will cleanup later. */
612 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
616 _javanet_create_localfd (env
, this);
617 if ((*env
)->ExceptionOccurred (env
))
619 /* We don't care whether this succeeds. close() will cleanup later. */
620 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
623 DBG ("_javanet_connect(): Created fd\n");
625 _javanet_set_int_field (env
, this, "java/net/SocketImpl", "localport",
627 if ((*env
)->ExceptionOccurred (env
))
629 /* We don't care whether this succeeds. close() will cleanup later. */
630 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
633 DBG ("_javanet_connect(): Set the local port\n");
635 TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (fd
, remote_address
,
636 remote_port
, result
);
637 if (result
!= TARGET_NATIVE_OK
)
639 JCL_ThrowException (env
, IO_EXCEPTION
,
640 TARGET_NATIVE_LAST_ERROR_STRING ());
641 /* We don't care whether this succeeds. close() will cleanup later. */
642 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
646 if (remote_address
== netaddr
)
648 _javanet_set_remhost_addr (env
, this, addr
);
652 _javanet_set_remhost (env
, this, remote_address
);
654 if ((*env
)->ExceptionOccurred (env
))
656 /* We don't care whether this succeeds. close() will cleanup later. */
657 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
660 DBG ("_javanet_connect(): Set the remote host\n");
662 _javanet_set_int_field (env
, this, "java/net/SocketImpl", "port",
664 if ((*env
)->ExceptionOccurred (env
))
666 /* We don't care whether this succeeds. close() will cleanup later. */
667 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd
, result
);
670 DBG ("_javanet_connect(): Set the remote port\n");
671 #else /* not WITHOUT_NETWORK */
672 #endif /* not WITHOUT_NETWORK */
675 /*************************************************************************/
678 * This method binds the specified address to the specified local port.
679 * Note that we have to set the local address and local
680 * port public instance variables.
683 _javanet_bind (JNIEnv
* env
, jobject
this, jobject addr
, jint port
,
686 #ifndef WITHOUT_NETWORK
694 int local_address
, local_port
;
696 assert (env
!= NULL
);
697 assert ((*env
) != NULL
);
699 DBG ("_javanet_bind(): Entering native bind()\n");
701 /* Get the address to connect to */
702 cls
= (*env
)->GetObjectClass (env
, addr
);
706 mid
= (*env
)->GetMethodID (env
, cls
, "getAddress", "()[B");
710 DBG ("_javanet_bind(): Past getAddress method id\n");
712 arr
= (*env
)->CallObjectMethod (env
, addr
, mid
);
713 if ((arr
== NULL
) || (*env
)->ExceptionOccurred (env
))
715 JCL_ThrowException (env
, IO_EXCEPTION
,
716 "Internal error: _javanet_bind()");
720 DBG ("_javanet_bind(): Past call object method\n");
722 octets
= (*env
)->GetByteArrayElements (env
, arr
, 0);
726 DBG ("_javanet_bind(): Past grab array\n");
728 /* Get the native socket file descriptor */
729 fd
= _javanet_get_int_field (env
, this, "native_fd");
732 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
733 JCL_ThrowException (env
, IO_EXCEPTION
,
734 "Internal error: _javanet_bind(): no native file descriptor");
737 DBG ("_javanet_bind(): Past native_fd lookup\n");
740 _javanet_set_option (env
, this, SOCKOPT_SO_REUSEADDR
,
741 _javanet_create_boolean (env
, JNI_TRUE
));
744 /* Bind the socket */
745 TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets
[0],
749 TARGET_NATIVE_NETWORK_SOCKET_BIND (fd
, tmpaddr
, port
, result
);
751 if (result
!= TARGET_NATIVE_OK
)
753 char *errorstr
= TARGET_NATIVE_LAST_ERROR_STRING ();
754 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
756 JCL_ThrowException (env
, BIND_EXCEPTION
,
760 DBG ("_javanet_bind(): Past bind\n");
762 (*env
)->ReleaseByteArrayElements (env
, arr
, octets
, 0);
764 /* Update instance variables, specifically the local port number */
765 TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd
, local_address
, local_port
,
767 if (result
!= TARGET_NATIVE_OK
)
769 JCL_ThrowException (env
, IO_EXCEPTION
,
770 TARGET_NATIVE_LAST_ERROR_STRING ());
775 _javanet_set_int_field (env
, this, "java/net/SocketImpl",
776 "localport", local_port
);
778 _javanet_set_int_field (env
, this, "java/net/DatagramSocketImpl",
779 "localPort", local_port
);
780 DBG ("_javanet_bind(): Past update port number\n");
783 #else /* not WITHOUT_NETWORK */
784 #endif /* not WITHOUT_NETWORK */
787 /*************************************************************************/
790 * Starts listening on a socket with the specified number of pending
791 * connections allowed.
794 _javanet_listen (JNIEnv
* env
, jobject
this, jint queuelen
)
796 #ifndef WITHOUT_NETWORK
800 assert (env
!= NULL
);
801 assert ((*env
) != NULL
);
803 /* Get the real file descriptor */
804 fd
= _javanet_get_int_field (env
, this, "native_fd");
807 JCL_ThrowException (env
, IO_EXCEPTION
,
808 "Internal error: _javanet_listen(): no native file descriptor");
812 /* Start listening */
813 TARGET_NATIVE_NETWORK_SOCKET_LISTEN (fd
, queuelen
, result
);
814 if (result
!= TARGET_NATIVE_OK
)
816 JCL_ThrowException (env
, IO_EXCEPTION
,
817 TARGET_NATIVE_LAST_ERROR_STRING ());
820 #else /* not WITHOUT_NETWORK */
821 #endif /* not WITHOUT_NETWORK */
824 /*************************************************************************/
827 * Accepts a new connection and assigns it to the passed in SocketImpl
828 * object. Note that we assume this is a PlainSocketImpl just like us
831 _javanet_accept (JNIEnv
* env
, jobject
this, jobject impl
)
833 #ifndef WITHOUT_NETWORK
836 int local_address
, local_port
;
837 int remote_address
, remote_port
;
839 assert (env
!= NULL
);
840 assert ((*env
) != NULL
);
842 /* Get the real file descriptor */
843 fd
= _javanet_get_int_field (env
, this, "native_fd");
846 JCL_ThrowException (env
, IO_EXCEPTION
,
847 "Internal error: _javanet_accept(): no native file descriptor");
851 /* Accept the connection */
854 TARGET_NATIVE_NETWORK_SOCKET_ACCEPT (fd
, newfd
, result
);
855 if (result
!= TARGET_NATIVE_OK
856 && (TARGET_NATIVE_LAST_ERROR ()
857 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
859 if (TARGET_NATIVE_LAST_ERROR () == EAGAIN
)
860 JCL_ThrowException (env
, "java/net/SocketTimeoutException",
863 JCL_ThrowException (env
, IO_EXCEPTION
,
864 TARGET_NATIVE_LAST_ERROR_STRING ());
868 while (result
!= TARGET_NATIVE_OK
);
870 /* Populate instance variables */
871 _javanet_set_int_field (env
, impl
, "gnu/java/net/PlainSocketImpl",
874 if ((*env
)->ExceptionOccurred (env
))
876 /* Try to make sure we close the socket since close() won't work. */
879 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
880 if (result
!= TARGET_NATIVE_OK
881 && (TARGET_NATIVE_LAST_ERROR ()
882 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
))
885 while (result
!= TARGET_NATIVE_OK
);
889 TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (newfd
, local_address
,
891 if (result
!= TARGET_NATIVE_OK
)
893 /* We don't care whether this succeeds. close() will cleanup later. */
894 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
895 JCL_ThrowException (env
, IO_EXCEPTION
,
896 TARGET_NATIVE_LAST_ERROR_STRING ());
900 _javanet_create_localfd (env
, impl
);
901 if ((*env
)->ExceptionOccurred (env
))
903 /* We don't care whether this succeeds. close() will cleanup later. */
904 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
908 _javanet_set_int_field (env
, impl
, "java/net/SocketImpl", "localport",
910 if ((*env
)->ExceptionOccurred (env
))
912 /* We don't care whether this succeeds. close() will cleanup later. */
913 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
917 TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (newfd
, remote_address
,
918 remote_port
, result
);
919 if (result
!= TARGET_NATIVE_OK
)
921 JCL_ThrowException (env
, IO_EXCEPTION
,
922 TARGET_NATIVE_LAST_ERROR_STRING ());
923 /* We don't care whether this succeeds. close() will cleanup later. */
924 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
928 _javanet_set_remhost (env
, impl
, remote_address
);
929 if ((*env
)->ExceptionOccurred (env
))
931 /* We don't care whether this succeeds. close() will cleanup later. */
932 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
936 _javanet_set_int_field (env
, impl
, "java/net/SocketImpl", "port",
938 if ((*env
)->ExceptionOccurred (env
))
940 /* We don't care whether this succeeds. close() will cleanup later. */
941 TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd
, result
);
944 #else /* not WITHOUT_NETWORK */
945 #endif /* not WITHOUT_NETWORK */
948 /*************************************************************************/
951 * Receives a buffer from a remote host. The args are:
953 * buf - The byte array into which the data received will be written
954 * offset - Offset into the byte array to start writing
955 * len - The number of bytes to read.
956 * addr - Pointer to 32 bit net address of host to receive from. If null,
957 * this parm is ignored. If pointing to an address of 0, the
958 * actual address read is stored here
959 * port - Pointer to the port to receive from. If null, this parm is ignored.
960 * If it is 0, the actual remote port received from is stored here
962 * The actual number of bytes read is returned.
965 _javanet_recvfrom (JNIEnv
* env
, jobject
this, jarray buf
, int offset
,
966 int len
, int *addr
, int *port
)
968 #ifndef WITHOUT_NETWORK
971 int from_address
, from_port
;
974 assert (env
!= NULL
);
975 assert ((*env
) != NULL
);
977 DBG ("_javanet_recvfrom(): Entered _javanet_recvfrom\n");
979 /* Get the real file descriptor */
980 fd
= _javanet_get_int_field (env
, this, "native_fd");
983 JCL_ThrowException (env
, IO_EXCEPTION
,
984 "Internal error: _javanet_recvfrom(): no native file descriptor");
987 DBG ("_javanet_recvfrom(): Got native_fd\n");
989 /* Get a pointer to the buffer */
990 p
= (*env
)->GetByteArrayElements (env
, buf
, 0);
994 DBG ("_javanet_recvfrom(): Got buffer\n");
1003 TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT (fd
,
1012 TARGET_NATIVE_NETWORK_SOCKET_RECEIVE (fd
, p
+ offset
, len
,
1016 while ((received_bytes
== -1) &&
1017 (TARGET_NATIVE_LAST_ERROR () ==
1018 TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
));
1020 if (received_bytes
== -1)
1022 if (TARGET_NATIVE_LAST_ERROR () == EAGAIN
)
1023 JCL_ThrowException (env
, "java/net/SocketTimeoutException", "Timeout");
1025 JCL_ThrowException (env
, IO_EXCEPTION
,
1026 TARGET_NATIVE_LAST_ERROR_STRING ());
1028 /* Cleanup and return. */
1029 (*env
)->ReleaseByteArrayElements (env
, buf
, p
, 0);
1033 (*env
)->ReleaseByteArrayElements (env
, buf
, p
, 0);
1035 /* Handle return addr case */
1038 (*addr
) = from_address
;
1040 (*port
) = from_port
;
1043 return (received_bytes
);
1044 #else /* not WITHOUT_NETWORK */
1045 #endif /* not WITHOUT_NETWORK */
1048 /*************************************************************************/
1051 * Sends a buffer to a remote host. The args are:
1053 * buf - A byte array
1054 * offset - Index into the byte array to start sendign
1055 * len - The number of bytes to write
1056 * addr - The 32bit address to send to (may be 0)
1057 * port - The port number to send to (may be 0)
1060 _javanet_sendto (JNIEnv
* env
, jobject
this, jarray buf
, int offset
, int len
,
1063 #ifndef WITHOUT_NETWORK
1068 assert (env
!= NULL
);
1069 assert ((*env
) != NULL
);
1071 /* Get the real file descriptor */
1072 fd
= _javanet_get_int_field (env
, this, "native_fd");
1075 JCL_ThrowException (env
, IO_EXCEPTION
,
1076 "Internal error: _javanet_sendto(): no native file descriptor");
1080 /* Get a pointer to the buffer */
1081 p
= (*env
)->GetByteArrayElements (env
, buf
, 0);
1085 /* We must send all the data, so repeat till done. */
1091 DBG ("_javanet_sendto(): Sending....\n");
1092 TARGET_NATIVE_NETWORK_SOCKET_SEND (fd
, p
+ offset
, len
, bytes_sent
);
1096 DBG ("_javanet_sendto(): Sending....\n");
1097 TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT (fd
, p
+ offset
,
1104 if (TARGET_NATIVE_LAST_ERROR ()
1105 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL
)
1107 JCL_ThrowException (env
, IO_EXCEPTION
,
1108 TARGET_NATIVE_LAST_ERROR_STRING ());
1119 (*env
)->ReleaseByteArrayElements (env
, buf
, p
, 0);
1121 #else /* not WITHOUT_NETWORK */
1122 #endif /* not WITHOUT_NETWORK */
1125 /*************************************************************************/
1128 * Sets the specified option for a socket
1131 _javanet_set_option (JNIEnv
* env
, jobject
this, jint option_id
, jobject val
)
1133 #ifndef WITHOUT_NETWORK
1141 assert (env
!= NULL
);
1142 assert ((*env
) != NULL
);
1144 /* Get the real file descriptor */
1145 fd
= _javanet_get_int_field (env
, this, "native_fd");
1148 JCL_ThrowException (env
, IO_EXCEPTION
,
1149 "Internal error: _javanet_set_option(): no native file descriptor");
1153 /* We need a class object for all cases below */
1154 cls
= (*env
)->GetObjectClass (env
, val
);
1158 /* Process the option request */
1159 result
= TARGET_NATIVE_ERROR
;
1162 /* TCP_NODELAY case. val is a Boolean that tells us what to do */
1163 case SOCKOPT_TCP_NODELAY
:
1164 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1167 JCL_ThrowException (env
, IO_EXCEPTION
,
1168 "Internal error: _javanet_set_option()");
1172 /* Should be a 0 or a 1 */
1173 optval
= (*env
)->CallBooleanMethod (env
, val
, mid
);
1174 if ((*env
)->ExceptionOccurred (env
))
1177 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY (fd
, optval
,
1181 /* SO_LINGER case. If val is a boolean, then it will always be set
1182 to false indicating disable linger, otherwise it will be an
1183 integer that contains the linger value */
1184 case SOCKOPT_SO_LINGER
:
1185 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1188 /* We are disabling linger */
1189 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd
, 1, 0,
1194 /* Clear exception if thrown for failure to do method lookup
1196 if ((*env
)->ExceptionOccurred (env
))
1197 (*env
)->ExceptionClear (env
);
1199 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1202 JCL_ThrowException (env
, IO_EXCEPTION
,
1203 "Internal error: _javanet_set_option()");
1207 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1208 if ((*env
)->ExceptionOccurred (env
))
1211 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd
, 0, optval
,
1216 /* SO_TIMEOUT case. Val will be an integer with the new value */
1217 /* Not writable on Linux */
1218 case SOCKOPT_SO_TIMEOUT
:
1220 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1223 JCL_ThrowException (env
, IO_EXCEPTION
,
1224 "Internal error: _javanet_set_option()");
1228 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1229 if ((*env
)->ExceptionOccurred (env
))
1232 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT (fd
, optval
, result
);
1234 result
= TARGET_NATIVE_OK
;
1238 case SOCKOPT_SO_SNDBUF
:
1239 case SOCKOPT_SO_RCVBUF
:
1240 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1243 JCL_ThrowException (env
, IO_EXCEPTION
,
1244 "Internal error: _javanet_set_option()");
1249 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1250 if ((*env
)->ExceptionOccurred (env
))
1253 if (option_id
== SOCKOPT_SO_SNDBUF
)
1254 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF (fd
, optval
,
1257 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF (fd
, optval
,
1261 /* TTL case. Val with be an Integer with the new time to live value */
1262 case SOCKOPT_IP_TTL
:
1263 mid
= (*env
)->GetMethodID (env
, cls
, "intValue", "()I");
1266 JCL_ThrowException (env
, IO_EXCEPTION
,
1267 "Internal error: _javanet_set_option()");
1271 optval
= (*env
)->CallIntMethod (env
, val
, mid
);
1272 if ((*env
)->ExceptionOccurred (env
))
1275 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL (fd
, optval
, result
);
1278 /* Multicast Interface case - val is InetAddress object */
1279 case SOCKOPT_IP_MULTICAST_IF
:
1280 address
= _javanet_get_netaddr (env
, val
);
1282 if ((*env
)->ExceptionOccurred (env
))
1285 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF (fd
, address
,
1289 case SOCKOPT_SO_REUSEADDR
:
1290 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1293 JCL_ThrowException (env
, IO_EXCEPTION
,
1294 "Internal error: _javanet_set_option()");
1298 /* Should be a 0 or a 1 */
1299 optval
= (*env
)->CallBooleanMethod (env
, val
, mid
);
1300 if ((*env
)->ExceptionOccurred (env
))
1303 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS (fd
, optval
,
1307 case SOCKOPT_SO_KEEPALIVE
:
1308 mid
= (*env
)->GetMethodID (env
, cls
, "booleanValue", "()Z");
1311 JCL_ThrowException (env
, IO_EXCEPTION
,
1312 "Internal error: _javanet_set_option()");
1316 /* Should be a 0 or a 1 */
1317 optval
= (*env
)->CallBooleanMethod (env
, val
, mid
);
1318 if ((*env
)->ExceptionOccurred (env
))
1321 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE (fd
, optval
, result
);
1324 case SOCKOPT_SO_BINDADDR
:
1325 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "This option cannot be set");
1329 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "Unrecognized option");
1333 /* Check to see if above operations succeeded */
1334 if (result
!= TARGET_NATIVE_OK
)
1336 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1337 TARGET_NATIVE_LAST_ERROR_STRING ());
1340 #else /* not WITHOUT_NETWORK */
1341 #endif /* not WITHOUT_NETWORK */
1344 /*************************************************************************/
1347 * Retrieves the specified option values for a socket
1350 _javanet_get_option (JNIEnv
* env
, jobject
this, jint option_id
)
1352 #ifndef WITHOUT_NETWORK
1358 assert (env
!= NULL
);
1359 assert ((*env
) != NULL
);
1361 /* Get the real file descriptor */
1362 fd
= _javanet_get_int_field (env
, this, "native_fd");
1365 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1366 "Internal error: _javanet_get_option(): no native file descriptor");
1370 /* Process the option requested */
1373 /* TCP_NODELAY case. Return a Boolean indicating on or off */
1374 case SOCKOPT_TCP_NODELAY
:
1375 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY (fd
, optval
,
1377 if (result
!= TARGET_NATIVE_OK
)
1379 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1380 TARGET_NATIVE_LAST_ERROR_STRING ());
1385 return (_javanet_create_boolean (env
, JNI_TRUE
));
1387 return (_javanet_create_boolean (env
, JNI_FALSE
));
1391 /* SO_LINGER case. If disabled, return a Boolean object that represents
1392 false, else return an Integer that is the value of SO_LINGER */
1393 case SOCKOPT_SO_LINGER
:
1394 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER (fd
, flag
, optval
,
1396 if (result
!= TARGET_NATIVE_OK
)
1398 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1399 TARGET_NATIVE_LAST_ERROR_STRING ());
1404 return (_javanet_create_integer (env
, JNI_TRUE
));
1406 return (_javanet_create_boolean (env
, JNI_FALSE
));
1410 /* SO_TIMEOUT case. Return an Integer object with the timeout value */
1411 case SOCKOPT_SO_TIMEOUT
:
1413 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT (fd
, optval
, result
);
1414 if (result
!= TARGET_NATIVE_OK
)
1416 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1417 TARGET_NATIVE_LAST_ERROR_STRING ());
1420 return (_javanet_create_integer (env
, optval
));
1422 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1423 "SO_TIMEOUT not supported on this platform");
1425 #endif /* not SO_TIMEOUT */
1428 case SOCKOPT_SO_SNDBUF
:
1429 case SOCKOPT_SO_RCVBUF
:
1430 if (option_id
== SOCKOPT_SO_SNDBUF
)
1431 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF (fd
, optval
,
1434 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF (fd
, optval
,
1436 if (result
!= TARGET_NATIVE_OK
)
1438 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1439 TARGET_NATIVE_LAST_ERROR_STRING ());
1443 return (_javanet_create_integer (env
, optval
));
1446 /* The TTL case. Return an Integer with the Time to Live value */
1447 case SOCKOPT_IP_TTL
:
1448 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL (fd
, optval
, result
);
1449 if (result
!= TARGET_NATIVE_OK
)
1451 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1452 TARGET_NATIVE_LAST_ERROR_STRING ());
1456 return (_javanet_create_integer (env
, optval
));
1459 /* Multicast interface case */
1460 case SOCKOPT_IP_MULTICAST_IF
:
1461 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF (fd
, address
,
1463 if (result
!= TARGET_NATIVE_OK
)
1465 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1466 TARGET_NATIVE_LAST_ERROR_STRING ());
1470 return (_javanet_create_inetaddress (env
, address
));
1473 case SOCKOPT_SO_BINDADDR
:
1474 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS (fd
, address
,
1476 if (result
!= TARGET_NATIVE_OK
)
1478 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1479 TARGET_NATIVE_LAST_ERROR_STRING ());
1483 return (_javanet_create_inetaddress (env
, address
));
1486 case SOCKOPT_SO_REUSEADDR
:
1487 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS (fd
, optval
,
1489 if (result
!= TARGET_NATIVE_OK
)
1491 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1492 TARGET_NATIVE_LAST_ERROR_STRING ());
1497 return (_javanet_create_boolean (env
, JNI_TRUE
));
1499 return (_javanet_create_boolean (env
, JNI_FALSE
));
1503 case SOCKOPT_SO_KEEPALIVE
:
1504 TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE (fd
, optval
, result
);
1505 if (result
!= TARGET_NATIVE_OK
)
1507 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1508 TARGET_NATIVE_LAST_ERROR_STRING ());
1513 return (_javanet_create_boolean (env
, JNI_TRUE
));
1515 return (_javanet_create_boolean (env
, JNI_FALSE
));
1520 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "No such option");
1525 #else /* not WITHOUT_NETWORK */
1526 #endif /* not WITHOUT_NETWORK */
1530 _javanet_shutdownInput (JNIEnv
* env
, jobject
this)
1534 assert (env
!= NULL
);
1535 assert ((*env
) != NULL
);
1537 /* Get the real file descriptor. */
1538 fd
= _javanet_get_int_field (env
, this, "native_fd");
1541 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1542 "Internal error: _javanet_get_option(): no native file descriptor");
1546 /* Shutdown input stream of socket. */
1547 if (shutdown (fd
, SHUT_RD
) == -1)
1549 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1555 _javanet_shutdownOutput (JNIEnv
* env
, jobject
this)
1559 assert (env
!= NULL
);
1560 assert ((*env
) != NULL
);
1562 /* Get the real file descriptor. */
1563 fd
= _javanet_get_int_field (env
, this, "native_fd");
1566 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1567 "Internal error: _javanet_get_option(): no native file descriptor");
1571 /* Shutdown output stream of socket. */
1572 if (shutdown (fd
, SHUT_WR
) == -1)
1574 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));