You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2011/05/06 18:09:11 UTC
svn commit: r1100260 - in /commons/sandbox/runtime/trunk/src/main:
java/org/apache/commons/runtime/net/ native/shared/
Author: mturk
Date: Fri May 6 16:09:10 2011
New Revision: 1100260
URL: http://svn.apache.org/viewvc?rev=1100260&view=rev
Log:
Simplify the native address code by making EndpointAddress.sa protected. It is visible but cannot be accessed outside Runtime, so safe
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalEndpointAddress.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java
commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java?rev=1100260&r1=1100259&r2=1100260&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java Fri May 6 16:09:10 2011
@@ -18,30 +18,25 @@
package org.apache.commons.runtime.net;
-import java.net.SocketAddress;
-
/**
* This class represents a network address.
*/
-public abstract class EndpointAddress extends SocketAddress
+public abstract class EndpointAddress
{
- private int family;
/**
- * Native representation of @{code this} address.
- * This is pointer to acr_sockaddr_t and is directly
- * used by socket functions.
+ * Native representation of {@code this} address.
+ * This is pointer to Operating System sockaddr structure and is used
+ * used internally by socket functions.
*/
- private long sa;
+ protected long sa;
- private static native void init0();
+ private int family;
private static native int family0(long sa);
private static native void free0(long sa);
private static native boolean hasnext0(long sa);
+ private static native boolean equals0(long sa1, long sa2);
private static native String name0(long sa);
- static {
- init0();
- }
/**
* Creates a new EndpointAddress object.
*/
@@ -91,6 +86,26 @@ public abstract class EndpointAddress ex
}
/**
+ * Compares this {@code SocketAddress} to the specified object.
+ *
+ * @param other the reference {@code SocketAddress} with which to compare.
+ * @return {@code true} if the class of this {@code SocketAddress} object and the
+ * class of {@code other} are exactly equal; {@code false} otherwise.
+ */
+ @Override
+ public final boolean equals(Object other)
+ {
+ if (other == null)
+ return false;
+ if (other == this)
+ return true;
+ if (other instanceof EndpointAddress)
+ return equals0(sa, ((EndpointAddress)other).sa);
+ else
+ return false;
+ }
+
+ /**
* Called by the garbage collector when the object is destroyed.
* The class will free internal resources allocated by the Operating system.
* @see Object#finalize()
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalEndpointAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalEndpointAddress.java?rev=1100260&r1=1100259&r2=1100260&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalEndpointAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalEndpointAddress.java Fri May 6 16:09:10 2011
@@ -34,7 +34,9 @@ import org.apache.commons.runtime.Invali
public final class LocalEndpointAddress extends EndpointAddress
{
- private native int sockaddr0(String name);
+ private long sa;
+ private native long sockaddr0(String name)
+ throws OutOfMemoryError, NetworkException;
private LocalEndpointAddress()
{
@@ -50,13 +52,7 @@ public final class LocalEndpointAddress
super(AddressFamily.LOCAL);
if (name == null || name.length() == 0)
throw new InvalidArgumentException();
- int rc = sockaddr0(name);
- if (rc != 0) {
- if (rc == Errno.ENOMEM)
- throw new OutOfMemoryError();
- else
- throw new NetworkException(Status.describe(rc));
- }
+ super.sa = sockaddr0(name);
}
/**
@@ -69,13 +65,7 @@ public final class LocalEndpointAddress
String name = path.getPath();
if (name == null || name.length() == 0)
throw new InvalidArgumentException();
- int rc = sockaddr0(name);
- if (rc != 0) {
- if (rc == Errno.ENOMEM)
- throw new OutOfMemoryError();
- else
- throw new NetworkException(Status.describe(rc));
- }
+ super.sa = sockaddr0(name);
}
}
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java?rev=1100260&r1=1100259&r2=1100260&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java Fri May 6 16:09:10 2011
@@ -31,6 +31,8 @@ import org.apache.commons.runtime.Invali
*/
public abstract class SocketAddress extends EndpointAddress
{
+ // Hide parent field.
+ // private long sa;
/**
* First query for IPv4 addresses; only look
* for IPv6 addresses if the first query failed;
@@ -47,17 +49,17 @@ public abstract class SocketAddress exte
private static final int IPV6_ADDR_OK = 2;
/* Structure members */
- private native String hostname0();
- private native String servname0();
- private native int port0();
-
- private native String ipaddr0()
- throws InvalidArgumentException;
- private native int sockaddr0(String hostname, int family, int port, int flags);
- private native boolean equals0(SocketAddress other);
- private native int next0();
- private native int next1(SocketAddress next);
+ private static native String hostname0(long sa);
+ private static native String hostname1(long sa);
+ private static native String servname0(long sa);
+ private static native int port0(long sa);
+
+ private static native String ipaddr0(long sa);
+ private static native long sockaddr0(String hostname, int family, int port, int flags)
+ throws OutOfMemoryError, NetworkException;
+ private static native int next0(long sa);
+ private String fqdn = null;
/**
* Creates an new object
*/
@@ -78,13 +80,7 @@ public abstract class SocketAddress exte
NetworkException
{
super(family);
- int rc = sockaddr0(host, family.valueOf(), port, flags);
- if (rc != 0) {
- if (rc == Errno.ENOMEM)
- throw new OutOfMemoryError();
- else
- throw new NetworkException(Status.describe(rc));
- }
+ super.sa = sockaddr0(host, family.valueOf(), port, flags);
}
protected SocketAddress(String host, AddressFamily family)
@@ -92,23 +88,34 @@ public abstract class SocketAddress exte
NetworkException
{
super(family);
- int rc = sockaddr0(host, family.valueOf(), 0, 0);
- if (rc != 0) {
- if (rc == Errno.ENOMEM)
- throw new OutOfMemoryError();
- else
- throw new NetworkException(Status.describe(rc));
- }
+ super.sa = sockaddr0(host, family.valueOf(), 0, 0);
}
/**
* Gets the hostname of this socket.
- *
+ * <p>
+ * The methods does not resolve the host name. If the address was
+ * not resloved already the method returns IP notion of the address.
+ * </p>
* @return the socket endpoint hostname.
*/
public final String getHostName()
{
- return hostname0();
+ return hostname0(super.sa);
+ }
+
+ /**
+ * Gets the fully qualified domain name of this address.
+ * <p>
+ * The methods resolves the host name.
+ * </p>
+ * @return the socket endpoint hostname.
+ */
+ public final String getCanonicalHostName()
+ {
+ if (fqdn == null)
+ fqdn = hostname1(super.sa);
+ return fqdn;
}
/**
@@ -118,7 +125,7 @@ public abstract class SocketAddress exte
*/
public final String getServiceName()
{
- return servname0();
+ return servname0(super.sa);
}
/**
@@ -128,51 +135,7 @@ public abstract class SocketAddress exte
*/
public final int getPort()
{
- return port0();
- }
-
- /**
- * Gets the next address.
- */
- public SocketAddress next()
- {
- int family = next0();
- if (family == -1)
- return null;
- AbstractSocketAddress next;
- try {
- next = new AbstractSocketAddress(AddressFamily.valueOf(family));
- } catch (Exception e) {
- // This should never happen.
- // Throw OOM since this is the only logical reason.
- throw new OutOfMemoryError();
- }
- int rc = next1(next);
- if (rc != 0) {
- next = null;
- throw new RuntimeException("internal error");
- }
- return next;
- }
-
- /**
- * Compares this {@code SocketAddress} to the specified object.
- *
- * @param other the reference {@code SocketAddress} with which to compare.
- * @return {@code true} if the class of this {@code SocketAddress} object and the
- * class of {@code other} are exactly equal; {@code false} otherwise.
- */
- @Override
- public final boolean equals(Object other)
- {
- if (other == null)
- return false;
- if (other == this)
- return true;
- if (other instanceof SocketAddress)
- return equals0((SocketAddress)other);
- else
- return false;
+ return port0(super.sa);
}
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c?rev=1100260&r1=1100259&r2=1100260&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c Fri May 6 16:09:10 2011
@@ -45,22 +45,6 @@
# define SET_H_ERRNO(newval)
#endif
-J_DECLARE_CLAZZ = {
- INVALID_FIELD_OFFSET,
- 0,
- 0,
- 0,
- ACR_NET_CP "EndpointAddress"
-};
-
-J_DECLARE_F_ID(0000) = {
- INVALID_FIELD_OFFSET,
- INVALID_FIELD_OFFSET,
- 0,
- "sa",
- "J"
-};
-
/* const char *
* inet_ntop4(src, dst, size)
* format an IPv4 address, more or less like inet_ntoa()
@@ -606,7 +590,7 @@ AcrFindAddresses(acr_sockaddr_t **sa, co
#define GETHOSTBYNAME_BUFLEN 512
int
-AcrGetNameInfo(char **hostname, acr_sockaddr_t *sockaddr, int flags)
+AcrGetNameInfo(const char **hostname, acr_sockaddr_t *sockaddr, int flags)
{
int rc;
char tmphostname[NI_MAXHOST];
@@ -633,7 +617,7 @@ AcrGetNameInfo(char **hostname, acr_sock
#endif
rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
- tmphostname, NI_MAXHOST, NULL, 0,
+ tmphostname, NI_MAXHOST, 0, 0,
flags != 0 ? flags : NI_NAMEREQD);
}
else if (sockaddr->family == AF_UNIX) {
@@ -642,7 +626,7 @@ AcrGetNameInfo(char **hostname, acr_sock
}
else
rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
- tmphostname, NI_MAXHOST, NULL, 0,
+ tmphostname, NI_MAXHOST, 0, 0,
flags != 0 ? flags : NI_NAMEREQD);
if (rc != 0) {
*hostname = 0;
@@ -671,14 +655,68 @@ AcrGetNameInfo(char **hostname, acr_sock
return 0;
}
-ACR_NET_EXPORT(void, EndpointAddress, init0)(JNI_STDARGS)
+int
+AcrGetServInfo(const char **servname, acr_sockaddr_t *sockaddr, int flags)
{
- _clazzn.i = (jclass)(*env)->NewGlobalRef(env, obj);
- if (_clazzn.i == 0)
- return;
- V_LOAD_IFIELD(0000);
- UNSAFE_IFIELD(0000);
- _clazzn.u = 1;
+ int rc;
+ char tmpservname[NI_MAXSERV];
+
+ /* don't know if it is portable for getnameinfo() to set h_errno;
+ * clear it then see if it was set */
+ SET_H_ERRNO(0);
+
+ /* For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
+ * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
+ */
+ if (sockaddr->family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
+ struct sockaddr_in tmpsa;
+ tmpsa.sin_family = AF_INET;
+ tmpsa.sin_port = 0;
+ tmpsa.sin_addr.s_addr = ((acr_u32_t *)sockaddr->ipaddr)[3];
+#ifdef SIN6_LEN
+ tmpsa.sin_len = sizeof(tmpsa);
+#endif
+
+ rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
+ 0, 0, tmpservname, NI_MAXSERV, flags);
+ }
+ else if (sockaddr->family == AF_UNIX) {
+#if defined(WINDOWS)
+ *servname = "pipe";
+#else
+ *servname = "socket";
+#endif
+ return 0;
+ }
+ else
+ rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
+ 0, 0, tmpservname, NI_MAXSERV, flags);
+ if (rc != 0) {
+ *servname = 0;
+
+#if !defined(WINDOWS)
+ /* something went wrong. Look at the EAI_ error code */
+ if (rc == EAI_SYSTEM) {
+ /* EAI_SYSTEM System error returned in errno. */
+ /* IMHO, Implementations that set h_errno a simply broken. */
+ if (h_errno) /* for broken implementations which set h_errno */
+ return h_errno + ACR_OS_START_SYSERR;
+ else /* "normal" case */
+ return errno + ACR_OS_START_SYSERR;
+ }
+ else
+#endif
+ {
+#if defined(NEGATIVE_EAI)
+ if (rc < 0) rc = -rc;
+#endif
+ return rc + ACR_OS_START_EAIERR; /* return the EAI_ error */
+ }
+ }
+ strlcpy(sockaddr->servname, tmpservname, NI_MAXSERV);
+ *servname = sockaddr->servname;
+ return 0;
}
ACR_NET_EXPORT(void, EndpointAddress, free0)(JNI_STDARGS, jlong sa)
@@ -723,61 +761,41 @@ ACR_NET_EXPORT(jboolean, EndpointAddress
ACR_NET_EXPORT(jstring, EndpointAddress, name0)(JNI_STDARGS, jlong sa)
{
char buf[256];
- const char *name = 0;
+ const char *name = "(null)";
acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
- if (a == 0)
- return 0;
- if (a->hostname[0] == '\0') {
- /* Return IP address representation
- */
- if (AcrGetSockaddrIp(buf, 256, a) == 0)
- name = buf;
- }
- else
- name = a->hostname;
- return AcrNewJavaStringA(env, name);
-}
-
-acr_sockaddr_t *
-AcrGetSockaddr(JNI_STDARGS)
-{
- jlong sa = 0;
-
- if (J4FLD_OFF(0000) != INVALID_FIELD_OFFSET) {
- char *oa = *(char **)obj;
- if (oa != 0) {
- char *fa = (oa + J4FLD_PTR(0000));
- sa = *((jlong *)fa);
+ if (a != 0) {
+ if (a->hostname[0] == '\0') {
+ /* Return IP address representation
+ */
+ if (AcrGetSockaddrIp(buf, 256, a) == 0)
+ name = buf;
}
+ else
+ name = a->hostname;
}
- else if (CLAZZ_LOADED) {
- sa = GET_IFIELD_J(0000, obj);
- }
- return J2P(sa, acr_sockaddr_t *);
+ return AcrNewJavaStringA(env, name);
}
-int
-AcrSetSockaddr(JNI_STDARGS, acr_sockaddr_t *sa)
+ACR_NET_EXPORT(jboolean, EndpointAddress, equals0)(JNI_STDARGS, jlong sa1, jlong sa2)
{
- int rc = ACR_EBADF;
+ acr_sockaddr_t *addr1 = J2P(sa1, acr_sockaddr_t *);
+ acr_sockaddr_t *addr2 = J2P(sa2, acr_sockaddr_t *);
- if (J4FLD_OFF(0000) != INVALID_FIELD_OFFSET) {
- char *oa = *(char **)obj;
- if (oa != 0) {
- char *fa = (oa + J4FLD_PTR(0000));
- *((jlong *)fa) = P2J(sa);
- rc = 0;
- }
- }
- else if (CLAZZ_LOADED) {
- SET_IFIELD_P(0000, obj, sa);
- rc = 0;
+ if (addr1 == 0 || addr2 == 0)
+ return JNI_FALSE;
+ if (addr1->iplen == addr2->iplen &&
+ memcmp(addr1->ipaddr, addr2->ipaddr, addr1->iplen) == 0) {
+ return JNI_TRUE;
}
- return rc;
+ if (V4MAPPED_EQUAL(addr1, addr2))
+ return 1;
+ if (V4MAPPED_EQUAL(addr2, addr1))
+ return JNI_TRUE;
+ return JNI_FALSE; /* not equal */
}
-ACR_NET_EXPORT(jint, LocalEndpointAddress, sockaddr0)(JNI_STDARGS, jstring hostname)
+ACR_NET_EXPORT(jlong, LocalEndpointAddress, sockaddr0)(JNI_STDARGS, jstring hostname)
{
acr_sockaddr_t *sa = 0;
char *np;
@@ -829,57 +847,84 @@ ACR_NET_EXPORT(jint, LocalEndpointAddres
#endif
} DONE_WITH_STR(hostname);
- if (rc == 0)
- rc = AcrSetSockaddr(env, obj, sa);
- return rc;
+ if (rc != 0)
+ ACR_THROW_NET_ERROR(rc);
+ return P2J(sa);;
}
-ACR_NET_EXPORT(jstring, SocketAddress, hostname0)(JNI_STDARGS)
+ACR_NET_EXPORT(jstring, SocketAddress, hostname0)(JNI_STDARGS, jlong a)
{
- acr_sockaddr_t *sa = AcrGetSockaddr(env, obj);
+ acr_sockaddr_t *sa = J2P(a, acr_sockaddr_t *);
if (sa != 0 && sa->hostname != '\0')
return AcrNewJavaStringA(env, sa->hostname);
- else
+ else {
+ char buf[256];
+ if (AcrGetSockaddrIp(buf, 256, sa) == 0)
+ return AcrNewJavaStringA(env, buf);
+ }
+ return 0;
+}
+
+ACR_NET_EXPORT(jstring, SocketAddress, hostname1)(JNI_STDARGS, jlong a)
+{
+ const char *host = 0;
+ int rc;
+ acr_sockaddr_t *sa = J2P(a, acr_sockaddr_t *);
+
+ if (sa == 0)
return 0;
+ rc = AcrGetNameInfo(&host, sa, 0);
+ if (rc == 0)
+ return AcrNewJavaStringA(env, host);
+ else {
+ char buf[256];
+ if (AcrGetSockaddrIp(buf, 256, sa) == 0)
+ return AcrNewJavaStringA(env, buf);
+ }
+ return 0;
}
-ACR_NET_EXPORT(jstring, SocketAddress, servname0)(JNI_STDARGS)
+ACR_NET_EXPORT(jstring, SocketAddress, servname0)(JNI_STDARGS, jlong a)
{
- acr_sockaddr_t *sa = AcrGetSockaddr(env, obj);
+ const char *serv = 0;
+ int rc;
+ acr_sockaddr_t *sa = J2P(a, acr_sockaddr_t *);
+
if (sa != 0 && sa->servname != '\0')
return AcrNewJavaStringA(env, sa->servname);
- else
- return 0;
+ else {
+ rc = AcrGetServInfo(&serv, sa, 0);
+ if (rc == 0)
+ return AcrNewJavaStringA(env, serv);
+ else
+ return 0;
+ }
}
-ACR_NET_EXPORT(jstring, SocketAddress, ipaddr0)(JNI_STDARGS)
+ACR_NET_EXPORT(jstring, SocketAddress, ipaddr0)(JNI_STDARGS, jlong a)
{
char buf[256];
- acr_sockaddr_t *sa = AcrGetSockaddr(env, obj);
+ acr_sockaddr_t *sa = J2P(a, acr_sockaddr_t *);
- if (sa == 0) {
- ACR_THROW(ACR_EX_ENULL, 0);
+ if (sa == 0)
return 0;
- }
if (AcrGetSockaddrIp(buf, 256, sa) == 0)
return AcrNewJavaStringA(env, buf);
- else {
- ACR_THROW_NET_ERROR(ACR_EINVAL);
+ else
return 0;
- }
}
-ACR_NET_EXPORT(jint, SocketAddress, port0)(JNI_STDARGS)
+ACR_NET_EXPORT(jint, SocketAddress, port0)(JNI_STDARGS, jlong a)
{
- acr_sockaddr_t *sa = AcrGetSockaddr(env, obj);
+ acr_sockaddr_t *sa = J2P(a, acr_sockaddr_t *);
if (sa != 0)
return sa->port;
else
return 0;
}
-ACR_NET_EXPORT(jint, SocketAddress, sockaddr0)(JNI_STDARGS, jstring hostname,
- jint family, jint port, jint flags)
+ACR_NET_EXPORT(jlong, SocketAddress, sockaddr0)(JNI_STDARGS, jstring hostname,
+ jint family, jint port, jint flags)
{
acr_sockaddr_t *sa = 0;
int ffamily = AF_UNSPEC;
@@ -902,7 +947,8 @@ ACR_NET_EXPORT(jint, SocketAddress, sock
if ((masked = flags & (ACR_IPV4_ADDR_OK | ACR_IPV6_ADDR_OK))) {
if (hostname == 0 || family != AF_UNSPEC ||
masked == (ACR_IPV4_ADDR_OK | ACR_IPV6_ADDR_OK)) {
- return ACR_EINVAL;
+ ACR_THROW(ACR_EX_EINVAL, 0);
+ return 0;
}
}
@@ -910,32 +956,14 @@ ACR_NET_EXPORT(jint, SocketAddress, sock
rc = AcrFindAddresses(&sa, J2S(hostname), ffamily, port, flags);
} DONE_WITH_STR(hostname);
- if (rc == 0)
- rc = AcrSetSockaddr(env, obj, sa);
- return rc;
-}
-
-ACR_NET_EXPORT(jboolean, SocketAddress, equals0)(JNI_STDARGS, jobject sa2)
-{
- acr_sockaddr_t *addr1 = AcrGetSockaddr(env, obj);
- acr_sockaddr_t *addr2 = AcrGetSockaddr(env, sa2);
-
- if (addr1 == 0 || addr2 == 0)
- return JNI_FALSE;
- if (addr1->iplen == addr2->iplen &&
- memcmp(addr1->ipaddr, addr2->ipaddr, addr1->iplen) == 0) {
- return JNI_TRUE;
- }
- if (V4MAPPED_EQUAL(addr1, addr2))
- return 1;
- if (V4MAPPED_EQUAL(addr2, addr1))
- return JNI_TRUE;
- return JNI_FALSE; /* not equal */
+ if (rc != 0)
+ ACR_THROW_NET_ERROR(rc);
+ return P2J(sa);
}
-ACR_NET_EXPORT(jint, SocketAddress, next0)(JNI_STDARGS)
+ACR_NET_EXPORT(jint, SocketAddress, next0)(JNI_STDARGS, jlong a)
{
- acr_sockaddr_t *sa = AcrGetSockaddr(env, obj);
+ acr_sockaddr_t *sa = J2P(a, acr_sockaddr_t *);
if (sa == 0 || sa->next == 0)
return -1;
@@ -953,19 +981,3 @@ ACR_NET_EXPORT(jint, SocketAddress, next
}
return 0;
}
-
-ACR_NET_EXPORT(jint, SocketAddress, next1)(JNI_STDARGS, jobject na)
-{
- int rc;
- acr_sockaddr_t *sa = AcrGetSockaddr(env, obj);
-
- if (sa == 0 || sa->next == 0)
- return ACR_EBADF;
- /* Detach the next address so that
- * cleanup can work.
- */
- rc = AcrSetSockaddr(env, na, sa->next);
- if (rc == 0)
- sa->next = 0;
- return rc;
-}