summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.native17
-rw-r--r--configure.ac2
-rw-r--r--m4/gcc_attribute.m4133
-rw-r--r--native/jni/java-net/javanet.c6
-rw-r--r--native/jni/native-lib/cpnet.c658
-rw-r--r--native/jni/native-lib/cpnet.h9
6 files changed, 818 insertions, 7 deletions
diff --git a/ChangeLog.native b/ChangeLog.native
index d036fae9f..b5a2d51a9 100644
--- a/ChangeLog.native
+++ b/ChangeLog.native
@@ -1,5 +1,22 @@
2006-02-19 Guilhem Lavaux <guilhem@kaffe.org>
+ * configure.ac: Invoke GCC_ATTRIBUTE_UNUSED.
+
+ * m4/gcc_attribute.m4: New file from ac_archive.
+
+ * native/jni/java-net/javanet.c: Adapted to cpnet API
+ modification.
+
+ * native/jni/native-lib/cpnet.c: Implemented.
+
+ * native/jni/native-lib/cpnet.h
+ (cpnet_openSocketDatagram,
+ cpnet_openSocketStream): These calls need an address family now.
+ (cpnet_IPV4AddressToBytes,
+ cpnet_bytesToIPV4Address): Convert the address to network order.
+
+2006-02-19 Guilhem Lavaux <guilhem@kaffe.org>
+
* native/jni/java-io/java_io_VMFile.c,
native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c,
native/jni/midi-dssi/dssi_data.h,
diff --git a/configure.ac b/configure.ac
index a19fead0f..4c27c0d0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -235,6 +235,8 @@ AC_PROG_CC
AC_PROG_CPP
if test "x${COMPILE_JNI}" = xyes; then
+ GCC_ATTRIBUTE_UNUSED
+
AC_HEADER_STDC
dnl Checking sizeof void * is needed for fdlibm to work properly on ppc64,
diff --git a/m4/gcc_attribute.m4 b/m4/gcc_attribute.m4
new file mode 100644
index 000000000..f0c25722b
--- /dev/null
+++ b/m4/gcc_attribute.m4
@@ -0,0 +1,133 @@
+dnl CACHED_TRY_COMPILE(<description>,<cachevar>,<include>,<program>,<ifyes>,<ifno>)
+AC_DEFUN([CACHED_TRY_COMPILE],[
+ AC_MSG_CHECKING($1)
+ AC_CACHE_VAL($2,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$3]], [[$4]])],[$2=yes],[$2=no])
+ ])
+ if test "x$$2" = xyes; then
+ true
+ $5
+ else
+ true
+ $6
+ fi
+])
+
+dnl GCC_ATTRIBUTE(<short-label>,<cachevar>,<func-params>,<attribute>,<HAVE>,<desc>,[<true-cmds>],[<false-cmds>])
+AC_DEFUN([GCC_ATTRIBUTE],[
+ CACHED_TRY_COMPILE(__attribute__(($1)),cv_c_gcc_attribute_$2,,
+ [extern int testfunction($3) __attribute__(($4))],
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GNUC25_$5,,$6)
+ $7,
+ AC_MSG_RESULT(no)
+ $8)
+])
+
+
+AC_DEFUN([GCC_ATTRIBUTE_SUPPORTED],[
+ GCC_ATTRIBUTE([,,],supported,[int x],[,,],ATTRIB,[Define if function attributes a la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C attributes. */
+#ifndef FUNCATTR
+#ifdef HAVE_GNUC25_ATTRIB
+#define FUNCATTR(x) __attribute__(x)
+#else
+#define FUNCATTR(x)
+#endif
+#endif])
+
+])
+AC_DEFUN([GCC_ATTRIBUTE_CONST],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(const,const,[int x],const,CONST,[Define if constant functions a la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C constant functions, or null. */
+#ifndef ATTRCONST
+#ifdef HAVE_GNUC25_CONST
+#define ATTRCONST const
+#else
+#define ATTRCONST
+#endif
+#endif
+#ifndef CONSTANT
+#define CONSTANT FUNCATTR((ATTRCONST))
+#endif])
+])
+AC_DEFUN([GCC_ATTRIBUTE_NORETURN],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(noreturn,noreturn,[int x],noreturn,NORETURN,[Define if nonreturning functions a la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C nonreturning functions, or null. */
+#ifndef ATTRNORETURN
+#ifdef HAVE_GNUC25_NORETURN
+#define ATTRNORETURN noreturn
+#else /* ! HAVE_GNUC25_NORETURN */
+#define ATTRNORETURN
+#endif /* HAVE_GNUC25_NORETURN */
+#endif /* ATTRNORETURN */
+#ifndef NONRETURNING
+#define NONRETURNING FUNCATTR((ATTRNORETURN))
+#endif /* NONRETURNING */])
+])
+AC_DEFUN([GCC_ATTRIBUTE_UNUSED],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(unused,unused,[int x],unused,UNUSED,[Define if unused variables la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C unused functions, or null. */
+#ifndef ATTRUNUSED
+#ifdef HAVE_GNUC25_UNUSED
+#define ATTRUNUSED unused
+#else
+#define ATTRUNUSED
+#endif
+#endif
+#ifndef UNUSED
+#define UNUSED FUNCATTR((ATTRUNUSED))
+#endif])
+])
+AC_DEFUN([GCC_ATTRIBUTE_FORMAT],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(format...,format,[char *y, ...],[format(printf,1,2)],PRINTFFORMAT,[Define if printf-format argument lists a la GCC are available.])
+ AH_BOTTOM([/* GNU C printf formats, or null. */
+#ifndef ATTRPRINTF
+#ifdef HAVE_GNUC25_PRINTFFORMAT
+#define ATTRPRINTF(si,tc) format(printf,si,tc)
+#else
+#define ATTRPRINTF(si,tc)
+#endif
+#endif
+#ifndef PRINTFFORMAT
+#define PRINTFFORMAT(si,tc) FUNCATTR((ATTRPRINTF(si,tc)))
+#endif
+
+#ifndef NONRETURNPRINTFFORMAT
+#define NONRETURNPRINTFFORMAT(si,tc) FUNCATTR((ATTRPRINTF(si,tc),ATTRNORETURN))
+#endif])
+])
+AC_DEFUN([GCC_ATTRIBUTE_ALWAYS_INLINE],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(always_inline,always_inline,[int x],always_inline,ALWAYS_INLINE,[Define if unconditional inlining of functions a la GCC 3.1 and higher are available.])
+ AH_BOTTOM([/* GNU C constant functions, or null. */
+#ifndef ATTRALWAYS_INLINE
+#ifdef HAVE_GNUC25_ALWAYS_INLINE
+#define ATTRALWAYS_INLINE always_inline
+#else
+#define ATTRALWAYS_INLINE
+#endif
+#endif
+#ifndef ALWAYS_INLINE
+#define ALWAYS_INLINE FUNCATTR((ATTRALWAYS_INLINE))
+#endif])
+])
+AC_DEFUN([GCC_ATTRIBUTE_PACKED],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(packed,packed,[int x],packed,PACKED,[Define if packing of struct members a la GCC 2.5 and higher is available.])
+ AH_BOTTOM([/* GNU C constant functions, or null. */
+#ifndef ATTRPACKED
+#ifdef HAVE_GNUC25_PACKED
+#define ATTRPACKED packed
+#else
+#define ATTRPACKED
+#endif
+#endif
+#ifndef PACKED
+#define PACKED FUNCATTR((ATTRPACKED))
+#endif])
+])
diff --git a/native/jni/java-net/javanet.c b/native/jni/java-net/javanet.c
index a79d80fe7..daec03f6b 100644
--- a/native/jni/java-net/javanet.c
+++ b/native/jni/java-net/javanet.c
@@ -430,7 +430,7 @@ _javanet_create (JNIEnv * env, jobject this, jboolean stream)
if (stream)
{
/* create a stream socket */
- result = cpnet_openSocketStream(env, &fd);
+ result = cpnet_openSocketStream(env, &fd, AF_INET);
if (result != CPNATIVE_OK)
{
JCL_ThrowException (env, IO_EXCEPTION,
@@ -441,7 +441,7 @@ _javanet_create (JNIEnv * env, jobject this, jboolean stream)
else
{
/* create a datagram socket, set broadcast option */
- result = cpnet_openSocketDatagram (env, &fd);
+ result = cpnet_openSocketDatagram (env, &fd, AF_INET);
if (result != CPNATIVE_OK)
{
JCL_ThrowException (env, IO_EXCEPTION,
@@ -1376,7 +1376,7 @@ _javanet_get_option (JNIEnv * env, jobject this, jint option_id)
break;
case SOCKOPT_SO_BINDADDR:
- result = cpnet_getBindAddress (env, fd, &address);
+ result = cpnet_getLocalAddr (env, fd, &address);
if (result != CPNATIVE_OK)
{
JCL_ThrowException (env, SOCKET_EXCEPTION,
diff --git a/native/jni/native-lib/cpnet.c b/native/jni/native-lib/cpnet.c
index e69de29bb..d89932049 100644
--- a/native/jni/native-lib/cpnet.c
+++ b/native/jni/native-lib/cpnet.c
@@ -0,0 +1,658 @@
+/* cpnet.c -
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include "config.h"
+#include <jni.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
+
+#include "cpnet.h"
+
+jint cpnet_openSocketStream(JNIEnv *env UNUSED, jint *fd, jint family)
+{
+ *fd = socket(family, SOCK_STREAM, 0);
+ if (*fd == -1)
+ return errno;
+
+ fcntl(*fd, F_SETFD, FD_CLOEXEC);
+ return 0;
+}
+
+jint cpnet_openSocketDatagram(JNIEnv *env UNUSED, jint *fd, jint family)
+{
+ *fd = socket(family, SOCK_DGRAM, 0);
+ if (*fd == -1)
+ return errno;
+
+ fcntl(*fd, F_SETFD, FD_CLOEXEC);
+ return 0;
+}
+
+jint cpnet_shutdown (JNIEnv *env UNUSED, jint fd, jbyte flag)
+{
+ int ret;
+ int shut_flag = 0;
+
+ if (flag == CPNET_SHUTDOWN_READ)
+ shut_flag = SHUT_RD;
+ else if (flag == CPNET_SHUTDOWN_WRITE)
+ shut_flag = SHUT_WR;
+
+ ret = shutdown (fd, shut_flag);
+ if (ret != 0)
+ return errno;
+ return 0;
+}
+
+jint cpnet_close(JNIEnv *env UNUSED, jint fd)
+{
+ if (close (fd) != 0)
+ return errno;
+ return 0;
+}
+
+jint cpnet_listen(JNIEnv *env UNUSED, jint fd, jint queuelen)
+{
+ if (listen (fd, queuelen) != 0)
+ return errno;
+ return 0;
+}
+
+jint cpnet_accept(JNIEnv *env UNUSED, jint fd, jint *newfd)
+{
+ *newfd = accept(fd, NULL, 0);
+ if (*newfd != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_bind(JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
+{
+ int ret;
+
+ ret = bind(fd, (struct sockaddr *)addr->data, addr->len);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_connect(JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
+{
+ int ret;
+
+ ret = connect(fd, (struct sockaddr *)addr->data, addr->len);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getLocalAddr(JNIEnv *env, jint fd, cpnet_address **addr)
+{
+ socklen_t slen = 1024;
+ int ret;
+
+ *addr = JCL_malloc(env, slen);
+
+ slen -= sizeof(jint);
+ ret = getsockname(fd, (struct sockaddr *)(*addr)->data, &slen );
+ if (ret != 0)
+ {
+ int err = errno;
+ JCL_free(env, *addr);
+ return err;
+ }
+
+ (*addr)->len = slen;
+
+ return 0;
+}
+
+jint cpnet_getRemoteAddr(JNIEnv *env, jint fd, cpnet_address **addr)
+{
+ socklen_t slen = 1024;
+ int ret;
+
+ *addr = JCL_malloc(env, slen);
+
+ slen -= sizeof(jint);
+ ret = getpeername(fd, (struct sockaddr *)(*addr)->data, &slen );
+ if (ret != 0)
+ {
+ int err = errno;
+ JCL_free(env, *addr);
+ return err;
+ }
+
+ (*addr)->len = slen;
+
+ return 0;
+}
+
+jint cpnet_setBroadcast(JNIEnv *env UNUSED, jint fd, jint flag)
+{
+ int ret;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_send (JNIEnv *env UNUSED, jint fd, jbyte *data, jint len, jint *bytes_sent)
+{
+ ssize_t ret;
+
+ ret = send(fd, data, len, MSG_NOSIGNAL);
+ if (ret < 0)
+ return errno;
+
+ *bytes_sent = ret;
+
+ return 0;
+}
+
+jint cpnet_sendTo (JNIEnv *env UNUSED, jint fd, jbyte *data, jint len, cpnet_address *addr, jint *bytes_sent)
+{
+ ssize_t ret;
+
+ ret = sendto(fd, data, len, MSG_NOSIGNAL, (struct sockaddr *)addr->data, addr->len);
+ if (ret < 0)
+ return errno;
+
+ *bytes_sent = ret;
+ return 0;
+}
+
+jint cpnet_recv (JNIEnv *env UNUSED, jint fd, jbyte *data, jint len, jint *bytes_recv)
+{
+ ssize_t ret;
+
+ ret = recv(fd, data, len, 0);
+ if (ret < 0)
+ return errno;
+
+ *bytes_recv = ret;
+
+ return 0;
+}
+
+jint cpnet_recvFrom (JNIEnv *env, jint fd, jbyte *data, jint len, cpnet_address **addr, jint *bytes_recv)
+{
+ socklen_t slen = 1024;
+ ssize_t ret;
+
+ *addr = JCL_malloc(env, slen);
+
+ slen -= sizeof(jint);
+ ret = recvfrom(fd, data, len, 0, (struct sockaddr *) (*addr)->data, &slen);
+ if (ret < 0)
+ {
+ int err = errno;
+ JCL_free(env, *addr);
+ return err;
+ }
+
+ (*addr)->len = slen;
+ *bytes_recv = len;
+
+ return 0;
+}
+
+jint cpnet_setSocketTCPNoDelay (JNIEnv *env UNUSED, jint fd, jint nodelay)
+{
+ socklen_t len = sizeof(jint);
+ int ret;
+
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, len);
+ if (ret < 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getSocketTCPNoDelay (JNIEnv *env UNUSED, jint fd, jint *nodelay)
+{
+ socklen_t len = sizeof(jint);
+ int ret;
+
+ ret = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, nodelay, &len);
+ if (ret < 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_setLinger (JNIEnv *env UNUSED, jint fd, jint flag, jint value)
+{
+ socklen_t len = sizeof(struct linger);
+ int ret;
+ struct linger __linger;
+
+ if (flag)
+ {
+ __linger.l_onoff = 0;
+ }
+ else
+ {
+ __linger.l_linger = value;
+ __linger.l_onoff = 1;
+ }
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, &__linger, len);
+ if (ret < 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getLinger (JNIEnv *env UNUSED, jint fd, jint *flag, jint *value)
+{
+ socklen_t slen = sizeof(struct linger);
+ struct linger __linger;
+ int ret;
+
+ ret = getsockopt(fd, SOL_SOCKET, SO_LINGER, &__linger, &slen);
+ if (ret != 0)
+ return errno;
+
+ *flag = __linger.l_onoff;
+ *value = __linger.l_linger;
+
+ return ret;
+}
+
+jint cpnet_setSocketTimeout (JNIEnv *env UNUSED, jint fd UNUSED, jint value UNUSED)
+{
+#if 0
+ /* This is not really the right default implementation. This will have to
+ * be changed. Most OSes do not completely/rightfully support SO_TIMEOUT.
+ */
+ struct timeval tval;
+ int ret;
+
+ tval.tv_sec = value / 1000;
+ tval.tv_usec = (value % 1000) * 1000;
+ ret = setsockopt (fd, SOL_SOCKET, SO_TIMEOUT, &tval, sizeof(tval));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+#else
+ return ENOSYS;
+#endif
+}
+
+jint cpnet_getSocketTimeout (JNIEnv *env UNUSED, jint fd UNUSED, jint *value UNUSED)
+{
+#if 0
+ /* This is not really the right default implementation. This will have to
+ * be changed. Most OSes do not completely/rightfully support SO_TIMEOUT.
+ */
+ struct timeval tval;
+ int ret;
+
+ ret = getsockopt (fd, SOL_SOCKET, SO_TIMEOUT, &tval, sizeof(tval));
+ if (ret != 0)
+ return errno;
+
+ *value = (tval.tv_sec * 1000) + (tval.tv_usec / 1000);
+
+ return 0;
+#else
+ return ENOSYS;
+#endif
+}
+
+jint cpnet_setSendBuf (JNIEnv *env UNUSED, jint fd, jint value)
+{
+ int ret;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getSendBuf (JNIEnv *env UNUSED, jint fd, jint *value)
+{
+ int ret;
+ socklen_t slen = sizeof(*value);
+
+ ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, value, &slen);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_setRecvBuf (JNIEnv *env UNUSED, jint fd, jint value)
+{
+ int ret;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getRecvBuf (JNIEnv *env UNUSED, jint fd, jint *value)
+{
+ int ret;
+ socklen_t slen = sizeof(*value);
+
+ ret = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, value, &slen);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_setTTL (JNIEnv *env UNUSED, jint fd, jint value)
+{
+ int ret;
+
+ ret = setsockopt(fd, IPPROTO_IP, IP_TTL, &value, sizeof(value));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getTTL (JNIEnv *env UNUSED, jint fd, jint *value)
+{
+ int ret;
+ socklen_t slen = sizeof(*value);
+
+ ret = getsockopt(fd, IPPROTO_IP, IP_TTL, value, &slen);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_setMulticastIF (JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
+{
+ int ret;
+
+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (struct sockaddr *)addr->data, addr->len);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getMulticastIF (JNIEnv *env, jint fd, cpnet_address **addr)
+{
+ socklen_t slen = 1024;
+ int ret;
+
+ *addr = JCL_malloc(env, slen);
+
+ slen -= sizeof(jint);
+ ret = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (struct sockaddr *)(*addr)->data, &slen);
+ (*addr)->len = slen;
+
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_setReuseAddress (JNIEnv *env UNUSED, jint fd, jint reuse)
+{
+ int ret;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getReuseAddress (JNIEnv *env UNUSED, jint fd, jint *reuse)
+{
+ int ret;
+ socklen_t slen = sizeof(*reuse);
+
+ ret = getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reuse, &slen);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_setKeepAlive (JNIEnv *env UNUSED, jint fd, jint keep)
+{
+ int ret;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep, sizeof(keep));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getKeepAlive (JNIEnv *env UNUSED, jint fd, jint *keep)
+{
+ int ret;
+ socklen_t slen = sizeof(*keep);
+
+ ret = getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, keep, &slen);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_addMembership (JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
+{
+ struct ip_mreq req;
+ int ret;
+
+ memset(&req, 0, sizeof(req));
+ req.imr_multiaddr = ((struct sockaddr_in *)addr->data)->sin_addr;
+ req.imr_interface.s_addr = INADDR_ANY;
+ ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_dropMembership (JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
+{
+ struct ip_mreq req;
+ int ret;
+
+ memset(&req, 0, sizeof(req));
+ req.imr_multiaddr = ((struct sockaddr_in *)addr->data)->sin_addr;
+ req.imr_interface.s_addr = INADDR_ANY;
+ ret = setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &req, sizeof(req));
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getAvailableBytes (JNIEnv *env UNUSED, jint fd, jint *availableBytes)
+{
+ int ret;
+
+ ret = ioctl(fd, FIONREAD, availableBytes);
+ if (ret != 0)
+ return errno;
+
+ return 0;
+}
+
+jint cpnet_getHostname (JNIEnv *env UNUSED, char *hostname, jint hostname_len)
+{
+ int ret;
+
+ ret = gethostname(hostname, hostname_len);
+ if (ret != 0)
+ return errno;
+
+ hostname[hostname_len-1] = 0;
+ return 0;
+}
+
+jint cpnet_getHostByName (JNIEnv *env, const char *hostname, cpnet_address ***addresses, jint *addresses_count)
+{
+ struct hostent hret;
+ struct hostent *result;
+ jint buflen = 1024;
+ int herr;
+ int ret;
+ int counter = 0;
+ cpnet_address **addr_arr;
+ int i;
+ char *buf;
+
+ do
+ {
+ buf = (char *)JCL_malloc(env, buflen);
+ ret = gethostbyname_r (hostname, &hret, buf, buflen, &result, &herr);
+ if (ret != 0)
+ {
+ if (herr == ERANGE)
+ {
+ buflen *= 2;
+ JCL_free(env, buf);
+ continue;
+ }
+ JCL_free(env, buf);
+
+ return herr;
+ }
+
+ break;
+ }
+ while (1);
+
+ while (hret.h_addr_list[counter] != NULL)
+ counter++;
+
+ *addresses_count = counter;
+ addr_arr = *addresses = JCL_malloc(env, sizeof(cpnet_address *) * counter);
+ switch (hret.h_addrtype)
+ {
+ case AF_INET:
+ for (i = 0; i < counter; i++)
+ {
+ addr_arr[i] = cpnet_newIPV4Address(env);
+ cpnet_bytesToIPV4Address(addr_arr[i], (jbyte *)hret.h_addr_list[counter]);
+ }
+ break;
+ case AF_INET6:
+ for (i = 0; i < counter; i++)
+ {
+ addr_arr[i] = cpnet_newIPV6Address(env);
+ cpnet_bytesToIPV6Address(addr_arr[i], (jbyte *)hret.h_addr_list[counter]);
+ }
+ break;
+ default:
+ *addresses_count = 0;
+ JCL_free(env, addr_arr);
+ break;
+ }
+
+ JCL_free(env, buf);
+
+ return 0;
+}
+
+jint cpnet_getHostByAddr (JNIEnv *env UNUSED, cpnet_address *addr, char *hostname, jint hostname_len)
+{
+ union
+ {
+ struct sockaddr_in *addr_v4;
+ struct sockaddr_in6 *addr_v6;
+ char *data;
+ } haddr;
+ void *raw_addr;
+ int addr_type;
+ struct hostent *ret;
+ int addr_len;
+
+ haddr.data = addr->data;
+
+ if (haddr.addr_v4->sin_family == AF_INET)
+ {
+ raw_addr = &haddr.addr_v4->sin_addr;
+ addr_len = sizeof(haddr.addr_v4->sin_addr);
+ addr_type = AF_INET;
+ }
+ else if (haddr.addr_v6->sin6_family == AF_INET6)
+ {
+ raw_addr = &haddr.addr_v6->sin6_addr;
+ addr_type = AF_INET6;
+ addr_len = sizeof(haddr.addr_v6->sin6_addr);
+ }
+ else
+ return EINVAL;
+
+ /* Here we do not have any thread safe call. VM implementors will have to
+ * do a big lock. Or it should be put on the Classpath VM interface.
+ */
+ ret = gethostbyaddr(raw_addr, addr_len, addr_type);
+ if (ret == NULL)
+ {
+ /* The trouble here is how to distinguish the two cases ? */
+ if (h_errno != 0)
+ return h_errno;
+ else
+ return errno;
+
+ }
+ strncpy(hostname, ret->h_name, hostname_len);
+
+ return 0;
+}
diff --git a/native/jni/native-lib/cpnet.h b/native/jni/native-lib/cpnet.h
index 85a287a33..a4aa8f15c 100644
--- a/native/jni/native-lib/cpnet.h
+++ b/native/jni/native-lib/cpnet.h
@@ -40,6 +40,7 @@ exception statement from your version. */
#include <jni.h>
#include <jcl.h>
+#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -53,8 +54,8 @@ typedef struct {
#define CPNET_SHUTDOWN_READ 1
#define CPNET_SHUTDOWN_WRITE 2
-JNIEXPORT jint cpnet_openSocketStream(JNIEnv *env, jint *fd);
-JNIEXPORT jint cpnet_openSocketDatagram(JNIEnv *env, jint *fd);
+JNIEXPORT jint cpnet_openSocketStream(JNIEnv *env, jint *fd, jint family);
+JNIEXPORT jint cpnet_openSocketDatagram(JNIEnv *env, jint *fd, jint family);
JNIEXPORT jint cpnet_shutdown (JNIEnv *env, jint fd, jbyte flag);
JNIEXPORT jint cpnet_close(JNIEnv *env, jint fd);
JNIEXPORT jint cpnet_listen(JNIEnv *env, jint fd, jint queuelen);
@@ -175,7 +176,7 @@ static inline jboolean cpnet_isIPV4Address(cpnet_address *addr)
static inline void cpnet_IPV4AddressToBytes(cpnet_address *netaddr, jbyte *octets)
{
struct sockaddr_in *ipaddr = (struct sockaddr_in *)&(netaddr->data[0]);
- jint sysaddr = ipaddr->sin_addr.s_addr;
+ jint sysaddr = ntohl(ipaddr->sin_addr.s_addr);
octets[0] = (sysaddr >> 24) & 0xff;
octets[1] = (sysaddr >> 16) & 0xff;
@@ -193,7 +194,7 @@ static inline void cpnet_bytesToIPV4Address(cpnet_address *netaddr, jbyte *octet
sysaddr |= ((jint)octets[2]) << 8;
sysaddr |= ((jint)octets[3]);
- ipaddr->sin_addr.s_addr = sysaddr;
+ ipaddr->sin_addr.s_addr = htonl(sysaddr);
}
static inline void cpnet_IPV6AddressToBytes(cpnet_address *netaddr, jbyte *octets)