diff options
Diffstat (limited to 'libjava/java/net/natInetAddressWin32.cc')
-rw-r--r-- | libjava/java/net/natInetAddressWin32.cc | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/libjava/java/net/natInetAddressWin32.cc b/libjava/java/net/natInetAddressWin32.cc new file mode 100644 index 0000000..f6748fd --- /dev/null +++ b/libjava/java/net/natInetAddressWin32.cc @@ -0,0 +1,355 @@ +/* Copyright (C) 2003 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#ifdef WIN32 + +#include <windows.h> +#include <winsock.h> +#undef STRICT + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif /* MAXHOSTNAMELEN */ + +#else /* WIN32 */ + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <errno.h> + +#include <sys/param.h> +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#endif /* WIN32 */ + +#include <gcj/cni.h> +#include <jvm.h> +#include <java/net/InetAddress.h> +#include <java/net/UnknownHostException.h> +#include <java/lang/SecurityException.h> + +#if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME) +#include <sys/utsname.h> +#endif + +#ifndef HAVE_GETHOSTNAME_DECL +extern "C" int gethostname (char *name, int namelen); +#endif + +#ifdef DISABLE_JAVA_NET + +jbyteArray +java::net::InetAddress::aton (jstring) +{ + return NULL; +} + +jint +java::net::InetAddress::getFamily (jbyteArray bytes) +{ + return 0; +} + +JArray<java::net::InetAddress*> * +java::net::InetAddress::lookup (jstring, java::net::InetAddress *, jboolean) +{ + return NULL; +} + +jstring +java::net::InetAddress::getLocalHostname () +{ + return NULL; +} + +#else /* DISABLE_JAVA_NET */ + +jbyteArray +java::net::InetAddress::aton (jstring host) +{ + char *hostname; + char buf[100]; + int len = JvGetStringUTFLength(host); + if (len < 100) + hostname = buf; + else + hostname = (char*) _Jv_AllocBytes (len+1); + JvGetStringUTFRegion (host, 0, host->length(), hostname); + buf[len] = '\0'; + char* bytes = NULL; + int blen = 0; +#ifdef HAVE_INET_ATON + struct in_addr laddr; + if (inet_aton (hostname, &laddr)) + { + bytes = (char*) &laddr; + blen = 4; + } +#elif defined(HAVE_INET_ADDR) +#if ! HAVE_IN_ADDR_T + typedef jint in_addr_t; +#endif + in_addr_t laddr = inet_addr (hostname); + if (laddr != (in_addr_t)(-1)) + { + bytes = (char*) &laddr; + blen = 4; + } +#endif +#if defined (HAVE_INET_PTON) && defined (HAVE_INET6) + char inet6_addr[16]; + if (len != 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0) + { + bytes = inet6_addr; + blen = 16; + } +#endif + if (blen == 0) + return NULL; + jbyteArray result = JvNewByteArray (blen); + memcpy (elements (result), bytes, blen); + return result; +} + +jint +java::net::InetAddress::getFamily (jbyteArray bytes) +{ + int len = bytes->length; + if (len == 4) + return AF_INET; +#ifdef HAVE_INET6 + else if (len == 16) + return AF_INET6; +#endif /* HAVE_INET6 */ + else + JvFail ("unrecognized size"); +} + + +JArray<java::net::InetAddress*> * +java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, + jboolean all) +{ + struct hostent *hptr = NULL; +#if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R) + struct hostent hent_r; +#if HAVE_STRUCT_HOSTENT_DATA + struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer; +#else +#if defined (__GLIBC__) + // FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and + // ERANGE to errno if the buffer size is too small, rather than what is + // expected here. We work around this by setting a bigger buffer size and + // hoping that it is big enough. + char fixed_buffer[1024]; +#else + char fixed_buffer[200]; +#endif + char *buffer_r = fixed_buffer; + int size_r = sizeof (fixed_buffer); +#endif +#endif + + if (host != NULL) + { + char *hostname; + char buf[100]; + int len = JvGetStringUTFLength(host); + if (len < 100) + hostname = buf; + else + hostname = (char*) _Jv_AllocBytes (len+1); + JvGetStringUTFRegion (host, 0, host->length(), hostname); + buf[len] = '\0'; +#ifdef HAVE_GETHOSTBYNAME_R + while (true) + { + int ok; +#if HAVE_STRUCT_HOSTENT_DATA + ok = ! gethostbyname_r (hostname, &hent_r, buffer_r); +#else + int herr = 0; +#ifdef GETHOSTBYNAME_R_RETURNS_INT + ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r, + &hptr, &herr); +#else + hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr); + ok = hptr != NULL; +#endif /* GETHOSTNAME_R_RETURNS_INT */ + if (! ok && herr == ERANGE) + { + size_r *= 2; + buffer_r = (char *) _Jv_AllocBytes (size_r); + } + else +#endif /* HAVE_STRUCT_HOSTENT_DATA */ + break; + } +#else + // FIXME: this is insufficient if some other piece of code calls + // this gethostbyname. + JvSynchronize sync (java::net::InetAddress::localhostAddress); + hptr = gethostbyname (hostname); +#endif /* HAVE_GETHOSTBYNAME_R */ + } + else + { + jbyteArray bytes = iaddr->addr; + char *chars = (char*) elements (bytes); + int len = bytes->length; + int type; + char *val; + if (len == 4) + { + val = chars; + type = iaddr->family = AF_INET; + } +#ifdef HAVE_INET6 + else if (len == 16) + { + val = (char *) &chars; + type = iaddr->family = AF_INET6; + } +#endif /* HAVE_INET6 */ + else + JvFail ("unrecognized size"); + +#ifdef HAVE_GETHOSTBYADDR_R + while (true) + { + int ok; +#if HAVE_STRUCT_HOSTENT_DATA + ok = ! gethostbyaddr_r (val, len, type, &hent_r, buffer_r); +#else + int herr = 0; +#ifdef GETHOSTBYADDR_R_RETURNS_INT + ok = ! gethostbyaddr_r (val, len, type, &hent_r, + buffer_r, size_r, &hptr, &herr); +#else + hptr = gethostbyaddr_r (val, len, type, &hent_r, + buffer_r, size_r, &herr); + ok = hptr != NULL; +#endif /* GETHOSTBYADDR_R_RETURNS_INT */ + if (! ok && herr == ERANGE) + { + size_r *= 2; + buffer_r = (char *) _Jv_AllocBytes (size_r); + } + else +#endif /* HAVE_STRUCT_HOSTENT_DATA */ + break; + } +#else /* HAVE_GETHOSTBYADDR_R */ + // FIXME: this is insufficient if some other piece of code calls + // this gethostbyaddr. + JvSynchronize sync (java::net::InetAddress::localhostAddress); + hptr = gethostbyaddr (val, len, type); +#endif /* HAVE_GETHOSTBYADDR_R */ + } + if (hptr != NULL) + { + if (!all) + host = JvNewStringUTF (hptr->h_name); + java::lang::SecurityException *ex = checkConnect (host); + if (ex != NULL) + { + if (iaddr == NULL || iaddr->addr == NULL) + throw ex; + hptr = NULL; + } + } + if (hptr == NULL) + { + if (iaddr != NULL && iaddr->addr != NULL) + { + iaddr->hostName = iaddr->getHostAddress(); + return NULL; + } + else + throw new java::net::UnknownHostException(host); + } + int count; + if (all) + { + char** ptr = hptr->h_addr_list; + count = 0; + while (*ptr++) count++; + } + else + count = 1; + JArray<java::net::InetAddress*> *result; + java::net::InetAddress** iaddrs; + if (all) + { + result = java::net::InetAddress::allocArray (count); + iaddrs = elements (result); + } + else + { + result = NULL; + iaddrs = &iaddr; + } + + for (int i = 0; i < count; i++) + { + if (iaddrs[i] == NULL) + iaddrs[i] = new java::net::InetAddress (NULL, NULL); + if (iaddrs[i]->hostName == NULL) + iaddrs[i]->hostName = host; + if (iaddrs[i]->addr == NULL) + { + char *bytes = hptr->h_addr_list[i]; + iaddrs[i]->addr = JvNewByteArray (hptr->h_length); + iaddrs[i]->family = getFamily (iaddrs[i]->addr); + memcpy (elements (iaddrs[i]->addr), bytes, hptr->h_length); + } + } + return result; +} + +jstring +java::net::InetAddress::getLocalHostname () +{ + char *chars; +#ifdef HAVE_GETHOSTNAME + char buffer[MAXHOSTNAMELEN]; + if (gethostname (buffer, MAXHOSTNAMELEN)) + return NULL; + chars = buffer; +#elif HAVE_UNAME + struct utsname stuff; + if (uname (&stuff) != 0) + return NULL; + chars = stuff.nodename; +#else + return NULL; +#endif + // It is admittedly non-optimal to convert the hostname to Unicode + // only to convert it back in getByName, but simplicity wins. Note + // that unless there is a SecurityManager, we only get called once + // anyway, thanks to the InetAddress.localhost cache. + return JvNewStringUTF (chars); +} + +#endif /* DISABLE_JAVA_NET */ |