mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			305 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			305 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| /* 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 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
 | |
| 
 | |
| #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
 | |
| 
 | |
| 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::loopbackAddress);
 | |
|       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::loopbackAddress);
 | |
|       hptr = gethostbyaddr (val, len, type);
 | |
| #endif /* HAVE_GETHOSTBYADDR_R */
 | |
|     }
 | |
|   if (hptr != NULL)
 | |
|     {
 | |
|       if (!all)
 | |
|         host = JvNewStringUTF (hptr->h_name);
 | |
|     }
 | |
|   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);
 | |
| }
 |