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/04 19:05:43 UTC

svn commit: r1099521 - in /commons/sandbox/runtime/trunk/src/main: java/org/apache/commons/runtime/net/ native/include/acr/ native/os/unix/ native/os/win32/ native/shared/

Author: mturk
Date: Wed May  4 17:05:43 2011
New Revision: 1099521

URL: http://svn.apache.org/viewvc?rev=1099521&view=rev
Log:
Add core sockaddr wrapper class

Added:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AbstractSocketAddress.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AddressFamily.java   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java
    commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h
    commons/sandbox/runtime/trunk/src/main/native/include/acr/netapi.h
    commons/sandbox/runtime/trunk/src/main/native/include/acr/netdefs.h
    commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c
    commons/sandbox/runtime/trunk/src/main/native/os/win32/wpipe.c
    commons/sandbox/runtime/trunk/src/main/native/shared/error.c
    commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AbstractSocketAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AbstractSocketAddress.java?rev=1099521&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AbstractSocketAddress.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AbstractSocketAddress.java Wed May  4 17:05:43 2011
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.runtime.net;
+
+import java.io.File;
+import java.net.SocketException;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import org.apache.commons.runtime.Status;
+
+/**
+ * This class represents an socket address.
+ * 
+ */
+abstract class AbstractSocketAddress extends SocketAddress
+{
+
+    /**
+     * First query for IPv4 addresses; only look
+     * for IPv6 addresses if the first query failed;
+     * only valid if family is UNSPEC and hostname
+     * isn't null; mutually exclusive with IPV6_ADDR_OK
+     */
+    public static final int IPV4_ADDR_OK  = 1;
+    /**
+     * First query for IPv6 addresses; only look
+     * for IPv4 addresses if the first query failed;
+     * only valid if family is UNSPEC and hostname
+     * isn't null; mutually exclusive with IPV4_ADDR_OK
+     */
+    public static final int IPV6_ADDR_OK  = 2;
+
+    private static native long alloc0()
+        throws OutOfMemoryError;
+    private static native void free0(long addr);
+    /* Structure members */
+    private static native String hostname0(long addr);
+    private static native String servname0(long addr);
+    private static native int    port0(long addr);
+    private static native int    family0(long addr);
+
+    private static native String ipaddr0(long addr);
+    private static native long   geti0(String hostname, int family, int port, int flags)
+        throws UnknownHostException;
+    /**
+     * Native representation of @{code this} address.
+     * This is pointer to acr_sockaddr_t and is directly
+     * used by socket functions.
+     * 
+     */
+    protected long      addr;
+    /**
+     * True if this address has been resolved.
+     */
+    protected boolean   resolved;
+
+    /**
+     * Creates an new object
+     */
+    protected AbstractSocketAddress()
+    {
+        addr     = 0L;
+        resolved = false;
+    }
+
+    protected void create(String hostname, AddressFamily family, int port, int flags)
+        throws UnknownHostException
+    {
+        addr = geti0(hostname, family.valueOf(), port, flags);
+    }
+
+    /**
+     * Called by the garbage collector when the object is destroyed.
+     * The class will free internal resources allocated by the Operating system.
+     * @see Object#finalize()
+     * @throws Throwable the {@code Exception} raised by this method.
+     */
+    @Override
+    protected void finalize()
+        throws Throwable
+    {
+        try {
+            free0(addr);
+        } finally {
+            addr = 0L;
+        }
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AbstractSocketAddress.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AddressFamily.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AddressFamily.java?rev=1099521&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AddressFamily.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AddressFamily.java Wed May  4 17:05:43 2011
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.runtime.net;
+
+/** Represents the protocol family which will be used for communication.
+ */
+public enum AddressFamily
+{
+    /** Unspecified address family */
+    UNSPEC(     0),
+    /** IPv4 Internet protocols */
+    INET(       1),
+    /** IPv6 Internet protocols */
+    INET6(      2),
+    /** Local communication */
+    LOCAL(      3);
+
+
+    private int value;
+    private AddressFamily(int v)
+    {
+        value = v;
+    }
+
+    public int valueOf()
+    {
+        return value;
+    }
+
+    public static AddressFamily valueOf(int value)
+    {
+        for (AddressFamily e : values()) {
+            if (e.value == value)
+                return e;
+        }
+        return UNSPEC;
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/AddressFamily.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java Wed May  4 17:05:43 2011
@@ -19,73 +19,32 @@
 package org.apache.commons.runtime.net;
 
 import java.io.File;
-import java.net.SocketAddress;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 import org.apache.commons.runtime.Memory;
 import org.apache.commons.runtime.Status;
 
-public final class LocalSocketAddress extends SocketAddress
+public final class LocalSocketAddress extends AbstractSocketAddress
 {
 
-    private static native long   addr0(String name);
-    private static native String prefix0();
-    private static final  String prefix;
-    static {
-        prefix = prefix0();
-
-    }
     private LocalSocketAddress()
     {
         // No instance
     }
 
-    private long    addr;
-    private String  path;
     public LocalSocketAddress(String name)
+        throws UnknownHostException
     {
         if (name == null)
             throw new IllegalArgumentException("name can't be null");
-        StringBuilder pn = new StringBuilder(prefix);
-        // Normalize the pipe or unix socket name
-        //
-        for (int i = 0; i < name.length(); i++) {
-            char c = name.charAt(i);
-            if (c == '\\' || c == '/')
-                c = '_';
-            pn.append(c);
-        }
-        path = pn.toString();
-        addr = addr0(name);
+        create(name, AddressFamily.LOCAL, 0, 0);
     }
 
     public LocalSocketAddress(File path)
+        throws UnknownHostException
     {
         if (path == null)
             throw new IllegalArgumentException("path can't be null");
-        // path is presumed to be correctly
-        // formatted.
-        this.path = path.getPath();
-        addr = addr0(this.path);
-    }
-
-    /**
-     * Called by the garbage collector when the object is destroyed.
-     * The class will free internal resources allocated by the Operating system.
-     * @see Object#finalize()
-     * @throws Throwable the {@code Exception} raised by this method.
-     */
-    @Override
-    protected final void finalize()
-        throws Throwable
-    {
-        if (addr != 0)
-            Memory.free(addr);
-    }
-    
-
-    @Override
-    public String toString()
-    {
-        return this.path;
+        create(path.getPath(), AddressFamily.LOCAL, 0, 0);
     }
 }

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h Wed May  4 17:05:43 2011
@@ -42,6 +42,8 @@ enum {
     ACR_EX_ENULL,           /* java/lang/NullPointerException */
     ACR_EX_ENOSYS,          /* java/lang/UnsupportedOperationException */
     ACR_EX_EIO,             /* java/io/IOException */
+    ACR_EX_ESOCK,           /* java/net/SocketException */
+    ACR_EX_EHOST,           /* java/net/UnknownHostException */
 
     ACR_EX_EBADF,           /* io/InvalidDescriptorException */
     ACR_EX_EACCES,          /* AccessDeniedException */
@@ -1342,6 +1344,9 @@ enum {
 #define ACR_ENOMSG ENOMSG
 #endif
 
+#if EAI_FAMILY < 0
+# define NEGATIVE_EAI   1
+#endif
 #endif
 
 #define ACR_OS_LAST_CANONERR    (ACR_OS_START_CANONERR + 91)

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/netapi.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/netapi.h?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/netapi.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/netapi.h Wed May  4 17:05:43 2011
@@ -23,9 +23,9 @@
 typedef struct acr_sockaddr_t acr_sockaddr_t;
 struct acr_sockaddr_t {
     /** The hostname */
-    char       hostname[256];
+    char       hostname[NI_MAXHOST];
     /** Either a string of the port number or the service name for the port */
-    char       servname[256];
+    char       servname[NI_MAXSERV];
     /** The numeric port */
     int         port;
     /** The family */

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/netdefs.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/netdefs.h?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/netdefs.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/netdefs.h Wed May  4 17:05:43 2011
@@ -51,6 +51,12 @@
 #define EAFNOSUPPORT WSAEAFNOSUPPORT
 #endif
 
+#if !defined(NI_MAXHOST)
+# define NI_MAXHOST 1025
+#endif
+#if !defined(NI_MAXSERV)
+# define NI_MAXSERV 32
+#endif
 #define ACR_IPV4_ADDR_OK  0x01
 #define ACR_IPV6_ADDR_OK  0x02
 

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c Wed May  4 17:05:43 2011
@@ -27,26 +27,3 @@
 #include <poll.h>
 #include <sys/un.h>
 
-ACR_NET_EXPORT(jstring, LocalSocketAddress, prefix0)(JNI_STDARGS)
-{
-    return CSTR_TO_JSTRING(VAR_RUN_PATH "/");
-}
-
-ACR_NET_EXPORT(jlong, LocalSocketAddress, addr0)(JNI_STDARGS, jstring name)
-{
-    struct sockaddr_un *un = 0;
-
-    un = ACR_TALLOC(struct sockaddr_un);
-    if (un == 0)
-        return 0;
-    WITH_CSTR(name) {
-        size_t len = strlcpy(un->sun_path, J2S(name), sizeof(un->sun_path));
-        if (len >= sizeof(un->sun_path)) {
-            AcrFree(un);
-            un = 0;
-            ACR_THROW(ACR_EX_ERANGE, 0);
-        }
-
-    } DONE_WITH_STR(name);
-    return P2J(un);
-}

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/wpipe.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/wpipe.c?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/wpipe.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/wpipe.c Wed May  4 17:05:43 2011
@@ -23,21 +23,3 @@
 #include "acr/unsafe.h"
 #include "arch_opts.h"
 
-ACR_NET_EXPORT(jstring, LocalSocketAddress, prefix0)(JNI_STDARGS)
-{
-    return WSTR_TO_JSTRING(L"\\\\.\\pipe\\");
-}
-
-ACR_NET_EXPORT(jlong, LocalSocketAddress, addr0)(JNI_STDARGS, jstring name)
-{
-    wchar_t *addr = 0;
-
-    WITH_WSTR(name) {
-        addr = wcsdup(J2S(name));
-        if (addr == 0) {
-            ACR_THROW(ACR_EX_ENOMEM, 0);
-        }
-
-    } DONE_WITH_STR(name);
-    return P2J(addr);
-}

Modified: commons/sandbox/runtime/trunk/src/main/native/shared/error.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/error.c?rev=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/error.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/error.c Wed May  4 17:05:43 2011
@@ -36,6 +36,8 @@ static struct {
     { 0, "java/lang/NullPointerException"                       }, /* EISNULL   */
     { 0, "java/lang/UnsupportedOperationException"              }, /* ENOSYS    */
     { 0, "java/io/IOException"                                  }, /* I/O Error */
+    { 0, "java/net/SocketException"                             }, /* Net Error */
+    { 0, "java/net/UnknownHostException"                        }, /* Net Error */
 
     { 0, ACR_IO_CP      "InvalidDescriptorException"            }, /* EBADF     */
     { 0, ACR_CLASS_PATH "AccessDeniedException"                 }, /* EACCESS   */

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=1099521&r1=1099520&r2=1099521&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c Wed May  4 17:05:43 2011
@@ -38,7 +38,9 @@
 # else
 #  define SET_H_ERRNO(newval) h_errno = (newval)
 # endif
+# define ACR_SOCKET(s) (s)
 #else
+# define ACR_SOCKET(s) (SOCKET)(s)
 # define SET_H_ERRNO(newval)
 #endif
 
@@ -378,6 +380,54 @@ AcrInetPton(int af, const char *src, voi
     /* NOTREACHED */
 }
 
+int
+AcrGetSockaddrIp(char *buf, int buflen, acr_sockaddr_t *sockaddr)
+{
+    if (AcrInetNtop(sockaddr->family, sockaddr->ipaddr, buf, buflen) == 0)
+        return ACR_ENOSPC;
+    if (sockaddr->family == AF_INET6 &&
+        IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr) &&
+        buflen > 7) {
+        /* Number 7 here is strlen("::ffff:") */    
+        /* This is an IPv4-mapped IPv6 address; drop the leading
+         * part of the address string so we're left with the familiar
+         * IPv4 format.
+         */
+        memmove(buf, buf + 7, strlen(buf + 7) + 1);
+    }
+    /* ensure NUL termination if the buffer is too short
+     */
+    buf[buflen - 1] = '\0';
+    return 0;
+}
+
+int
+AcrGetLocalAddr(int sockfd, acr_sockaddr_t *sockaddr)
+{
+    socklen_t salen = sizeof(sockaddr->sa);
+    if (getsockname(ACR_SOCKET(sockfd), (struct sockaddr *)&sockaddr->sa, &salen) < 0) {
+        return ACR_GET_NETOS_ERROR();
+    }
+    else {
+        /* XXX assumes sin_port and sin6_port at same offset */
+        sockaddr->port = ntohs(sockaddr->sa.sin.sin_port);
+        return 0;
+    }
+}
+
+int
+AcrGetRemoteAddr(int sockfd, acr_sockaddr_t *sockaddr)
+{
+    socklen_t salen = sizeof(sockaddr->sa);
+    if (getpeername(ACR_SOCKET(sockfd), (struct sockaddr *)&sockaddr->sa, &salen) < 0) {
+        return ACR_GET_NETOS_ERROR();
+    }
+    else {
+        /* XXX assumes sin_port and sin6_port at same offset */
+        sockaddr->port = ntohs(sockaddr->sa.sin.sin_port);
+        return 0;
+    }
+}
 
 static void
 sockaddr_vars_set(acr_sockaddr_t *addr, int family, int port)
@@ -496,11 +546,11 @@ call_resolver(acr_sockaddr_t **sa, const
 
         if (!prev_sa) { /* first element in new list */
             if (hostname != 0)
-                strlcpy(new_sa->hostname, hostname, 256);
+                strlcpy(new_sa->hostname, hostname, NI_MAXHOST);
             *sa = new_sa;
         }
         else {
-            strlcpy(new_sa->hostname, prev_sa->hostname, 256);
+            strlcpy(new_sa->hostname, prev_sa->hostname, NI_MAXHOST);
             prev_sa->next = new_sa;
         }
 
@@ -537,8 +587,13 @@ AcrGetSockaddrInfo(acr_sockaddr_t **sa, 
                    int family, int port, int flags)
 {
     int masked;
+#if defined(WINDOWS)
+    char *np;
+#endif
     *sa = 0;
 
+    /* TODO: Move the param checks to java code
+     */
     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)) {
@@ -566,7 +621,14 @@ AcrGetSockaddrInfo(acr_sockaddr_t **sa, 
             *sa = calloc(1, sizeof(acr_sockaddr_t));
             if (*sa == 0)
                 return ACR_ENOMEM;
-            strlcpy((*sa)->hostname, hostname, sizeof((*sa)->hostname));
+            strlcpy((*sa)->hostname, "\\\\.\\pipe\\", sizeof((*sa)->hostname));
+            strlcat((*sa)->hostname, hostname, sizeof((*sa)->hostname));
+            np = (*sa)->hostname + 9;
+            while (*np != '\0') {
+                if (*np == '/' || *np == '\\'|| *np == ' ')
+                    *np = '_';
+                np++;
+            }
             (*sa)->family  = AF_LOCAL;
             (*sa)->addrlen = ISIZEOF((*sa)->hostname);
             (*sa)->ipaddr  = &((*sa)->hostname);
@@ -585,6 +647,17 @@ AcrGetSockaddrInfo(acr_sockaddr_t **sa, 
     return find_addresses(sa, hostname, family, port, flags);
 }
 
+void
+AcrFreeSockaddr(acr_sockaddr_t *sa)
+{
+    acr_sockaddr_t *sp = sa;
+    while (sp != 0) {
+        sa = sp->next;
+        AcrFree(sp);
+        sp = sa;
+    }
+}
+
 int
 AcrIsSockaddrEqual(const acr_sockaddr_t *addr1,
                    const acr_sockaddr_t *addr2)
@@ -606,9 +679,6 @@ int
 AcrGetNameInfo(char **hostname, acr_sockaddr_t *sockaddr, int flags)
 {
     int rc;
-#if !defined(NI_MAXHOST)
-# define NI_MAXHOST 256
-#endif
     char tmphostname[NI_MAXHOST];
 
     /* don't know if it is portable for getnameinfo() to set h_errno;
@@ -666,7 +736,100 @@ AcrGetNameInfo(char **hostname, acr_sock
             return rc + ACR_OS_START_EAIERR; /* return the EAI_ error */
         }
     }
-    strlcpy(sockaddr->hostname, tmphostname, 256);
+    strlcpy(sockaddr->hostname, tmphostname, NI_MAXHOST);
     *hostname = sockaddr->hostname;
     return 0;
 }
+
+ACR_NET_EXPORT(jlong, AbstractSocketAddress, alloc0)(JNI_STDARGS)
+{
+    return P2J(ACR_TALLOC(acr_sockaddr_t));
+}
+
+ACR_NET_EXPORT(void, AbstractSocketAddress, free0)(JNI_STDARGS, jlong sa)
+{
+    AcrFreeSockaddr(J2P(sa, acr_sockaddr_t *));
+}
+
+ACR_NET_EXPORT(jstring, AbstractSocketAddress, hostname0)(JNI_STDARGS, jlong sa)
+{
+    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);  
+    if (a->hostname != '\0')
+        return AcrNewJavaStringA(env, a->hostname);
+    else
+        return 0;
+}
+
+ACR_NET_EXPORT(jstring, AbstractSocketAddress, servname0)(JNI_STDARGS, jlong sa)
+{
+    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
+    if (a->servname != '\0')
+        return AcrNewJavaStringA(env, a->servname);
+    else
+        return 0;
+}
+
+ACR_NET_EXPORT(jstring, AbstractSocketAddress, ipaddr0)(JNI_STDARGS, jlong sa)
+{
+    char buf[256];
+    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
+
+    if (AcrGetSockaddrIp(buf, 256, a) == 0)
+        return AcrNewJavaStringA(env, buf);
+    else {
+        ACR_THROW(ACR_EX_ENOMEM, ACR_ENOSPC);
+        return 0;
+    }
+}
+
+ACR_NET_EXPORT(jint, AbstractSocketAddress, port0)(JNI_STDARGS, jlong sa)
+{
+    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
+    return a->port;
+}
+
+ACR_NET_EXPORT(jint, AbstractSocketAddress, family0)(JNI_STDARGS, jlong sa)
+{
+    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
+    switch (a->family) {
+        case AF_INET:
+            return 1;
+        case AF_INET6:
+            return 2;
+        case AF_LOCAL:
+            return 3;
+        default:
+        break;
+    }
+    return 0;
+}
+
+ACR_NET_EXPORT(jlong, AbstractSocketAddress, geti0)(JNI_STDARGS, jstring hostname,
+                                                    jint family, jint port, jint flags)
+{
+    acr_sockaddr_t *sa = 0;
+    int ffamily = AF_UNSPEC;
+    int rc = 0;
+
+    switch (family) {
+        case 1:
+            ffamily = AF_INET;
+        break;    
+        case 2:
+            ffamily = AF_INET6;
+        break;
+        case 3:
+            ffamily = AF_LOCAL;
+        break;
+    }
+    WITH_CSTR(hostname) {
+        rc = AcrGetSockaddrInfo(&sa, J2S(hostname), ffamily, port, flags);
+    } DONE_WITH_STR(hostname);
+
+    if (rc != 0) {
+        /* XXX: Throw UnknownHostException?
+         */
+        ACR_THROW(ACR_EX_EHOST, rc);
+    }
+    return P2J(sa);
+}