aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/native/jni/java-net/javanet.c
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/native/jni/java-net/javanet.c')
-rw-r--r--libjava/classpath/native/jni/java-net/javanet.c1500
1 files changed, 0 insertions, 1500 deletions
diff --git a/libjava/classpath/native/jni/java-net/javanet.c b/libjava/classpath/native/jni/java-net/javanet.c
deleted file mode 100644
index 1f093f4..0000000
--- a/libjava/classpath/native/jni/java-net/javanet.c
+++ /dev/null
@@ -1,1500 +0,0 @@
-/* javanet.c - Common internal functions for the java.net package
- Copyright (C) 1998, 2002, 2004, 2005, 2006 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 <jni.h>
-#include <jcl.h>
-
-#include "cpnative.h"
-#include "cpnet.h"
-
-#include "javanet.h"
-
-#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;
-
- 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;
-
- 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, jboolean stream)
-{
- jclass this_cls, fd_cls;
- jfieldID fid;
- jmethodID mid;
- jobject fd_obj;
-
- DBG ("_javanet_create_localfd(): Entered _javanet_create_localfd\n");
-
- /* Look up the fd field */
- if (stream)
- this_cls = (*env)->FindClass(env, "java/net/SocketImpl");
- else
- this_cls = (*env)->FindClass(env, "java/net/DatagramSocketImpl");
- 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;
-
- 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;
-
- 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
- */
-jobject
-_javanet_create_inetaddress (JNIEnv * env, cpnet_address *netaddr)
-{
-#ifndef WITHOUT_NETWORK
- jbyte octets[4];
- char buf[64];
- jclass ia_cls;
- jmethodID mid;
- jstring ip_str;
- jobject ia;
-
- /* Build a string IP address */
- cpnet_IPV4AddressToBytes(netaddr, octets);
- sprintf (buf, "%d.%d.%d.%d", (int) (unsigned char)octets[0], (int)(unsigned char)octets[1], (int)(unsigned char)octets[2], (int)(unsigned char)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;
-
- /* 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, cpnet_address *netaddr)
-{
- jobject ia;
-
- 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 an Internet address for the passed in InetAddress object
- */
-cpnet_address *
-_javanet_get_ip_netaddr (JNIEnv * env, jobject addr)
-{
-#ifndef WITHOUT_NETWORK
- jclass cls = 0;
- jmethodID mid;
- jarray arr = 0;
- jbyte *octets;
- cpnet_address *netaddr;
- jint len;
-
- DBG ("_javanet_get_ip_netaddr(): Entered _javanet_get_ip_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_ip_netaddr(): Got getAddress method\n");
-
- arr = (*env)->CallObjectMethod (env, addr, mid);
- if (arr == NULL)
- return 0;
-
- DBG ("_javanet_get_ip_netaddr(): Got the address\n");
-
- /* Turn the IP address into a system cpnet address.
- * If the length is 4 then it is an IPV4 address, if it
- * is 16 then it is an IPV6 address else it is an InternError. */
- len = (*env)->GetArrayLength (env, arr);
- if (len != 4 && len != 16)
- {
- JCL_ThrowException (env, IO_EXCEPTION, "Internal Error");
- return 0;
- }
- DBG ("_javanet_get_ip_netaddr(): Length ok\n");
-
- octets = (*env)->GetByteArrayElements (env, arr, 0);
- if (octets == NULL)
- return 0;
-
- DBG ("_javanet_get_ip_netaddr(): Grabbed bytes\n");
-
- switch (len)
- {
- case 4:
- netaddr = cpnet_newIPV4Address(env);
- cpnet_bytesToIPV4Address(netaddr, octets);
- break;
-#ifdef HAVE_INET6
- case 16:
- netaddr = cpnet_newIPV6Address(env);
- cpnet_bytesToIPV6Address(netaddr, octets);
- break;
-#endif
- default:
- /* This should not happen as we have checked before.
- * But that way we shut the compiler warnings */
- JCL_ThrowException (env, IO_EXCEPTION, "Internal Error");
- return 0;
-
- }
-
- (*env)->ReleaseByteArrayElements (env, arr, octets, 0);
- DBG ("_javanet_get_ip_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;
-
- if (stream)
- {
- /* create a stream socket */
- result = cpnet_openSocketStream(env, &fd, AF_INET);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- }
- else
- {
- /* create a datagram socket, set broadcast option */
- result = cpnet_openSocketDatagram (env, &fd, AF_INET);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- result = cpnet_setBroadcast(env, fd, 1);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- 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
- {
- result = cpnet_close(env, fd);
- if (result != CPNATIVE_OK && result != CPNATIVE_EINTR)
- return;
- }
- while (result != CPNATIVE_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;
-
- 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
- {
- result = cpnet_close (env, fd);
- if (result != CPNATIVE_OK)
- {
- /* Only throw an error when a "real" error occurs. */
- if (result != CPNATIVE_EINTR && result != ENOTCONN && result != ECONNRESET && result != EBADF)
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- }
- }
- while (error == CPNATIVE_EINTR);
-
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Connects to the specified destination.
- */
-void
-_javanet_connect (JNIEnv * env, jobject this, jobject addr, jint port,
- jboolean stream)
-{
-#ifndef WITHOUT_NETWORK
- cpnet_address *netaddr;
- int fd;
- int result;
- cpnet_address *local_addr;
- cpnet_address *remote_addr;
-
- DBG ("_javanet_connect(): Entered _javanet_connect\n");
-
- /* Pre-process input variables */
- netaddr = _javanet_get_ip_netaddr (env, addr);
- if ((*env)->ExceptionOccurred (env))
- return;
-
- if (port == -1)
- port = 0;
-
- cpnet_addressSetPort(netaddr, port);
-
- 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
- {
- result = cpnet_connect (env, fd, netaddr);
- if (result != CPNATIVE_OK && result != CPNATIVE_EINTR)
- {
- JCL_ThrowException (env, CONNECT_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- }
- while (result != CPNATIVE_OK);
-
- DBG ("_javanet_connect(): Connected successfully\n");
-
- /* Populate instance variables */
- result = cpnet_getLocalAddr (env, fd, &local_addr);
- if (result != CPNATIVE_OK)
- {
- cpnet_freeAddress(env, netaddr);
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, fd);
- return;
- }
-
- _javanet_create_localfd (env, this, stream);
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_freeAddress(env, netaddr);
- cpnet_freeAddress(env, local_addr);
- cpnet_close (env, fd);
- return;
- }
- DBG ("_javanet_connect(): Created fd\n");
-
- if (stream)
- _javanet_set_int_field (env, this, "java/net/SocketImpl", "localport",
- cpnet_addressGetPort(local_addr));
- else
- _javanet_set_int_field (env, this, "java/net/DatagramSocketImpl",
- "localPort", cpnet_addressGetPort(local_addr));
-
- cpnet_freeAddress (env, local_addr);
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_freeAddress(env, netaddr);
- cpnet_close (env, fd);
- return;
- }
- DBG ("_javanet_connect(): Set the local port\n");
-
- result = cpnet_getRemoteAddr (env, fd, &remote_addr);
- if (result != CPNATIVE_OK)
- {
- cpnet_freeAddress(env, netaddr);
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, fd);
- return;
- }
-
- if (stream)
- {
- if (cpnet_isAddressEqual(remote_addr, netaddr))
- {
- _javanet_set_remhost_addr (env, this, addr);
- }
- else
- {
- _javanet_set_remhost (env, this, remote_addr);
- }
- cpnet_freeAddress(env, netaddr);
-
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later.
- */
- cpnet_freeAddress (env, remote_addr);
- cpnet_close (env, fd);
- return;
- }
- DBG ("_javanet_connect(): Set the remote host\n");
-
- _javanet_set_int_field (env, this, "java/net/SocketImpl", "port",
- cpnet_addressGetPort(remote_addr));
- cpnet_freeAddress (env, remote_addr);
-
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later.
- */
- cpnet_close (env, fd);
- 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
- jint fd;
- cpnet_address *tmpaddr;
- cpnet_address *local_addr;
- int result;
-
- DBG ("_javanet_bind(): Entering native bind()\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;
- }
-
- cpnet_setReuseAddress (env, fd, 1);
-
- /* Get the address to connect to */
- tmpaddr = _javanet_get_ip_netaddr (env, addr);
- if ((*env)->ExceptionOccurred (env))
- return;
-
- cpnet_addressSetPort (tmpaddr, port);
- result = cpnet_bind(env, fd, tmpaddr);
- cpnet_freeAddress (env, tmpaddr);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, BIND_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- DBG ("_javanet_bind(): Past bind\n");
-
- /* Update instance variables, specifically the local port number */
- result = cpnet_getLocalAddr (env, fd, &local_addr);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
-
- if (stream)
- _javanet_set_int_field (env, this, "java/net/SocketImpl",
- "localport", cpnet_addressGetPort (local_addr));
- else
- _javanet_set_int_field (env, this, "java/net/DatagramSocketImpl",
- "localPort", cpnet_addressGetPort (local_addr));
- DBG ("_javanet_bind(): Past update port number\n");
-
- cpnet_freeAddress (env, local_addr);
-
- 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;
-
- /* 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 */
- result = cpnet_listen (env, fd, queuelen);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- 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;
- cpnet_address *remote_addr, *local_addr;
-
- /* 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
- {
- result = cpnet_accept (env, fd, &newfd);
- if (result != CPNATIVE_OK && result != CPNATIVE_EINTR)
- {
- if (result == ETIMEDOUT || result == EAGAIN)
- JCL_ThrowException (env, "java/net/SocketTimeoutException",
- "Accept operation timed out");
- else
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- }
- while (result != CPNATIVE_OK);
-
- /* Reset the inherited timeout. */
- cpnet_setSocketTimeout (env, newfd, 0);
-
- /* 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
- {
- result = cpnet_close (env, newfd);
- if (result != CPNATIVE_OK && result != CPNATIVE_EINTR)
- return;
- }
- while (result != CPNATIVE_OK);
- return;
- }
-
- result = cpnet_getLocalAddr (env, newfd, &local_addr);
- if (result != CPNATIVE_OK)
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, newfd);
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
-
- _javanet_create_localfd (env, impl, 1);
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_freeAddress (env, local_addr);
- cpnet_close (env, newfd);
- return;
- }
-
- _javanet_set_int_field (env, impl, "java/net/SocketImpl", "localport",
- cpnet_addressGetPort (local_addr));
- cpnet_freeAddress (env, local_addr);
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, newfd);
- return;
- }
-
- result = cpnet_getRemoteAddr (env, newfd, &remote_addr);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, newfd);
- return;
- }
-
- _javanet_set_remhost (env, impl, remote_addr);
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, newfd);
- cpnet_freeAddress (env, remote_addr);
- return;
- }
-
- _javanet_set_int_field (env, impl, "java/net/SocketImpl", "port",
- cpnet_addressGetPort (remote_addr));
- cpnet_freeAddress (env, remote_addr);
- if ((*env)->ExceptionOccurred (env))
- {
- /* We don't care whether this succeeds. close() will cleanup later. */
- cpnet_close (env, newfd);
- 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, cpnet_address **addr)
-{
-#ifndef WITHOUT_NETWORK
- int fd;
- jbyte *p;
- cpnet_address *from_addr;
- jint received_bytes;
- int result;
-
- 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_addr = NULL;
- do
- {
- if (addr != NULL)
- {
- result = cpnet_recvFrom (env, fd, p + offset, len, &from_addr, &received_bytes);
- }
- else
- {
- result = cpnet_recv (env, fd, p + offset, len, &received_bytes);
- }
- }
- while (result == CPNATIVE_EINTR);
- if (result != 0)
- {
- if (result == EAGAIN || result == ETIMEDOUT)
- JCL_ThrowException (env, "java/net/SocketTimeoutException", "Receive operation timed out");
- else
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
-
- /* 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_addr;
- }
-
- /* zero bytes received means recv() noticed the other side orderly
- closing the connection. */
- if (received_bytes == 0)
- received_bytes = -1;
-
- 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,
- cpnet_address *addr)
-{
-#ifndef WITHOUT_NETWORK
- int fd;
- jbyte *p;
- jint bytes_sent;
- int result;
-
- /* 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 == NULL)
- {
- DBG ("_javanet_sendto(): Sending....\n");
- result = cpnet_send (env, fd, p + offset, len, &bytes_sent);
- }
- else
- {
- DBG ("_javanet_sendto(): Sending....\n");
- result = cpnet_sendTo (env, fd, p + offset, len, addr, &bytes_sent);
- }
-
- if (result == EDESTADDRREQ)
- {
- JCL_ThrowException (env, NULL_EXCEPTION,
- "Socket is not connected and no address is given");
- break;
- }
-
- if (bytes_sent < 0)
- {
- if (result != CPNATIVE_EINTR)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- 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;
- cpnet_address * address;
- int result = CPNATIVE_OK;
-
- /* 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 */
- 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;
-
- result = cpnet_setSocketTCPNoDelay (env, fd, optval);
- 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 */
- result = cpnet_setLinger (env, fd, JNI_FALSE, 0);
- }
- 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;
-
- result = cpnet_setLinger(env, fd, JNI_TRUE, optval);
- }
- break;
-
- /* SO_TIMEOUT case. Val will be an integer with the new value */
- /* Not writable on Linux */
- case SOCKOPT_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;
-
- result = cpnet_setSocketTimeout (env, fd, optval);
- 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)
- result = cpnet_setSendBuf (env, fd, optval);
- else
- result = cpnet_setRecvBuf (env, fd, optval);
- 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;
-
- result = cpnet_setTTL (env, fd, optval);
- break;
-
- /* Multicast Interface case - val is InetAddress object */
- case SOCKOPT_IP_MULTICAST_IF:
- address = _javanet_get_ip_netaddr (env, val);
-
- if ((*env)->ExceptionOccurred (env))
- return;
-
- result = cpnet_setMulticastIF (env, fd, address);
- cpnet_freeAddress (env, address);
- 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;
-
- result = cpnet_setReuseAddress (env, fd, optval);
- 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;
-
- result = cpnet_setKeepAlive (env, fd, optval);
- 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 != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- 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;
- cpnet_address *address;
- int result;
- jobject obj;
-
- /* 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:
- result = cpnet_getSocketTCPNoDelay (env, fd, &optval);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- 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:
- result = cpnet_getLinger (env, fd, &flag, &optval);
-
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return (0);
- }
-
- if (flag)
- return (_javanet_create_integer (env, optval));
- else
- return (_javanet_create_boolean (env, JNI_FALSE));
-
- break;
-
- /* SO_TIMEOUT case. Return an Integer object with the timeout value */
- case SOCKOPT_SO_TIMEOUT:
- result = cpnet_getSocketTimeout (env, fd, &optval);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return (0);
- }
- return (_javanet_create_integer (env, optval));
- break;
-
- case SOCKOPT_SO_SNDBUF:
- case SOCKOPT_SO_RCVBUF:
- if (option_id == SOCKOPT_SO_SNDBUF)
- result = cpnet_getSendBuf (env, fd, &optval);
- else
- result = cpnet_getRecvBuf (env, fd, &optval);
-
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- 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:
- result = cpnet_getTTL (env, fd, &optval);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return (0);
- }
-
- return (_javanet_create_integer (env, optval));
- break;
-
- /* Multicast interface case */
- case SOCKOPT_IP_MULTICAST_IF:
- result = cpnet_getMulticastIF (env, fd, &address);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return (0);
- }
-
- obj = _javanet_create_inetaddress (env, address);
- cpnet_freeAddress (env, address);
-
- return obj;
- break;
-
- case SOCKOPT_SO_BINDADDR:
- result = cpnet_getLocalAddr (env, fd, &address);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return (0);
- }
-
- obj = _javanet_create_inetaddress (env, address);
- cpnet_freeAddress (env, address);
-
- return obj;
- break;
-
- case SOCKOPT_SO_REUSEADDR:
- result = cpnet_getReuseAddress (env, fd, &optval);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return (0);
- }
-
- if (optval)
- return _javanet_create_boolean (env, JNI_TRUE);
- else
- return _javanet_create_boolean (env, JNI_FALSE);
-
- break;
-
- case SOCKOPT_SO_KEEPALIVE:
- result = cpnet_getKeepAlive (env, fd, &optval);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- 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 result;
- int fd;
-
- /* 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. */
- result = cpnet_shutdown (env, fd, CPNET_SHUTDOWN_READ);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
-}
-
-void
-_javanet_shutdownOutput (JNIEnv * env, jobject this)
-{
- int fd;
- int result;
-
- /* 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. */
- result = cpnet_shutdown (env, fd, CPNET_SHUTDOWN_WRITE);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, SOCKET_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
-}
-
-/* end of file */