Commit 71a15b15 by Michael Koch Committed by Michael Koch

configure.in: Fixed links to platform dependant java.net files.

2003-03-18  Michael Koch  <konqueror@gmx.de>

	* configure.in: Fixed links to platform dependant java.net files.
	* configure: Regenerated.
	* java/net/natInetAddress.cc,
	java/net/natNetworkInterface.cc,
	java/net/natPlainDatagramSocketImpl.cc,
	java/net/natPlainSocketImpl.cc:
	Removed.

From-SVN: r64527
parent 9b5f18b1
2003-03-18 Michael Koch <konqueror@gmx.de>
* configure.in: Fixed links to platform dependant java.net files.
* configure: Regenerated.
* java/net/natInetAddress.cc,
java/net/natNetworkInterface.cc,
java/net/natPlainDatagramSocketImpl.cc,
java/net/natPlainSocketImpl.cc:
Removed.
2003-03-18 Michael Koch <konqueror@gmx.de>
* configure.in: Create links to architecture dependent files,
introduced PLATFORMNET variable (set to NoNet for newlib usage).
* configure: Regenerated.
......
......@@ -9136,7 +9136,7 @@ EOF
cat >> $CONFIG_STATUS <<EOF
ac_sources="include/$PLATFORMH java/io/natFile${FILE-${PLATFORM}}.cc java/io/natFileDescriptor${FILE-${PLATFORM}}.cc java/lang/${PLATFORM}Process.java java/lang/nat${PLATFORM}Process.cc java/net/natInetAddress${PLATFORMNET}.cc java/net/natNetworkInterface${PLATFORMNET}.cc java/net/natPlainSocketImpl${PLATFORMNET}.cc java/net/natPlainDatagramSocketImpl${PLATFORMNET}.cc include/$GCHDR include/$THREADH sysdep/$sysdeps_dir/locks.h $SIGNAL_HANDLER"
ac_dests="include/platform.h java/io/natFile.cc java/io/natFileDescriptor.cc java/lang/ConcreteProcess.java java/lang/natConcreteProcess.cc java/lang/natInetAddress.cc java/lang/natNetworkInterface.cc java/lang/natPlainSocketImpl.cc java/lang/natPlainDatagramSocketImpl.cc include/java-gc.h include/java-threads.h sysdep/locks.h include/java-signal.h"
ac_dests="include/platform.h java/io/natFile.cc java/io/natFileDescriptor.cc java/lang/ConcreteProcess.java java/lang/natConcreteProcess.cc java/net/natInetAddress.cc java/net/natNetworkInterface.cc java/net/natPlainSocketImpl.cc java/net/natPlainDatagramSocketImpl.cc include/java-gc.h include/java-threads.h sysdep/locks.h include/java-signal.h"
EOF
cat >> $CONFIG_STATUS <<\EOF
......
......@@ -275,10 +275,10 @@ AC_LINK_FILES(java/lang/nat${PLATFORM}Process.cc, java/lang/natConcreteProcess.c
dnl Likewise for natInetAddress.cc, natNetworkInterface.cc, natPlainSocketImpl.cc
dnl and natPlainDatagramSocketImpl.cc
test -d java/net || mkdir java/net
AC_LINK_FILES(java/net/natInetAddress${PLATFORMNET}.cc, java/lang/natInetAddress.cc)
AC_LINK_FILES(java/net/natNetworkInterface${PLATFORMNET}.cc, java/lang/natNetworkInterface.cc)
AC_LINK_FILES(java/net/natPlainSocketImpl${PLATFORMNET}.cc, java/lang/natPlainSocketImpl.cc)
AC_LINK_FILES(java/net/natPlainDatagramSocketImpl${PLATFORMNET}.cc, java/lang/natPlainDatagramSocketImpl.cc)
AC_LINK_FILES(java/net/natInetAddress${PLATFORMNET}.cc, java/net/natInetAddress.cc)
AC_LINK_FILES(java/net/natNetworkInterface${PLATFORMNET}.cc, java/net/natNetworkInterface.cc)
AC_LINK_FILES(java/net/natPlainSocketImpl${PLATFORMNET}.cc, java/net/natPlainSocketImpl.cc)
AC_LINK_FILES(java/net/natPlainDatagramSocketImpl${PLATFORMNET}.cc, java/net/natPlainDatagramSocketImpl.cc)
case "${host}" in
*mingw*)
......
// natInetAddress.cc
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#undef STRICT
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif /* MAXHOSTNAMELEN */
#else /* WIN32 */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#endif /* WIN32 */
#include <gcj/cni.h>
#include <jvm.h>
#include <java/net/InetAddress.h>
#include <java/net/UnknownHostException.h>
#include <java/lang/SecurityException.h>
#if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME)
#include <sys/utsname.h>
#endif
#ifndef HAVE_GETHOSTNAME_DECL
extern "C" int gethostname (char *name, int namelen);
#endif
#ifdef DISABLE_JAVA_NET
jbyteArray
java::net::InetAddress::aton (jstring)
{
return NULL;
}
jint
java::net::InetAddress::getFamily (jbyteArray bytes)
{
return 0;
}
JArray<java::net::InetAddress*> *
java::net::InetAddress::lookup (jstring, java::net::InetAddress *, jboolean)
{
return NULL;
}
jstring
java::net::InetAddress::getLocalHostname ()
{
return NULL;
}
#else /* DISABLE_JAVA_NET */
jbyteArray
java::net::InetAddress::aton (jstring host)
{
char *hostname;
char buf[100];
int len = JvGetStringUTFLength(host);
if (len < 100)
hostname = buf;
else
hostname = (char*) _Jv_AllocBytes (len+1);
JvGetStringUTFRegion (host, 0, host->length(), hostname);
buf[len] = '\0';
char* bytes = NULL;
int blen = 0;
#ifdef HAVE_INET_ATON
struct in_addr laddr;
if (inet_aton (hostname, &laddr))
{
bytes = (char*) &laddr;
blen = 4;
}
#elif defined(HAVE_INET_ADDR)
#if ! HAVE_IN_ADDR_T
typedef jint in_addr_t;
#endif
in_addr_t laddr = inet_addr (hostname);
if (laddr != (in_addr_t)(-1))
{
bytes = (char*) &laddr;
blen = 4;
}
#endif
#if defined (HAVE_INET_PTON) && defined (HAVE_INET6)
char inet6_addr[16];
if (len != 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0)
{
bytes = inet6_addr;
blen = 16;
}
#endif
if (blen == 0)
return NULL;
jbyteArray result = JvNewByteArray (blen);
memcpy (elements (result), bytes, blen);
return result;
}
jint
java::net::InetAddress::getFamily (jbyteArray bytes)
{
int len = bytes->length;
if (len == 4)
return AF_INET;
#ifdef HAVE_INET6
else if (len == 16)
return AF_INET6;
#endif /* HAVE_INET6 */
else
JvFail ("unrecognized size");
}
JArray<java::net::InetAddress*> *
java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr,
jboolean all)
{
struct hostent *hptr = NULL;
#if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R)
struct hostent hent_r;
#if HAVE_STRUCT_HOSTENT_DATA
struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer;
#else
#if defined (__GLIBC__)
// FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and
// ERANGE to errno if the buffer size is too small, rather than what is
// expected here. We work around this by setting a bigger buffer size and
// hoping that it is big enough.
char fixed_buffer[1024];
#else
char fixed_buffer[200];
#endif
char *buffer_r = fixed_buffer;
int size_r = sizeof (fixed_buffer);
#endif
#endif
if (host != NULL)
{
char *hostname;
char buf[100];
int len = JvGetStringUTFLength(host);
if (len < 100)
hostname = buf;
else
hostname = (char*) _Jv_AllocBytes (len+1);
JvGetStringUTFRegion (host, 0, host->length(), hostname);
buf[len] = '\0';
#ifdef HAVE_GETHOSTBYNAME_R
while (true)
{
int ok;
#if HAVE_STRUCT_HOSTENT_DATA
ok = ! gethostbyname_r (hostname, &hent_r, buffer_r);
#else
int herr = 0;
#ifdef GETHOSTBYNAME_R_RETURNS_INT
ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r,
&hptr, &herr);
#else
hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr);
ok = hptr != NULL;
#endif /* GETHOSTNAME_R_RETURNS_INT */
if (! ok && herr == ERANGE)
{
size_r *= 2;
buffer_r = (char *) _Jv_AllocBytes (size_r);
}
else
#endif /* HAVE_STRUCT_HOSTENT_DATA */
break;
}
#else
// FIXME: this is insufficient if some other piece of code calls
// this gethostbyname.
JvSynchronize sync (java::net::InetAddress::localhostAddress);
hptr = gethostbyname (hostname);
#endif /* HAVE_GETHOSTBYNAME_R */
}
else
{
jbyteArray bytes = iaddr->addr;
char *chars = (char*) elements (bytes);
int len = bytes->length;
int type;
char *val;
if (len == 4)
{
val = chars;
type = iaddr->family = AF_INET;
}
#ifdef HAVE_INET6
else if (len == 16)
{
val = (char *) &chars;
type = iaddr->family = AF_INET6;
}
#endif /* HAVE_INET6 */
else
JvFail ("unrecognized size");
#ifdef HAVE_GETHOSTBYADDR_R
while (true)
{
int ok;
#if HAVE_STRUCT_HOSTENT_DATA
ok = ! gethostbyaddr_r (val, len, type, &hent_r, buffer_r);
#else
int herr = 0;
#ifdef GETHOSTBYADDR_R_RETURNS_INT
ok = ! gethostbyaddr_r (val, len, type, &hent_r,
buffer_r, size_r, &hptr, &herr);
#else
hptr = gethostbyaddr_r (val, len, type, &hent_r,
buffer_r, size_r, &herr);
ok = hptr != NULL;
#endif /* GETHOSTBYADDR_R_RETURNS_INT */
if (! ok && herr == ERANGE)
{
size_r *= 2;
buffer_r = (char *) _Jv_AllocBytes (size_r);
}
else
#endif /* HAVE_STRUCT_HOSTENT_DATA */
break;
}
#else /* HAVE_GETHOSTBYADDR_R */
// FIXME: this is insufficient if some other piece of code calls
// this gethostbyaddr.
JvSynchronize sync (java::net::InetAddress::localhostAddress);
hptr = gethostbyaddr (val, len, type);
#endif /* HAVE_GETHOSTBYADDR_R */
}
if (hptr != NULL)
{
if (!all)
host = JvNewStringUTF (hptr->h_name);
java::lang::SecurityException *ex = checkConnect (host);
if (ex != NULL)
{
if (iaddr == NULL || iaddr->addr == NULL)
throw ex;
hptr = NULL;
}
}
if (hptr == NULL)
{
if (iaddr != NULL && iaddr->addr != NULL)
{
iaddr->hostName = iaddr->getHostAddress();
return NULL;
}
else
throw new java::net::UnknownHostException(host);
}
int count;
if (all)
{
char** ptr = hptr->h_addr_list;
count = 0;
while (*ptr++) count++;
}
else
count = 1;
JArray<java::net::InetAddress*> *result;
java::net::InetAddress** iaddrs;
if (all)
{
result = java::net::InetAddress::allocArray (count);
iaddrs = elements (result);
}
else
{
result = NULL;
iaddrs = &iaddr;
}
for (int i = 0; i < count; i++)
{
if (iaddrs[i] == NULL)
iaddrs[i] = new java::net::InetAddress (NULL, NULL);
if (iaddrs[i]->hostName == NULL)
iaddrs[i]->hostName = host;
if (iaddrs[i]->addr == NULL)
{
char *bytes = hptr->h_addr_list[i];
iaddrs[i]->addr = JvNewByteArray (hptr->h_length);
iaddrs[i]->family = getFamily (iaddrs[i]->addr);
memcpy (elements (iaddrs[i]->addr), bytes, hptr->h_length);
}
}
return result;
}
jstring
java::net::InetAddress::getLocalHostname ()
{
char *chars;
#ifdef HAVE_GETHOSTNAME
char buffer[MAXHOSTNAMELEN];
if (gethostname (buffer, MAXHOSTNAMELEN))
return NULL;
chars = buffer;
#elif HAVE_UNAME
struct utsname stuff;
if (uname (&stuff) != 0)
return NULL;
chars = stuff.nodename;
#else
return NULL;
#endif
// It is admittedly non-optimal to convert the hostname to Unicode
// only to convert it back in getByName, but simplicity wins. Note
// that unless there is a SecurityManager, we only get called once
// anyway, thanks to the InetAddress.localhost cache.
return JvNewStringUTF (chars);
}
#endif /* DISABLE_JAVA_NET */
// natNetworkInterface.cc
/* Copyright (C) 2002 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <platform.h>
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#undef STRICT
#else /* WIN32 */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#define BSD_COMP /* Get FIONREAD on Solaris2. */
#include <sys/ioctl.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#endif /* WIN32 */
#include <gcj/cni.h>
#include <jvm.h>
#include <java/net/NetworkInterface.h>
#include <java/net/Inet4Address.h>
#include <java/net/SocketException.h>
#include <java/util/Vector.h>
#ifdef DISABLE_JAVA_NET
::java::util::Vector*
java::net::NetworkInterface::getRealNetworkInterfaces ()
{
::java::util::Vector* ht = new ::java::util::Vector();
return ht;
}
#else /* DISABLE_JAVA_NET */
::java::util::Vector*
java::net::NetworkInterface::getRealNetworkInterfaces ()
{
#ifdef WIN32
throw new ::java::net::SocketException;
#else
int fd;
int num_interfaces = 0;
struct ifconf if_data;
struct ifreq* if_record;
::java::util::Vector* ht = new ::java::util::Vector ();
if_data.ifc_len = 0;
if_data.ifc_buf = NULL;
// Open a (random) socket to have a file descriptor for the ioctl calls.
fd = _Jv_socket (PF_INET, SOCK_DGRAM, htons (IPPROTO_IP));
if (fd < 0)
throw new ::java::net::SocketException;
// Get all interfaces. If not enough buffers are available try it
// with a bigger buffer size.
do
{
num_interfaces += 16;
if_data.ifc_len = sizeof (struct ifreq) * num_interfaces;
if_data.ifc_buf =
(char*) _Jv_Realloc (if_data.ifc_buf, if_data.ifc_len);
// Try to get all local interfaces.
if (::ioctl (fd, SIOCGIFCONF, &if_data) < 0)
throw new java::net::SocketException;
}
while (if_data.ifc_len >= (sizeof (struct ifreq) * num_interfaces));
// Get addresses of all interfaces.
if_record = if_data.ifc_req;
for (int n = 0; n < if_data.ifc_len; n += sizeof (struct ifreq))
{
struct ifreq ifr;
memset (&ifr, 0, sizeof (ifr));
strcpy (ifr.ifr_name, if_record->ifr_name);
// Try to get the IPv4-address of the local interface
if (::ioctl (fd, SIOCGIFADDR, &ifr) < 0)
throw new java::net::SocketException;
int len = 4;
struct sockaddr_in sa = *((sockaddr_in*) &(ifr.ifr_addr));
jbyteArray baddr = JvNewByteArray (len);
memcpy (elements (baddr), &(sa.sin_addr), len);
jstring if_name = JvNewStringLatin1 (if_record->ifr_name);
Inet4Address* address =
new java::net::Inet4Address (baddr, JvNewStringLatin1 (""));
ht->add (new NetworkInterface (if_name, address));
if_record++;
}
#ifdef HAVE_INET6
// FIXME: read /proc/net/if_inet6 (on Linux 2.4)
#endif
_Jv_Free (if_data.ifc_buf);
if (fd >= 0)
_Jv_close (fd);
return ht;
#endif /* WIN32 */
}
#endif // DISABLE_JAVA_NET //
/* Copyright (C) 1999, 2000, 2002 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <platform.h>
#ifdef WIN32
#include <errno.h>
#include <string.h>
#else /* WIN32 */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <errno.h>
#include <string.h>
#endif /* WIN32 */
#if HAVE_BSTRING_H
// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
#include <bstring.h>
#endif
#include <gcj/cni.h>
#include <java/io/IOException.h>
#include <java/io/InterruptedIOException.h>
#include <java/net/BindException.h>
#include <java/net/SocketException.h>
#include <java/net/PlainDatagramSocketImpl.h>
#include <java/net/InetAddress.h>
#include <java/net/NetworkInterface.h>
#include <java/net/DatagramPacket.h>
#include <java/net/PortUnreachableException.h>
#include <java/lang/InternalError.h>
#include <java/lang/Object.h>
#include <java/lang/Boolean.h>
#include <java/lang/Integer.h>
#ifdef DISABLE_JAVA_NET
void
java::net::PlainDatagramSocketImpl::create ()
{
throw new SocketException (
JvNewStringLatin1 ("DatagramSocketImpl.create: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::bind (jint, java::net::InetAddress *)
{
throw new BindException (
JvNewStringLatin1 ("DatagramSocketImpl.bind: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint)
{
throw new SocketException (
JvNewStringLatin1 ("DatagramSocketImpl.connect: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::disconnect ()
{
throw new SocketException (
JvNewStringLatin1 ("DatagramSocketImpl.disconnect: unimplemented"));
}
jint
java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *)
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.peek: unimplemented"));
}
jint
java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *)
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.peekData: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::close ()
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.close: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *)
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.send: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *)
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.receive: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::setTimeToLive (jint)
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.setTimeToLive: unimplemented"));
}
jint
java::net::PlainDatagramSocketImpl::getTimeToLive ()
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.getTimeToLive: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *,
java::net::NetworkInterface *,
jboolean)
{
throw new java::io::IOException (
JvNewStringLatin1 ("DatagramSocketImpl.mcastGrp: unimplemented"));
}
void
java::net::PlainDatagramSocketImpl::setOption (jint, java::lang::Object *)
{
throw new SocketException (
JvNewStringLatin1 ("DatagramSocketImpl.setOption: unimplemented"));
}
java::lang::Object *
java::net::PlainDatagramSocketImpl::getOption (jint)
{
throw new SocketException (
JvNewStringLatin1 ("DatagramSocketImpl.getOption: unimplemented"));
}
#else /* DISABLE_JAVA_NET */
union SockAddr
{
struct sockaddr_in address;
#ifdef HAVE_INET6
struct sockaddr_in6 address6;
#endif
};
union McastReq
{
#if HAVE_STRUCT_IP_MREQ
struct ip_mreq mreq;
#endif
#if HAVE_STRUCT_IPV6_MREQ
struct ipv6_mreq mreq6;
#endif
};
union InAddr
{
struct in_addr addr;
#ifdef HAVE_INET6
struct in6_addr addr6;
#endif
};
// FIXME: routines here and/or in natPlainSocketImpl.cc could throw
// NoRouteToHostException; also consider UnknownHostException, ConnectException.
void
java::net::PlainDatagramSocketImpl::create ()
{
int sock = _Jv_socket (AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
char* strerr = strerror (errno);
throw new java::net::SocketException (JvNewStringUTF (strerr));
}
_Jv_platform_close_on_exec (sock);
// We use fnum in place of fd here. From leaving fd null we avoid
// the double close problem in FileDescriptor.finalize.
fnum = sock;
}
void
java::net::PlainDatagramSocketImpl::bind (jint lport,
java::net::InetAddress *host)
{
union SockAddr u;
struct sockaddr *ptr = (struct sockaddr *) &u.address;
// FIXME: Use getaddrinfo() to get actual protocol instead of assuming ipv4.
jbyteArray haddress = host->addr;
jbyte *bytes = elements (haddress);
int len = haddress->length;
if (len == 4)
{
u.address.sin_family = AF_INET;
if (host != NULL)
memcpy (&u.address.sin_addr, bytes, len);
else
u.address.sin_addr.s_addr = htonl (INADDR_ANY);
len = sizeof (struct sockaddr_in);
u.address.sin_port = htons (lport);
}
#ifdef HAVE_INET6
else if (len == 16)
{
u.address6.sin6_family = AF_INET6;
memcpy (&u.address6.sin6_addr, bytes, len);
len = sizeof (struct sockaddr_in6);
u.address6.sin6_port = htons (lport);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
if (_Jv_bind (fnum, ptr, len) == 0)
{
socklen_t addrlen = sizeof(u);
if (lport != 0)
localPort = lport;
else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
localPort = ntohs (u.address.sin_port);
else
goto error;
/* Allow broadcast by default. */
int broadcast = 1;
if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast,
sizeof (broadcast)) != 0)
goto error;
return;
}
error:
char* strerr = strerror (errno);
throw new java::net::BindException (JvNewStringUTF (strerr));
}
void
java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint)
{
throw new ::java::lang::InternalError (JvNewStringLatin1 (
"PlainDatagramSocketImpl::connect: not implemented yet"));
}
void
java::net::PlainDatagramSocketImpl::disconnect ()
{
throw new ::java::lang::InternalError (JvNewStringLatin1 (
"PlainDatagramSocketImpl::disconnect: not implemented yet"));
}
jint
java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i)
{
// FIXME: Deal with Multicast and if the socket is connected.
union SockAddr u;
socklen_t addrlen = sizeof(u);
ssize_t retlen =
::recvfrom (fnum, (char *) NULL, 0, MSG_PEEK, (sockaddr*) &u,
&addrlen);
if (retlen < 0)
goto error;
// FIXME: Deal with Multicast addressing and if the socket is connected.
jbyteArray raddr;
jint rport;
if (u.address.sin_family == AF_INET)
{
raddr = JvNewByteArray (4);
memcpy (elements (raddr), &u.address.sin_addr, 4);
rport = ntohs (u.address.sin_port);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
raddr = JvNewByteArray (16);
memcpy (elements (raddr), &u.address6.sin6_addr, 16);
rport = ntohs (u.address6.sin6_port);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
i->addr = raddr;
return rport;
error:
char* strerr = strerror (errno);
if (errno == ECONNREFUSED)
throw new PortUnreachableException (JvNewStringUTF (strerr));
throw new java::io::IOException (JvNewStringUTF (strerr));
}
jint
java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *p)
{
// FIXME: Deal with Multicast and if the socket is connected.
union SockAddr u;
socklen_t addrlen = sizeof(u);
jbyte *dbytes = elements (p->getData());
ssize_t retlen = 0;
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select since SO_RCVTIMEO is not always available.
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rset;
struct timeval tv;
FD_ZERO(&rset);
FD_SET(fnum, &rset);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
int retval;
if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
goto error;
else if (retval == 0)
throw new java::io::InterruptedIOException ();
}
#endif /* WIN32 */
retlen =
::recvfrom (fnum, (char *) dbytes, p->getLength(), MSG_PEEK, (sockaddr*) &u,
&addrlen);
if (retlen < 0)
goto error;
// FIXME: Deal with Multicast addressing and if the socket is connected.
jbyteArray raddr;
jint rport;
if (u.address.sin_family == AF_INET)
{
raddr = JvNewByteArray (4);
memcpy (elements (raddr), &u.address.sin_addr, 4);
rport = ntohs (u.address.sin_port);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
raddr = JvNewByteArray (16);
memcpy (elements (raddr), &u.address6.sin6_addr, 16);
rport = ntohs (u.address6.sin6_port);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
p->setAddress (new InetAddress (raddr, NULL));
p->setPort (rport);
p->setLength ((jint) retlen);
return rport;
error:
char* strerr = strerror (errno);
if (errno == ECONNREFUSED)
throw new PortUnreachableException (JvNewStringUTF (strerr));
throw new java::io::IOException (JvNewStringUTF (strerr));
}
// Close(shutdown) the socket.
void
java::net::PlainDatagramSocketImpl::close ()
{
// Avoid races from asynchronous finalization.
JvSynchronize sync (this);
// The method isn't declared to throw anything, so we disregard
// the return value.
_Jv_close (fnum);
fnum = -1;
timeout = 0;
}
void
java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *p)
{
// FIXME: Deal with Multicast and if the socket is connected.
jint rport = p->getPort();
union SockAddr u;
jbyteArray haddress = p->getAddress()->addr;
jbyte *bytes = elements (haddress);
int len = haddress->length;
struct sockaddr *ptr = (struct sockaddr *) &u.address;
jbyte *dbytes = elements (p->getData());
if (len == 4)
{
u.address.sin_family = AF_INET;
memcpy (&u.address.sin_addr, bytes, len);
len = sizeof (struct sockaddr_in);
u.address.sin_port = htons (rport);
}
#ifdef HAVE_INET6
else if (len == 16)
{
u.address6.sin6_family = AF_INET6;
memcpy (&u.address6.sin6_addr, bytes, len);
len = sizeof (struct sockaddr_in6);
u.address6.sin6_port = htons (rport);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
if (::sendto (fnum, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0)
return;
char* strerr = strerror (errno);
if (errno == ECONNREFUSED)
throw new PortUnreachableException (JvNewStringUTF (strerr));
throw new java::io::IOException (JvNewStringUTF (strerr));
}
void
java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p)
{
// FIXME: Deal with Multicast and if the socket is connected.
union SockAddr u;
socklen_t addrlen = sizeof(u);
jbyte *dbytes = elements (p->getData());
ssize_t retlen = 0;
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select since SO_RCVTIMEO is not always available.
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rset;
struct timeval tv;
FD_ZERO(&rset);
FD_SET(fnum, &rset);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
int retval;
if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
goto error;
else if (retval == 0)
throw new java::io::InterruptedIOException ();
}
#endif /* WIN32 */
retlen =
::recvfrom (fnum, (char *) dbytes, p->getLength(), 0, (sockaddr*) &u,
&addrlen);
if (retlen < 0)
goto error;
// FIXME: Deal with Multicast addressing and if the socket is connected.
jbyteArray raddr;
jint rport;
if (u.address.sin_family == AF_INET)
{
raddr = JvNewByteArray (4);
memcpy (elements (raddr), &u.address.sin_addr, 4);
rport = ntohs (u.address.sin_port);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
raddr = JvNewByteArray (16);
memcpy (elements (raddr), &u.address6.sin6_addr, 16);
rport = ntohs (u.address6.sin6_port);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
p->setAddress (new InetAddress (raddr, NULL));
p->setPort (rport);
p->setLength ((jint) retlen);
return;
error:
char* strerr = strerror (errno);
if (errno == ECONNREFUSED)
throw new PortUnreachableException (JvNewStringUTF (strerr));
throw new java::io::IOException (JvNewStringUTF (strerr));
}
void
java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
{
// Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
char val = (char) ttl;
socklen_t val_len = sizeof(val);
if (::setsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0)
return;
char* strerr = strerror (errno);
throw new java::io::IOException (JvNewStringUTF (strerr));
}
jint
java::net::PlainDatagramSocketImpl::getTimeToLive ()
{
// Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
char val;
socklen_t val_len = sizeof(val);
if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0)
return ((int) val) & 0xFF;
char* strerr = strerror (errno);
throw new java::io::IOException (JvNewStringUTF (strerr));
}
void
java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr,
java::net::NetworkInterface *,
jboolean join)
{
// FIXME: implement use of NetworkInterface
union McastReq u;
jbyteArray haddress = inetaddr->addr;
jbyte *bytes = elements (haddress);
int len = haddress->length;
int level, opname;
const char *ptr;
if (0)
;
#if HAVE_STRUCT_IP_MREQ
else if (len == 4)
{
level = IPPROTO_IP;
opname = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
memcpy (&u.mreq.imr_multiaddr, bytes, len);
// FIXME: If a non-default interface is set, use it; see Stevens p. 501.
// Maybe not, see note in last paragraph at bottom of Stevens p. 497.
u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
len = sizeof (struct ip_mreq);
ptr = (const char *) &u.mreq;
}
#endif
#if HAVE_STRUCT_IPV6_MREQ
else if (len == 16)
{
level = IPPROTO_IPV6;
/* Prefer new RFC 2553 names. */
#ifndef IPV6_JOIN_GROUP
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
#endif
#ifndef IPV6_LEAVE_GROUP
#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
#endif
opname = join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
// FIXME: If a non-default interface is set, use it; see Stevens p. 501.
// Maybe not, see note in last paragraph at bottom of Stevens p. 497.
u.mreq6.ipv6mr_interface = 0;
len = sizeof (struct ipv6_mreq);
ptr = (const char *) &u.mreq6;
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
if (::setsockopt (fnum, level, opname, ptr, len) == 0)
return;
char* strerr = strerror (errno);
throw new java::io::IOException (JvNewStringUTF (strerr));
}
void
java::net::PlainDatagramSocketImpl::setOption (jint optID,
java::lang::Object *value)
{
int val;
socklen_t val_len = sizeof (val);
if (fnum < 0)
throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
{
java::lang::Boolean *boolobj =
static_cast<java::lang::Boolean *> (value);
val = boolobj->booleanValue() ? 1 : 0;
}
else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
{
java::lang::Integer *intobj =
static_cast<java::lang::Integer *> (value);
val = (int) intobj->intValue();
}
// Else assume value to be an InetAddress for use with IP_MULTICAST_IF.
switch (optID)
{
case _Jv_TCP_NODELAY_ :
throw new java::net::SocketException (
JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
return;
case _Jv_SO_LINGER_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_LINGER not valid for UDP"));
return;
case _Jv_SO_KEEPALIVE_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
return;
case _Jv_SO_BROADCAST_ :
if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
val_len) != 0)
goto error;
break;
case _Jv_SO_OOBINLINE_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_OOBINLINE: not valid for UDP"));
break;
case _Jv_SO_SNDBUF_ :
case _Jv_SO_RCVBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
int opt;
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
goto error;
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
#endif
return;
case _Jv_SO_REUSEADDR_ :
#if defined(SO_REUSEADDR)
if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
val_len) != 0)
goto error;
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_REUSEADDR not supported"));
#endif
return;
case _Jv_SO_BINDADDR_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_BINDADDR: read only option"));
return;
case _Jv_IP_MULTICAST_IF_ :
union InAddr u;
jbyteArray haddress;
jbyte *bytes;
int len;
int level, opname;
const char *ptr;
haddress = ((java::net::InetAddress *) value)->addr;
bytes = elements (haddress);
len = haddress->length;
if (len == 4)
{
level = IPPROTO_IP;
opname = IP_MULTICAST_IF;
memcpy (&u.addr, bytes, len);
len = sizeof (struct in_addr);
ptr = (const char *) &u.addr;
}
// Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF
#if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF)
else if (len == 16)
{
level = IPPROTO_IPV6;
opname = IPV6_MULTICAST_IF;
memcpy (&u.addr6, bytes, len);
len = sizeof (struct in6_addr);
ptr = (const char *) &u.addr6;
}
#endif
else
throw
new java::net::SocketException (JvNewStringUTF ("invalid length"));
if (::setsockopt (fnum, level, opname, ptr, len) != 0)
goto error;
return;
case _Jv_IP_MULTICAST_IF2_ :
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
break;
case _Jv_IP_MULTICAST_LOOP_ :
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_LOOP: not yet implemented"));
break;
case _Jv_IP_TOS_ :
if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
val_len) != 0)
goto error;
return;
case _Jv_SO_TIMEOUT_ :
timeout = val;
return;
default :
errno = ENOPROTOOPT;
}
error:
char* strerr = strerror (errno);
throw new java::net::SocketException (JvNewStringUTF (strerr));
}
java::lang::Object *
java::net::PlainDatagramSocketImpl::getOption (jint optID)
{
int val;
socklen_t val_len = sizeof(val);
union SockAddr u;
socklen_t addrlen = sizeof(u);
switch (optID)
{
case _Jv_TCP_NODELAY_ :
throw new java::net::SocketException (
JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
break;
case _Jv_SO_LINGER_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_LINGER not valid for UDP"));
break;
case _Jv_SO_KEEPALIVE_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
break;
case _Jv_SO_BROADCAST_ :
if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Boolean (val != 0);
case _Jv_SO_OOBINLINE_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_OOBINLINE not valid for UDP"));
break;
case _Jv_SO_RCVBUF_ :
case _Jv_SO_SNDBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
int opt;
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
goto error;
else
return new java::lang::Integer (val);
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
#endif
break;
case _Jv_SO_BINDADDR_:
// cache the local address
if (localAddress == NULL)
{
jbyteArray laddr;
if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
goto error;
if (u.address.sin_family == AF_INET)
{
laddr = JvNewByteArray (4);
memcpy (elements (laddr), &u.address.sin_addr, 4);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
laddr = JvNewByteArray (16);
memcpy (elements (laddr), &u.address6.sin6_addr, 16);
}
#endif
else
throw new java::net::SocketException (
JvNewStringUTF ("invalid family"));
localAddress = new java::net::InetAddress (laddr, NULL);
}
return localAddress;
break;
case _Jv_SO_REUSEADDR_ :
#if defined(SO_REUSEADDR)
if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Boolean (val != 0);
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_REUSEADDR not supported"));
#endif
break;
case _Jv_IP_MULTICAST_IF_ :
#ifdef HAVE_INET_NTOA
struct in_addr inaddr;
socklen_t inaddr_len;
char *bytes;
inaddr_len = sizeof(inaddr);
if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr,
&inaddr_len) != 0)
goto error;
bytes = inet_ntoa (inaddr);
return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes));
#else
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_IF: not available - no inet_ntoa()"));
#endif
break;
case _Jv_SO_TIMEOUT_ :
return new java::lang::Integer (timeout);
break;
case _Jv_IP_MULTICAST_IF2_ :
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
break;
case _Jv_IP_MULTICAST_LOOP_ :
if (::getsockopt (fnum, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Boolean (val != 0);
case _Jv_IP_TOS_ :
if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Integer (val);
default :
errno = ENOPROTOOPT;
}
error:
char* strerr = strerror (errno);
throw new java::net::SocketException (JvNewStringUTF (strerr));
}
#endif /* DISABLE_JAVA_NET */
/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <platform.h>
#ifndef DISABLE_JAVA_NET
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#include <errno.h>
#include <string.h>
#undef STRICT
#undef MAX_PRIORITY
#undef MIN_PRIORITY
#undef FIONREAD
// These functions make the Win32 socket API look more POSIXy
static inline int
write(int s, void *buf, int len)
{
return send(s, (char*)buf, len, 0);
}
static inline int
read(int s, void *buf, int len)
{
return recv(s, (char*)buf, len, 0);
}
// these errors cannot occur on Win32
#else /* WIN32 */
#ifdef HAVE_SYS_IOCTL_H
#define BSD_COMP /* Get FIONREAD on Solaris2. */
#include <sys/ioctl.h>
#endif
// Pick up FIONREAD on Solaris 2.5.
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <string.h>
#endif /* WIN32 */
#endif /* DISABLE_JAVA_NET */
#if HAVE_BSTRING_H
// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
#include <bstring.h>
#endif
#include <gcj/cni.h>
#include <gcj/javaprims.h>
#include <java/io/IOException.h>
#include <java/io/InterruptedIOException.h>
#include <java/net/BindException.h>
#include <java/net/ConnectException.h>
#include <java/net/PlainSocketImpl.h>
#include <java/net/InetAddress.h>
#include <java/net/InetSocketAddress.h>
#include <java/net/SocketException.h>
#include <java/net/SocketTimeoutException.h>
#include <java/lang/InternalError.h>
#include <java/lang/Object.h>
#include <java/lang/Boolean.h>
#include <java/lang/Class.h>
#include <java/lang/Integer.h>
#include <java/lang/Thread.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalArgumentException.h>
#ifdef DISABLE_JAVA_NET
void
java::net::PlainSocketImpl::create (jboolean)
{
throw new java::io::IOException (
JvNewStringLatin1 ("SocketImpl.create: unimplemented"));
}
void
java::net::PlainSocketImpl::bind (java::net::InetAddress *, jint)
{
throw new BindException (
JvNewStringLatin1 ("SocketImpl.bind: unimplemented"));
}
void
java::net::PlainSocketImpl::connect (java::net::SocketAddress *, jint)
{
throw new ConnectException (
JvNewStringLatin1 ("SocketImpl.connect: unimplemented"));
}
void
java::net::PlainSocketImpl::listen (jint)
{
throw new java::io::IOException (
JvNewStringLatin1 ("SocketImpl.listen: unimplemented"));
}
void
java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *)
{
throw new java::io::IOException (
JvNewStringLatin1 ("SocketImpl.accept: unimplemented"));
}
void
java::net::PlainSocketImpl::setOption (jint, java::lang::Object *)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.setOption: unimplemented"));
}
java::lang::Object *
java::net::PlainSocketImpl::getOption (jint)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.getOption: unimplemented"));
}
jint
java::net::PlainSocketImpl::read(void)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
}
jint
java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
}
void
java::net::PlainSocketImpl::write(jint b)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
}
void
java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
}
void
java::net::PlainSocketImpl::sendUrgentData(jint data)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.sendUrgentData: unimplemented"));
}
jint
java::net::PlainSocketImpl::available(void)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.available: unimplemented"));
}
void
java::net::PlainSocketImpl::close(void)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.close: unimplemented"));
}
void
java::net::PlainSocketImpl::shutdownInput (void)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.shutdownInput: unimplemented"));
}
void
java::net::PlainSocketImpl::shutdownOutput (void)
{
throw new SocketException (
JvNewStringLatin1 ("SocketImpl.shutdownOutput: unimplemented"));
}
#else /* DISABLE_JAVA_NET */
union SockAddr
{
struct sockaddr_in address;
#ifdef HAVE_INET6
struct sockaddr_in6 address6;
#endif
};
void
java::net::PlainSocketImpl::create (jboolean stream)
{
int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
if (sock < 0)
{
char* strerr = strerror (errno);
throw new java::io::IOException (JvNewStringUTF (strerr));
}
_Jv_platform_close_on_exec (sock);
// We use fnum in place of fd here. From leaving fd null we avoid
// the double close problem in FileDescriptor.finalize.
fnum = sock;
}
void
java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
{
union SockAddr u;
struct sockaddr *ptr = (struct sockaddr *) &u.address;
jbyteArray haddress = host->addr;
jbyte *bytes = elements (haddress);
int len = haddress->length;
int i = 1;
if (len == 4)
{
u.address.sin_family = AF_INET;
if (host != NULL)
memcpy (&u.address.sin_addr, bytes, len);
else
u.address.sin_addr.s_addr = htonl (INADDR_ANY);
len = sizeof (struct sockaddr_in);
u.address.sin_port = htons (lport);
}
#ifdef HAVE_INET6
else if (len == 16)
{
u.address6.sin6_family = AF_INET6;
memcpy (&u.address6.sin6_addr, bytes, len);
len = sizeof (struct sockaddr_in6);
u.address6.sin6_port = htons (lport);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
// Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
::setsockopt(fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
if (_Jv_bind (fnum, ptr, len) == 0)
{
address = host;
socklen_t addrlen = sizeof(u);
if (lport != 0)
localport = lport;
else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
localport = ntohs (u.address.sin_port);
else
goto error;
return;
}
error:
char* strerr = strerror (errno);
throw new java::net::BindException (JvNewStringUTF (strerr));
}
void
java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr,
jint timeout)
{
java::net::InetSocketAddress *tmp = (java::net::InetSocketAddress*) addr;
java::net::InetAddress *host = tmp->getAddress();
jint rport = tmp->getPort();
union SockAddr u;
socklen_t addrlen = sizeof(u);
jbyteArray haddress = host->addr;
jbyte *bytes = elements (haddress);
int len = haddress->length;
struct sockaddr *ptr = (struct sockaddr *) &u.address;
if (len == 4)
{
u.address.sin_family = AF_INET;
memcpy (&u.address.sin_addr, bytes, len);
len = sizeof (struct sockaddr_in);
u.address.sin_port = htons (rport);
}
#ifdef HAVE_INET6
else if (len == 16)
{
u.address6.sin6_family = AF_INET6;
memcpy (&u.address6.sin6_addr, bytes, len);
len = sizeof (struct sockaddr_in6);
u.address6.sin6_port = htons (rport);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
// FIXME: implement timeout support for Win32
#ifndef WIN32
if (timeout > 0)
{
int flags = ::fcntl (fnum, F_GETFL);
::fcntl (fnum, F_SETFL, flags | O_NONBLOCK);
if ((_Jv_connect (fnum, ptr, len) != 0) && (errno != EINPROGRESS))
goto error;
fd_set rset;
struct timeval tv;
FD_ZERO(&rset);
FD_SET(fnum, &rset);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
int retval;
if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
goto error;
else if (retval == 0)
throw new java::net::SocketTimeoutException
(JvNewStringUTF ("Connect timed out"));
}
else
#endif
{
if (_Jv_connect (fnum, ptr, len) != 0)
goto error;
}
address = host;
port = rport;
// A bind may not have been done on this socket; if so, set localport now.
if (localport == 0)
{
if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
localport = ntohs (u.address.sin_port);
else
goto error;
}
return;
error:
char* strerr = strerror (errno);
throw new java::net::ConnectException (JvNewStringUTF (strerr));
}
void
java::net::PlainSocketImpl::listen (jint backlog)
{
if (::listen (fnum, backlog) != 0)
{
char* strerr = strerror (errno);
throw new java::io::IOException (JvNewStringUTF (strerr));
}
}
void
java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
{
union SockAddr u;
socklen_t addrlen = sizeof(u);
int new_socket = 0;
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select since SO_RCVTIMEO is not always available.
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rset;
struct timeval tv;
FD_ZERO(&rset);
FD_SET(fnum, &rset);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
int retval;
if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
goto error;
else if (retval == 0)
throw new java::io::InterruptedIOException (
JvNewStringUTF("Accept timed out"));
}
#endif /* WIN32 */
new_socket = _Jv_accept (fnum, (sockaddr*) &u, &addrlen);
if (new_socket < 0)
goto error;
_Jv_platform_close_on_exec (new_socket);
jbyteArray raddr;
jint rport;
if (u.address.sin_family == AF_INET)
{
raddr = JvNewByteArray (4);
memcpy (elements (raddr), &u.address.sin_addr, 4);
rport = ntohs (u.address.sin_port);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
raddr = JvNewByteArray (16);
memcpy (elements (raddr), &u.address6.sin6_addr, 16);
rport = ntohs (u.address6.sin6_port);
}
#endif
else
throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
s->fnum = new_socket;
s->localport = localport;
s->address = new InetAddress (raddr, NULL);
s->port = rport;
return;
error:
char* strerr = strerror (errno);
throw new java::io::IOException (JvNewStringUTF (strerr));
}
// Close(shutdown) the socket.
void
java::net::PlainSocketImpl::close()
{
// Avoid races from asynchronous finalization.
JvSynchronize sync (this);
// should we use shutdown here? how would that effect so_linger?
int res = _Jv_close (fnum);
if (res == -1)
{
// These three errors are not errors according to tests performed
// on the reference implementation.
if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
}
// Safe place to reset the file pointer.
fnum = -1;
timeout = 0;
}
// Write a byte to the socket.
void
java::net::PlainSocketImpl::write(jint b)
{
jbyte d =(jbyte) b;
int r = 0;
while (r != 1)
{
r = _Jv_write (fnum, &d, 1);
if (r == -1)
{
if (java::lang::Thread::interrupted())
{
java::io::InterruptedIOException *iioe
= new java::io::InterruptedIOException
(JvNewStringLatin1 (strerror (errno)));
iioe->bytesTransferred = 0;
throw iioe;
}
// Some errors should not cause exceptions.
if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
break;
}
}
}
// Write some bytes to the socket.
void
java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
{
if (! b)
throw new java::lang::NullPointerException;
if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
throw new java::lang::ArrayIndexOutOfBoundsException;
jbyte *bytes = elements (b) + offset;
int written = 0;
while (len > 0)
{
int r = _Jv_write (fnum, bytes, len);
if (r == -1)
{
if (java::lang::Thread::interrupted())
{
java::io::InterruptedIOException *iioe
= new java::io::InterruptedIOException
(JvNewStringLatin1 (strerror (errno)));
iioe->bytesTransferred = written;
throw iioe;
}
// Some errors should not cause exceptions.
if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
break;
}
written += r;
len -= r;
bytes += r;
}
}
void
java::net::PlainSocketImpl::sendUrgentData (jint)
{
throw new SocketException (JvNewStringLatin1 (
"PlainSocketImpl: sending of urgent data not supported by this socket"));
}
// Read a single byte from the socket.
jint
java::net::PlainSocketImpl::read(void)
{
jbyte b;
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select.
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
// Create the file descriptor set.
fd_set read_fds;
FD_ZERO (&read_fds);
FD_SET (fnum,&read_fds);
// Create the timeout struct based on our internal timeout value.
struct timeval timeout_value;
timeout_value.tv_sec = timeout / 1000;
timeout_value.tv_usec = (timeout % 1000) * 1000;
// Select on the fds.
int sel_retval =
_Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value);
// If select returns 0 we've waited without getting data...
// that means we've timed out.
if (sel_retval == 0)
throw new java::io::InterruptedIOException
(JvNewStringUTF ("read timed out") );
// If select returns ok we know we either got signalled or read some data...
// either way we need to try to read.
}
#endif /* WIN32 */
int r = _Jv_read (fnum, &b, 1);
if (r == 0)
return -1;
if (java::lang::Thread::interrupted())
{
java::io::InterruptedIOException *iioe =
new java::io::InterruptedIOException
(JvNewStringUTF("read interrupted"));
iioe->bytesTransferred = r == -1 ? 0 : r;
throw iioe;
}
else if (r == -1)
{
// Some errors cause us to return end of stream...
if (errno == ENOTCONN)
return -1;
// Other errors need to be signalled.
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
}
return b & 0xFF;
}
// Read count bytes into the buffer, starting at offset.
jint
java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
{
if (! buffer)
throw new java::lang::NullPointerException;
jsize bsize = JvGetArrayLength (buffer);
if (offset < 0 || count < 0 || offset + count > bsize)
throw new java::lang::ArrayIndexOutOfBoundsException;
jbyte *bytes = elements (buffer) + offset;
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select.
if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
// Create the file descriptor set.
fd_set read_fds;
FD_ZERO (&read_fds);
FD_SET (fnum, &read_fds);
// Create the timeout struct based on our internal timeout value.
struct timeval timeout_value;
timeout_value.tv_sec = timeout / 1000;
timeout_value.tv_usec =(timeout % 1000) * 1000;
// Select on the fds.
int sel_retval =
_Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value);
// We're only interested in the 0 return.
// error returns still require us to try to read
// the socket to see what happened.
if (sel_retval == 0)
{
java::io::InterruptedIOException *iioe =
new java::io::InterruptedIOException
(JvNewStringUTF ("read interrupted"));
iioe->bytesTransferred = 0;
throw iioe;
}
}
#endif
// Read the socket.
int r = ::recv (fnum, (char *) bytes, count, 0);
if (r == 0)
return -1;
if (java::lang::Thread::interrupted())
{
java::io::InterruptedIOException *iioe =
new java::io::InterruptedIOException
(JvNewStringUTF ("read interrupted"));
iioe->bytesTransferred = r == -1 ? 0 : r;
throw iioe;
}
else if (r == -1)
{
// Some errors cause us to return end of stream...
if (errno == ENOTCONN)
return -1;
// Other errors need to be signalled.
throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
}
return r;
}
// How many bytes are available?
jint
java::net::PlainSocketImpl::available(void)
{
#if defined(FIONREAD) || defined(HAVE_SELECT)
long num = 0;
int r = 0;
bool num_set = false;
#if defined(FIONREAD)
r = ::ioctl (fnum, FIONREAD, &num);
if (r == -1 && errno == ENOTTY)
{
// If the ioctl doesn't work, we don't care.
r = 0;
num = 0;
}
else
num_set = true;
#elif defined(HAVE_SELECT)
if (fnum < 0)
{
errno = EBADF;
r = -1;
}
#endif
if (r == -1)
{
posix_error:
throw new java::io::IOException(JvNewStringUTF(strerror(errno)));
}
// If we didn't get anything we can use select.
#if defined(HAVE_SELECT)
if (! num_set)
if (! num_set && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rd;
FD_ZERO (&rd);
FD_SET (fnum, &rd);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
r = _Jv_select (fnum + 1, &rd, NULL, NULL, &tv);
if(r == -1)
goto posix_error;
num = r == 0 ? 0 : 1;
}
#endif /* HAVE_SELECT */
return (jint) num;
#else
throw new java::io::IOException (JvNewStringUTF ("unimplemented"));
#endif
}
void
java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
{
int val;
socklen_t val_len = sizeof (val);
if (fnum < 0)
throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
{
java::lang::Boolean *boolobj =
static_cast<java::lang::Boolean *> (value);
if (boolobj->booleanValue())
val = 1;
else
{
if (optID == _Jv_SO_LINGER_)
val = -1;
else
val = 0;
}
}
else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
{
java::lang::Integer *intobj =
static_cast<java::lang::Integer *> (value);
val = (int) intobj->intValue();
}
else
{
throw new java::lang::IllegalArgumentException (
JvNewStringLatin1 ("`value' must be Boolean or Integer"));
}
switch (optID)
{
case _Jv_TCP_NODELAY_ :
#ifdef TCP_NODELAY
if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
val_len) != 0)
goto error;
#else
throw new java::lang::InternalError
(JvNewStringUTF ("TCP_NODELAY not supported"));
#endif /* TCP_NODELAY */
return;
case _Jv_SO_KEEPALIVE_ :
if (::setsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
val_len) != 0)
goto error;
break;
case _Jv_SO_BROADCAST_ :
throw new java::net::SocketException
(JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
break;
case _Jv_SO_OOBINLINE_ :
if (::setsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
val_len) != 0)
goto error;
break;
case _Jv_SO_LINGER_ :
#ifdef SO_LINGER
struct linger l_val;
l_val.l_onoff = (val != -1);
l_val.l_linger = val;
if (::setsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
sizeof(l_val)) != 0)
goto error;
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_LINGER not supported"));
#endif /* SO_LINGER */
return;
case _Jv_SO_SNDBUF_ :
case _Jv_SO_RCVBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
int opt;
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
goto error;
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
#endif
return;
case _Jv_SO_BINDADDR_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_BINDADDR: read only option"));
return;
case _Jv_IP_MULTICAST_IF_ :
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
return;
case _Jv_IP_MULTICAST_IF2_ :
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
break;
case _Jv_IP_MULTICAST_LOOP_ :
throw new java::net::SocketException (
JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
break;
case _Jv_IP_TOS_ :
if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
val_len) != 0)
goto error;
break;
case _Jv_SO_REUSEADDR_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
return;
case _Jv_SO_TIMEOUT_ :
timeout = val;
return;
default :
errno = ENOPROTOOPT;
}
error:
char* strerr = strerror (errno);
throw new java::net::SocketException (JvNewStringUTF (strerr));
}
java::lang::Object *
java::net::PlainSocketImpl::getOption (jint optID)
{
int val;
socklen_t val_len = sizeof(val);
union SockAddr u;
socklen_t addrlen = sizeof(u);
struct linger l_val;
socklen_t l_val_len = sizeof(l_val);
switch (optID)
{
#ifdef TCP_NODELAY
case _Jv_TCP_NODELAY_ :
if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
&val_len) != 0)
goto error;
else
return new java::lang::Boolean (val != 0);
#else
throw new java::lang::InternalError
(JvNewStringUTF ("TCP_NODELAY not supported"));
#endif
break;
case _Jv_SO_LINGER_ :
#ifdef SO_LINGER
if (::getsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
&l_val_len) != 0)
goto error;
if (l_val.l_onoff)
return new java::lang::Integer (l_val.l_linger);
else
return new java::lang::Boolean ((jboolean)false);
#else
throw new java::lang::InternalError
(JvNewStringUTF ("SO_LINGER not supported"));
#endif
break;
case _Jv_SO_KEEPALIVE_ :
if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
&val_len) != 0)
goto error;
else
return new java::lang::Boolean (val != 0);
case _Jv_SO_BROADCAST_ :
if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Boolean ((jboolean)val);
case _Jv_SO_OOBINLINE_ :
if (::getsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Boolean ((jboolean)val);
case _Jv_SO_RCVBUF_ :
case _Jv_SO_SNDBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
int opt;
optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
goto error;
else
return new java::lang::Integer (val);
#else
throw new java::lang::InternalError
(JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
#endif
break;
case _Jv_SO_BINDADDR_:
// cache the local address
if (localAddress == NULL)
{
jbyteArray laddr;
if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
goto error;
if (u.address.sin_family == AF_INET)
{
laddr = JvNewByteArray (4);
memcpy (elements (laddr), &u.address.sin_addr, 4);
}
#ifdef HAVE_INET6
else if (u.address.sin_family == AF_INET6)
{
laddr = JvNewByteArray (16);
memcpy (elements (laddr), &u.address6.sin6_addr, 16);
}
#endif
else
throw new java::net::SocketException
(JvNewStringUTF ("invalid family"));
localAddress = new java::net::InetAddress (laddr, NULL);
}
return localAddress;
break;
case _Jv_IP_MULTICAST_IF_ :
throw new java::net::SocketException
(JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
break;
case _Jv_IP_MULTICAST_IF2_ :
throw new java::net::SocketException
(JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
break;
case _Jv_IP_MULTICAST_LOOP_ :
throw new java::net::SocketException
(JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
break;
case _Jv_IP_TOS_ :
if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
&val_len) != 0)
goto error;
return new java::lang::Integer (val);
break;
case _Jv_SO_REUSEADDR_ :
throw new java::net::SocketException
(JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
break;
case _Jv_SO_TIMEOUT_ :
return new java::lang::Integer (timeout);
break;
default :
errno = ENOPROTOOPT;
}
error:
char* strerr = strerror (errno);
throw new java::net::SocketException (JvNewStringUTF (strerr));
}
void
java::net::PlainSocketImpl::shutdownInput (void)
{
if (::shutdown (fnum, 0))
throw new SocketException (JvNewStringUTF (strerror (errno)));
}
void
java::net::PlainSocketImpl::shutdownOutput (void)
{
if (::shutdown (fnum, 1))
throw new SocketException (JvNewStringUTF (strerror (errno)));
}
#endif /* DISABLE_JAVA_NET */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment