提交 82d31a26 编写于 作者: M martin

6981157: Improve UnknownHostException with EAI error details and other cleanups

Summary: generify; remove compiler warnings, typos, casts; return status information via gai_strerror when getaddrinfo fails; show full stack of native failures
Reviewed-by: michaelm, alanb
上级 4a120b94
...@@ -677,19 +677,20 @@ class InetAddress implements java.io.Serializable { ...@@ -677,19 +677,20 @@ class InetAddress implements java.io.Serializable {
static InetAddressImpl impl; static InetAddressImpl impl;
private static HashMap lookupTable = new HashMap(); private static HashMap<String, InetAddress[]> lookupTable
= new HashMap<String, InetAddress[]>();
/** /**
* Represents a cache entry * Represents a cache entry
*/ */
static final class CacheEntry { static final class CacheEntry {
CacheEntry(Object address, long expiration) { CacheEntry(InetAddress[] addresses, long expiration) {
this.address = address; this.addresses = addresses;
this.expiration = expiration; this.expiration = expiration;
} }
Object address; InetAddress[] addresses;
long expiration; long expiration;
} }
...@@ -698,7 +699,7 @@ class InetAddress implements java.io.Serializable { ...@@ -698,7 +699,7 @@ class InetAddress implements java.io.Serializable {
* at creation time. * at creation time.
*/ */
static final class Cache { static final class Cache {
private LinkedHashMap cache; private LinkedHashMap<String, CacheEntry> cache;
private Type type; private Type type;
enum Type {Positive, Negative}; enum Type {Positive, Negative};
...@@ -708,7 +709,7 @@ class InetAddress implements java.io.Serializable { ...@@ -708,7 +709,7 @@ class InetAddress implements java.io.Serializable {
*/ */
public Cache(Type type) { public Cache(Type type) {
this.type = type; this.type = type;
cache = new LinkedHashMap(); cache = new LinkedHashMap<String, CacheEntry>();
} }
private int getPolicy() { private int getPolicy() {
...@@ -724,7 +725,7 @@ class InetAddress implements java.io.Serializable { ...@@ -724,7 +725,7 @@ class InetAddress implements java.io.Serializable {
* entry then for this host then the entry will be * entry then for this host then the entry will be
* replaced. * replaced.
*/ */
public Cache put(String host, Object address) { public Cache put(String host, InetAddress[] addresses) {
int policy = getPolicy(); int policy = getPolicy();
if (policy == InetAddressCachePolicy.NEVER) { if (policy == InetAddressCachePolicy.NEVER) {
return this; return this;
...@@ -736,12 +737,10 @@ class InetAddress implements java.io.Serializable { ...@@ -736,12 +737,10 @@ class InetAddress implements java.io.Serializable {
// As we iterate in insertion order we can // As we iterate in insertion order we can
// terminate when a non-expired entry is found. // terminate when a non-expired entry is found.
LinkedList expired = new LinkedList(); LinkedList<String> expired = new LinkedList<String>();
Iterator i = cache.keySet().iterator();
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
while (i.hasNext()) { for (String key : cache.keySet()) {
String key = (String)i.next(); CacheEntry entry = cache.get(key);
CacheEntry entry = (CacheEntry)cache.get(key);
if (entry.expiration >= 0 && entry.expiration < now) { if (entry.expiration >= 0 && entry.expiration < now) {
expired.add(key); expired.add(key);
...@@ -750,9 +749,8 @@ class InetAddress implements java.io.Serializable { ...@@ -750,9 +749,8 @@ class InetAddress implements java.io.Serializable {
} }
} }
i = expired.iterator(); for (String key : expired) {
while (i.hasNext()) { cache.remove(key);
cache.remove(i.next());
} }
} }
...@@ -766,7 +764,7 @@ class InetAddress implements java.io.Serializable { ...@@ -766,7 +764,7 @@ class InetAddress implements java.io.Serializable {
} else { } else {
expiration = System.currentTimeMillis() + (policy * 1000); expiration = System.currentTimeMillis() + (policy * 1000);
} }
CacheEntry entry = new CacheEntry(address, expiration); CacheEntry entry = new CacheEntry(addresses, expiration);
cache.put(host, entry); cache.put(host, entry);
return this; return this;
} }
...@@ -780,7 +778,7 @@ class InetAddress implements java.io.Serializable { ...@@ -780,7 +778,7 @@ class InetAddress implements java.io.Serializable {
if (policy == InetAddressCachePolicy.NEVER) { if (policy == InetAddressCachePolicy.NEVER) {
return null; return null;
} }
CacheEntry entry = (CacheEntry)cache.get(host); CacheEntry entry = cache.get(host);
// check if entry has expired // check if entry has expired
if (entry != null && policy != InetAddressCachePolicy.FOREVER) { if (entry != null && policy != InetAddressCachePolicy.FOREVER) {
...@@ -814,42 +812,41 @@ class InetAddress implements java.io.Serializable { ...@@ -814,42 +812,41 @@ class InetAddress implements java.io.Serializable {
} }
/* /*
* Cache the given hostname and address. * Cache the given hostname and addresses.
*/ */
private static void cacheAddress(String hostname, Object address, private static void cacheAddresses(String hostname,
boolean success) { InetAddress[] addresses,
boolean success) {
hostname = hostname.toLowerCase(); hostname = hostname.toLowerCase();
synchronized (addressCache) { synchronized (addressCache) {
cacheInitIfNeeded(); cacheInitIfNeeded();
if (success) { if (success) {
addressCache.put(hostname, address); addressCache.put(hostname, addresses);
} else { } else {
negativeCache.put(hostname, address); negativeCache.put(hostname, addresses);
} }
} }
} }
/* /*
* Lookup hostname in cache (positive & negative cache). If * Lookup hostname in cache (positive & negative cache). If
* found return address, null if not found. * found return addresses, null if not found.
*/ */
private static Object getCachedAddress(String hostname) { private static InetAddress[] getCachedAddresses(String hostname) {
hostname = hostname.toLowerCase(); hostname = hostname.toLowerCase();
// search both positive & negative caches // search both positive & negative caches
synchronized (addressCache) { synchronized (addressCache) {
CacheEntry entry;
cacheInitIfNeeded(); cacheInitIfNeeded();
entry = addressCache.get(hostname); CacheEntry entry = addressCache.get(hostname);
if (entry == null) { if (entry == null) {
entry = negativeCache.get(hostname); entry = negativeCache.get(hostname);
} }
if (entry != null) { if (entry != null) {
return entry.address; return entry.addresses;
} }
} }
...@@ -911,7 +908,7 @@ class InetAddress implements java.io.Serializable { ...@@ -911,7 +908,7 @@ class InetAddress implements java.io.Serializable {
static { static {
// create the impl // create the impl
impl = (new InetAddressImplFactory()).create(); impl = InetAddressImplFactory.create();
// get name service if provided and requested // get name service if provided and requested
String provider = null;; String provider = null;;
...@@ -931,7 +928,7 @@ class InetAddress implements java.io.Serializable { ...@@ -931,7 +928,7 @@ class InetAddress implements java.io.Serializable {
} }
// if not designate any name services provider, // if not designate any name services provider,
// creat a default one // create a default one
if (nameServices.size() == 0) { if (nameServices.size() == 0) {
NameService ns = createNSProvider("default"); NameService ns = createNSProvider("default");
nameServices.add(ns); nameServices.add(ns);
...@@ -939,7 +936,7 @@ class InetAddress implements java.io.Serializable { ...@@ -939,7 +936,7 @@ class InetAddress implements java.io.Serializable {
} }
/** /**
* Create an InetAddress based on the provided host name and IP address * Creates an InetAddress based on the provided host name and IP address.
* No name service is checked for the validity of the address. * No name service is checked for the validity of the address.
* *
* <p> The host name can either be a machine name, such as * <p> The host name can either be a machine name, such as
...@@ -1067,13 +1064,13 @@ class InetAddress implements java.io.Serializable { ...@@ -1067,13 +1064,13 @@ class InetAddress implements java.io.Serializable {
boolean ipv6Expected = false; boolean ipv6Expected = false;
if (host.charAt(0) == '[') { if (host.charAt(0) == '[') {
// This is supposed to be an IPv6 litteral // This is supposed to be an IPv6 literal
if (host.length() > 2 && host.charAt(host.length()-1) == ']') { if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
host = host.substring(1, host.length() -1); host = host.substring(1, host.length() -1);
ipv6Expected = true; ipv6Expected = true;
} else { } else {
// This was supposed to be a IPv6 address, but it's not! // This was supposed to be a IPv6 address, but it's not!
throw new UnknownHostException(host); throw new UnknownHostException(host + ": invalid IPv6 address");
} }
} }
...@@ -1180,8 +1177,6 @@ class InetAddress implements java.io.Serializable { ...@@ -1180,8 +1177,6 @@ class InetAddress implements java.io.Serializable {
throws UnknownHostException { throws UnknownHostException {
/* If it gets here it is presumed to be a hostname */ /* If it gets here it is presumed to be a hostname */
/* Cache.get can return: null, unknownAddress, or InetAddress[] */ /* Cache.get can return: null, unknownAddress, or InetAddress[] */
Object obj = null;
Object objcopy = null;
/* make sure the connection to the host is allowed, before we /* make sure the connection to the host is allowed, before we
* give out a hostname * give out a hostname
...@@ -1193,26 +1188,23 @@ class InetAddress implements java.io.Serializable { ...@@ -1193,26 +1188,23 @@ class InetAddress implements java.io.Serializable {
} }
} }
obj = getCachedAddress(host); InetAddress[] addresses = getCachedAddresses(host);
/* If no entry in cache, then do the host lookup */ /* If no entry in cache, then do the host lookup */
if (obj == null) { if (addresses == null) {
obj = getAddressFromNameService(host); addresses = getAddressesFromNameService(host);
} }
if (obj == unknown_array) if (addresses == unknown_array)
throw new UnknownHostException(host); throw new UnknownHostException(host);
/* Make a copy of the InetAddress array */ return addresses.clone();
objcopy = ((InetAddress [])obj).clone();
return (InetAddress [])objcopy;
} }
private static Object getAddressFromNameService(String host) private static InetAddress[] getAddressesFromNameService(String host)
throws UnknownHostException throws UnknownHostException
{ {
Object obj = null; InetAddress[] addresses = null;
boolean success = false; boolean success = false;
UnknownHostException ex = null; UnknownHostException ex = null;
...@@ -1226,16 +1218,16 @@ class InetAddress implements java.io.Serializable { ...@@ -1226,16 +1218,16 @@ class InetAddress implements java.io.Serializable {
// would be blocked until the host is removed // would be blocked until the host is removed
// from the lookupTable. Then this thread // from the lookupTable. Then this thread
// should try to look up the addressCache. // should try to look up the addressCache.
// i) if it found the address in the // i) if it found the addresses in the
// addressCache, checkLookupTable() would // addressCache, checkLookupTable() would
// return the address. // return the addresses.
// ii) if it didn't find the address in the // ii) if it didn't find the addresses in the
// addressCache for any reason, // addressCache for any reason,
// it should add the host in the // it should add the host in the
// lookupTable and return null so the // lookupTable and return null so the
// following code would do a lookup itself. // following code would do a lookup itself.
if ((obj = checkLookupTable(host)) == null) { if ((addresses = checkLookupTable(host)) == null) {
// This is the first thread which looks up the address // This is the first thread which looks up the addresses
// this host or the cache entry for this host has been // this host or the cache entry for this host has been
// expired so this thread should do the lookup. // expired so this thread should do the lookup.
for (NameService nameService : nameServices) { for (NameService nameService : nameServices) {
...@@ -1246,26 +1238,26 @@ class InetAddress implements java.io.Serializable { ...@@ -1246,26 +1238,26 @@ class InetAddress implements java.io.Serializable {
* allocating space when the lookup fails. * allocating space when the lookup fails.
*/ */
obj = nameService.lookupAllHostAddr(host); addresses = nameService.lookupAllHostAddr(host);
success = true; success = true;
break; break;
} catch (UnknownHostException uhe) { } catch (UnknownHostException uhe) {
if (host.equalsIgnoreCase("localhost")) { if (host.equalsIgnoreCase("localhost")) {
InetAddress[] local = new InetAddress[] { impl.loopbackAddress() }; InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
obj = local; addresses = local;
success = true; success = true;
break; break;
} }
else { else {
obj = unknown_array; addresses = unknown_array;
success = false; success = false;
ex = uhe; ex = uhe;
} }
} }
} }
// Cache the address. // Cache the addresses.
cacheAddress(host, obj, success); cacheAddresses(host, addresses, success);
// Delete the host from the lookupTable, and // Delete the host from the lookupTable, and
// notify all threads waiting for the monitor // notify all threads waiting for the monitor
// for lookupTable. // for lookupTable.
...@@ -1274,13 +1266,13 @@ class InetAddress implements java.io.Serializable { ...@@ -1274,13 +1266,13 @@ class InetAddress implements java.io.Serializable {
throw ex; throw ex;
} }
return obj; return addresses;
} }
private static Object checkLookupTable(String host) { private static InetAddress[] checkLookupTable(String host) {
// make sure obj is null. // make sure addresses is null.
Object obj = null; InetAddress[] addresses = null;
synchronized (lookupTable) { synchronized (lookupTable) {
// If the host isn't in the lookupTable, add it in the // If the host isn't in the lookupTable, add it in the
...@@ -1288,11 +1280,11 @@ class InetAddress implements java.io.Serializable { ...@@ -1288,11 +1280,11 @@ class InetAddress implements java.io.Serializable {
// the lookup. // the lookup.
if (lookupTable.containsKey(host) == false) { if (lookupTable.containsKey(host) == false) {
lookupTable.put(host, null); lookupTable.put(host, null);
return obj; return addresses;
} }
// If the host is in the lookupTable, it means that another // If the host is in the lookupTable, it means that another
// thread is trying to look up the address of this host. // thread is trying to look up the addresses of this host.
// This thread should wait. // This thread should wait.
while (lookupTable.containsKey(host)) { while (lookupTable.containsKey(host)) {
try { try {
...@@ -1302,18 +1294,18 @@ class InetAddress implements java.io.Serializable { ...@@ -1302,18 +1294,18 @@ class InetAddress implements java.io.Serializable {
} }
} }
// The other thread has finished looking up the address of // The other thread has finished looking up the addresses of
// the host. This thread should retry to get the address // the host. This thread should retry to get the addresses
// from the addressCache. If it doesn't get the address from // from the addressCache. If it doesn't get the addresses from
// the cache, it will try to look up the address itself. // the cache, it will try to look up the addresses itself.
obj = getCachedAddress(host); addresses = getCachedAddresses(host);
if (obj == null) { if (addresses == null) {
synchronized (lookupTable) { synchronized (lookupTable) {
lookupTable.put(host, null); lookupTable.put(host, null);
} }
} }
return obj; return addresses;
} }
private static void updateLookupTable(String host) { private static void updateLookupTable(String host) {
...@@ -1396,15 +1388,20 @@ class InetAddress implements java.io.Serializable { ...@@ -1396,15 +1388,20 @@ class InetAddress implements java.io.Serializable {
cachedLocalHost = null; cachedLocalHost = null;
} }
// we are calling getAddressFromNameService directly // we are calling getAddressesFromNameService directly
// to avoid getting localHost from cache // to avoid getting localHost from cache
if (ret == null) { if (ret == null) {
InetAddress[] localAddrs; InetAddress[] localAddrs;
try { try {
localAddrs = localAddrs =
(InetAddress[]) InetAddress.getAddressFromNameService(local); InetAddress.getAddressesFromNameService(local);
} catch (UnknownHostException uhe) { } catch (UnknownHostException uhe) {
throw new UnknownHostException(local + ": " + uhe.getMessage()); // Rethrow with a more informative error message.
UnknownHostException uhe2 =
new UnknownHostException(local + ": " +
uhe.getMessage());
uhe2.initCause(uhe);
throw uhe2;
} }
cachedLocalHost = localAddrs[0]; cachedLocalHost = localAddrs[0];
cacheTime = now; cacheTime = now;
...@@ -1434,8 +1431,8 @@ class InetAddress implements java.io.Serializable { ...@@ -1434,8 +1431,8 @@ class InetAddress implements java.io.Serializable {
/* /*
* Load and instantiate an underlying impl class * Load and instantiate an underlying impl class
*/ */
static Object loadImpl(String implName) { static InetAddressImpl loadImpl(String implName) {
Object impl; Object impl = null;
/* /*
* Property "impl.prefix" will be prepended to the classname * Property "impl.prefix" will be prepended to the classname
...@@ -1446,7 +1443,6 @@ class InetAddress implements java.io.Serializable { ...@@ -1446,7 +1443,6 @@ class InetAddress implements java.io.Serializable {
*/ */
String prefix = AccessController.doPrivileged( String prefix = AccessController.doPrivileged(
new GetPropertyAction("impl.prefix", "")); new GetPropertyAction("impl.prefix", ""));
impl = null;
try { try {
impl = Class.forName("java.net." + prefix + implName).newInstance(); impl = Class.forName("java.net." + prefix + implName).newInstance();
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
...@@ -1471,7 +1467,7 @@ class InetAddress implements java.io.Serializable { ...@@ -1471,7 +1467,7 @@ class InetAddress implements java.io.Serializable {
} }
} }
return impl; return (InetAddressImpl) impl;
} }
private void readObjectNoData (ObjectInputStream s) throws private void readObjectNoData (ObjectInputStream s) throws
...@@ -1498,13 +1494,8 @@ class InetAddress implements java.io.Serializable { ...@@ -1498,13 +1494,8 @@ class InetAddress implements java.io.Serializable {
class InetAddressImplFactory { class InetAddressImplFactory {
static InetAddressImpl create() { static InetAddressImpl create() {
Object o; return InetAddress.loadImpl(isIPv6Supported() ?
if (isIPv6Supported()) { "Inet6AddressImpl" : "Inet4AddressImpl");
o = InetAddress.loadImpl("Inet6AddressImpl");
} else {
o = InetAddress.loadImpl("Inet4AddressImpl");
}
return (InetAddressImpl)o;
} }
static native boolean isIPv6Supported(); static native boolean isIPv6Supported();
......
...@@ -124,7 +124,7 @@ static jfieldID ni_ia6ipaddressID; ...@@ -124,7 +124,7 @@ static jfieldID ni_ia6ipaddressID;
static int initialized = 0; static int initialized = 0;
/* /*
* Find an internet address for a given hostname. Not this this * Find an internet address for a given hostname. Note that this
* code only works for addresses of type INET. The translation * code only works for addresses of type INET. The translation
* of %d.%d.%d.%d to an address (int) occurs in java now, so the * of %d.%d.%d.%d to an address (int) occurs in java now, so the
* String "host" shouldn't *ever* be a %d.%d.%d.%d string * String "host" shouldn't *ever* be a %d.%d.%d.%d string
...@@ -200,7 +200,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -200,7 +200,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
*/ */
if (isspace((unsigned char)hostname[0])) { if (isspace((unsigned char)hostname[0])) {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
(char *)hostname); hostname);
JNU_ReleaseStringPlatformChars(env, host, hostname); JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL; return NULL;
} }
...@@ -210,8 +210,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -210,8 +210,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
if (error) { if (error) {
/* report error */ /* report error */
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
(char *)hostname);
JNU_ReleaseStringPlatformChars(env, host, hostname); JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL; return NULL;
} else { } else {
...@@ -407,7 +406,7 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, ...@@ -407,7 +406,7 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
addr |= ((caddr[1] <<16) & 0xff0000); addr |= ((caddr[1] <<16) & 0xff0000);
addr |= ((caddr[2] <<8) & 0xff00); addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff); addr |= (caddr[3] & 0xff);
memset((char *) &him4, 0, sizeof(him4)); memset((void *) &him4, 0, sizeof(him4));
him4.sin_addr.s_addr = (uint32_t) htonl(addr); him4.sin_addr.s_addr = (uint32_t) htonl(addr);
him4.sin_family = AF_INET; him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4; sa = (struct sockaddr *) &him4;
...@@ -417,7 +416,7 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, ...@@ -417,7 +416,7 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
* For IPv6 address construct a sockaddr_in6 structure. * For IPv6 address construct a sockaddr_in6 structure.
*/ */
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
memset((char *) &him6, 0, sizeof(him6)); memset((void *) &him6, 0, sizeof(him6));
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
him6.sin6_family = AF_INET6; him6.sin6_family = AF_INET6;
sa = (struct sockaddr *) &him6 ; sa = (struct sockaddr *) &him6 ;
...@@ -579,8 +578,8 @@ Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this, ...@@ -579,8 +578,8 @@ Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
ifArray, ttl); ifArray, ttl);
} }
memset((char *) caddr, 0, 16); memset((void *) caddr, 0, 16);
memset((char *) &him6, 0, sizeof(him6)); memset((void *) &him6, 0, sizeof(him6));
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
him6.sin6_family = AF_INET6; him6.sin6_family = AF_INET6;
...@@ -600,8 +599,8 @@ Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this, ...@@ -600,8 +599,8 @@ Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
* for it. * for it.
*/ */
if (!(IS_NULL(ifArray))) { if (!(IS_NULL(ifArray))) {
memset((char *) caddr, 0, 16); memset((void *) caddr, 0, 16);
memset((char *) &inf6, 0, sizeof(inf6)); memset((void *) &inf6, 0, sizeof(inf6));
(*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr); (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) ); memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
inf6.sin6_family = AF_INET6; inf6.sin6_family = AF_INET6;
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
getaddrinfo_f getaddrinfo_ptr = NULL; getaddrinfo_f getaddrinfo_ptr = NULL;
freeaddrinfo_f freeaddrinfo_ptr = NULL; freeaddrinfo_f freeaddrinfo_ptr = NULL;
gai_strerror_f gai_strerror_ptr = NULL;
getnameinfo_f getnameinfo_ptr = NULL; getnameinfo_f getnameinfo_ptr = NULL;
/* /*
...@@ -342,11 +343,14 @@ jint IPv6_supported() ...@@ -342,11 +343,14 @@ jint IPv6_supported()
freeaddrinfo_ptr = (freeaddrinfo_f) freeaddrinfo_ptr = (freeaddrinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo"); JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
gai_strerror_ptr = (gai_strerror_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
getnameinfo_ptr = (getnameinfo_f) getnameinfo_ptr = (getnameinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo"); JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) { if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
/* Wee need all 3 of them */ /* We need all 3 of them */
getaddrinfo_ptr = NULL; getaddrinfo_ptr = NULL;
} }
...@@ -355,6 +359,32 @@ jint IPv6_supported() ...@@ -355,6 +359,32 @@ jint IPv6_supported()
#endif /* AF_INET6 */ #endif /* AF_INET6 */
} }
void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
const char* hostname,
int gai_error)
{
const char *format = "%s: %s";
const char *error_string =
(gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
if (error_string == NULL)
error_string = "unknown error";
int size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
char *buf = (char *) malloc(size);
if (buf) {
sprintf(buf, format, hostname, error_string);
jstring s = JNU_NewStringPlatform(env, buf);
if (s != NULL) {
jobject x = JNU_NewObjectByName(env,
"java/net/UnknownHostException",
"(Ljava/lang/String;)V", s);
if (x != NULL)
(*env)->Throw(env, x);
}
free(buf);
}
}
void void
NET_AllocSockaddr(struct sockaddr **him, int *len) { NET_AllocSockaddr(struct sockaddr **him, int *len) {
#ifdef AF_INET6 #ifdef AF_INET6
......
...@@ -84,11 +84,13 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr); ...@@ -84,11 +84,13 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr);
/* needed from libsocket on Solaris 8 */ /* needed from libsocket on Solaris 8 */
typedef int (*getaddrinfo_f)(const char *nodename, const char *servname, typedef int (*getaddrinfo_f)(const char *nodename, const char *servname,
const struct addrinfo *hints, struct addrinfo **res); const struct addrinfo *hints, struct addrinfo **res);
typedef void (*freeaddrinfo_f)(struct addrinfo *); typedef void (*freeaddrinfo_f)(struct addrinfo *);
typedef const char * (*gai_strerror_f)(int ecode);
typedef int (*getnameinfo_f)(const struct sockaddr *, size_t, typedef int (*getnameinfo_f)(const struct sockaddr *, size_t,
char *, size_t, char *, size_t, int); char *, size_t, char *, size_t, int);
...@@ -96,6 +98,10 @@ extern getaddrinfo_f getaddrinfo_ptr; ...@@ -96,6 +98,10 @@ extern getaddrinfo_f getaddrinfo_ptr;
extern freeaddrinfo_f freeaddrinfo_ptr; extern freeaddrinfo_f freeaddrinfo_ptr;
extern getnameinfo_f getnameinfo_ptr; extern getnameinfo_f getnameinfo_ptr;
void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
const char* hostname,
int gai_error);
/* do we have address translation support */ /* do we have address translation support */
extern jboolean NET_addrtransAvailable(); extern jboolean NET_addrtransAvailable();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册