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); +}