From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../java/net/natPlainDatagramSocketImplWin32.cc | 712 +++++++++++++++++++++ 1 file changed, 712 insertions(+) create mode 100644 libjava/gnu/java/net/natPlainDatagramSocketImplWin32.cc (limited to 'libjava/gnu/java/net/natPlainDatagramSocketImplWin32.cc') diff --git a/libjava/gnu/java/net/natPlainDatagramSocketImplWin32.cc b/libjava/gnu/java/net/natPlainDatagramSocketImplWin32.cc new file mode 100644 index 000000000..e41019665 --- /dev/null +++ b/libjava/gnu/java/net/natPlainDatagramSocketImplWin32.cc @@ -0,0 +1,712 @@ +/* Copyright (C) 2003, 2006 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 +#include +#include + +#if HAVE_BSTRING_H +// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 +gnu::java::net::PlainDatagramSocketImpl::create () +{ + SOCKET sock = ::socket (AF_INET, SOCK_DGRAM, 0); + + if (sock == INVALID_SOCKET) + { + _Jv_ThrowSocketException (); + } + + // Cast this to a HANDLE so we can make + // it non-inheritable via _Jv_platform_close_on_exec. + HANDLE hSocket = (HANDLE) sock; + _Jv_platform_close_on_exec (hSocket); + + // We use native_fd in place of fd here. From leaving fd null we avoid + // the double close problem in FileDescriptor.finalize. + native_fd = (jint) hSocket; +} + +void +gnu::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 (::bind (native_fd, ptr, len) == 0) + { + socklen_t addrlen = sizeof(u); + + if (lport != 0) + localPort = lport; + else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0) + localPort = ntohs (u.address.sin_port); + else + goto error; + + /* Allow broadcast by default. */ + int broadcast = 1; + if (::setsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast, + sizeof (broadcast)) != 0) + goto error; + + return; + } + +error: + DWORD dwErrorCode = WSAGetLastError (); + throw new ::java::net::BindException (_Jv_WinStrError (dwErrorCode)); +} + +void +gnu::java::net::PlainDatagramSocketImpl::connect (::java::net::InetAddress *, jint) +{ + throw new ::java::lang::InternalError (JvNewStringLatin1 ( + "PlainDatagramSocketImpl::connect: not implemented yet")); +} + +void +gnu::java::net::PlainDatagramSocketImpl::disconnect () +{ + throw new ::java::lang::InternalError (JvNewStringLatin1 ( + "PlainDatagramSocketImpl::disconnect: not implemented yet")); +} + +jint +gnu::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 (native_fd, (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: + DWORD dwErrorCode = WSAGetLastError (); + if (dwErrorCode == WSAECONNRESET) + throw new ::java::net::PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + + _Jv_ThrowIOException (); + return -1; + // we should never get here +} + +jint +gnu::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()) + p->getOffset(); + jint maxlen = p->maxlen - p->getOffset(); + ssize_t retlen = 0; + + if (timeout > 0) + { + int nRet= ::setsockopt(native_fd, SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (nRet != NO_ERROR) + goto error; + } + + retlen = + ::recvfrom (native_fd, (char *) dbytes, maxlen, MSG_PEEK, (sockaddr*) &u, + &addrlen); + if (retlen == SOCKET_ERROR) + 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 (::java::net::InetAddress::getByAddress (raddr)); + p->setPort (rport); + p->length = (jint) retlen; + return rport; + +error: + DWORD dwErrorCode = WSAGetLastError (); + if (dwErrorCode == WSAECONNRESET) + throw new ::java::net::PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + else if (dwErrorCode == WSAETIMEDOUT) + throw new ::java::net::SocketTimeoutException (_Jv_WinStrError (dwErrorCode)); + else + _Jv_ThrowIOException (); + + return -1; + // we should never get here +} + +// Close(shutdown) the socket. +void +gnu::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. + ::closesocket (native_fd); + native_fd = -1; + timeout = 0; +} + +void +gnu::java::net::PlainDatagramSocketImpl::send (::java::net::DatagramPacket *p) +{ + JvSynchronize lock (SEND_LOCK); + + // 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()) + p->getOffset(); + 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 (native_fd, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0) + return; + + DWORD dwErrorCode = WSAGetLastError (); + if (dwErrorCode == WSAECONNRESET) + throw new ::java::net::PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + + _Jv_ThrowIOException (); +} + +void +gnu::java::net::PlainDatagramSocketImpl::receive (::java::net::DatagramPacket *p) +{ + JvSynchronize lock (RECEIVE_LOCK); + + // FIXME: Deal with Multicast and if the socket is connected. + union SockAddr u; + socklen_t addrlen = sizeof(u); + jbyte *dbytes = elements (p->getData()) + p->getOffset(); + jint maxlen = p->maxlen - p->getOffset(); + ssize_t retlen = 0; + + if (timeout > 0) + { + // This implementation doesn't allow specifying an infinite + // timeout after specifying a finite one, but Sun's JDK 1.4.1 + // didn't seem to allow this either.... + int nRet= ::setsockopt(native_fd, SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (nRet != NO_ERROR) + goto error; + } + + retlen = + ::recvfrom (native_fd, (char *) dbytes, maxlen, 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 (::java::net::InetAddress::getByAddress (raddr)); + p->setPort (rport); + p->length = (jint) retlen; + return; + + error: + DWORD dwErrorCode = WSAGetLastError(); + if (dwErrorCode == WSAECONNRESET) + throw new ::java::net::PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + else if (dwErrorCode == WSAETIMEDOUT) + throw new ::java::net::SocketTimeoutException (_Jv_WinStrError (dwErrorCode)); + else + throw new ::java::io::IOException (_Jv_WinStrError (dwErrorCode)); +} + +void +gnu::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 (native_fd, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0) + return; + + _Jv_ThrowIOException (); +} + +jint +gnu::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 (native_fd, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0) + return ((int) val) & 0xFF; + + _Jv_ThrowIOException (); + + return -1; + // we should never get here +} + +void +gnu::java::net::PlainDatagramSocketImpl::mcastGrp (::java::net::InetAddress *inetaddr, + ::java::net::NetworkInterface *, + jboolean join) +{ + // FIXME: implement use of NetworkInterface + jbyteArray haddress = inetaddr->addr; + 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 (native_fd, level, opname, ptr, len) == 0) + return; + + _Jv_ThrowIOException (); +} + +void +gnu::java::net::PlainDatagramSocketImpl::setOption (jint optID, + ::java::lang::Object *value) +{ + int val; + socklen_t val_len = sizeof (val); + + if (native_fd < 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 (native_fd, 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_ : + int opt; + optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; + if (::setsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, val_len) != 0) + goto error; + return; + case _Jv_SO_REUSEADDR_ : + if (::setsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, + val_len) != 0) + goto error; + 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 (native_fd, 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 (native_fd, SOL_SOCKET, IP_TOS, (char *) &val, + val_len) != 0) + goto error; + return; + + case _Jv_SO_TIMEOUT_ : + timeout = val; + return; + default : + WSASetLastError (WSAENOPROTOOPT); + } + + error: + _Jv_ThrowSocketException (); +} + +::java::lang::Object * +gnu::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 (native_fd, 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_ : + int opt; + optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; + if (::getsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, &val_len) != 0) + goto error; + else + return new ::java::lang::Integer (val); + break; + case _Jv_SO_BINDADDR_: + // cache the local address + if (localAddress == NULL) + { + jbyteArray laddr; + if (::getsockname (native_fd, (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 = ::java::net::InetAddress::getByAddress (laddr); + } + return localAddress; + break; + case _Jv_SO_REUSEADDR_ : + if (::getsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, + &val_len) != 0) + goto error; + return new ::java::lang::Boolean (val != 0); + break; + case _Jv_IP_MULTICAST_IF_ : + struct in_addr inaddr; + socklen_t inaddr_len; + char *bytes; + + inaddr_len = sizeof(inaddr); + if (::getsockopt (native_fd, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr, + &inaddr_len) != 0) + goto error; + + bytes = inet_ntoa (inaddr); + + return ::java::net::InetAddress::getByName (JvNewStringLatin1 (bytes)); + 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 (native_fd, 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 (native_fd, SOL_SOCKET, IP_TOS, (char *) &val, + &val_len) != 0) + goto error; + return new ::java::lang::Integer (val); + + default : + WSASetLastError (WSAENOPROTOOPT); + } + +error: + _Jv_ThrowSocketException (); + return 0; + // we should never get here +} -- cgit v1.2.3