diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/native/jni/java-net | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/native/jni/java-net')
8 files changed, 2828 insertions, 0 deletions
diff --git a/libjava/classpath/native/jni/java-net/.cvsignore b/libjava/classpath/native/jni/java-net/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-net/Makefile.am b/libjava/classpath/native/jni/java-net/Makefile.am new file mode 100644 index 00000000000..3e8c863a9a9 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/Makefile.am @@ -0,0 +1,14 @@ +pkglib_LTLIBRARIES = libjavanet.la + +libjavanet_la_SOURCES = javanet.c \ + javanet.h \ + java_net_VMInetAddress.c \ + java_net_VMNetworkInterface.c \ + gnu_java_net_PlainDatagramSocketImpl.c \ + gnu_java_net_PlainSocketImpl.c + +libjavanet_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c new file mode 100644 index 00000000000..5bc284f6426 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c @@ -0,0 +1,452 @@ +/* PlainDatagramSocketImpl.c - Native methods for PlainDatagramSocketImpl class + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "gnu_java_net_PlainDatagramSocketImpl.h" + +/* + * Note that most of the functions in this module simply redirect to another + * internal function. Why? Because many of these functions are shared + * with PlainSocketImpl. + */ + +/*************************************************************************/ + +/* + * Creates a new datagram socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_create (JNIEnv * env, jobject obj) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_create (env, obj, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Close the socket. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_close (JNIEnv * env, jobject obj) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_close (env, obj, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method binds the specified address to the specified local port. + * Note that we have to set the local address and local port public instance + * variables. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_bind (JNIEnv * env, jobject obj, + jint port, jobject addr) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_bind (env, obj, addr, port, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_setOption (JNIEnv * env, + jobject obj, + jint option_id, + jobject val) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_set_option (env, obj, option_id, val); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_getOption (JNIEnv * env, + jobject obj, + jint option_id) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + return (_javanet_get_option (env, obj, option_id)); +#else /* not WITHOUT_NETWORK */ + return NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Reads a buffer from a remote host + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_receive0 (JNIEnv * env, jobject obj, + jobject packet) +{ +#ifndef WITHOUT_NETWORK + int addr, port, bytes_read; + unsigned int maxlen, offset; + jclass cls, addr_cls; + jfieldID fid; + jmethodID mid; + jarray arr; + unsigned char octets[4]; + char ip_str[16]; + jobject ip_str_obj, addr_obj; + + assert (env != NULL); + assert ((*env) != NULL); + + addr = 0; + port = 0; + maxlen = 0; + offset = 0; + bytes_read = 0; + + if (packet == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "Null datagram packet"); + return; + } + + /* Get the buffer from the packet */ + cls = (*env)->GetObjectClass (env, packet); + if (cls == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error"); + return; + } + + mid = (*env)->GetMethodID (env, cls, "getData", "()[B"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: getData"); + return; + } + + arr = (*env)->CallObjectMethod (env, packet, mid); + if ((*env)->ExceptionOccurred (env)) + return; + if (arr == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: call getData"); + return; + } + + /* Now get the offset from the packet */ + mid = (*env)->GetMethodID (env, cls, "getOffset", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: getOffset"); + return; + } + + offset = (*env)->CallIntMethod (env, packet, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Got the offset\n"); + + /* Now get the maximal available length from the packet */ + fid = (*env)->GetFieldID (env, cls, "maxlen", "I"); + if (fid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: maxlen"); + return; + } + + maxlen = (*env)->GetIntField (env, packet, fid); + if ((*env)->ExceptionOccurred (env)) + return; + + /* Receive the packet */ + /* should we try some sort of validation on the length? */ + bytes_read = + _javanet_recvfrom (env, obj, arr, offset, maxlen, &addr, &port); + if ((*env)->ExceptionOccurred (env)) + return; + if (bytes_read == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: receive"); + return; + } + + DBG ("PlainDatagramSocketImpl.receive(): Received packet\n"); + + /* Store the address */ + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (addr, + octets[0], + octets[1], + octets[2], octets[3]); + sprintf (ip_str, "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); + ip_str_obj = (*env)->NewStringUTF (env, ip_str); + if (ip_str_obj == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: new string"); + return; + } + + addr_cls = (*env)->FindClass (env, "java/net/InetAddress"); + if (addr_cls == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: InetAddress class"); + return; + } + DBG ("PlainDatagramSocketImpl.receive(): Found InetAddress class\n"); + + mid = (*env)->GetStaticMethodID (env, addr_cls, "getByName", + "(Ljava/lang/String;)Ljava/net/InetAddress;"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal Error"); + return; + } + DBG + ("PlainDatagramSocketImpl.receive(): Found InetAddress.getByName method\n"); + + addr_obj = (*env)->CallStaticObjectMethod (env, addr_cls, mid, ip_str_obj); + if ((*env)->ExceptionOccurred (env)) + return; + + mid = (*env)->GetMethodID (env, cls, "setAddress", + "(Ljava/net/InetAddress;)V"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: setAddress"); + return; + } + + (*env)->CallVoidMethod (env, packet, mid, addr_obj); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Stored the address\n"); + + /* Store the port */ + mid = (*env)->GetMethodID (env, cls, "setPort", "(I)V"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: setPort"); + return; + } + + (*env)->CallVoidMethod (env, packet, mid, port); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Stored the port\n"); + + /* Store back the length */ + fid = (*env)->GetFieldID (env, cls, "length", "I"); + if (fid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: length"); + return; + } + + (*env)->SetIntField (env, packet, fid, bytes_read); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Stored the length\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Writes a buffer to the remote host + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_sendto (JNIEnv * env, jobject obj, + jobject addr, jint port, + jarray buf, jint offset, + jint len) +{ +#ifndef WITHOUT_NETWORK + jint netAddress; + + assert (env != NULL); + assert ((*env) != NULL); + + netAddress = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.sendto(): have addr\n"); + + _javanet_sendto (env, obj, buf, offset, len, netAddress, port); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.sendto(): finished\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Joins a multicast group + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_join (JNIEnv * env, jobject obj, + jobject addr) +{ +#ifndef WITHOUT_NETWORK + jint netAddress; + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + netAddress = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + fd = _javanet_get_int_field (env, obj, "native_fd"); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.join(): have native fd\n"); + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_ADD_MEMBERSHIP (fd, netAddress, + result); + + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + DBG ("PlainDatagramSocketImpl.join(): finished\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Leaves a multicast group + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_leave (JNIEnv * env, jobject obj, + jobject addr) +{ +#ifndef WITHOUT_NETWORK + jint netAddress; + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + netAddress = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + fd = _javanet_get_int_field (env, obj, "native_fd"); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.leave(): have native fd\n"); + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_DROP_MEMBERSHIP (fd, netAddress, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + DBG ("PlainDatagramSocketImpl.leave(): finished\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} diff --git a/libjava/classpath/native/jni/java-net/gnu_java_net_PlainSocketImpl.c b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainSocketImpl.c new file mode 100644 index 00000000000..a5261514dce --- /dev/null +++ b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainSocketImpl.c @@ -0,0 +1,320 @@ +/* PlainSocketImpl.c - Native methods for PlainSocketImpl class + Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "gnu_java_net_PlainSocketImpl.h" + +/* + * Note that the functions in this module simply redirect to another + * internal function. Why? Because many of these functions are shared + * with PlainDatagramSocketImpl. The unshared ones were done the same + * way for consistency. + */ + +/*************************************************************************/ + +/* + * Creates a new stream or datagram socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_create (JNIEnv * env, jobject this, + jboolean stream) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_create (env, this, stream); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Close the socket. Any underlying streams will be closed by this + * action as well. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_close (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_close (env, this, 1); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Connects to the specified destination. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_connect (JNIEnv * env, jobject this, + jobject addr, jint port) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_connect (env, this, addr, port); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method binds the specified address to the specified local port. + * Note that we have to set the local address and local port public instance + * variables. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_bind (JNIEnv * env, jobject this, + jobject addr, jint port) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_bind (env, this, addr, port, 1); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Starts listening on a socket with the specified number of pending + * connections allowed. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_listen (JNIEnv * env, jobject this, + jint queuelen) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_listen (env, this, queuelen); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Accepts a new connection and assigns it to the passed in SocketImpl + * object. Note that we assume this is a PlainSocketImpl just like us. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_accept (JNIEnv * env, jobject this, + jobject impl) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_accept (env, this, impl); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +JNIEXPORT jint JNICALL +Java_gnu_java_net_PlainSocketImpl_available (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + jclass cls; + jfieldID fid; + int fd; + int bytesAvailable; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->GetObjectClass (env, this); + if (cls == 0) + { + JCL_ThrowException (env, IO_EXCEPTION, "internal error"); + return 0; + } + + fid = (*env)->GetFieldID (env, cls, "native_fd", "I"); + if (fid == 0) + { + JCL_ThrowException (env, IO_EXCEPTION, "internal error"); + return 0; + } + + fd = (*env)->GetIntField (env, this, fid); + + TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE (fd, bytesAvailable, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return 0; + } + + return bytesAvailable; +#else /* not WITHOUT_NETWORK */ + return 0; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_setOption (JNIEnv * env, jobject this, + jint option_id, jobject val) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_set_option (env, this, option_id, val); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_net_PlainSocketImpl_getOption (JNIEnv * env, jobject this, + jint option_id) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + return (_javanet_get_option (env, this, option_id)); +#else /* not WITHOUT_NETWORK */ + return NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Reads a buffer from a remote host + */ +JNIEXPORT jint JNICALL +Java_gnu_java_net_PlainSocketImpl_read (JNIEnv * env, jobject this, + jarray buf, jint offset, jint len) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + return (_javanet_recvfrom (env, this, buf, offset, len, 0, 0)); +#else /* not WITHOUT_NETWORK */ + return 0; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Writes a buffer to the remote host + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_write (JNIEnv * env, jobject this, + jarray buf, jint offset, jint len) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_sendto (env, this, buf, offset, len, 0, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_shutdownInput (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_shutdownInput (env, this); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_shutdownOutput (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_shutdownOutput (env, this); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/java_net_VMInetAddress.c b/libjava/classpath/native/jni/java-net/java_net_VMInetAddress.c new file mode 100644 index 00000000000..d33265cff7e --- /dev/null +++ b/libjava/classpath/native/jni/java-net/java_net_VMInetAddress.c @@ -0,0 +1,282 @@ +/* VMInetAddress.c - Native methods for InetAddress class + Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "java_net_VMInetAddress.h" + +/*************************************************************************/ + +/* + * Function to return the local hostname + */ +JNIEXPORT jstring JNICALL +Java_java_net_VMInetAddress_getLocalHostname (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + char hostname[256]; + int result; + jstring retval; + + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + TARGET_NATIVE_NETWORK_GET_HOSTNAME (hostname, sizeof (hostname), result); + if (result != TARGET_NATIVE_OK) + { + strcpy (hostname, "localhost"); + } +#else /* not WITHOUT_NETWORK */ + strcpy (hostname, "localhost"); +#endif /* not WITHOUT_NETWORK */ + + retval = (*env)->NewStringUTF (env, hostname); + + return (retval); +} + +/*************************************************************************/ + +/* + * Returns the value of the special IP address INADDR_ANY + */ +JNIEXPORT jarray JNICALL +Java_java_net_VMInetAddress_lookupInaddrAny (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + jarray IParray; + jbyte *octets; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Allocate an array for the IP address */ + IParray = (*env)->NewByteArray (env, 4); + if (IParray == NULL) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jarray) NULL; + } + + /* Copy in the values */ + octets = (*env)->GetByteArrayElements (env, IParray, 0); + +#ifndef WITHOUT_NETWORK + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (INADDR_ANY, + octets[0], + octets[1], + octets[2], octets[3]); + (*env)->ReleaseByteArrayElements (env, IParray, octets, 0); +#else /* not WITHOUT_NETWORK */ + octets[0] = 0; + octets[1] = 0; + octets[2] = 0; + octets[3] = 0; +#endif /* not WITHOUT_NETWORK */ + + return (IParray); +} + +/*************************************************************************/ + +/* + * Function to return the canonical hostname for a given IP address passed + * in as a byte array + */ +JNIEXPORT jstring JNICALL +Java_java_net_VMInetAddress_getHostByAddr (JNIEnv * env, + jclass class + __attribute__ ((__unused__)), + jarray arr) +{ +#ifndef WITHOUT_NETWORK + jbyte *octets; + jsize len; + int addr; + char hostname[255]; + int result; + jstring retval; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Grab the byte[] array with the IP out of the input data */ + len = (*env)->GetArrayLength (env, arr); + if (len != 4) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Bad IP Address"); + return (jstring) NULL; + } + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (!octets) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Bad IP Address"); + return (jstring) NULL; + } + + /* Convert it to a 32 bit address */ + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], octets[3], addr); + + /* Release some memory */ + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + + /* Resolve the address and return the name */ + TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_ADDRESS (addr, hostname, + sizeof (hostname), result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Bad IP address"); + return (jstring) NULL; + } + + retval = (*env)->NewStringUTF (env, hostname); + + return (retval); +#else /* not WITHOUT_NETWORK */ + return (jstring) NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +JNIEXPORT jobjectArray JNICALL +Java_java_net_VMInetAddress_getHostByName (JNIEnv * env, + jclass class + __attribute__ ((__unused__)), + jstring host) +{ +#ifndef WITHOUT_NETWORK + const char *hostname; +/* FIXME: limitation of max. 64 addresses - how to make it more flexibale? */ + int addresses[64]; + jsize addresses_count; + int result; + jclass arr_class; + jobjectArray addrs; + int i; + jbyte *octets; + jarray ret_octets; + int max_addresses; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Grab the hostname string */ + hostname = (*env)->GetStringUTFChars (env, host, 0); + if (!hostname) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Null hostname"); + return (jobjectArray) NULL; + } + + max_addresses = sizeof (addresses) / sizeof (addresses[0]); + TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME (hostname, + addresses, + max_addresses, + addresses_count, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, (char *) hostname); + return (jobjectArray) NULL; + } + (*env)->ReleaseStringUTFChars (env, host, hostname); + + arr_class = (*env)->FindClass (env, "[B"); + if (!arr_class) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jobjectArray) NULL; + } + + addrs = (*env)->NewObjectArray (env, addresses_count, arr_class, 0); + if (!addrs) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jobjectArray) NULL; + } + + /* Now loop and copy in each address */ + for (i = 0; i < addresses_count; i++) + { + ret_octets = (*env)->NewByteArray (env, 4); + if (!ret_octets) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jobjectArray) NULL; + } + + octets = (*env)->GetByteArrayElements (env, ret_octets, 0); + + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (addresses[i], + octets[0], + octets[1], + octets[2], octets[3]); + + (*env)->ReleaseByteArrayElements (env, ret_octets, octets, 0); + + (*env)->SetObjectArrayElement (env, addrs, i, ret_octets); + } + + return (addrs); +#else /* not WITHOUT_NETWORK */ + return (jobjectArray) NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/java_net_VMNetworkInterface.c b/libjava/classpath/native/jni/java-net/java_net_VMNetworkInterface.c new file mode 100644 index 00000000000..71f5e8927e5 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/java_net_VMNetworkInterface.c @@ -0,0 +1,66 @@ +/* VMNetworkInterface.c - Native methods for NetworkInterface class + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_net_VMNetworkInterface.h" + +#include "javanet.h" + +/* + * Returns all local network interfaces as vector + */ +JNIEXPORT jobject JNICALL +Java_java_net_VMNetworkInterface_getInterfaces (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.net.VMNetworkInterface.getInterfaces(): not implemented"); + return 0; +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/javanet.c b/libjava/classpath/native/jni/java-net/javanet.c new file mode 100644 index 00000000000..fdc1c22ecbf --- /dev/null +++ b/libjava/classpath/native/jni/java-net/javanet.c @@ -0,0 +1,1577 @@ +/* javanet.c - Common internal functions for the java.net package + Copyright (C) 1998, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#ifndef WITHOUT_NETWORK +/* Need to have some value for SO_TIMEOUT */ +#ifndef SO_TIMEOUT +#ifndef SO_RCVTIMEO +#warning Neither SO_TIMEOUT or SO_RCVTIMEO are defined! +#warning This will cause all get/setOption calls with that value to throw an exception +#else +#define SO_TIMEOUT SO_RCVTIMEO +#endif /* not SO_RCVTIMEO */ +#endif /* not SO_TIMEOUT */ +#endif /* WITHOUT_NETWORK */ + +/*************************************************************************/ + +/* + * Sets an integer field in the specified object. + */ +static void +_javanet_set_int_field (JNIEnv * env, jobject obj, + const char *class, const char *field, int val) +{ + jclass cls; + jfieldID fid; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->FindClass (env, class); + if (cls == NULL) + return; + + fid = (*env)->GetFieldID (env, cls, field, "I"); + if (fid == NULL) + return; + + (*env)->SetIntField (env, obj, fid, val); + + return; +} + +/*************************************************************************/ + +/* + * Returns the value of the specified integer instance variable field or + * -1 if an error occurs. + */ +int +_javanet_get_int_field (JNIEnv * env, jobject obj, const char *field) +{ + jclass cls = 0; + jfieldID fid; + int fd; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_get_int_field(): Entered _javanet_get_int_field\n"); + + cls = (*env)->GetObjectClass (env, obj); + if (cls == NULL) + return -1; + + fid = (*env)->GetFieldID (env, cls, field, "I"); + if (fid == NULL) + return -1; + DBG ("_javanet_get_int_field(): Found field id\n"); + + fd = (*env)->GetIntField (env, obj, fid); + + return fd; +} + +/*************************************************************************/ + +/* + * Creates a FileDescriptor object in the parent class. It is not used + * by this implementation, but the docs list it as a variable, so we + * need to include it. + */ +static void +_javanet_create_localfd (JNIEnv * env, jobject this) +{ + jclass this_cls, fd_cls; + jfieldID fid; + jmethodID mid; + jobject fd_obj; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_create_localfd(): Entered _javanet_create_localfd\n"); + + /* Look up the fd field */ + this_cls = (*env)->FindClass (env, "java/net/SocketImpl"); + if (this_cls == NULL) + return; + + fid = (*env)->GetFieldID (env, this_cls, "fd", "Ljava/io/FileDescriptor;"); + if (fid == NULL) + return; + + DBG ("_javanet_create_localfd(): Found fd variable\n"); + + /* Create a FileDescriptor */ + fd_cls = (*env)->FindClass (env, "java/io/FileDescriptor"); + if (fd_cls == NULL) + return; + + DBG ("_javanet_create_localfd(): Found FileDescriptor class\n"); + + mid = (*env)->GetMethodID (env, fd_cls, "<init>", "()V"); + if (mid == NULL) + return; + + DBG ("_javanet_create_localfd(): Found FileDescriptor constructor\n"); + + fd_obj = (*env)->NewObject (env, fd_cls, mid); + if (fd_obj == NULL) + return; + + DBG ("_javanet_create_localfd(): Created FileDescriptor\n"); + + /* Now set the pointer to the new FileDescriptor */ + (*env)->SetObjectField (env, this, fid, fd_obj); + DBG ("_javanet_create_localfd(): Set fd field\n"); + + return; +} + +/*************************************************************************/ + +/* + * Returns a Boolean object with the specfied value + */ +static jobject +_javanet_create_boolean (JNIEnv * env, jboolean val) +{ + jclass cls; + jmethodID mid; + jobject obj; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->FindClass (env, "java/lang/Boolean"); + if (cls == NULL) + return NULL; + + mid = (*env)->GetMethodID (env, cls, "<init>", "(Z)V"); + if (mid == NULL) + return NULL; + + obj = (*env)->NewObject (env, cls, mid, val); + if (obj == NULL) + return NULL; + + return obj; +} + +/*************************************************************************/ + +/* + * Returns an Integer object with the specfied value + */ +static jobject +_javanet_create_integer (JNIEnv * env, jint val) +{ + jclass cls; + jmethodID mid; + jobject obj; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->FindClass (env, "java/lang/Integer"); + if (cls == NULL) + return NULL; + + mid = (*env)->GetMethodID (env, cls, "<init>", "(I)V"); + if (mid == NULL) + return NULL; + + obj = (*env)->NewObject (env, cls, mid, val); + if (obj == NULL) + return NULL; + + return obj; +} + +/*************************************************************************/ + +/* + * Builds an InetAddress object from a 32 bit address in host byte order + */ +static jobject +_javanet_create_inetaddress (JNIEnv * env, int netaddr) +{ +#ifndef WITHOUT_NETWORK + unsigned char octets[4]; + char buf[16]; + jclass ia_cls; + jmethodID mid; + jstring ip_str; + jobject ia; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Build a string IP address */ + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (netaddr, + octets[0], + octets[1], + octets[2], octets[3]); + sprintf (buf, "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); + DBG ("_javanet_create_inetaddress(): Created ip addr string\n"); + + /* Get an InetAddress object for this IP */ + ia_cls = (*env)->FindClass (env, "java/net/InetAddress"); + if (ia_cls == NULL) + { + return NULL; + } + + DBG ("_javanet_create_inetaddress(): Found InetAddress class\n"); + + mid = (*env)->GetStaticMethodID (env, ia_cls, "getByName", + "(Ljava/lang/String;)Ljava/net/InetAddress;"); + if (mid == NULL) + { + return NULL; + } + + DBG ("_javanet_create_inetaddress(): Found getByName method\n"); + + ip_str = (*env)->NewStringUTF (env, buf); + if (ip_str == NULL) + { + return NULL; + } + + ia = (*env)->CallStaticObjectMethod (env, ia_cls, mid, ip_str); + if (ia == NULL) + { + return NULL; + } + + DBG ("_javanet_create_inetaddress(): Called getByName method\n"); + + return ia; +#else /* not WITHOUT_NETWORK */ + return NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +static void +_javanet_set_remhost_addr (JNIEnv * env, jobject this, jobject ia) +{ + jclass this_cls; + jfieldID fid; + + assert (env != NULL); + assert ((*env) != NULL); + + /* 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"); +} + +/* + * Set's the value of the "addr" field in PlainSocketImpl with a new + * InetAddress for the specified addr + */ +static void +_javanet_set_remhost (JNIEnv * env, jobject this, int netaddr) +{ + jobject ia; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_set_remhost(): Entered _javanet_set_remhost\n"); + + /* Get an InetAddress object */ + ia = _javanet_create_inetaddress (env, netaddr); + if (ia == NULL) + return; + + _javanet_set_remhost_addr (env, this, ia); +} + + +/*************************************************************************/ + +/* + * Returns a 32 bit Internet address for the passed in InetAddress object + */ +int +_javanet_get_netaddr (JNIEnv * env, jobject addr) +{ +#ifndef WITHOUT_NETWORK + jclass cls = 0; + jmethodID mid; + jarray arr = 0; + jbyte *octets; + int netaddr, len; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_get_netaddr(): Entered _javanet_get_netaddr\n"); + + if (addr == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "Null address"); + return 0; + } + + /* Call the getAddress method on the object to retrieve the IP address */ + cls = (*env)->GetObjectClass (env, addr); + if (cls == NULL) + return 0; + + mid = (*env)->GetMethodID (env, cls, "getAddress", "()[B"); + if (mid == NULL) + return 0; + + DBG ("_javanet_get_netaddr(): Got getAddress method\n"); + + arr = (*env)->CallObjectMethod (env, addr, mid); + if (arr == NULL) + return 0; + + DBG ("_javanet_get_netaddr(): Got the address\n"); + + /* Turn the IP address into a 32 bit Internet address in network byte order */ + len = (*env)->GetArrayLength (env, arr); + if (len != 4) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal Error"); + return 0; + } + DBG ("_javanet_get_netaddr(): Length ok\n"); + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (octets == NULL) + return 0; + + DBG ("_javanet_get_netaddr(): Grabbed bytes\n"); + + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], + octets[3], netaddr); + + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + DBG ("_javanet_get_netaddr(): Done getting addr\n"); + + return netaddr; +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Creates a new stream or datagram socket + */ +void +_javanet_create (JNIEnv * env, jobject this, jboolean stream) +{ +#ifndef WITHOUT_NETWORK + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + if (stream) + { + /* create a stream socket */ + TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM (fd, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + else + { + /* create a datagram socket, set broadcast option */ + TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM (fd, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST (fd, 1, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + + if (stream) + _javanet_set_int_field (env, this, "gnu/java/net/PlainSocketImpl", + "native_fd", fd); + else + _javanet_set_int_field (env, this, "gnu/java/net/PlainDatagramSocketImpl", + "native_fd", fd); + + if ((*env)->ExceptionOccurred (env)) + { + /* Try to make sure we close the socket since close() won't work. */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + return; + } + while (result != TARGET_NATIVE_OK); + return; + } + +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Close the socket. Any underlying streams will be closed by this + * action as well. + */ +void +_javanet_close (JNIEnv * env, jobject this, int stream) +{ +#ifndef WITHOUT_NETWORK + int fd; + int result; + int error = 0; + + assert (env != NULL); + assert ((*env) != NULL); + + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + return; + + if (stream) + _javanet_set_int_field (env, this, "gnu/java/net/PlainSocketImpl", + "native_fd", -1); + else + _javanet_set_int_field (env, this, "gnu/java/net/PlainDatagramSocketImpl", + "native_fd", -1); + do + { + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + if (result != TARGET_NATIVE_OK) + { + /* Only throw an error when a "real" error occurs. */ + error = TARGET_NATIVE_LAST_ERROR (); + if (error != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL + && error != ENOTCONN && error != ECONNRESET && error != EBADF) + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + } + } + while (error == TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL); + +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Connects to the specified destination. + */ +void +_javanet_connect (JNIEnv * env, jobject this, jobject addr, jint port) +{ +#ifndef WITHOUT_NETWORK + int netaddr, fd; + int result; + int local_address, local_port; + int remote_address, remote_port; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_connect(): Entered _javanet_connect\n"); + + /* Pre-process input variables */ + netaddr = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + if (port == -1) + port = 0; + DBG ("_javanet_connect(): Got network address\n"); + + /* Grab the real socket file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_connect(): no native file descriptor"); + return; + } + DBG ("_javanet_connect(): Got native fd\n"); + + /* Connect up */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_CONNECT (fd, netaddr, port, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + while (result != TARGET_NATIVE_OK); + + DBG ("_javanet_connect(): Connected successfully\n"); + + /* Populate instance variables */ + TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd, local_address, local_port, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + + _javanet_create_localfd (env, this); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Created fd\n"); + + _javanet_set_int_field (env, this, "java/net/SocketImpl", "localport", + local_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Set the local port\n"); + + TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (fd, remote_address, + remote_port, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + + if (remote_address == netaddr) + { + _javanet_set_remhost_addr (env, this, addr); + } + else + { + _javanet_set_remhost (env, this, remote_address); + } + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Set the remote host\n"); + + _javanet_set_int_field (env, this, "java/net/SocketImpl", "port", + remote_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Set the remote port\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method binds the specified address to the specified local port. + * Note that we have to set the local address and local + * port public instance variables. + */ +void +_javanet_bind (JNIEnv * env, jobject this, jobject addr, jint port, + int stream) +{ +#ifndef WITHOUT_NETWORK + jclass cls; + jmethodID mid; + jbyteArray arr = 0; + jbyte *octets; + jint fd; + int tmpaddr; + int result; + int local_address, local_port; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_bind(): Entering native bind()\n"); + + /* Get the address to connect to */ + cls = (*env)->GetObjectClass (env, addr); + if (cls == NULL) + return; + + mid = (*env)->GetMethodID (env, cls, "getAddress", "()[B"); + if (mid == NULL) + return; + + DBG ("_javanet_bind(): Past getAddress method id\n"); + + arr = (*env)->CallObjectMethod (env, addr, mid); + if ((arr == NULL) || (*env)->ExceptionOccurred (env)) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_bind()"); + return; + } + + DBG ("_javanet_bind(): Past call object method\n"); + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (octets == NULL) + return; + + DBG ("_javanet_bind(): Past grab array\n"); + + /* Get the native socket file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_bind(): no native file descriptor"); + return; + } + DBG ("_javanet_bind(): Past native_fd lookup\n"); + + /* XXX NYI ??? */ + _javanet_set_option (env, this, SOCKOPT_SO_REUSEADDR, + _javanet_create_boolean (env, JNI_TRUE)); + + + /* Bind the socket */ + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], + octets[3], tmpaddr); + TARGET_NATIVE_NETWORK_SOCKET_BIND (fd, tmpaddr, port, result); + + if (result != TARGET_NATIVE_OK) + { + char *errorstr = TARGET_NATIVE_LAST_ERROR_STRING (); + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + + JCL_ThrowException (env, BIND_EXCEPTION, + errorstr); + return; + } + DBG ("_javanet_bind(): Past bind\n"); + + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + + /* Update instance variables, specifically the local port number */ + TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd, local_address, local_port, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + if (stream) + _javanet_set_int_field (env, this, "java/net/SocketImpl", + "localport", local_port); + else + _javanet_set_int_field (env, this, "java/net/DatagramSocketImpl", + "localPort", local_port); + DBG ("_javanet_bind(): Past update port number\n"); + + return; +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Starts listening on a socket with the specified number of pending + * connections allowed. + */ +void +_javanet_listen (JNIEnv * env, jobject this, jint queuelen) +{ +#ifndef WITHOUT_NETWORK + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_listen(): no native file descriptor"); + return; + } + + /* Start listening */ + TARGET_NATIVE_NETWORK_SOCKET_LISTEN (fd, queuelen, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Accepts a new connection and assigns it to the passed in SocketImpl + * object. Note that we assume this is a PlainSocketImpl just like us + */ +void +_javanet_accept (JNIEnv * env, jobject this, jobject impl) +{ +#ifndef WITHOUT_NETWORK + int fd, newfd; + int result; + int local_address, local_port; + int remote_address, remote_port; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_accept(): no native file descriptor"); + return; + } + + /* Accept the connection */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_ACCEPT (fd, newfd, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_accept(): "); + return; + } + } + while (result != TARGET_NATIVE_OK); + + /* Populate instance variables */ + _javanet_set_int_field (env, impl, "gnu/java/net/PlainSocketImpl", + "native_fd", newfd); + + if ((*env)->ExceptionOccurred (env)) + { + /* Try to make sure we close the socket since close() won't work. */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + return; + } + while (result != TARGET_NATIVE_OK); + return; + } + + TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (newfd, local_address, + local_port, result); + if (result != TARGET_NATIVE_OK) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + _javanet_create_localfd (env, impl); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + _javanet_set_int_field (env, impl, "java/net/SocketImpl", "localport", + local_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (newfd, remote_address, + remote_port, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + _javanet_set_remhost (env, impl, remote_address); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + _javanet_set_int_field (env, impl, "java/net/SocketImpl", "port", + remote_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Receives a buffer from a remote host. The args are: + * + * buf - The byte array into which the data received will be written + * offset - Offset into the byte array to start writing + * len - The number of bytes to read. + * addr - Pointer to 32 bit net address of host to receive from. If null, + * this parm is ignored. If pointing to an address of 0, the + * actual address read is stored here + * port - Pointer to the port to receive from. If null, this parm is ignored. + * If it is 0, the actual remote port received from is stored here + * + * The actual number of bytes read is returned. + */ +int +_javanet_recvfrom (JNIEnv * env, jobject this, jarray buf, int offset, + int len, int *addr, int *port) +{ +#ifndef WITHOUT_NETWORK + int fd; + jbyte *p; + int from_address, from_port; + int received_bytes; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_recvfrom(): Entered _javanet_recvfrom\n"); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_recvfrom(): no native file descriptor"); + return 0; + } + DBG ("_javanet_recvfrom(): Got native_fd\n"); + + /* Get a pointer to the buffer */ + p = (*env)->GetByteArrayElements (env, buf, 0); + if (p == NULL) + return 0; + + DBG ("_javanet_recvfrom(): Got buffer\n"); + + /* Read the data */ + from_address = 0; + from_port = 0; + do + { + if (addr != NULL) + { + TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT (fd, + p + offset, + len, + from_address, + from_port, + received_bytes); + } + else + { + TARGET_NATIVE_NETWORK_SOCKET_RECEIVE (fd, p + offset, len, + received_bytes); + } + } + while ((received_bytes == -1) && + (TARGET_NATIVE_LAST_ERROR () == + TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)); + + if (received_bytes == -1) + { + if (TARGET_NATIVE_LAST_ERROR () == EAGAIN) + JCL_ThrowException (env, "java/net/SocketTimeoutException", "Timeout"); + else + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + + /* Cleanup and return. */ + (*env)->ReleaseByteArrayElements (env, buf, p, 0); + return 0; + } + + (*env)->ReleaseByteArrayElements (env, buf, p, 0); + + /* Handle return addr case */ + if (addr != NULL) + { + (*addr) = from_address; + if (port != NULL) + (*port) = from_port; + } + + return (received_bytes); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Sends a buffer to a remote host. The args are: + * + * buf - A byte array + * offset - Index into the byte array to start sendign + * len - The number of bytes to write + * addr - The 32bit address to send to (may be 0) + * port - The port number to send to (may be 0) + */ +void +_javanet_sendto (JNIEnv * env, jobject this, jarray buf, int offset, int len, + int addr, int port) +{ +#ifndef WITHOUT_NETWORK + int fd; + jbyte *p; + int bytes_sent; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_sendto(): no native file descriptor"); + return; + } + + /* Get a pointer to the buffer */ + p = (*env)->GetByteArrayElements (env, buf, 0); + if (p == NULL) + return; + + /* We must send all the data, so repeat till done. */ + while (len > 0) + { + /* Send the data */ + if (addr == 0) + { + DBG ("_javanet_sendto(): Sending....\n"); + TARGET_NATIVE_NETWORK_SOCKET_SEND (fd, p + offset, len, bytes_sent); + } + else + { + DBG ("_javanet_sendto(): Sending....\n"); + TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT (fd, p + offset, + len, addr, port, + bytes_sent); + } + + if (bytes_sent < 0) + { + if (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + break; + } + } + else + { + len -= bytes_sent; + addr += bytes_sent; + } + } + + (*env)->ReleaseByteArrayElements (env, buf, p, 0); + +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Sets the specified option for a socket + */ +void +_javanet_set_option (JNIEnv * env, jobject this, jint option_id, jobject val) +{ +#ifndef WITHOUT_NETWORK + int fd; + int optval; + jclass cls; + jmethodID mid; + int address; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option(): no native file descriptor"); + return; + } + + /* We need a class object for all cases below */ + cls = (*env)->GetObjectClass (env, val); + if (cls == NULL) + return; + + /* Process the option request */ + result = TARGET_NATIVE_ERROR; + switch (option_id) + { + /* TCP_NODELAY case. val is a Boolean that tells us what to do */ + case SOCKOPT_TCP_NODELAY: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + /* Should be a 0 or a 1 */ + optval = (*env)->CallBooleanMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY (fd, optval, + result); + break; + + /* SO_LINGER case. If val is a boolean, then it will always be set + to false indicating disable linger, otherwise it will be an + integer that contains the linger value */ + case SOCKOPT_SO_LINGER: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid) + { + /* We are disabling linger */ + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd, 1, 0, + result); + } + else + { + /* Clear exception if thrown for failure to do method lookup + above */ + if ((*env)->ExceptionOccurred (env)) + (*env)->ExceptionClear (env); + + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd, 0, optval, + result); + } + break; + + /* SO_TIMEOUT case. Val will be an integer with the new value */ + /* Not writable on Linux */ + case SOCKOPT_SO_TIMEOUT: +#ifdef SO_TIMEOUT + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT (fd, optval, result); +#else + result = TARGET_NATIVE_OK; +#endif + break; + + case SOCKOPT_SO_SNDBUF: + case SOCKOPT_SO_RCVBUF: + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + if (option_id == SOCKOPT_SO_SNDBUF) + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF (fd, optval, + result); + else + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF (fd, optval, + result); + break; + + /* TTL case. Val with be an Integer with the new time to live value */ + case SOCKOPT_IP_TTL: + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (!mid) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL (fd, optval, result); + break; + + /* Multicast Interface case - val is InetAddress object */ + case SOCKOPT_IP_MULTICAST_IF: + address = _javanet_get_netaddr (env, val); + + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF (fd, address, + result); + break; + + case SOCKOPT_SO_REUSEADDR: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + /* Should be a 0 or a 1 */ + optval = (*env)->CallBooleanMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS (fd, optval, + result); + break; + + case SOCKOPT_SO_KEEPALIVE: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + /* Should be a 0 or a 1 */ + optval = (*env)->CallBooleanMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE (fd, optval, result); + break; + + case SOCKOPT_SO_BINDADDR: + JCL_ThrowException (env, SOCKET_EXCEPTION, "This option cannot be set"); + break; + + default: + JCL_ThrowException (env, SOCKET_EXCEPTION, "Unrecognized option"); + return; + } + + /* Check to see if above operations succeeded */ + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Retrieves the specified option values for a socket + */ +jobject +_javanet_get_option (JNIEnv * env, jobject this, jint option_id) +{ +#ifndef WITHOUT_NETWORK + int fd; + int flag, optval; + int address; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Internal error: _javanet_get_option(): no native file descriptor"); + return (0); + } + + /* Process the option requested */ + switch (option_id) + { + /* TCP_NODELAY case. Return a Boolean indicating on or off */ + case SOCKOPT_TCP_NODELAY: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY (fd, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_boolean (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + /* SO_LINGER case. If disabled, return a Boolean object that represents + false, else return an Integer that is the value of SO_LINGER */ + case SOCKOPT_SO_LINGER: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER (fd, flag, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_integer (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + /* SO_TIMEOUT case. Return an Integer object with the timeout value */ + case SOCKOPT_SO_TIMEOUT: +#ifdef SO_TIMEOUT + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT (fd, optval, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + return (_javanet_create_integer (env, optval)); +#else + JCL_ThrowException (env, SOCKET_EXCEPTION, + "SO_TIMEOUT not supported on this platform"); + return (0); +#endif /* not SO_TIMEOUT */ + break; + + case SOCKOPT_SO_SNDBUF: + case SOCKOPT_SO_RCVBUF: + if (option_id == SOCKOPT_SO_SNDBUF) + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF (fd, optval, + result); + else + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF (fd, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_integer (env, optval)); + break; + + /* The TTL case. Return an Integer with the Time to Live value */ + case SOCKOPT_IP_TTL: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL (fd, optval, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_integer (env, optval)); + break; + + /* Multicast interface case */ + case SOCKOPT_IP_MULTICAST_IF: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF (fd, address, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_inetaddress (env, address)); + break; + + case SOCKOPT_SO_BINDADDR: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS (fd, address, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_inetaddress (env, address)); + break; + + case SOCKOPT_SO_REUSEADDR: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS (fd, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_boolean (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + case SOCKOPT_SO_KEEPALIVE: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE (fd, optval, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_boolean (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + default: + JCL_ThrowException (env, SOCKET_EXCEPTION, "No such option"); + return (0); + } + + return (0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +void +_javanet_shutdownInput (JNIEnv * env, jobject this) +{ + int fd; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor. */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Internal error: _javanet_get_option(): no native file descriptor"); + return; + } + + /* Shutdown input stream of socket. */ + if (shutdown (fd, SHUT_RD) == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Can't shutdown input of socket"); + return; + } +} + +void +_javanet_shutdownOutput (JNIEnv * env, jobject this) +{ + int fd; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor. */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Internal error: _javanet_get_option(): no native file descriptor"); + return; + } + + /* Shutdown output stream of socket. */ + if (shutdown (fd, SHUT_WR) == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Can't shutdown output of socket"); + return; + } +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/javanet.h b/libjava/classpath/native/jni/java-net/javanet.h new file mode 100644 index 00000000000..7c77ea77f84 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/javanet.h @@ -0,0 +1,109 @@ +/* javanet.h - Declarations for common functions for the java.net package + Copyright (C) 1998, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#ifndef _JAVANET_LOADED +#define _JAVANET_LOADED + +#include <jni.h> + +/*************************************************************************/ + +/* + * Defined constants + */ + +/* Exception Classes */ +#define BIND_EXCEPTION "java/net/BindException" +#define IO_EXCEPTION "java/io/IOException" +#define SOCKET_EXCEPTION "java/net/SocketException" +#define UNKNOWN_HOST_EXCEPTION "java/net/UnknownHostException" + +/* Socket Option Identifiers - Don't change or binary compatibility with + the JDK will be broken! These also need to + be kept compatible with java.net.SocketOptions */ +#define SOCKOPT_TCP_NODELAY 1 +#define SOCKOPT_SO_BINDADDR 15 +#define SOCKOPT_SO_LINGER 128 +#define SOCKOPT_SO_TIMEOUT 4102 +#define SOCKOPT_SO_SNDBUF 4097 +#define SOCKOPT_SO_RCVBUF 4098 +#define SOCKOPT_SO_REUSEADDR 4 +#define SOCKOPT_IP_MULTICAST_IF 16 +#define SOCKOPT_SO_KEEPALIVE 8 + +/* Internal option identifiers. Not needed for JDK compatibility */ +#define SOCKOPT_IP_TTL 7777 + +/*************************************************************************/ + +/* + * Macros + */ + +/* Simple debug macro */ +#ifdef DEBUG +#define DBG(x) fprintf(stderr, (x)); +#else +#define DBG(x) +#endif + +/*************************************************************************/ + +/* + * Function Prototypes + */ + +extern int _javanet_get_int_field(JNIEnv *, jobject, const char *); +extern int _javanet_get_netaddr(JNIEnv *, jobject); +extern void _javanet_create(JNIEnv *, jobject, jboolean); +extern void _javanet_close(JNIEnv *, jobject, int); +extern void _javanet_connect(JNIEnv *, jobject, jobject, jint); +extern void _javanet_bind(JNIEnv *, jobject, jobject, jint, int); +extern void _javanet_listen(JNIEnv *, jobject, jint); +extern void _javanet_accept(JNIEnv *, jobject, jobject); +extern int _javanet_recvfrom(JNIEnv *, jobject, jarray, int, int, int *, int *); +extern void _javanet_sendto(JNIEnv *, jobject, jarray, int, int, int, int); +extern jobject _javanet_get_option(JNIEnv *, jobject, jint); +extern void _javanet_set_option(JNIEnv *, jobject, jint, jobject); +extern void _javanet_shutdownInput (JNIEnv *, jobject); +extern void _javanet_shutdownOutput (JNIEnv *, jobject); + +/*************************************************************************/ + +#endif /* not _JAVANET_H_LOADED */ + |