diff options
author | jfrijters <jfrijters> | 2010-09-09 10:55:31 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2010-09-09 10:55:31 +0400 |
commit | e57a3213625777da5740614fc86afb6cb4e9e23e (patch) | |
tree | d117f574bdbb2afc471339612187b8bcc5dd57bc /openjdk/java/net | |
parent | 0720c24a212c240d952a1d20f5595ed15f7fabf3 (diff) |
Implemented IPv6 support for java.net package APIs.
Diffstat (limited to 'openjdk/java/net')
-rw-r--r-- | openjdk/java/net/DefaultDatagramSocketImplFactory.java | 33 | ||||
-rw-r--r-- | openjdk/java/net/PlainDatagramSocketImpl.java | 779 | ||||
-rw-r--r-- | openjdk/java/net/PlainSocketImpl.java | 1044 | ||||
-rw-r--r-- | openjdk/java/net/SocketInputStream.java | 71 | ||||
-rw-r--r-- | openjdk/java/net/SocketOutputStream.java | 82 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java | 139 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java | 1383 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainSocketImpl.java | 100 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainSocketImpl_c.java | 674 | ||||
-rw-r--r-- | openjdk/java/net/net_util_md.java | 824 |
10 files changed, 2027 insertions, 3102 deletions
diff --git a/openjdk/java/net/DefaultDatagramSocketImplFactory.java b/openjdk/java/net/DefaultDatagramSocketImplFactory.java deleted file mode 100644 index 54bae661..00000000 --- a/openjdk/java/net/DefaultDatagramSocketImplFactory.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2008 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -package java.net; - -class DefaultDatagramSocketImplFactory -{ - static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast) throws SocketException - { - return new PlainDatagramSocketImpl(); - } -} diff --git a/openjdk/java/net/PlainDatagramSocketImpl.java b/openjdk/java/net/PlainDatagramSocketImpl.java deleted file mode 100644 index 0ec993d9..00000000 --- a/openjdk/java/net/PlainDatagramSocketImpl.java +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code 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 - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.net; - -import cli.System.Net.IPAddress; -import cli.System.Net.IPEndPoint; -import cli.System.Net.Sockets.SelectMode; -import cli.System.Net.Sockets.SocketOptionName; -import cli.System.Net.Sockets.SocketOptionLevel; -import cli.System.Net.Sockets.MulticastOption; -import cli.System.Net.Sockets.SocketFlags; -import cli.System.Net.Sockets.SocketType; -import cli.System.Net.Sockets.ProtocolType; -import cli.System.Net.Sockets.AddressFamily; -import ikvm.lang.CIL; -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.util.Enumeration; - -/** - * Concrete datagram and multicast socket implementation base class. - * Note: This is not a public class, so that applets cannot call - * into the implementation directly and hence cannot bypass the - * security checks present in the DatagramSocket and MulticastSocket - * classes. - * - * @author Pavani Diwanji - */ - -class PlainDatagramSocketImpl extends DatagramSocketImpl -{ - // Windows 2000 introduced a "feature" that causes it to return WSAECONNRESET from receive, - // if a previous send resulted in an ICMP port unreachable. We disable this feature by using - // this ioctl. - private static final int IOC_IN = (int)0x80000000; - private static final int IOC_VENDOR = 0x18000000; - private static final int SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; - - // Winsock Error Codes - private static final int WSAEMSGSIZE = 10040; - private static final int WSAECONNRESET = 10054; - - private cli.System.Net.Sockets.Socket netSocket; - /* timeout value for receive() */ - private int timeout = 0; - private int trafficClass = 0; - private boolean connected = false; - private InetAddress connectedAddress = null; - private int connectedPort = -1; - - /* cached socket options */ - private int multicastInterface = 0; - private boolean loopbackMode = true; - private int ttl = -1; - - /* Used for IPv6 on Windows only */ - private FileDescriptor fd1; - private int fduse=-1; /* saved between peek() and receive() calls */ - - /* saved between successive calls to receive, if data is detected - * on both sockets at same time. To ensure that one socket is not - * starved, they rotate using this field - */ - private int lastfd=-1; - - /* - * Needed for ipv6 on windows because we need to know - * if the socket was bound to ::0 or 0.0.0.0, when a caller - * asks for it. In this case, both sockets are used, but we - * don't know whether the caller requested ::0 or 0.0.0.0 - * and need to remember it here. - */ - private InetAddress anyLocalBoundAddr=null; - - /** - * Creates a datagram socket - */ - protected synchronized void create() throws SocketException { - fd = new FileDescriptor(); - fd1 = new FileDescriptor(); - datagramSocketCreate(); - } - - /** - * Binds a datagram socket to a local port. - */ - protected synchronized void bind(int lport, InetAddress laddr) - throws SocketException { - - bind0(lport, laddr); - if (laddr.isAnyLocalAddress()) { - anyLocalBoundAddr = laddr; - } - } - - protected synchronized void bind0(int lport, InetAddress laddr) throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - netSocket.Bind(new IPEndPoint(SocketUtil.getAddressFromInetAddress(laddr), lport)); - localPort = ((IPEndPoint)netSocket.get_LocalEndPoint()).get_Port(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new BindException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - /** - * Sends a datagram packet. The packet contains the data and the - * destination address to send the packet to. - * @param packet to be sent. - */ - protected void send(DatagramPacket p) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - int len = p.getLength(); - int port = p.getPort(); - if (port < 1 || port > 65535) - { - throw new SocketException("Invalid port"); - } - if (netSocket.SendTo(p.getData(), p.getOffset(), len, SocketFlags.wrap(SocketFlags.None), new IPEndPoint(SocketUtil.getAddressFromInetAddress(p.getAddress()), port)) != len) - { - throw new SocketException("Not all data was sent"); - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - /** - * Connects a datagram socket to a remote destination. This associates the remote - * address with the local socket so that datagrams may only be sent to this destination - * and received from this destination. - * @param address the remote InetAddress to connect to - * @param port the remote port number - */ - protected void connect(InetAddress address, int port) throws SocketException { - connect0(address, port); - connectedAddress = address; - connectedPort = port; - connected = true; - } - - /** - * Disconnects a previously connected socket. Does nothing if the socket was - * not connected already. - */ - protected void disconnect() { - disconnect0(connectedAddress.family); - connected = false; - connectedAddress = null; - connectedPort = -1; - } - - /** - * Peek at the packet to see who it is from. - * @param return the address which the packet came from. - */ - protected synchronized int peek(InetAddress i) throws IOException - { - DatagramPacket p = new DatagramPacket(new byte[1], 1); - receiveImpl(p, SocketFlags.Peek); - i.address = p.getAddress().address; - i.family = InetAddress.IPv4; - return p.getPort(); - } - - protected synchronized int peekData(DatagramPacket p) throws IOException - { - receiveImpl(p, SocketFlags.Peek); - return p.getPort(); - } - - /** - * Receive the datagram packet. - * @param Packet Received. - */ - protected synchronized void receive(DatagramPacket p) - throws IOException { - try { - receive0(p); - } finally { - fduse = -1; - } - } - - protected synchronized void receive0(DatagramPacket p) throws IOException - { - receiveImpl(p, SocketFlags.None); - } - - private void receiveImpl(DatagramPacket p, int socketFlags) throws IOException - { - cli.System.Net.EndPoint[] remoteEP = new cli.System.Net.EndPoint[] - { - new cli.System.Net.IPEndPoint(0, 0) - }; - int length; - for (; ; ) - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - if (timeout > 0 && !netSocket.Poll(Math.min(timeout, Integer.MAX_VALUE / 1000) * 1000, - SelectMode.wrap(SelectMode.SelectRead))) - { - throw new SocketTimeoutException(); - } - length = netSocket.ReceiveFrom(p.buf, p.offset, p.bufLength, SocketFlags.wrap(socketFlags), remoteEP); - break; - } - catch (cli.System.Net.Sockets.SocketException x) - { - if (x.get_ErrorCode() == WSAECONNRESET) - { - // A previous send failed (i.e. the remote host responded with a ICMP that the port is closed) and - // the winsock stack helpfully lets us know this, but we only care about this when we're connected, - // otherwise we'll simply retry the receive (note that we use SIO_UDP_CONNRESET to prevent these - // WSAECONNRESET exceptions, but when switching from connected to disconnected, some can slip through). - if ((socketFlags & SocketFlags.Peek) != 0) - { - // We did a peek, so we still need to remove the error result. - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - netSocket.ReceiveFrom(p.buf, 0, 0, SocketFlags.wrap(SocketFlags.None), remoteEP); - } - catch (cli.System.Net.Sockets.SocketException _) - { - } - catch (cli.System.ObjectDisposedException _) - { - } - } - if (connected) - { - throw new PortUnreachableException("ICMP Port Unreachable"); - } - continue; - } - if (x.get_ErrorCode() == WSAEMSGSIZE) - { - // The buffer size was too small for the packet, ReceiveFrom receives the part of the packet - // that fits in the buffer and then throws an exception, so we have to ignore the exception in this case. - length = p.bufLength; - break; - } - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - IPEndPoint endpoint = (IPEndPoint)remoteEP[0]; - p.address = SocketUtil.getInetAddressFromIPEndPoint(endpoint); - p.port = endpoint.get_Port(); - p.length = length; - } - - /** - * Set the TTL (time-to-live) option. - * @param TTL to be set. - */ - protected void setTimeToLive(int ttl) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive), ttl); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x2) - { - throw new SocketException("Socket is closed"); - } - } - - /** - * Get the TTL (time-to-live) option. - */ - protected int getTimeToLive() throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive))); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x2) - { - throw new SocketException("Socket is closed"); - } - } - - /** - * Set the TTL (time-to-live) option. - * @param TTL to be set. - */ - protected void setTTL(byte ttl) throws IOException - { - setTimeToLive(ttl & 0xFF); - } - - /** - * Get the TTL (time-to-live) option. - */ - protected byte getTTL() throws IOException - { - return (byte)getTimeToLive(); - } - - /** - * Join the multicast group. - * @param multicast address to join. - */ - protected void join(InetAddress inetaddr) throws IOException { - join(inetaddr, null); - } - - /** - * Leave the multicast group. - * @param multicast address to leave. - */ - protected void leave(InetAddress inetaddr) throws IOException { - leave(inetaddr, null); - } - /** - * Join the multicast group. - * @param multicast address to join. - * @param netIf specifies the local interface to receive multicast - * datagram packets - * @throws IllegalArgumentException if mcastaddr is null or is a - * SocketAddress subclass not supported by this socket - * @since 1.4 - */ - - protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) - throws IOException { - if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) - throw new IllegalArgumentException("Unsupported address type"); - join(((InetSocketAddress)mcastaddr).getAddress(), netIf); - } - - private void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ArgumentException(); - if (false) throw new cli.System.ObjectDisposedException(""); - IPAddress mcastAddr = SocketUtil.getAddressFromInetAddress(inetaddr); - if (netIf == null) - { - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.AddMembership), new MulticastOption(mcastAddr)); - } - else - { - Enumeration e = netIf.getInetAddresses(); - if (e.hasMoreElements()) - { - IPAddress bindAddr = SocketUtil.getAddressFromInetAddress((InetAddress)e.nextElement()); - MulticastOption mcastOption = new MulticastOption(mcastAddr, bindAddr); - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.AddMembership), mcastOption); - } - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ArgumentException x1) - { - throw new IOException(x1.getMessage()); - } - catch (cli.System.ObjectDisposedException x2) - { - throw new SocketException("Socket is closed"); - } - } - - /** - * Leave the multicast group. - * @param multicast address to leave. - * @param netIf specified the local interface to leave the group at - * @throws IllegalArgumentException if mcastaddr is null or is a - * SocketAddress subclass not supported by this socket - * @since 1.4 - */ - protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) - throws IOException { - if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) - throw new IllegalArgumentException("Unsupported address type"); - leave(((InetSocketAddress)mcastaddr).getAddress(), netIf); - } - - private void leave(InetAddress inetaddr, NetworkInterface netIf) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ArgumentException(); - if (false) throw new cli.System.ObjectDisposedException(""); - IPAddress mcastAddr = SocketUtil.getAddressFromInetAddress(inetaddr); - if (netIf == null) - { - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.DropMembership), new MulticastOption(mcastAddr)); - } - else - { - Enumeration e = netIf.getInetAddresses(); - if (e.hasMoreElements()) - { - IPAddress bindAddr = SocketUtil.getAddressFromInetAddress((InetAddress)e.nextElement()); - MulticastOption mcastOption = new MulticastOption(mcastAddr, bindAddr); - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.DropMembership), mcastOption); - } - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ArgumentException x1) - { - throw new IOException(x1.getMessage()); - } - catch (cli.System.ObjectDisposedException x2) - { - throw new SocketException("Socket is closed"); - } - } - - /** - * Close the socket. - */ - protected void close() { - if (fd != null || fd1 != null) { - datagramSocketClose(); - fd = null; - fd1 = null; - } - } - - /** - * set a value - since we only support (setting) binary options - * here, o must be a Boolean - */ - - public void setOption(int optID, Object o) throws SocketException { - if (fd == null && fd1 == null) { - throw new SocketException("Socket Closed"); - } - switch (optID) { - /* check type safety b4 going native. These should never - * fail, since only java.Socket* has access to - * PlainSocketImpl.setOption(). - */ - case SO_TIMEOUT: - if (o == null || !(o instanceof Integer)) { - throw new SocketException("bad argument for SO_TIMEOUT"); - } - int tmp = ((Integer) o).intValue(); - if (tmp < 0) - throw new IllegalArgumentException("timeout < 0"); - timeout = tmp; - return; - case IP_TOS: - if (o == null || !(o instanceof Integer)) { - throw new SocketException("bad argument for IP_TOS"); - } - trafficClass = ((Integer)o).intValue(); - break; - case SO_REUSEADDR: - if (o == null || !(o instanceof Boolean)) { - throw new SocketException("bad argument for SO_REUSEADDR"); - } - break; - case SO_BROADCAST: - if (o == null || !(o instanceof Boolean)) { - throw new SocketException("bad argument for SO_BROADCAST"); - } - break; - case SO_BINDADDR: - throw new SocketException("Cannot re-bind Socket"); - case SO_RCVBUF: - case SO_SNDBUF: - if (o == null || !(o instanceof Integer) || - ((Integer)o).intValue() < 0) { - throw new SocketException("bad argument for SO_SNDBUF or " + - "SO_RCVBUF"); - } - break; - case IP_MULTICAST_IF: - if (o == null || !(o instanceof InetAddress)) - throw new SocketException("bad argument for IP_MULTICAST_IF"); - break; - case IP_MULTICAST_IF2: - if (o == null || !(o instanceof NetworkInterface)) - throw new SocketException("bad argument for IP_MULTICAST_IF2"); - break; - case IP_MULTICAST_LOOP: - if (o == null || !(o instanceof Boolean)) - throw new SocketException("bad argument for IP_MULTICAST_LOOP"); - break; - default: - throw new SocketException("invalid option: " + optID); - } - socketSetOption(optID, o); - } - - /* - * get option's state - set or not - */ - - public Object getOption(int optID) throws SocketException { - if (fd == null && fd1 == null) { - throw new SocketException("Socket Closed"); - } - - Object result; - - switch (optID) { - case SO_TIMEOUT: - result = new Integer(timeout); - break; - - case IP_TOS: - result = socketGetOption(optID); - if ( ((Integer)result).intValue() == -1) { - result = new Integer(trafficClass); - } - break; - - case SO_BINDADDR: - if (fd != null && fd1 != null) { - return anyLocalBoundAddr; - } - /* fall through */ - case IP_MULTICAST_IF: - case IP_MULTICAST_IF2: - case SO_RCVBUF: - case SO_SNDBUF: - case IP_MULTICAST_LOOP: - case SO_REUSEADDR: - case SO_BROADCAST: - result = socketGetOption(optID); - break; - - default: - throw new SocketException("invalid option: " + optID); - } - - return result; - } - - private void datagramSocketCreate() throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - netSocket = new cli.System.Net.Sockets.Socket( - AddressFamily.wrap(AddressFamily.InterNetwork), - SocketType.wrap(SocketType.Dgram), - ProtocolType.wrap(ProtocolType.Udp)); - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast), 1); - netSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); - fd1 = null; - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - } - - private void datagramSocketClose() - { - netSocket.Close(); - } - - private void socketSetOption(int opt, Object val) throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - switch (opt) - { - case SocketOptions.SO_BROADCAST: - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast), ((Boolean)val).booleanValue() ? 1 : 0); - break; - case SocketOptions.IP_MULTICAST_IF: - { - InetAddress addr = (InetAddress)val; - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface), (int)SocketUtil.getAddressFromInetAddress(addr).get_Address()); - break; - } - case SocketOptions.IP_MULTICAST_IF2: - { - NetworkInterface netIf = (NetworkInterface)val; - Enumeration e = netIf.getInetAddresses(); - while (e.hasMoreElements()) - { - InetAddress addr = (InetAddress)e.nextElement(); - if (addr.getAddress().length == 4) - { - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface), (int)SocketUtil.getAddressFromInetAddress(addr).get_Address()); - return; - } - } - throw new SocketException("No IPv4 address found on interface"); - } - case SocketOptions.IP_MULTICAST_LOOP: - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastLoopback), ((Boolean)val).booleanValue() ? 1 : 0); - break; - case SocketOptions.SO_REUSEADDR: - SocketUtil.setCommonSocketOption(netSocket, opt, ((Boolean)val).booleanValue(), null); - break; - default: - SocketUtil.setCommonSocketOption(netSocket, opt, false, val); - break; - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private static InetAddress getInetAddressFromInt(int addr) throws SocketException - { - try - { - return InetAddress.getByAddress(cli.System.BitConverter.GetBytes(addr)); - } - catch (UnknownHostException x) - { - throw new SocketException(x.getMessage()); - } - } - - private Object socketGetOption(int opt) throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - switch (opt) - { - case SocketOptions.SO_BROADCAST: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast))) != 0; - case SocketOptions.IP_MULTICAST_IF: - return getInetAddressFromInt(CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface)))); - case SocketOptions.IP_MULTICAST_IF2: - { - NetworkInterface inf = NetworkInterface.getByInetAddress(getInetAddressFromInt(CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface))))); - return inf != null ? inf : new NetworkInterface(null, -1, new InetAddress[] { new Inet4Address() }); - } - case SocketOptions.IP_MULTICAST_LOOP: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastLoopback))) != 0; - case SocketOptions.SO_REUSEADDR: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress))) != 0; - case SocketOptions.SO_SNDBUF: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer))); - case SocketOptions.SO_RCVBUF: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer))); - case SocketOptions.IP_TOS: - // TODO handle IPv6 here - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService))); - case SocketOptions.SO_BINDADDR: - return SocketUtil.getInetAddressFromIPEndPoint((IPEndPoint)netSocket.get_LocalEndPoint()); - default: - throw new SocketException("Invalid socket option: " + opt); - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void connect0(InetAddress address, int port) throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - IPEndPoint ep = new IPEndPoint(SocketUtil.getAddressFromInetAddress(address), port); - // NOTE we use async connect to work around the issue that the .NET Socket class disallows sync Connect after the socket has received WSAECONNRESET - netSocket.EndConnect(netSocket.BeginConnect(ep, null, null)); - netSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 1 }, null); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void disconnect0(int family) - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - // NOTE we use async connect to work around the issue that the .NET Socket class disallows sync Connect after the socket has received WSAECONNRESET - netSocket.EndConnect(netSocket.BeginConnect(new IPEndPoint(IPAddress.Any, 0), null, null)); - netSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); - } - catch (cli.System.Net.Sockets.SocketException x) - { - } - catch (cli.System.ObjectDisposedException x1) - { - } - } -} diff --git a/openjdk/java/net/PlainSocketImpl.java b/openjdk/java/net/PlainSocketImpl.java deleted file mode 100644 index 84bc91c0..00000000 --- a/openjdk/java/net/PlainSocketImpl.java +++ /dev/null @@ -1,1044 +0,0 @@ -/* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code 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 - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.net; - -import cli.System.Net.IPAddress; -import cli.System.Net.IPEndPoint; -import cli.System.Net.Sockets.LingerOption; -import cli.System.Net.Sockets.SelectMode; -import cli.System.Net.Sockets.SocketOptionName; -import cli.System.Net.Sockets.SocketOptionLevel; -import cli.System.Net.Sockets.SocketFlags; -import cli.System.Net.Sockets.SocketType; -import cli.System.Net.Sockets.ProtocolType; -import cli.System.Net.Sockets.AddressFamily; -import cli.System.Net.Sockets.SocketShutdown; -import ikvm.lang.CIL; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.InterruptedIOException; -import java.io.FileDescriptor; -import java.io.ByteArrayOutputStream; - -import sun.net.ConnectionResetException; - -/** - * Default Socket Implementation. This implementation does - * not implement any security checks. - * Note this class should <b>NOT</b> be public. - * - * @author Steven B. Byrne - * @version 1.73, 05/05/07 - */ -@ikvm.lang.Internal -public class PlainSocketImpl extends SocketImpl -{ - private cli.System.Net.Sockets.Socket netSocket; - /* instance variable for SO_TIMEOUT */ - int timeout; // timeout in millisec - // traffic class - private int trafficClass; - - private boolean shut_rd = false; - private boolean shut_wr = false; - - private SocketInputStream socketInputStream = null; - - /* number of threads using the FileDescriptor */ - private int fdUseCount = 0; - - /* lock when increment/decrementing fdUseCount */ - private Object fdLock = new Object(); - - /* indicates a close is pending on the file descriptor */ - private boolean closePending = false; - - /* indicates connection reset state */ - private int CONNECTION_NOT_RESET = 0; - private int CONNECTION_RESET_PENDING = 1; - private int CONNECTION_RESET = 2; - private int resetState; - private Object resetLock = new Object(); - - /* second fd, used for ipv6 on windows only. - * fd1 is used for listeners and for client sockets at initialization - * until the socket is connected. Up to this point fd always refers - * to the ipv4 socket and fd1 to the ipv6 socket. After the socket - * becomes connected, fd always refers to the connected socket - * (either v4 or v6) and fd1 is closed. - * - * For ServerSockets, fd always refers to the v4 listener and - * fd1 the v6 listener. - */ - private FileDescriptor fd1; - /* - * Needed for ipv6 on windows because we need to know - * if the socket is bound to ::0 or 0.0.0.0, when a caller - * asks for it. Otherwise we don't know which socket to ask. - */ - private InetAddress anyLocalBoundAddr=null; - - /* to prevent starvation when listening on two sockets, this is - * is used to hold the id of the last socket we accepted on. - */ - private int lastfd = -1; - - /** - * Constructs an empty instance. - */ - PlainSocketImpl() { } - - /** - * Creates a socket with a boolean that specifies whether this - * is a stream socket (true) or an unconnected UDP socket (false). - */ - protected synchronized void create(boolean stream) throws IOException { - fd = new FileDescriptor(); - fd1 = new FileDescriptor(); - socketCreate(stream); - if (socket != null) - socket.setCreated(); - if (serverSocket != null) - serverSocket.setCreated(); - } - - /** - * Creates a socket and connects it to the specified port on - * the specified host. - * @param host the specified host - * @param port the specified port - */ - protected void connect(String host, int port) - throws UnknownHostException, IOException - { - IOException pending = null; - try { - InetAddress address = InetAddress.getByName(host); - - try { - connectToAddress(address, port, timeout); - return; - } catch (IOException e) { - pending = e; - } - } catch (UnknownHostException e) { - pending = e; - } - - // everything failed - close(); - throw pending; - } - - /** - * Creates a socket and connects it to the specified address on - * the specified port. - * @param address the address - * @param port the specified port - */ - protected void connect(InetAddress address, int port) throws IOException { - this.port = port; - this.address = address; - - try { - connectToAddress(address, port, timeout); - return; - } catch (IOException e) { - // everything failed - close(); - throw e; - } - } - - /** - * Creates a socket and connects it to the specified address on - * the specified port. - * @param address the address - * @param timeout the timeout value in milliseconds, or zero for no timeout. - * @throws IOException if connection fails - * @throws IllegalArgumentException if address is null or is a - * SocketAddress subclass not supported by this socket - * @since 1.4 - */ - protected void connect(SocketAddress address, int timeout) throws IOException { - if (address == null || !(address instanceof InetSocketAddress)) - throw new IllegalArgumentException("unsupported address type"); - InetSocketAddress addr = (InetSocketAddress) address; - if (addr.isUnresolved()) - throw new UnknownHostException(addr.getHostName()); - this.port = addr.getPort(); - this.address = addr.getAddress(); - - try { - connectToAddress(this.address, port, timeout); - return; - } catch (IOException e) { - // everything failed - close(); - throw e; - } - } - - private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { - if (address.isAnyLocalAddress()) { - doConnect(InetAddress.getLocalHost(), port, timeout); - } else { - doConnect(address, port, timeout); - } - } - - public void setOption(int opt, Object val) throws SocketException { - if (isClosedOrPending()) { - throw new SocketException("Socket Closed"); - } - boolean on = true; - switch (opt) { - /* check type safety b4 going native. These should never - * fail, since only java.Socket* has access to - * PlainSocketImpl.setOption(). - */ - case SO_LINGER: - if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean))) - throw new SocketException("Bad parameter for option"); - if (val instanceof Boolean) { - /* true only if disabling - enabling should be Integer */ - on = false; - } - break; - case SO_TIMEOUT: - if (val == null || (!(val instanceof Integer))) - throw new SocketException("Bad parameter for SO_TIMEOUT"); - int tmp = ((Integer) val).intValue(); - if (tmp < 0) - throw new IllegalArgumentException("timeout < 0"); - timeout = tmp; - break; - case IP_TOS: - if (val == null || !(val instanceof Integer)) { - throw new SocketException("bad argument for IP_TOS"); - } - trafficClass = ((Integer)val).intValue(); - break; - case SO_BINDADDR: - throw new SocketException("Cannot re-bind socket"); - case TCP_NODELAY: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for TCP_NODELAY"); - on = ((Boolean)val).booleanValue(); - break; - case SO_SNDBUF: - case SO_RCVBUF: - if (val == null || !(val instanceof Integer) || - !(((Integer)val).intValue() > 0)) { - throw new SocketException("bad parameter for SO_SNDBUF " + - "or SO_RCVBUF"); - } - break; - case SO_KEEPALIVE: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for SO_KEEPALIVE"); - on = ((Boolean)val).booleanValue(); - break; - case SO_OOBINLINE: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for SO_OOBINLINE"); - on = ((Boolean)val).booleanValue(); - break; - case SO_REUSEADDR: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for SO_REUSEADDR"); - on = ((Boolean)val).booleanValue(); - break; - default: - throw new SocketException("unrecognized TCP option: " + opt); - } - socketSetOption(opt, on, val); - } - public Object getOption(int opt) throws SocketException { - if (isClosedOrPending()) { - throw new SocketException("Socket Closed"); - } - if (opt == SO_TIMEOUT) { - return new Integer(timeout); - } - int ret = 0; - /* - * The native socketGetOption() knows about 3 options. - * The 32 bit value it returns will be interpreted according - * to what we're asking. A return of -1 means it understands - * the option but its turned off. It will raise a SocketException - * if "opt" isn't one it understands. - */ - - switch (opt) { - case TCP_NODELAY: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - case SO_OOBINLINE: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - case SO_LINGER: - ret = socketGetOption(opt, null); - return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret)); - case SO_REUSEADDR: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - case SO_BINDADDR: - if (fd != null && fd1 != null ) { - /* must be unbound or else bound to anyLocal */ - return anyLocalBoundAddr; - } - InetAddressContainer in = new InetAddressContainer(); - ret = socketGetOption(opt, in); - return in.addr; - case SO_SNDBUF: - case SO_RCVBUF: - ret = socketGetOption(opt, null); - return new Integer(ret); - case IP_TOS: - ret = socketGetOption(opt, null); - if (ret == -1) { // ipv6 tos - return new Integer(trafficClass); - } else { - return new Integer(ret); - } - case SO_KEEPALIVE: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - // should never get here - default: - return null; - } - } - - /** - * The workhorse of the connection operation. Tries several times to - * establish a connection to the given <host, port>. If unsuccessful, - * throws an IOException indicating what went wrong. - */ - - private synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { - try { - FileDescriptor fd = acquireFD(); - try { - socketConnect(address, port, timeout); - // If we have a ref. to the Socket, then sets the flags - // created, bound & connected to true. - // This is normally done in Socket.connect() but some - // subclasses of Socket may call impl.connect() directly! - if (socket != null) { - socket.setBound(); - socket.setConnected(); - } - } finally { - releaseFD(); - } - } catch (IOException e) { - close(); - throw e; - } - } - - /** - * Binds the socket to the specified address of the specified local port. - * @param address the address - * @param port the port - */ - protected synchronized void bind(InetAddress address, int lport) - throws IOException - { - socketBind(address, lport); - if (socket != null) - socket.setBound(); - if (serverSocket != null) - serverSocket.setBound(); - if (address.isAnyLocalAddress()) { - anyLocalBoundAddr = address; - } - } - - /** - * Listens, for a specified amount of time, for connections. - * @param count the amount of time to listen for connections - */ - protected synchronized void listen(int count) throws IOException { - socketListen(count); - } - - /** - * Accepts connections. - * @param s the connection - */ - protected synchronized void accept(SocketImpl s) throws IOException { - FileDescriptor fd = acquireFD(); - try { - socketAccept(s); - } finally { - releaseFD(); - } - } - - void setFileDescriptor(FileDescriptor fd) { - this.netSocket = fd.getSocket(); - } - - void setAddress(InetAddress address) { - this.address = address; - } - - void setPort(int port) { - this.port = port; - } - - void setLocalPort(int localPort) { - this.localport = localPort; - } - - /** - * Gets an InputStream for this socket. - */ - protected synchronized InputStream getInputStream() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Socket Closed"); - } - if (shut_rd) { - throw new IOException("Socket input is shutdown"); - } - if (socketInputStream == null) { - socketInputStream = new SocketInputStream(this); - } - return socketInputStream; - } - - void setInputStream(SocketInputStream in) { - socketInputStream = in; - } - - /** - * Gets an OutputStream for this socket. - */ - protected synchronized OutputStream getOutputStream() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Socket Closed"); - } - if (shut_wr) { - throw new IOException("Socket output is shutdown"); - } - return new SocketOutputStream(this); - } - - /** - * Returns the number of bytes that can be read without blocking. - */ - protected synchronized int available() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Stream closed."); - } - - /* - * If connection has been reset then return 0 to indicate - * there are no buffered bytes. - */ - if (isConnectionReset()) { - return 0; - } - - /* - * If no bytes available and we were previously notified - * of a connection reset then we move to the reset state. - * - * If are notified of a connection reset then check - * again if there are bytes buffered on the socket. - */ - int n = 0; - try { - n = socketAvailable(); - if (n == 0 && isConnectionResetPending()) { - setConnectionReset(); - } - } catch (ConnectionResetException exc1) { - setConnectionResetPending(); - try { - n = socketAvailable(); - if (n == 0) { - setConnectionReset(); - } - } catch (ConnectionResetException exc2) { - } - } - return n; - } - - /** - * Closes the socket. - */ - protected void close() throws IOException { - synchronized(fdLock) { - if (fd != null || fd1 != null) { - if (fdUseCount == 0) { - if (closePending) { - return; - } - closePending = true; - /* - * We close the FileDescriptor in two-steps - first the - * "pre-close" which closes the socket but doesn't - * release the underlying file descriptor. This operation - * may be lengthy due to untransmitted data and a long - * linger interval. Once the pre-close is done we do the - * actual socket to release the fd. - */ - try { - socketPreClose(); - } finally { - socketClose(); - } - fd = null; - fd1 = null; - return; - } else { - /* - * If a thread has acquired the fd and a close - * isn't pending then use a deferred close. - * Also decrement fdUseCount to signal the last - * thread that releases the fd to close it. - */ - if (!closePending) { - closePending = true; - fdUseCount--; - socketPreClose(); - } - } - } - } - } - - void reset() throws IOException { - if (fd != null || fd1 != null) { - socketClose(); - } - fd = null; - fd1 = null; - super.reset(); - } - - - /** - * Shutdown read-half of the socket connection; - */ - protected void shutdownInput() throws IOException { - if (fd != null) { - socketShutdown(SHUT_RD); - if (socketInputStream != null) { - socketInputStream.setEOF(true); - } - shut_rd = true; - } - } - - /** - * Shutdown write-half of the socket connection; - */ - protected void shutdownOutput() throws IOException { - if (fd != null) { - socketShutdown(SHUT_WR); - shut_wr = true; - } - } - - protected boolean supportsUrgentData () { - return true; - } - - protected void sendUrgentData (int data) throws IOException { - if (fd == null) { - throw new IOException("Socket Closed"); - } - socketSendUrgentData (data); - } - - /* - * "Acquires" and returns the FileDescriptor for this impl - * - * A corresponding releaseFD is required to "release" the - * FileDescriptor. - */ - public final FileDescriptor acquireFD() { - synchronized (fdLock) { - fdUseCount++; - return fd; - } - } - - /* - * "Release" the FileDescriptor for this impl. - * - * If the use count goes to -1 then the socket is closed. - */ - public final void releaseFD() { - synchronized (fdLock) { - fdUseCount--; - if (fdUseCount == -1) { - if (fd != null) { - try { - socketClose(); - } catch (IOException e) { - } finally { - fd = null; - } - } - } - } - } - - public boolean isConnectionReset() { - synchronized (resetLock) { - return (resetState == CONNECTION_RESET); - } - } - - public boolean isConnectionResetPending() { - synchronized (resetLock) { - return (resetState == CONNECTION_RESET_PENDING); - } - } - - public void setConnectionReset() { - synchronized (resetLock) { - resetState = CONNECTION_RESET; - } - } - - public void setConnectionResetPending() { - synchronized (resetLock) { - if (resetState == CONNECTION_NOT_RESET) { - resetState = CONNECTION_RESET_PENDING; - } - } - - } - - /* - * Return true if already closed or close is pending - */ - public boolean isClosedOrPending() { - /* - * Lock on fdLock to ensure that we wait if a - * close is in progress. - */ - synchronized (fdLock) { - if (closePending || (fd == null && fd1 == null)) { - return true; - } else { - return false; - } - } - } - - /* - * Return the current value of SO_TIMEOUT - */ - public int getTimeout() { - return timeout; - } - - /* - * "Pre-close" a socket by dup'ing the file descriptor - this enables - * the socket to be closed without releasing the file descriptor. - */ - private void socketPreClose() throws IOException { - socketClose0(true); - } - - /* - * Close the socket (and release the file descriptor). - */ - private void socketClose() throws IOException { - socketClose0(false); - } - - private void socketCreate(boolean stream) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - if (stream) - { - netSocket = new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Stream), ProtocolType.wrap(ProtocolType.Tcp)); - } - else - { - netSocket = new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Dgram), ProtocolType.wrap(ProtocolType.Udp)); - } - fd1 = null; - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketConnect(InetAddress address, int port, int timeout) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - IPEndPoint ep = new IPEndPoint(SocketUtil.getAddressFromInetAddress(address), port); - if (timeout <= 0) - { - netSocket.Connect(ep); - } - else - { - cli.System.IAsyncResult result = netSocket.BeginConnect(ep, null, null); - if (!result.get_AsyncWaitHandle().WaitOne(timeout, false)) - { - netSocket.Close(); - throw new SocketTimeoutException(); - } - netSocket.EndConnect(result); - } - this.address = address; - this.port = port; - if (this.localport == 0) - { - this.localport = ((IPEndPoint)netSocket.get_LocalEndPoint()).get_Port(); - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new ConnectException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketBind(InetAddress address, int localport) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - netSocket.Bind(new IPEndPoint(SocketUtil.getAddressFromInetAddress(address), localport)); - this.address = address; - if (localport == 0) - { - this.localport = ((IPEndPoint)netSocket.get_LocalEndPoint()).get_Port(); - } - else - { - this.localport = localport; - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new BindException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketListen(int count) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - netSocket.Listen(count); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketAccept(SocketImpl s) throws IOException - { - PlainSocketImpl impl = (PlainSocketImpl)s; - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - if (timeout > 0 && !netSocket.Poll(Math.min(timeout, Integer.MAX_VALUE / 1000) * 1000, - SelectMode.wrap(SelectMode.SelectRead))) - { - throw new SocketTimeoutException("Accept timed out"); - } - cli.System.Net.Sockets.Socket accept = netSocket.Accept(); - impl.netSocket = accept; - IPEndPoint remoteEndPoint = ((IPEndPoint)accept.get_RemoteEndPoint()); - impl.address = SocketUtil.getInetAddressFromIPEndPoint(remoteEndPoint); - impl.port = remoteEndPoint.get_Port(); - impl.localport = ((IPEndPoint)accept.get_LocalEndPoint()).get_Port(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - // TODO we may have to throw java.io.InterruptedIOException here - throw new SocketException("Socket is closed"); - } - } - - private int socketAvailable() throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - return netSocket.get_Available(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketClose0(boolean useDeferredClose) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - if (netSocket != null) - { - netSocket.Close(); - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketShutdown(int howto) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - netSocket.Shutdown(SocketShutdown.wrap(howto == SHUT_RD ? SocketShutdown.Receive : SocketShutdown.Send)); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketSetOption(int cmd, boolean on, Object value) throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - switch (cmd) - { - case SocketOptions.SO_LINGER: - if (on) - { - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger), new LingerOption(true, ((Integer)value).intValue())); - } - else - { - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger), new LingerOption(false, 0)); - } - break; - case SocketOptions.SO_TIMEOUT: - if (serverSocket == null) - { - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout), timeout <= 5000 ? 0 : timeout); - } - break; - case SocketOptions.TCP_NODELAY: - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay), on ? 1 : 0); - break; - case SocketOptions.SO_KEEPALIVE: - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive), on ? 1 : 0); - break; - case SocketOptions.SO_OOBINLINE: - netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline), on ? 1 : 0); - break; - default: - SocketUtil.setCommonSocketOption(netSocket, cmd, on, value); - break; - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private int socketGetOption(int opt, Object iaContainerObj) throws SocketException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - switch (opt) - { - case SocketOptions.TCP_NODELAY: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay))) == 0 ? -1 : 1; - case SocketOptions.SO_KEEPALIVE: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive))) == 0 ? -1 : 1; - case SocketOptions.SO_LINGER: - { - LingerOption linger = (LingerOption)netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger)); - if (linger.get_Enabled()) - { - return linger.get_LingerTime(); - } - return -1; - } - case SocketOptions.SO_OOBINLINE: - return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline))) == 0 ? -1 : 1; - default: - return SocketUtil.getCommonSocketOption(netSocket, opt, iaContainerObj); - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new SocketException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void socketSendUrgentData(int data) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - byte[] oob = { (byte)data }; - netSocket.Send(oob, SocketFlags.wrap(SocketFlags.OutOfBand)); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - // used by SocketInputStream - int read(byte[] buf, int offset, int len, int timeout) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - if (timeout > 0 && !netSocket.Poll(Math.min(timeout, Integer.MAX_VALUE / 1000) * 1000, - SelectMode.wrap(SelectMode.SelectRead))) - { - throw new SocketTimeoutException(); - } - int read = netSocket.Receive(buf, offset, len, SocketFlags.wrap(SocketFlags.None)); - return read == 0 ? -1 : read; - } - catch (cli.System.Net.Sockets.SocketException x) - { - if (x.get_ErrorCode() == SocketUtil.WSAESHUTDOWN) - { - // the socket was shutdown, so we have to return EOF - return -1; - } - else if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) - { - // nothing to read and would block - return 0; - } - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - // used by SocketOutputStream - int write(byte[] buf, int offset, int len) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - return netSocket.Send(buf, offset, len, SocketFlags.wrap(SocketFlags.None)); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - public final static int SHUT_RD = 0; - public final static int SHUT_WR = 1; -} - -class InetAddressContainer { - InetAddress addr; -} diff --git a/openjdk/java/net/SocketInputStream.java b/openjdk/java/net/SocketInputStream.java index 68824313..0346864b 100644 --- a/openjdk/java/net/SocketInputStream.java +++ b/openjdk/java/net/SocketInputStream.java @@ -29,6 +29,8 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.nio.channels.FileChannel; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; import sun.net.ConnectionResetException; @@ -39,12 +41,13 @@ import sun.net.ConnectionResetException; * * @author Jonathan Payne * @author Arthur van Hoff + * @author Jeroen Frijters */ class SocketInputStream extends FileInputStream { private boolean eof; - private PlainSocketImpl impl = null; + private AbstractPlainSocketImpl impl = null; private byte temp[]; private Socket socket = null; @@ -54,7 +57,7 @@ class SocketInputStream extends FileInputStream * that the fd will not be closed. * @param impl the implemented socket input stream */ - SocketInputStream(PlainSocketImpl impl) throws IOException { + SocketInputStream(AbstractPlainSocketImpl impl) throws IOException { super(impl.getFileDescriptor()); this.impl = impl; socket = impl.getSocket(); @@ -88,9 +91,69 @@ class SocketInputStream extends FileInputStream * returned when the end of the stream is reached. * @exception IOException If an I/O error has occurred. */ - private int socketRead0(FileDescriptor fd, byte b[], int off, int len, int timeout) throws IOException + private int socketRead0(FileDescriptor fdObj, byte bufP[], int off, int len, int timeout) throws IOException { - return impl.read(b, off, len, timeout); + // [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketInputStream.c + cli.System.Net.Sockets.Socket fd = null; + int nread; + + if (IS_NULL(fdObj)) { + throw new SocketException("socket closed"); + } + fd = fdObj.getSocket(); + if (fd == null) { + throw new SocketException("Socket closed"); + } + + if (timeout != 0) { + if (timeout <= 5000 || !isRcvTimeoutSupported) { + int ret = NET_Timeout (fd, timeout); + + if (ret <= 0) { + if (ret == 0) { + throw new SocketTimeoutException("Read timed out"); + } else { + // [IKVM] the OpenJDK native code is broken and always throws this exception on any failure of NET_Timeout + throw new SocketException("socket closed"); + } + } + + /*check if the socket has been closed while we were in timeout*/ + if (fdObj.getSocket() == null) { + throw new SocketException("Socket Closed"); + } + } + } + + nread = recv(fd, bufP, len, 0); + if (nread > 0) { + // ok + } else { + if (nread < 0) { + /* + * Recv failed. + */ + switch (WSAGetLastError()) { + case WSAEINTR: + throw new SocketException("socket closed"); + + case WSAECONNRESET: + case WSAESHUTDOWN: + /* + * Connection has been reset - Windows sometimes reports + * the reset as a shutdown error. + */ + throw new ConnectionResetException(); + + case WSAETIMEDOUT : + throw new SocketTimeoutException("Read timed out"); + + default: + throw NET_ThrowCurrent("recv failed"); + } + } + } + return nread; } /** diff --git a/openjdk/java/net/SocketOutputStream.java b/openjdk/java/net/SocketOutputStream.java index 11e178e2..a1295f21 100644 --- a/openjdk/java/net/SocketOutputStream.java +++ b/openjdk/java/net/SocketOutputStream.java @@ -29,6 +29,8 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; /** * This stream extends FileOutputStream to implement a @@ -37,10 +39,11 @@ import java.nio.channels.FileChannel; * * @author Jonathan Payne * @author Arthur van Hoff + * @author Jeroen Frijters */ class SocketOutputStream extends FileOutputStream { - private PlainSocketImpl impl = null; + private AbstractPlainSocketImpl impl = null; private byte temp[] = new byte[1]; private Socket socket = null; @@ -50,7 +53,7 @@ class SocketOutputStream extends FileOutputStream * that the fd will not be closed. * @param impl the socket output stream inplemented */ - SocketOutputStream(PlainSocketImpl impl) throws IOException { + SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException { super(impl.getFileDescriptor()); this.impl = impl; socket = impl.getSocket(); @@ -80,9 +83,80 @@ class SocketOutputStream extends FileOutputStream * @param len the number of bytes that are written * @exception IOException If an I/O error has occurred. */ - private void socketWrite0(FileDescriptor fd, byte[] b, int off, int len) throws IOException + private void socketWrite0(FileDescriptor fdObj, byte[] data, int off, int len) throws IOException { - impl.write(b, off, len); + // [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketOutputStream.c + final int MAX_BUFFER_LEN = 2048; + cli.System.Net.Sockets.Socket fd; + int buflen = 65536; // MAX_HEAP_BUFFER_LEN + int n; + + if (IS_NULL(fdObj)) { + throw new SocketException("socket closed"); + } else { + fd = fdObj.getSocket(); + } + if (IS_NULL(data)) { + throw new NullPointerException("data argument"); + } + + while(len > 0) { + int loff = 0; + int chunkLen = Math.min(buflen, len); + int llen = chunkLen; + int retry = 0; + + while(llen > 0) { + n = send(fd, data, off + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; + continue; + } + + /* + * Due to a bug in Windows Sockets (observed on NT and Windows + * 2000) it may be necessary to retry the send. The issue is that + * on blocking sockets send/WSASend is supposed to block if there + * is insufficient buffer space available. If there are a large + * number of threads blocked on write due to congestion then it's + * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. + * The workaround we use is to retry the send. If we have a + * large buffer to send (>2k) then we retry with a maximum of + * 2k buffer. If we hit the issue with <=2k buffer then we backoff + * for 1 second and retry again. We repeat this up to a reasonable + * limit before bailing out and throwing an exception. In load + * conditions we've observed that the send will succeed after 2-3 + * attempts but this depends on network buffers associated with + * other sockets draining. + */ + if (WSAGetLastError() == WSAENOBUFS) { + if (llen > MAX_BUFFER_LEN) { + buflen = MAX_BUFFER_LEN; + chunkLen = MAX_BUFFER_LEN; + llen = MAX_BUFFER_LEN; + continue; + } + if (retry >= 30) { + throw new SocketException("No buffer space available - exhausted attempts to queue buffer"); + } + cli.System.Threading.Thread.Sleep(1000); + retry++; + continue; + } + + /* + * Send failed - can be caused by close or write error. + */ + if (WSAGetLastError() == WSAENOTSOCK) { + throw new SocketException("Socket closed"); + } else { + throw NET_ThrowCurrent("socket write error"); + } + } + len -= chunkLen; + off += chunkLen; + } } /** diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java index 8a4fd5df..bb6374f4 100644 --- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -37,12 +37,13 @@ import java.io.FileDescriptor; * during socket creation. * * @author Chris Hegarty + * @author Jeroen Frijters */ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl { /* Used for IPv6 on Windows only */ - private FileDescriptor fd1; + FileDescriptor fd1; /* * Needed for ipv6 on windows because we need to know @@ -53,17 +54,13 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl */ private InetAddress anyLocalBoundAddr=null; - private int fduse=-1; /* saved between peek() and receive() calls */ + cli.System.Net.Sockets.Socket fduse=null; /* saved between peek() and receive() calls */ /* saved between successive calls to receive, if data is detected * on both sockets at same time. To ensure that one socket is not * starved, they rotate using this field */ - private int lastfd=-1; - - static { - init(); - } + cli.System.Net.Sockets.Socket lastfd=null; protected synchronized void create() throws SocketException { fd1 = new FileDescriptor(); @@ -83,7 +80,7 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl try { receive0(p); } finally { - fduse = -1; + fduse = null; } } @@ -115,47 +112,121 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl /* Native methods */ - protected synchronized native void bind0(int lport, InetAddress laddr) - throws SocketException; + protected synchronized void bind0(int lport, InetAddress laddr) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.bind0(env, this, lport, laddr); + env.ThrowPendingException(); + } + + protected void send(DatagramPacket packet) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.send(env, this, packet); + env.ThrowPendingException(); + } - protected native void send(DatagramPacket p) throws IOException; + protected synchronized int peek(InetAddress addressObj) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainDatagramSocketImpl_c.peek(env, this, addressObj); + env.ThrowPendingException(); + return ret; + } - protected synchronized native int peek(InetAddress i) throws IOException; + protected synchronized int peekData(DatagramPacket p) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainDatagramSocketImpl_c.peekData(env, this, p); + env.ThrowPendingException(); + return ret; + } - protected synchronized native int peekData(DatagramPacket p) throws IOException; + protected synchronized void receive0(DatagramPacket packet) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.receive0(env, this, packet); + env.ThrowPendingException(); + } - protected synchronized native void receive0(DatagramPacket p) - throws IOException; + protected void setTimeToLive(int ttl) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.setTimeToLive(env, this, ttl); + env.ThrowPendingException(); + } - protected native void setTimeToLive(int ttl) throws IOException; + protected int getTimeToLive() throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainDatagramSocketImpl_c.getTimeToLive(env, this); + env.ThrowPendingException(); + return ret; + } - protected native int getTimeToLive() throws IOException; + protected void setTTL(byte ttl) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.setTTL(env, this, ttl); + env.ThrowPendingException(); + } - protected native void setTTL(byte ttl) throws IOException; + protected byte getTTL() throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + byte ret = TwoStacksPlainDatagramSocketImpl_c.getTTL(env, this); + env.ThrowPendingException(); + return ret; + } - protected native byte getTTL() throws IOException; + protected void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.join(env, this, inetaddr, netIf); + env.ThrowPendingException(); + } - protected native void join(InetAddress inetaddr, NetworkInterface netIf) - throws IOException; + protected void leave(InetAddress inetaddr, NetworkInterface netIf) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.leave(env, this, inetaddr, netIf); + env.ThrowPendingException(); + } - protected native void leave(InetAddress inetaddr, NetworkInterface netIf) - throws IOException; + protected void datagramSocketCreate() throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.datagramSocketCreate(env, this); + env.ThrowPendingException(); + } - protected native void datagramSocketCreate() throws SocketException; + protected void datagramSocketClose() { + TwoStacksPlainDatagramSocketImpl_c.datagramSocketClose(this); + } - protected native void datagramSocketClose(); + protected void socketSetOption(int opt, Object val) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.socketSetOption(env, this, opt, val); + env.ThrowPendingException(); + } - protected native void socketSetOption(int opt, Object val) - throws SocketException; + protected Object socketGetOption(int opt) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + Object ret = TwoStacksPlainDatagramSocketImpl_c.socketGetOption(env, this, opt); + env.ThrowPendingException(); + return ret; + } - protected native Object socketGetOption(int opt) throws SocketException; + protected void connect0(InetAddress address, int port) throws SocketException { + if (runningOnMono) { + // MONOBUG Mono doesn't allow Socket.Connect(IPAddress.Any, 0) to disconnect a datagram socket, + // so we throw a SocketException, this will cause DatagramSocket to emulate connectedness + throw new SocketException("connected datagram sockets not supported on Mono"); + } + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainDatagramSocketImpl_c.connect0(env, this, address, port); + env.ThrowPendingException(); + } - protected native void connect0(InetAddress address, int port) throws SocketException; + protected void disconnect0(int family) { + TwoStacksPlainDatagramSocketImpl_c.disconnect0(this, family); + } - protected native void disconnect0(int family); + private static final boolean runningOnMono = cli.System.Type.GetType("Mono.Runtime") != null; +} - /** - * Perform class load-time initializations. - */ - private native static void init(); +// we don't support a dual-stack approach yet, so we simply make it an alias for the two-stacks approach +class DualStackPlainDatagramSocketImpl extends TwoStacksPlainDatagramSocketImpl { + // we need this method, because DatagramSocket uses reflection to check for this methods existance + protected int peekData(DatagramPacket p) throws IOException { + return super.peekData(p); + } } diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java index 8e73b352..1564c5e7 100644 --- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java +++ b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java @@ -22,6 +22,32 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ +package java.net; + +import java.io.FileDescriptor; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; +import static java.net.InetAddress.IPv4; +import static java.net.InetAddress.IPv6; + +final class TwoStacksPlainDatagramSocketImpl_c +{ +static final int ni_class = 0; +static final int JVM_IO_ERR = -1; +static final int JVM_IO_INTR = -2; + +static final int java_net_SocketOptions_SO_BINDADDR = SocketOptions.SO_BINDADDR; +static final int java_net_SocketOptions_SO_SNDBUF = SocketOptions.SO_SNDBUF; +static final int java_net_SocketOptions_SO_RCVBUF = SocketOptions.SO_RCVBUF; +static final int java_net_SocketOptions_IP_TOS = SocketOptions.IP_TOS; +static final int java_net_SocketOptions_SO_REUSEADDR = SocketOptions.SO_REUSEADDR; +static final int java_net_SocketOptions_SO_BROADCAST = SocketOptions.SO_BROADCAST; +static final int java_net_SocketOptions_IP_MULTICAST_LOOP = SocketOptions.IP_MULTICAST_LOOP; +static final int java_net_SocketOptions_IP_MULTICAST_IF = SocketOptions.IP_MULTICAST_IF; +static final int java_net_SocketOptions_IP_MULTICAST_IF2 = SocketOptions.IP_MULTICAST_IF2; + +/* #include <windows.h> #include <winsock2.h> @@ -50,10 +76,17 @@ #define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) #define IN_MULTICAST(i) IN_CLASSD(i) +*/ + +static boolean IN_MULTICAST(int ipv4address) { + return ((ipv4address >> 24) & 0xf0) == 0xe0; +} + /************************************************************************ * TwoStacksPlainDatagramSocketImpl */ +/* static jfieldID IO_fd_fdID; static jfieldID pdsi_trafficClassID; jfieldID pdsi_fdID; @@ -69,11 +102,12 @@ static jclass ia4_clazz; static jmethodID ia4_ctor; static CRITICAL_SECTION sizeCheckLock; +*/ /* Windows OS version is XP or better */ -static int xp_or_later = 0; +static final boolean xp_or_later = true; /* Windows OS version is Windows 2000 or better */ -static int w2k_or_later = 0; +//static int w2k_or_later = 0; /* * Notes about UDP/IPV6 on Windows (XP and 2003 server): @@ -86,6 +120,7 @@ static int w2k_or_later = 0; /* * Returns a java.lang.Integer based on 'i' */ +/* jobject createInteger(JNIEnv *env, int i) { static jclass i_class; static jmethodID i_ctrID; @@ -102,10 +137,12 @@ jobject createInteger(JNIEnv *env, int i) { return ( (*env)->NewObject(env, i_class, i_ctrID, i) ); } +*/ /* * Returns a java.lang.Boolean based on 'b' */ +/* jobject createBoolean(JNIEnv *env, int b) { static jclass b_class; static jmethodID b_ctrID; @@ -122,24 +159,25 @@ jobject createBoolean(JNIEnv *env, int b) { return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) ); } +*/ -static int getFD(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); +static cli.System.Net.Sockets.Socket getFD(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd; if (fdObj == NULL) { - return -1; + return null; } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); + return fdObj.getSocket(); } -static int getFD1(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); +static cli.System.Net.Sockets.Socket getFD1(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd1; if (fdObj == NULL) { - return -1; + return null; } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); + return fdObj.getSocket(); } /* @@ -160,6 +198,7 @@ static int getFD1(JNIEnv *env, jobject this) { * another machine then WSAEINVAL is returned. * */ +/* jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) { #define DEFAULT_MSG_SIZE 65527 @@ -167,7 +206,7 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) static jboolean is95or98; static int maxmsg; - typedef struct _netaddr { /* Windows 95/98 only */ + typedef struct _netaddr { /* Windows 95/98 only *-/ unsigned long addr; struct _netaddr *next; } netaddr; @@ -179,12 +218,12 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) * get the maximum size supported by the underlying provider. * * In addition on 95/98 we must enumerate our IP addresses. - */ + *-/ if (!initDone) { EnterCriticalSection(&sizeCheckLock); if (initDone) { - /* another thread got there first */ + /* another thread got there first *-/ LeaveCriticalSection(&sizeCheckLock); } else { @@ -193,7 +232,7 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) /* * Step 1: Determine which OS this is. - */ + *-/ ver.dwOSVersionInfoSize = sizeof(ver); GetVersionEx(&ver); @@ -210,7 +249,7 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) * underlying provider. On Windows 95 if winsock hasn't been * upgraded (ie: unsupported configuration) then we assume * the default 64k limit. - */ + *-/ len = sizeof(maxmsg); if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) { maxmsg = DEFAULT_MSG_SIZE; @@ -220,7 +259,7 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) * Step 3: On Windows 95/98 then enumerate the IP addresses on * this machine. This is necesary because we need to check if the * datagram is being sent to an application on the same machine. - */ + *-/ if (is95or98) { char hostname[255]; struct hostent *hp; @@ -256,7 +295,7 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) /* * Step 4: initialization is done so set flag and unlock cs - */ + *-/ initDone = JNI_TRUE; LeaveCriticalSection(&sizeCheckLock); } @@ -271,18 +310,18 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) * (c) On 95/98 if the size is <12k we are okay. * (d) On 95/98 if size > 12k then check if the destination is the current * machine. - */ - if (size > maxmsg) { /* step (a) */ + *-/ + if (size > maxmsg) { /* step (a) *-/ return JNI_TRUE; } - if (!is95or98) { /* step (b) */ + if (!is95or98) { /* step (b) *-/ return JNI_FALSE; } - if (size <= 12280) { /* step (c) */ + if (size <= 12280) { /* step (c) *-/ return JNI_FALSE; } - /* step (d) */ + /* step (d) *-/ if ((addr & 0x7f000000) == 0x7f000000) { return JNI_TRUE; @@ -296,26 +335,14 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) } return JNI_FALSE; } +*/ /* * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable */ -__inline static jboolean supportPortUnreachable() { - static jboolean initDone; - static jboolean portUnreachableSupported; - - if (!initDone) { - OSVERSIONINFO ver; - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 5) { - portUnreachableSupported = JNI_TRUE; - } else { - portUnreachableSupported = JNI_FALSE; - } - initDone = JNI_TRUE; - } - return portUnreachableSupported; +static boolean supportPortUnreachable() { + // we don't support anything pre-Win2K anyway + return true; } /* @@ -325,14 +352,13 @@ __inline static jboolean supportPortUnreachable() { * behaviour whereby receiving a "connection reset" status resets the * socket. */ -static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd) +static boolean purgeOutstandingICMP(cli.System.Net.Sockets.Socket fd) { - jboolean got_icmp = JNI_FALSE; - char buf[1]; - fd_set tbl; - struct timeval t = { 0, 0 }; - struct sockaddr_in rmtaddr; - int addrlen = sizeof(rmtaddr); + boolean got_icmp = false; + byte[] buf = new byte[1]; + fd_set tbl = new fd_set(); + timeval t = new timeval(); + SOCKETADDRESS rmtaddr = null; /* * A no-op if this OS doesn't support it. @@ -345,14 +371,14 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd) * Peek at the queue to see if there is an ICMP port unreachable. If there * is then receive it. */ - FD_ZERO(&tbl); - FD_SET(fd, &tbl); - while(1) { - if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) { + FD_ZERO(tbl); + FD_SET(fd, tbl); + while(true) { + if (select(tbl, null, null, t) <= 0) { break; } if (recvfrom(fd, buf, 1, MSG_PEEK, - (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) { + rmtaddr) != JVM_IO_ERR) { break; } if (WSAGetLastError() != WSAECONNRESET) { @@ -360,7 +386,7 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd) break; } - recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen); + recvfrom(fd, buf, 1, 0, rmtaddr); got_icmp = JNI_TRUE; } @@ -373,6 +399,7 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd) * Method: init * Signature: ()V */ +/* JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { @@ -385,7 +412,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51); w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50); - /* get fieldIDs */ + /* get fieldIDs *-/ pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;"); CHECK_NULL(pdsi_fdID); pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;"); @@ -418,72 +445,75 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { InitializeCriticalSection(&sizeCheckLock); } +*/ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, - jint port, jobject addressObj) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); +static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int port, InetAddress addressObj) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; - int fd, fd1, family; - int ipv6_supported = ipv6_available(); + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int family; + boolean ipv6_supported = ipv6_available(); SOCKETADDRESS lcladdr; - int lcladdrlen; - int address; + lcladdr = new SOCKETADDRESS(); - family = (*env)->GetIntField(env, addressObj, ia_familyID); + if (IS_NULL(addressObj)) { + JNU_ThrowNullPointerException(env, "argument address"); + return; + } + + family = addressObj.family; if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol family not supported"); return; } if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return; } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); if (ipv6_supported) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } } if (IS_NULL(addressObj)) { JNU_ThrowNullPointerException(env, "argument address"); return; - } else { - address = (*env)->GetIntField(env, addressObj, ia_addressID); } - if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, addressObj, port, lcladdr, JNI_FALSE) != 0) { return; } if (ipv6_supported) { - struct ipv6bind v6bind; - v6bind.addr = &lcladdr; + ipv6bind v6bind = new ipv6bind(); + v6bind.addr = lcladdr; v6bind.ipv4_fd = fd; v6bind.ipv6_fd = fd1; - if (NET_BindV6(&v6bind) != -1) { + if (NET_BindV6(v6bind) != -1) { /* check if the fds have changed */ if (v6bind.ipv4_fd != fd) { fd = v6bind.ipv4_fd; - if (fd == -1) { + if (fd == null) { /* socket is closed. */ - (*env)->SetObjectField(env, this, pdsi_fdID, NULL); + _this.fd = null; } else { /* socket was re-created */ - (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); + fdObj.setSocket(fd); } } if (v6bind.ipv6_fd != fd1) { fd1 = v6bind.ipv6_fd; - if (fd1 == -1) { + if (fd1 == null) { /* socket is closed. */ - (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); + _this.fd1 = null; } else { /* socket was re-created */ - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + fd1Obj.setSocket(fd1); } } } else { @@ -491,7 +521,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, return; } } else { - if (bind(fd, (struct sockaddr *)&lcladdr, lcladdrlen) == -1) { + if (bind(fd, lcladdr) == -1) { if (WSAGetLastError() == WSAEACCES) { WSASetLastError(WSAEADDRINUSE); } @@ -501,17 +531,17 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, } if (port == 0) { - if (fd == -1) { + if (fd == null) { /* must be an IPV6 only socket. */ fd = fd1; } - if (getsockname(fd, (struct sockaddr *)&lcladdr, &lcladdrlen) == -1) { + if (getsockname(fd, lcladdr) == -1) { NET_ThrowCurrent(env, "JVM_GetSockName"); return; } - port = ntohs((u_short) GET_PORT (&lcladdr)); + port = ntohs(GET_PORT (lcladdr)); } - (*env)->SetIntField(env, this, pdsi_localPortID, port); + _this.localPort = port; } @@ -521,30 +551,30 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, * Signature: (Ljava/net/InetAddress;I)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this, - jobject address, jint port) { +static void connect0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress address, int port) { /* The object's field */ - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; /* The fdObj'fd */ - jint fd=-1, fd1=-1, fdc; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + cli.System.Net.Sockets.Socket fdc; /* The packetAddress address, family and port */ - jint addr, family; + int addr, family; SOCKETADDRESS rmtaddr; - int rmtaddrlen; - int ipv6_supported = ipv6_available(); + rmtaddr = new SOCKETADDRESS(); + boolean ipv6_supported = ipv6_available(); if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } if (IS_NULL(address)) { @@ -552,11 +582,11 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject thi return; } - addr = (*env)->GetIntField(env, address, ia_addressID); + addr = address.address; - family = (*env)->GetIntField(env, address, ia_familyID); + family = address.family; if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol family not supported"); return; } @@ -569,16 +599,14 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject thi * as connected sockets. The solution is to only enable this feature * when the socket is connected */ - DWORD x1, x2; /* ignored result codes */ - int res, t = TRUE; - res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); + WSAIoctl(fdc, SIO_UDP_CONNRESET, true); } - if (NET_InetAddressToSockaddr(env, address, port,(struct sockaddr *)&rmtaddr, &rmtaddrlen, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, address, port, rmtaddr, JNI_FALSE) != 0) { return; } - if (connect(fdc, (struct sockaddr *)&rmtaddr, sizeof(rmtaddr)) == -1) { + if (connect(fdc, rmtaddr) == -1) { NET_ThrowCurrent(env, "connect"); return; } @@ -590,39 +618,34 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject thi * Signature: ()V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this, jint family) { +static void disconnect0(TwoStacksPlainDatagramSocketImpl _this, int family) { /* The object's field */ - jobject fdObj; + FileDescriptor fdObj; /* The fdObj'fd */ - jint fd, len; + cli.System.Net.Sockets.Socket fd; SOCKETADDRESS addr; + addr = new SOCKETADDRESS(); if (family == IPv4) { - fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - len = sizeof (struct sockaddr_in); + fdObj = _this.fd; } else { - fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - len = sizeof (struct SOCKADDR_IN6); + fdObj = _this.fd1; } if (IS_NULL(fdObj)) { /* disconnect doesn't throw any exceptions */ return; } - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); - memset(&addr, 0, len); - connect(fd, (struct sockaddr *)&addr, len); + connect(fd, addr); /* * use SIO_UDP_CONNRESET * to disable ICMP port unreachable handling here. */ if (xp_or_later) { - DWORD x1, x2; /* ignored result codes */ - int t = FALSE; - WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); + WSAIoctl(fd,SIO_UDP_CONNRESET,false); } } @@ -631,76 +654,68 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject * Method: send * Signature: (Ljava/net/DatagramPacket;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, - jobject packet) { +static void send(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { + FileDescriptor fdObj; + cli.System.Net.Sockets.Socket fd; - char BUF[MAX_BUFFER_LEN]; - char *fullPacket; - jobject fdObj; - jint fd; - - jobject iaObj; - jint address; - jint family; + InetAddress iaObj; + int address; + int family; - jint packetBufferOffset, packetBufferLen, packetPort; - jbyteArray packetBuffer; - jboolean connected; + int packetBufferOffset, packetBufferLen, packetPort; + byte[] packetBuffer; + boolean connected; SOCKETADDRESS rmtaddr; - SOCKETADDRESS *addrp = &rmtaddr; - int addrlen; - int x; /* DELETE ME */ - + rmtaddr = new SOCKETADDRESS(); if (IS_NULL(packet)) { JNU_ThrowNullPointerException(env, "null packet"); return; } - iaObj = (*env)->GetObjectField(env, packet, dp_addressID); + iaObj = packet.address; - packetPort = (*env)->GetIntField(env, packet, dp_portID); - packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); - packetBuffer = (jbyteArray)(*env)->GetObjectField(env, packet, dp_bufID); - connected = (*env)->GetBooleanField(env, this, pdsi_connected); + packetPort = packet.port; + packetBufferOffset = packet.offset; + packetBuffer = packet.buf; + connected = _this.connected; if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) { JNU_ThrowNullPointerException(env, "null address || null buffer"); return; } - family = (*env)->GetIntField(env, iaObj, ia_familyID); + family = iaObj.family; if (family == IPv4) { - fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + fdObj = _this.fd; } else { if (!ipv6_available()) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol not allowed"); return; } - fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + fdObj = _this.fd1; } if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); - packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID); + packetBufferLen = packet.length; if (connected) { - addrp = 0; /* arg to JVM_Sendto () null in this case */ - addrlen = 0; + rmtaddr = null; } else { - if (NET_InetAddressToSockaddr(env, iaObj, packetPort, (struct sockaddr *)&rmtaddr, &addrlen, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, packetPort, rmtaddr, JNI_FALSE) != 0) { return; } } + /* if (packetBufferLen > MAX_BUFFER_LEN) { /* @@ -711,9 +726,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, * On ME if we try to send a datagram with a size greater than * that supported by the service provider then no error is * returned. - */ + *-/ if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6. - * Check is not necessary on these OSes */ + * Check is not necessary on these OSes *-/ if (connected) { address = (*env)->GetIntField(env, iaObj, ia_addressID); } else { @@ -738,7 +753,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, * we *must* alloc the buffer. Note it needn't be bigger * than 65,536 (0xFFFF) the max size of an IP packet. * anything bigger is truncated anyway. - */ + *-/ fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); @@ -747,34 +762,28 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, } else { fullPacket = &(BUF[0]); } + */ - (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen, - (jbyte *)fullPacket); - switch (sendto(fd, fullPacket, packetBufferLen, 0, - (struct sockaddr *)addrp, addrlen)) { + switch (sendto(fd, packetBuffer, packetBufferOffset, packetBufferLen, 0, rmtaddr)) { case JVM_IO_ERR: NET_ThrowCurrent(env, "Datagram send failed"); break; case JVM_IO_INTR: - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } - - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } } /* * check which socket was last serviced when there was data on both sockets. * Only call this if sure that there is data on both sockets. */ -static int checkLastFD (JNIEnv *env, jobject this, int fd, int fd1) { - int nextfd, lastfd = (*env)->GetIntField(env, this, pdsi_lastfdID); - if (lastfd == -1) { +private static cli.System.Net.Sockets.Socket checkLastFD (TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1) { + cli.System.Net.Sockets.Socket nextfd, lastfd = _this.lastfd; + if (lastfd == null) { /* arbitrary. Choose fd */ - (*env)->SetIntField(env, this, pdsi_lastfdID, fd); + _this.lastfd = fd; return fd; } else { if (lastfd == fd) { @@ -782,7 +791,7 @@ static int checkLastFD (JNIEnv *env, jobject this, int fd, int fd1) { } else { nextfd = fd; } - (*env)->SetIntField(env, this, pdsi_lastfdID, nextfd); + _this.lastfd = nextfd; return nextfd; } } @@ -792,39 +801,36 @@ static int checkLastFD (JNIEnv *env, jobject this, int fd, int fd1) { * Method: peek * Signature: (Ljava/net/InetAddress;)I */ -JNIEXPORT jint JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, - jobject addressObj) { - - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); - jint fd; +static int peek(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress addressObj) { + FileDescriptor fdObj = _this.fd; + int timeout = _this.timeout; + cli.System.Net.Sockets.Socket fd; /* The address and family fields of addressObj */ - jint address, family; + int address, family; int n; - struct sockaddr_in remote_addr; - jint remote_addrsize = sizeof (remote_addr); - char buf[1]; - BOOL retry; - jlong prevTime = 0; + SOCKETADDRESS remote_addr = new SOCKETADDRESS(); + byte[] buf = new byte[1]; + boolean retry; + long prevTime = 0; if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return -1; } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (fd < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + fd = fdObj.getSocket(); + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return -1; } } if (IS_NULL(addressObj)) { JNU_ThrowNullPointerException(env, "Null address in peek()"); + return -1; } else { - address = (*env)->GetIntField(env, addressObj, ia_addressID); + address = addressObj.address; /* We only handle IPv4 for now. Will support IPv6 once its in the os */ family = AF_INET; } @@ -836,19 +842,19 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, * If a timeout has been specified then we select on the socket * waiting for a read event or a timeout. */ - if (timeout) { + if (timeout != 0) { int ret; prevTime = JVM_CurrentTimeMillis(env, 0); ret = NET_Timeout (fd, timeout); if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Peek timed out"); return ret; } else if (ret == JVM_IO_ERR) { NET_ThrowCurrent(env, "timeout in datagram socket peek"); return ret; } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); return ret; } @@ -856,22 +862,22 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, /* now try the peek */ n = recvfrom(fd, buf, 1, MSG_PEEK, - (struct sockaddr *)&remote_addr, &remote_addrsize); + remote_addr); if (n == JVM_IO_ERR) { if (WSAGetLastError() == WSAECONNRESET) { - jboolean connected; + boolean connected; /* * An icmp port unreachable - we must receive this as Windows * does not reset the state of the socket until this has been * received. */ - purgeOutstandingICMP(env, this, fd); + purgeOutstandingICMP(fd); - connected = (*env)->GetBooleanField(env, this, pdsi_connected); + connected = _this.connected; if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", "ICMP Port Unreachable"); return 0; } @@ -881,11 +887,11 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, * we may have used up some of the timeout befor the icmp port * unreachable arrived. */ - if (timeout) { - jlong newTime = JVM_CurrentTimeMillis(env, 0); + if (timeout != 0) { + long newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); if (timeout <= 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Receive timed out"); return 0; } @@ -903,45 +909,42 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, return 0; } if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", 0); + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", null); return 0; } - (*env)->SetIntField(env, addressObj, ia_addressID, - ntohl(remote_addr.sin_addr.s_addr)); - (*env)->SetIntField(env, addressObj, ia_familyID, IPv4); + addressObj.address = ntohl(remote_addr.sin_addr.s_addr); + addressObj.family = IPv4; /* return port */ return ntohs(remote_addr.sin_port); } -JNIEXPORT jint JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this, - jobject packet) { +static int peekData(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { - char BUF[MAX_BUFFER_LEN]; - char *fullPacket; - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + int timeout = _this.timeout; - jbyteArray packetBuffer; - jint packetBufferOffset, packetBufferLen; + byte[] packetBuffer; + int packetBufferOffset, packetBufferLen; - int fd, fd1, fduse, nsockets=0, errorCode; + cli.System.Net.Sockets.Socket fd = null, fd1 = null, fduse = null; + int nsockets=0, errorCode; int port; - jbyteArray data; + byte[] data; - int checkBoth = 0, datalen; + boolean checkBoth = false; + int datalen; int n; SOCKETADDRESS remote_addr; - jint remote_addrsize=sizeof(remote_addr); - BOOL retry; - jlong prevTime = 0; + remote_addr = new SOCKETADDRESS(); + boolean retry; + long prevTime = 0; if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (fd < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + fd = fdObj.getSocket(); + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return -1; } @@ -949,9 +952,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - if (fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + fd1 = fd1Obj.getSocket(); + if (fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return -1; } @@ -960,7 +963,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi switch (nsockets) { case 0: - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return -1; case 1: @@ -980,16 +983,17 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi return -1; } - packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID); + packetBuffer = packet.buf; if (IS_NULL(packetBuffer)) { JNU_ThrowNullPointerException(env, "packet buffer"); return -1; } - packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); - packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); + packetBufferOffset = packet.offset; + packetBufferLen = packet.bufLength; + /* if (packetBufferLen > MAX_BUFFER_LEN) { /* When JNI-ifying the JDK's IO routines, we turned @@ -1002,7 +1006,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi * we *must* alloc the buffer. Note it needn't be bigger * than 65,536 (0xFFFF) the max size of an IP packet. * anything bigger is truncated anyway. - */ + *-/ fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); @@ -1011,6 +1015,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi } else { fullPacket = &(BUF[0]); } + */ do { int ret; @@ -1023,74 +1028,66 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi if (checkBoth) { int t = timeout == 0 ? -1: timeout; prevTime = JVM_CurrentTimeMillis(env, 0); - ret = NET_Timeout2 (fd, fd1, t, &fduse); + cli.System.Net.Sockets.Socket[] tmp = new cli.System.Net.Sockets.Socket[] { fduse }; + ret = NET_Timeout2 (fd, fd1, t, tmp); + fduse = tmp[0]; /* all subsequent calls to recv() or select() will use the same fd * for this call to peek() */ if (ret <= 0) { if (ret == 0) { - JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", "Peek timed out"); } else if (ret == JVM_IO_ERR) { NET_ThrowCurrent(env, "timeout in datagram socket peek"); } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return -1; } if (ret == 2) { - fduse = checkLastFD (env, this, fd, fd1); + fduse = checkLastFD (_this, fd, fd1); } checkBoth = FALSE; - } else if (timeout) { + } else if (timeout != 0) { if (prevTime == 0) { prevTime = JVM_CurrentTimeMillis(env, 0); } ret = NET_Timeout (fduse, timeout); if (ret <= 0) { if (ret == 0) { - JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", "Receive timed out"); } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return -1; } } /* receive the packet */ - n = recvfrom(fduse, fullPacket, packetBufferLen, MSG_PEEK, - (struct sockaddr *)&remote_addr, &remote_addrsize); - port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&remote_addr)); + n = recvfrom(fduse, packetBuffer, packetBufferOffset, packetBufferLen, MSG_PEEK, remote_addr); + port = ntohs (GET_PORT(remote_addr)); if (n == JVM_IO_ERR) { if (WSAGetLastError() == WSAECONNRESET) { - jboolean connected; + boolean connected; /* * An icmp port unreachable - we must receive this as Windows * does not reset the state of the socket until this has been * received. */ - purgeOutstandingICMP(env, this, fduse); + purgeOutstandingICMP(fduse); - connected = (*env)->GetBooleanField(env, this, pdsi_connected); + connected = _this.connected; if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", "ICMP Port Unreachable"); - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return -1; } @@ -1099,15 +1096,12 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi * we may have used up some of the timeout befor the icmp port * unreachable arrived. */ - if (timeout) { - jlong newTime = JVM_CurrentTimeMillis(env, 0); + if (timeout != 0) { + long newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); if (timeout <= 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Receive timed out"); - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return -1; } prevTime = newTime; @@ -1117,10 +1111,6 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi } } while (retry); - /* truncate the data if the packet's length is too small */ - if (n > packetBufferLen) { - n = packetBufferLen; - } if (n < 0) { errorCode = WSAGetLastError(); /* check to see if it's because the buffer was too small */ @@ -1132,52 +1122,47 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi n = packetBufferLen; } else { /* failure */ - (*env)->SetIntField(env, packet, dp_lengthID, 0); + packet.length = 0; } } if (n == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); } else if (n == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } else if (n < 0) { NET_ThrowCurrent(env, "Datagram receive failed"); } else { - jobject packetAddress; + InetAddress packetAddress; /* * Check if there is an InetAddress already associated with this * packet. If so we check if it is the same source address. We * can't update any existing InetAddress because it is immutable */ - packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); + packetAddress = packet.address; if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *) - &remote_addr, packetAddress)) { + if (!NET_SockaddrEqualsInetAddress(remote_addr, packetAddress)) { /* force a new InetAddress to be created */ - packetAddress = NULL; + packetAddress = null; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *) - &remote_addr, &port); + int[] tmp = { port }; + packetAddress = NET_SockaddrToInetAddress(remote_addr, tmp); + port = tmp[0]; /* stuff the new Inetaddress in the packet */ - (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); + packet.address = packetAddress; } /* populate the packet */ - (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, - (jbyte *)fullPacket); - (*env)->SetIntField(env, packet, dp_portID, port); - (*env)->SetIntField(env, packet, dp_lengthID, n); + packet.port = port; + packet.length = n; } /* make sure receive() picks up the right fd */ - (*env)->SetIntField(env, this, pdsi_fduseID, fduse); + _this.fduse = fduse; - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return port; } @@ -1186,66 +1171,64 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi * Method: receive * Signature: (Ljava/net/DatagramPacket;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this, - jobject packet) { - - char BUF[MAX_BUFFER_LEN]; - char *fullPacket; - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); - jbyteArray packetBuffer; - jint packetBufferOffset, packetBufferLen; - int ipv6_supported = ipv6_available(); +static void receive0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + int timeout = _this.timeout; + byte[] packetBuffer; + int packetBufferOffset, packetBufferLen; + boolean ipv6_supported = ipv6_available(); /* as a result of the changes for ipv6, peek() or peekData() * must be called prior to receive() so that fduse can be set. */ - int fd, fd1, fduse, errorCode; - jbyteArray data; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + cli.System.Net.Sockets.Socket fduse = null; + int errorCode; - int datalen; int n, nsockets=0; SOCKETADDRESS remote_addr; - jint remote_addrsize=sizeof(remote_addr); - BOOL retry; - jlong prevTime = 0, selectTime=0; - jboolean connected; + remote_addr = new SOCKETADDRESS(); + boolean retry; + long prevTime = 0, selectTime=0; + boolean connected; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); nsockets ++; } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); nsockets ++; } if (nsockets == 2) { /* need to choose one of them */ /* was fduse set in peek? */ - fduse = (*env)->GetIntField(env, this, pdsi_fduseID); - if (fduse == -1) { + fduse = _this.fduse; + if (fduse == null) { /* not set in peek(), must select on both sockets */ int ret, t = (timeout == 0) ? -1: timeout; - ret = NET_Timeout2 (fd, fd1, t, &fduse); + cli.System.Net.Sockets.Socket[] tmp = new cli.System.Net.Sockets.Socket[] { fduse }; + ret = NET_Timeout2 (fd, fd1, t, tmp); + fduse = tmp[0]; if (ret == 2) { - fduse = checkLastFD (env, this, fd, fd1); + fduse = checkLastFD (_this, fd, fd1); } else if (ret <= 0) { if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Receive timed out"); } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } return; @@ -1266,16 +1249,17 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi return; } - packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID); + packetBuffer = packet.buf; if (IS_NULL(packetBuffer)) { JNU_ThrowNullPointerException(env, "packet buffer"); return; } - packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); - packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); + packetBufferOffset = packet.offset; + packetBufferLen = packet.bufLength; + /* if (packetBufferLen > MAX_BUFFER_LEN) { /* When JNI-ifying the JDK's IO routines, we turned @@ -1288,7 +1272,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi * we *must* alloc the buffer. Note it needn't be bigger * than 65,536 (0xFFFF) the max size of an IP packet. * anything bigger is truncated anyway. - */ + *-/ fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); @@ -1297,6 +1281,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi } else { fullPacket = &(BUF[0]); } + */ @@ -1309,28 +1294,25 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi * t2 < t1. In this case we must discard the ICMP packets and then * wait for the next packet up to a maximum of t1 minus t2. */ - connected = (*env)->GetBooleanField(env, this, pdsi_connected); - if (supportPortUnreachable() && !connected && timeout &&!ipv6_supported) { + connected = _this.connected; + if (supportPortUnreachable() && !connected && timeout != 0 &&!ipv6_supported) { prevTime = JVM_CurrentTimeMillis(env, 0); } - if (timeout && nsockets == 1) { + if (timeout != 0 && nsockets == 1) { int ret; ret = NET_Timeout(fduse, timeout); if (ret <= 0) { if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Receive timed out"); } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return; } } @@ -1342,8 +1324,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi retry = FALSE; /* receive the packet */ - n = recvfrom(fduse, fullPacket, packetBufferLen, 0, - (struct sockaddr *)&remote_addr, &remote_addrsize); + n = recvfrom(fduse, packetBuffer, packetBufferOffset, packetBufferLen, 0, remote_addr); if (n == JVM_IO_ERR) { if (WSAGetLastError() == WSAECONNRESET) { @@ -1351,20 +1332,15 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi * An icmp port unreachable has been received - consume any other * outstanding packets. */ - purgeOutstandingICMP(env, this, fduse); + purgeOutstandingICMP(fduse); /* * If connected throw a PortUnreachableException */ if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", "ICMP Port Unreachable"); - - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return; } @@ -1373,9 +1349,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi * we may have used up some of the timeout before the icmp port * unreachable arrived. */ - if (timeout) { + if (timeout != 0) { int ret; - jlong newTime = JVM_CurrentTimeMillis(env, 0); + long newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); prevTime = newTime; @@ -1387,18 +1363,15 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi if (ret <= 0) { if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Receive timed out"); } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } return; } } @@ -1412,10 +1385,6 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi } } while (retry); - /* truncate the data if the packet's length is too small */ - if (n > packetBufferLen) { - n = packetBufferLen; - } if (n < 0) { errorCode = WSAGetLastError(); /* check to see if it's because the buffer was too small */ @@ -1427,49 +1396,46 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi n = packetBufferLen; } else { /* failure */ - (*env)->SetIntField(env, packet, dp_lengthID, 0); + packet.length = 0; } } if (n == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); } else if (n == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } else if (n < 0) { NET_ThrowCurrent(env, "Datagram receive failed"); } else { int port; - jobject packetAddress; + InetAddress packetAddress; /* * Check if there is an InetAddress already associated with this * packet. If so we check if it is the same source address. We * can't update any existing InetAddress because it is immutable */ - packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); + packetAddress = packet.address; if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) { + if (!NET_SockaddrEqualsInetAddress(remote_addr, packetAddress)) { /* force a new InetAddress to be created */ - packetAddress = NULL; + packetAddress = null; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port); + int[] tmp = { 0 }; + packetAddress = NET_SockaddrToInetAddress(remote_addr, tmp); + port = tmp[0]; /* stuff the new Inetaddress in the packet */ - (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); + packet.address = packetAddress; } else { /* only get the new port number */ - port = NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr); + port = NET_GetPortFromSockaddr(remote_addr); } /* populate the packet */ - (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, - (jbyte *)fullPacket); - (*env)->SetIntField(env, packet, dp_portID, port); - (*env)->SetIntField(env, packet, dp_lengthID, n); - } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); + packet.port = port; + packet.length = n; } } @@ -1478,32 +1444,25 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi * Method: datagramSocketCreate * Signature: ()V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, - jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - - int fd, fd1; - int t = TRUE; - DWORD x1, x2; /* ignored result codes */ - int ipv6_supported = ipv6_available(); - - int arg = -1; +static void datagramSocketCreate(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + boolean ipv6_supported = ipv6_available(); if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } else { - fd = (int) socket (AF_INET, SOCK_DGRAM, 0); + fd = socket (AF_INET, SOCK_DGRAM, 0); } - if (fd == JVM_IO_ERR) { + if (fd == INVALID_SOCKET) { NET_ThrowCurrent(env, "Socket creation failed"); return; } - SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); - NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); + fdObj.setSocket(fd); + NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, true); if (ipv6_supported) { /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which @@ -1511,22 +1470,18 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, * as connected sockets. The solution is to only enable this feature * when the socket is connected */ - t = FALSE; - WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); - t = TRUE; + WSAIoctl(fd,SIO_UDP_CONNRESET,false); fd1 = socket (AF_INET6, SOCK_DGRAM, 0); - if (fd1 == JVM_IO_ERR) { + if (fd1 == INVALID_SOCKET) { NET_ThrowCurrent(env, "Socket creation failed"); return; } - NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); - t = FALSE; - WSAIoctl(fd1,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); - SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE); + NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, true); + WSAIoctl(fd1,SIO_UDP_CONNRESET,false); + fd1Obj.setSocket(fd1); } else { /* drop the second fd */ - (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); + _this.fd1 = null; } } @@ -1535,35 +1490,33 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, * Method: datagramSocketClose * Signature: ()V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env, - jobject this) { +static void datagramSocketClose(TwoStacksPlainDatagramSocketImpl _this) { /* * REMIND: PUT A LOCK AROUND THIS CODE */ - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - int ipv6_supported = ipv6_available(); - int fd=-1, fd1=-1; + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + boolean ipv6_supported = ipv6_available(); + cli.System.Net.Sockets.Socket fd = null, fd1 = null; if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) { return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (fd != -1) { - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + fd = fdObj.getSocket(); + if (fd != null) { + fdObj.setSocket(null); NET_SocketClose(fd); } } if (ipv6_supported && fd1Obj != NULL) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - if (fd1 == -1) { + fd1 = fd1Obj.getSocket(); + if (fd1 == null) { return; } - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); + fd1Obj.setSocket(null); NET_SocketClose(fd1); } } @@ -1574,84 +1527,87 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env, * in *iaddr */ -static int getInetAddrFromIf (JNIEnv *env, int family, jobject nif, jobject *iaddr) +private static int getInetAddrFromIf (JNIEnv env, int family, NetworkInterface nif, InetAddress[] iaddr) { - jobjectArray addrArray; - static jfieldID ni_addrsID=0; - static jfieldID ia_familyID=0; - jsize len; - jobject addr; + InetAddress[] addrArray; + int len; + InetAddress addr; int i; - if (ni_addrsID == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN (c, -1); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN (ni_addrsID, -1); - c = (*env)->FindClass(env,"java/net/InetAddress"); - CHECK_NULL_RETURN (c, -1); - ia_familyID = (*env)->GetFieldID(env, c, "family", "I"); - CHECK_NULL_RETURN (ia_familyID, -1); - } - - addrArray = (*env)->GetObjectField(env, nif, ni_addrsID); - len = (*env)->GetArrayLength(env, addrArray); + addrArray = getNetworkInterfaceAddresses(nif); + len = addrArray.length; /* * Check that there is at least one address bound to this * interface. */ if (len < 1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface"); return -1; } for (i=0; i<len; i++) { int fam; - addr = (*env)->GetObjectArrayElement(env, addrArray, i); - fam = (*env)->GetIntField(env, addr, ia_familyID); + addr = addrArray[i]; + fam = addr.family; if (fam == family) { - *iaddr = addr; + iaddr[0] = addr; return 0; } } return -1; } -static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr) +private static int getInet4AddrFromIf (JNIEnv env, NetworkInterface nif, in_addr iaddr) { - jobject addr; - static jfieldID ia_addressID; + InetAddress[] addr = new InetAddress[1]; - int ret = getInetAddrFromIf (env, IPv4, nif, &addr); + int ret = getInetAddrFromIf (env, IPv4, nif, addr); if (ret == -1) { return -1; } - if (ia_addressID == 0) { - jclass c = (*env)->FindClass(env,"java/net/InetAddress"); - CHECK_NULL_RETURN (c, -1); - ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); - CHECK_NULL_RETURN (ia_addressID, -1); - } - iaddr->s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID)); + iaddr.s_addr = htonl(addr[0].address); return 0; } /* Get the multicasting index from the interface */ -static int getIndexFromIf (JNIEnv *env, jobject nif) { - static jfieldID ni_indexID; +private static int getIndexFromIf (JNIEnv env, NetworkInterface nif) { + return nif.getIndex(); +} - if (ni_indexID == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, -1); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, -1); +private static InetAddress[] getNetworkInterfaceAddresses(final NetworkInterface nif) { + // [IKVM] this is IKVM specific, because I don't want to use reflection (or map.xml hacks) to access the "addrs" member of NetworkInterface + return java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<InetAddress[]>() { + public InetAddress[] run() { + java.util.ArrayList<InetAddress> list = new java.util.ArrayList<InetAddress>(); + for (java.util.Enumeration<InetAddress> e = nif.getInetAddresses(); e.hasMoreElements(); ) { + list.add(e.nextElement()); + } + return list.toArray(new InetAddress[list.size()]); + } + }); +} + +private static NetworkInterface Java_java_net_NetworkInterface_getByIndex(JNIEnv env, int ni_class, int index) +{ + try { + return NetworkInterface.getByIndex(index); + } catch (Exception x) { + env.Throw(x); + return null; } +} - return (*env)->GetIntField(env, nif, ni_indexID); +private static NetworkInterface Java_java_net_NetworkInterface_getByInetAddress0(JNIEnv env, int ni_class, Object address) +{ + try { + return NetworkInterface.getByInetAddress((InetAddress)address); + } catch (Exception x) { + env.Throw(x); + return null; + } } /* @@ -1677,10 +1633,10 @@ static int getIndexFromIf (JNIEnv *env, jobject nif) { * IPPROTO_IPV6/IPV6_MULTICAST_IF * */ -static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, - jint opt, jobject value) +private static void setMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, + int opt, Object value) { - int ipv6_supported = ipv6_available(); + boolean ipv6_supported = ipv6_available(); if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { /* @@ -1691,40 +1647,24 @@ static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, * option instead of IP_MULTICAST_IF */ if (ipv6_supported) { - static jclass ni_class; - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL(c); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL(ni_class); - } - value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value); if (value == NULL) { - if (!(*env)->ExceptionOccurred(env)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + if (env.ExceptionOccurred() == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "bad argument for IP_MULTICAST_IF" - ": address not bound to any interface"); + +": address not bound to any interface"); } return; } opt = java_net_SocketOptions_IP_MULTICAST_IF2; } else { - static jfieldID ia_addressID; - struct in_addr in; - - if (ia_addressID == NULL) { - jclass c = (*env)->FindClass(env,"java/net/InetAddress"); - CHECK_NULL(c); - ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); - CHECK_NULL(ia_addressID); - } + in_addr in = new in_addr(); - in.s_addr = htonl((*env)->GetIntField(env, value, ia_addressID)); + in.s_addr = htonl(((InetAddress)value).address); if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error setting socket option"); } return; @@ -1740,26 +1680,19 @@ static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, * option. For IPv6 both must be done. */ if (ipv6_supported) { - static jfieldID ni_indexID; - struct in_addr in; + in_addr in = new in_addr(); int index; - if (ni_indexID == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL(c); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL(ni_indexID); - } - index = (*env)->GetIntField(env, value, ni_indexID); + index = ((NetworkInterface)value).getIndex(); if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (const char*)&index, sizeof(index)) < 0) { - if (errno == EINVAL && index > 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + index) < 0) { + if (WSAGetLastError() == WSAEINVAL && index > 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IPV6_MULTICAST_IF failed (interface has IPv4 " - "address only?)"); + +"address only?)"); } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error setting socket option"); } return; @@ -1768,30 +1701,30 @@ static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, /* If there are any IPv4 addresses on this interface then * repeat the operation on the IPv4 fd */ - if (getInet4AddrFromIf (env, value, &in) < 0) { + if (getInet4AddrFromIf (env, (NetworkInterface)value, in) < 0) { return; } if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error setting socket option"); } return; } else { - struct in_addr in; + in_addr in = new in_addr(); - if (getInet4AddrFromIf (env, value, &in) < 0) { - if ((*env)->ExceptionOccurred(env)) { + if (getInet4AddrFromIf (env, (NetworkInterface)value, in) < 0) { + if (env.ExceptionOccurred() != null) { return; } - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "no InetAddress instances of requested type"); return; } if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error setting socket option"); } return; @@ -1804,32 +1737,30 @@ static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, * Method: socketSetOption * Signature: (ILjava/lang/Object;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobject this, - jint opt,jobject value) { - - int fd=-1, fd1=-1; - int levelv4, levelv6, optnamev4, optnamev6, optlen; - union { - int i; - char c; - } optval; - int ipv6_supported = ipv6_available(); - - fd = getFD(env, this); +static void socketSetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt, Object value) { + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int[] levelv4 = new int[1]; + int[] levelv6 = new int[1]; + int[] optnamev4 = new int[1]; + int[] optnamev6 = new int[1]; + Object optval; + boolean ipv6_supported = ipv6_available(); + + fd = getFD(env, _this); if (ipv6_supported) { - fd1 = getFD1(env, this); + fd1 = getFD1(env, _this); } - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return; } if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { - setMulticastInterface(env, this, fd, fd1, opt, value); + setMulticastInterface(env, _this, fd, fd1, opt, value); return; } @@ -1837,15 +1768,15 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobje * Map the Java level socket option to the platform specific * level(s) and option name(s). */ - if (fd1 != -1) { - if (NET_MapSocketOptionV6(opt, &levelv6, &optnamev6)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + if (fd1 != null) { + if (NET_MapSocketOptionV6(opt, levelv6, optnamev6) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); return; } } - if (fd != -1) { - if (NET_MapSocketOption(opt, &levelv4, &optnamev4)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + if (fd != null) { + if (NET_MapSocketOption(opt, levelv4, optnamev4) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); return; } } @@ -1854,61 +1785,39 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobje case java_net_SocketOptions_SO_SNDBUF : case java_net_SocketOptions_SO_RCVBUF : case java_net_SocketOptions_IP_TOS : - { - jclass cls; - jfieldID fid; - - cls = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "I"); - CHECK_NULL(fid); - - optval.i = (*env)->GetIntField(env, value, fid); - optlen = sizeof(optval.i); - } + optval = ((Integer)value).intValue(); break; case java_net_SocketOptions_SO_REUSEADDR: case java_net_SocketOptions_SO_BROADCAST: case java_net_SocketOptions_IP_MULTICAST_LOOP: { - jclass cls; - jfieldID fid; - jboolean on; - - cls = (*env)->FindClass(env, "java/lang/Boolean"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "Z"); - CHECK_NULL(fid); - - on = (*env)->GetBooleanField(env, value, fid); - optval.i = (on ? 1 : 0); + boolean on = ((Boolean)value).booleanValue(); + optval = on; /* * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather * than enabling it. */ if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) { - optval.i = !optval.i; + optval = !on; } - optlen = sizeof(optval.i); } break; default : - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket option not supported by PlainDatagramSocketImp"); - break; - + return; } - if (fd1 != -1) { - if (NET_SetSockOpt(fd1, levelv6, optnamev6, (void *)&optval, optlen) < 0) { + if (fd1 != null) { + if (NET_SetSockOpt(fd1, levelv6[0], optnamev6[0], optval) < 0) { NET_ThrowCurrent(env, "setsockopt IPv6"); return; } } - if (fd != -1) { - if (NET_SetSockOpt(fd, levelv4, optnamev4, (void *)&optval, optlen) < 0) { + if (fd != null) { + if (NET_SetSockOpt(fd, levelv4[0], optnamev4[0], optval) < 0) { NET_ThrowCurrent(env, "setsockopt"); return; } @@ -1940,33 +1849,20 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobje * Query NetworkInterface by index and * return NetworkInterface. */ -jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint opt) { - jboolean isIPV4 = !ipv6_available() || fd1 == -1; +private static Object getMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, int opt) { + boolean isIPV4 = !ipv6_available() || fd1 == null; /* * IPv4 implementation */ if (isIPV4) { - static jclass inet4_class; - static jmethodID inet4_ctrID; - static jfieldID inet4_addrID; - - static jclass ni_class; - static jmethodID ni_ctrID; - static jfieldID ni_indexID; - static jfieldID ni_addrsID; + Inet4Address addr; - jobjectArray addrArray; - jobject addr; - jobject ni; - - struct in_addr in; - struct in_addr *inP = ∈ - int len = sizeof(struct in_addr); + in_addr in = new in_addr(); if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (char *)inP, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + in) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error getting socket option"); return NULL; } @@ -1974,20 +1870,8 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o /* * Construct and populate an Inet4Address */ - if (inet4_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); - CHECK_NULL_RETURN(c, NULL); - inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); - CHECK_NULL_RETURN(inet4_ctrID, NULL); - inet4_addrID = (*env)->GetFieldID(env, c, "address", "I"); - CHECK_NULL_RETURN(inet4_addrID, NULL); - inet4_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(inet4_class, NULL); - } - addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0); - CHECK_NULL_RETURN(addr, NULL); - - (*env)->SetIntField(env, addr, inet4_addrID, ntohl(in.s_addr)); + addr = new Inet4Address(); + addr.address = ntohl(in.s_addr); /* * For IP_MULTICAST_IF return InetAddress @@ -1996,25 +1880,9 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o return addr; } - /* - * For IP_MULTICAST_IF2 we get the NetworkInterface for - * this address and return it - */ - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, NULL); - ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); - CHECK_NULL_RETURN(ni_ctrID, NULL); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, NULL); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ni_addrsID, NULL); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(ni_class, NULL); - } + NetworkInterface ni; ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); - if (ni) { + if (ni != null) { return ni; } @@ -2023,15 +1891,7 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o * NetworkInterface. Therefore we construct a NetworkInterface * with this address. */ - ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); - CHECK_NULL_RETURN(ni, NULL); - - (*env)->SetIntField(env, ni, ni_indexID, -1); - addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL); - CHECK_NULL_RETURN(addrArray, NULL); - (*env)->SetObjectArrayElement(env, addrArray, 0, addr); - (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); - return ni; + return new NetworkInterface(null, -1, new InetAddress[] { addr }); } @@ -2041,51 +1901,21 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { - static jclass ni_class; - static jmethodID ni_ctrID; - static jfieldID ni_indexID; - static jfieldID ni_addrsID; - static jclass ia_class; - static jmethodID ia_anyLocalAddressID; - int index; - int len = sizeof(index); - jobjectArray addrArray; - jobject addr; - jobject ni; + InetAddress[] addrArray; + InetAddress addr; + NetworkInterface ni; { + int[] tmp = { 0 }; if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (char*)&index, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + tmp) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error getting socket option"); return NULL; } - } - - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, NULL); - ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); - CHECK_NULL_RETURN(ni_ctrID, NULL); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, NULL); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ni_addrsID, NULL); - - ia_class = (*env)->FindClass(env, "java/net/InetAddress"); - CHECK_NULL_RETURN(ia_class, NULL); - ia_class = (*env)->NewGlobalRef(env, ia_class); - CHECK_NULL_RETURN(ia_class, NULL); - ia_anyLocalAddressID = (*env)->GetStaticMethodID(env, - ia_class, - "anyLocalAddress", - "()Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(ni_class, NULL); + index = tmp[0]; } /* @@ -2097,11 +1927,8 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o ni = Java_java_net_NetworkInterface_getByIndex(env, ni_class, index); if (ni == NULL) { - char errmsg[255]; - sprintf(errmsg, - "IPV6_MULTICAST_IF returned index to unrecognized interface: %d", - index); - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); + String errmsg = "IPV6_MULTICAST_IF returned index to unrecognized interface: " + index; + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", errmsg); return NULL; } @@ -2115,14 +1942,14 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o /* * For IP_MULTICAST_IF return addrs[0] */ - addrArray = (*env)->GetObjectField(env, ni, ni_addrsID); - if ((*env)->GetArrayLength(env, addrArray) < 1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + addrArray = getNetworkInterfaceAddresses(ni); + if (addrArray.length < 1) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IPV6_MULTICAST_IF returned interface without IP bindings"); return NULL; } - addr = (*env)->GetObjectArrayElement(env, addrArray, 0); + addr = addrArray[0]; return addr; } @@ -2131,20 +1958,12 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o * or a NetworkInterface with addrs[0] set to anyLocalAddress */ - addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID, - NULL); + addr = InetAddress.anyLocalAddress(); if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { return addr; } - ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); - CHECK_NULL_RETURN(ni, NULL); - (*env)->SetIntField(env, ni, ni_indexID, -1); - addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL); - CHECK_NULL_RETURN(addrArray, NULL); - (*env)->SetObjectArrayElement(env, addrArray, 0, addr); - (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); - return ni; + return new NetworkInterface(null, -1, new InetAddress[] { addr }); } return NULL; } @@ -2155,24 +1974,21 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint o * Method: socketGetOption * Signature: (I)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, - jint opt) { - - int fd=-1, fd1=-1; - int level, optname, optlen; - union { - int i; - } optval; - int ipv6_supported = ipv6_available(); - - fd = getFD(env, this); +static Object socketGetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt) { + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int[] level = new int[1]; + int[] optname = new int[1]; + int[] optval = new int[1]; + boolean ipv6_supported = ipv6_available(); + + fd = getFD(env, _this); if (ipv6_supported) { - fd1 = getFD1(env, this); + fd1 = getFD1(env, _this); } - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return NULL; } @@ -2182,29 +1998,25 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobj */ if (opt == java_net_SocketOptions_IP_MULTICAST_IF || opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - return getMulticastInterface(env, this, fd, fd1, opt); + return getMulticastInterface(env, _this, fd, fd1, opt); } if (opt == java_net_SocketOptions_SO_BINDADDR) { /* find out local IP address */ SOCKETADDRESS him; - int len = 0; - int port; - jobject iaObj; - - len = sizeof (struct sockaddr_in); + him = new SOCKETADDRESS(); + InetAddress iaObj; - if (fd == -1) { + if (fd == null) { fd = fd1; /* must be IPv6 only */ - len = sizeof (struct SOCKADDR_IN6); } - if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + if (getsockname(fd, him) == -1) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error getting socket name"); return NULL; } - iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); + iaObj = NET_SockaddrToInetAddress(him, new int[1]); return iaObj; } @@ -2213,43 +2025,41 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobj * Map the Java level socket option to the platform specific * level and option name. */ - if (NET_MapSocketOption(opt, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + if (NET_MapSocketOption(opt, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); return NULL; } - if (fd == -1) { - if (NET_MapSocketOptionV6(opt, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + if (fd == null) { + if (NET_MapSocketOptionV6(opt, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); return NULL; } fd = fd1; /* must be IPv6 only */ } - optlen = sizeof(optval.i); - if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { - char errmsg[255]; - sprintf(errmsg, "error getting socket option: %s\n", strerror(errno)); - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); + if (NET_GetSockOpt(fd, level[0], optname[0], optval) < 0) { + String errmsg = "error getting socket option: " + WSAGetLastError(); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", errmsg); return NULL; } switch (opt) { case java_net_SocketOptions_SO_BROADCAST: case java_net_SocketOptions_SO_REUSEADDR: - return createBoolean(env, optval.i); + return optval[0] != 0; case java_net_SocketOptions_IP_MULTICAST_LOOP: /* getLoopbackMode() returns true if IP_MULTICAST_LOOP is disabled */ - return createBoolean(env, !optval.i); + return optval[0] == 0; case java_net_SocketOptions_SO_SNDBUF: case java_net_SocketOptions_SO_RCVBUF: case java_net_SocketOptions_IP_TOS: - return createInteger(env, optval.i); + return optval[0]; default : - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket option not supported by TwoStacksPlainDatagramSocketImpl"); return NULL; @@ -2261,39 +2071,34 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobj * Method: setTimeToLive * Signature: (I)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this, - jint ttl) { - - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - int fd = -1, fd1 = -1; - int ittl = (int)ttl; +static void setTimeToLive(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int ttl) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } else { if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } } /* setsockopt to be correct ttl */ - if (fd >= 0) { - if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl, - sizeof (ittl)) < 0) { + if (fd != null) { + if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl) < 0) { NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); } } - if (fd1 >= 0) { - if (NET_SetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ittl, - sizeof(ittl)) <0) { + if (fd1 != null) { + if (NET_SetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl) <0) { NET_ThrowCurrent(env, "set IPV6_MULTICAST_HOPS failed"); } } @@ -2304,11 +2109,8 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobjec * Method: setTTL * Signature: (B)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_setTTL(JNIEnv *env, jobject this, - jbyte ttl) { - Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(env, this, - (jint)ttl & 0xFF); +static void setTTL(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, byte ttl) { + setTimeToLive(env, _this, ttl & 0xFF); } /* @@ -2316,41 +2118,40 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_setTTL(JNIEnv *env, jobject this, * Method: getTimeToLive * Signature: ()I */ -JNIEXPORT jint JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - int fd = -1, fd1 = -1; - int ttl = 0; - int len = sizeof(ttl); +static int getTimeToLive(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + int[] ttl = new int[1]; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return -1; } else { if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } } /* getsockopt of ttl */ - if (fd >= 0) { - if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, &len) < 0) { + if (fd != null) { + if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl) < 0) { NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); return -1; } - return (jint)ttl; + return ttl[0]; } - if (fd1 >= 0) { - if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&ttl, &len) < 0) { + if (fd1 != null) { + if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl) < 0) { NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); return -1; } - return (jint)ttl; + return ttl[0]; } return -1; } @@ -2360,45 +2161,44 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobjec * Method: getTTL * Signature: ()B */ -JNIEXPORT jbyte JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_getTTL(JNIEnv *env, jobject this) { - int result = Java_java_net_TwoStacksPlainDatagramSocketImpl_getTimeToLive(env, this); +static byte getTTL(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { + int result = getTimeToLive(env, _this); - return (jbyte)result; + return (byte)result; } /* join/leave the named group on the named interface, or if no interface specified * then the interface set with setInterfac(), or the default interface otherwise */ -static void mcast_join_leave(JNIEnv *env, jobject this, - jobject iaObj, jobject niObj, - jboolean join) +private static void mcast_join_leave(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress iaObj, NetworkInterface niObj, boolean join) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - jint fd = -1, fd1 = -1; + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; SOCKETADDRESS name; - struct ip_mreq mname; - struct ipv6_mreq mname6; + name = new SOCKETADDRESS(); + ip_mreq mname = new ip_mreq(); + ipv6_mreq mname6 = new ipv6_mreq(); - struct in_addr in; - DWORD ifindex; + in_addr in = new in_addr(); + int ifindex; - int len, family; - int ipv6_supported = ipv6_available(); + int family; + boolean ipv6_supported = ipv6_available(); int cmd ; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (ipv6_supported && !IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } if (IS_NULL(iaObj)) { @@ -2406,7 +2206,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this, return; } - if (NET_InetAddressToSockaddr(env, iaObj, 0, (struct sockaddr *)&name, &len, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, 0, name, JNI_FALSE) != 0) { return; } @@ -2418,24 +2218,22 @@ static void mcast_join_leave(JNIEnv *env, jobject this, if (family == AF_INET) { int address = name.him4.sin_addr.s_addr; if (!IN_MULTICAST(ntohl(address))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "not in multicast"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "not in multicast"); return; } mname.imr_multiaddr.s_addr = address; - if (fd < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Can't join an IPv4 group on an IPv6 only socket"); + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Can't join an IPv4 group on an IPv6 only socket"); return; } if (IS_NULL(niObj)) { - len = sizeof (in); - if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&in, &len) < 0) { + if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, in) < 0) { NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed"); return; } mname.imr_interface.s_addr = in.s_addr; } else { - if (getInet4AddrFromIf (env, niObj, &mname.imr_interface) != 0) { + if (getInet4AddrFromIf (env, niObj, mname.imr_interface) != 0) { NET_ThrowCurrent(env, "no Inet4Address associated with interface"); return; } @@ -2444,37 +2242,38 @@ static void mcast_join_leave(JNIEnv *env, jobject this, cmd = join ? IP_ADD_MEMBERSHIP: IP_DROP_MEMBERSHIP; /* Join the multicast group */ - if (NET_SetSockOpt(fd, IPPROTO_IP, cmd, (char *) &mname, sizeof (mname)) < 0) { + if (NET_SetSockOpt(fd, IPPROTO_IP, cmd, mname) < 0) { if (WSAGetLastError() == WSAENOBUFS) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException","error setting options"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException","error setting options"); } } } else /* AF_INET6 */ { if (ipv6_supported) { - struct in6_addr *address; - address = &name.him6.sin6_addr; + in6_addr address; + address = in6_addr.FromSockAddr(name); if (!IN6_IS_ADDR_MULTICAST(address)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "not in6 multicast"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "not in6 multicast"); return; } - mname6.ipv6mr_multiaddr = *address; + mname6.ipv6mr_multiaddr = address; } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPv6 not supported"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IPv6 not supported"); return; } - if (fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Can't join an IPv6 group on a IPv4 socket"); + if (fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Can't join an IPv6 group on a IPv4 socket"); return; } if (IS_NULL(niObj)) { - len = sizeof (ifindex); - if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, &len) < 0) { + int[] tmp = { 0 }; + if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, tmp) < 0) { NET_ThrowCurrent(env, "get IPV6_MULTICAST_IF failed"); return; } + ifindex = tmp[0]; } else { ifindex = getIndexFromIf (env, niObj); if (ifindex == -1) { @@ -2486,12 +2285,12 @@ static void mcast_join_leave(JNIEnv *env, jobject this, cmd = join ? IPV6_ADD_MEMBERSHIP: IPV6_DROP_MEMBERSHIP; /* Join the multicast group */ - if (NET_SetSockOpt(fd1, IPPROTO_IPV6, cmd, (char *) &mname6, sizeof (mname6)) < 0) { + if (NET_SetSockOpt(fd1, IPPROTO_IPV6, cmd, mname6) < 0) { if (WSAGetLastError() == WSAENOBUFS) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException","error setting options"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException","error setting options"); } } } @@ -2504,11 +2303,8 @@ static void mcast_join_leave(JNIEnv *env, jobject this, * Method: join * Signature: (Ljava/net/InetAddress;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_join(JNIEnv *env, jobject this, - jobject iaObj, jobject niObj) -{ - mcast_join_leave (env, this, iaObj, niObj, JNI_TRUE); +static void join(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress inetaddr, NetworkInterface netIf) { + mcast_join_leave(env, _this, inetaddr, netIf, true); } /* @@ -2516,9 +2312,8 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_join(JNIEnv *env, jobject this, * Method: leave * Signature: (Ljava/net/InetAddress;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_leave(JNIEnv *env, jobject this, - jobject iaObj, jobject niObj) -{ - mcast_join_leave (env, this, iaObj, niObj, JNI_FALSE); +static void leave(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress inetaddr, NetworkInterface netIf) { + mcast_join_leave(env, _this, inetaddr, netIf, false); +} + } diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl.java b/openjdk/java/net/TwoStacksPlainSocketImpl.java index 9475bd3f..873d5d5f 100644 --- a/openjdk/java/net/TwoStacksPlainSocketImpl.java +++ b/openjdk/java/net/TwoStacksPlainSocketImpl.java @@ -37,6 +37,7 @@ import java.io.FileDescriptor; * during socket creation. * * @author Chris Hegarty + * @author Jeroen Frijters */ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl @@ -51,7 +52,7 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl * For ServerSockets, fd always refers to the v4 listener and * fd1 the v6 listener. */ - private FileDescriptor fd1; + FileDescriptor fd1; /* * Needed for ipv6 on windows because we need to know @@ -63,11 +64,7 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl /* to prevent starvation when listening on two sockets, this is * is used to hold the id of the last socket we accepted on. */ - private int lastfd = -1; - - static { - initProto(); - } + cli.System.Net.Sockets.Socket lastfd = null; public TwoStacksPlainSocketImpl() {} @@ -173,34 +170,87 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl } /* Native methods */ + + void socketCreate(boolean stream) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketCreate(env, this, stream); + env.ThrowPendingException(); + } - static native void initProto(); - - native void socketCreate(boolean isServer) throws IOException; - - native void socketConnect(InetAddress address, int port, int timeout) - throws IOException; + void socketConnect(InetAddress address, int port, int timeout) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketConnect(env, this, address, port, timeout); + env.ThrowPendingException(); + } + + void socketBind(InetAddress address, int localport) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketBind(env, this, address, localport); + env.ThrowPendingException(); + } + + void socketListen(int count) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketListen(env, this, count); + env.ThrowPendingException(); + } - native void socketBind(InetAddress address, int port) - throws IOException; + void socketAccept(SocketImpl socket) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketAccept(env, this, socket); + env.ThrowPendingException(); + } - native void socketListen(int count) throws IOException; + int socketAvailable() throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainSocketImpl_c.socketAvailable(env, this); + env.ThrowPendingException(); + return ret; + } - native void socketAccept(SocketImpl s) throws IOException; + void socketClose0(boolean useDeferredClose) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketClose0(env, this, useDeferredClose); + env.ThrowPendingException(); + } - native int socketAvailable() throws IOException; + void socketShutdown(int howto) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketShutdown(env, this, howto); + env.ThrowPendingException(); + } - native void socketClose0(boolean useDeferredClose) throws IOException; + void socketSetOption(int cmd, boolean on, Object value) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketSetOption(env, this, cmd, on, value); + env.ThrowPendingException(); + } - native void socketShutdown(int howto) throws IOException; + int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + int ret = TwoStacksPlainSocketImpl_c.socketGetOption(env, this, opt, iaContainerObj); + env.ThrowPendingException(); + return ret; + } - native void socketSetOption(int cmd, boolean on, Object value) - throws SocketException; + int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException { + throw new UnsatisfiedLinkError(); + } - native int socketGetOption(int opt, Object iaContainerObj) throws SocketException; + void socketSendUrgentData(int data) throws IOException { + ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); + TwoStacksPlainSocketImpl_c.socketSendUrgentData(env, this, data); + env.ThrowPendingException(); + } +} - native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) - throws SocketException; +// we don't support a dual-stack approach yet, so we simply make it an alias for the two-stacks approach +class DualStackPlainSocketImpl extends TwoStacksPlainSocketImpl +{ + DualStackPlainSocketImpl() { + } - native void socketSendUrgentData(int data) throws IOException; + DualStackPlainSocketImpl(FileDescriptor fd) { + super(fd); + } } diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java index cd694933..4764acfc 100644 --- a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java +++ b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java @@ -22,7 +22,32 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ +package java.net; +import java.io.FileDescriptor; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; +import static java.net.net_util_md.*; +import static java.net.InetAddress.IPv4; +import static java.net.InetAddress.IPv6; + +final class TwoStacksPlainSocketImpl_c +{ +static final int JVM_IO_ERR = -1; +static final int JVM_IO_INTR = -2; + +static final int java_net_SocketOptions_SO_TIMEOUT = SocketOptions.SO_TIMEOUT; +static final int java_net_SocketOptions_SO_BINDADDR = SocketOptions.SO_BINDADDR; +static final int java_net_SocketOptions_SO_SNDBUF = SocketOptions.SO_SNDBUF; +static final int java_net_SocketOptions_SO_RCVBUF = SocketOptions.SO_RCVBUF; +static final int java_net_SocketOptions_IP_TOS = SocketOptions.IP_TOS; +static final int java_net_SocketOptions_SO_REUSEADDR = SocketOptions.SO_REUSEADDR; +static final int java_net_SocketOptions_TCP_NODELAY = SocketOptions.TCP_NODELAY; +static final int java_net_SocketOptions_SO_OOBINLINE = SocketOptions.SO_OOBINLINE; +static final int java_net_SocketOptions_SO_KEEPALIVE = SocketOptions.SO_KEEPALIVE; +static final int java_net_SocketOptions_SO_LINGER = SocketOptions.SO_LINGER; + +/* #include <windows.h> #include <winsock2.h> #include <ctype.h> @@ -41,11 +66,13 @@ #include "jvm.h" #include "net_util.h" #include "jni_util.h" +*/ /************************************************************************ * TwoStacksPlainSocketImpl */ +/* static jfieldID IO_fd_fdID; jfieldID psi_fdID; @@ -57,6 +84,7 @@ jfieldID psi_timeoutID; jfieldID psi_trafficClassID; jfieldID psi_serverSocketID; jfieldID psi_lastfdID; +*/ /* * the level of the TCP protocol for setsockopt and getsockopt @@ -65,22 +93,22 @@ jfieldID psi_lastfdID; */ static int tcp_level = -1; -static int getFD(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); +static cli.System.Net.Sockets.Socket getFD(JNIEnv env, TwoStacksPlainSocketImpl _this) { + FileDescriptor fdObj = _this.fd; if (fdObj == NULL) { - return -1; + return null; } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); + return fdObj.getSocket(); } -static int getFD1(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID); +static cli.System.Net.Sockets.Socket getFD1(JNIEnv env, TwoStacksPlainSocketImpl _this) { + FileDescriptor fdObj = _this.fd1; if (fdObj == NULL) { - return -1; + return null; } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); + return fdObj.getSocket(); } @@ -94,6 +122,7 @@ static int getFD1(JNIEnv *env, jobject this) { * Signature: ()V */ +/* JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) { @@ -123,55 +152,53 @@ Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) { IO_fd_fdID = NET_GetFileDescriptorID(env); CHECK_NULL(IO_fd_fdID); } +*/ /* * Class: java_net_TwoStacksPlainSocketImpl * Method: socketCreate * Signature: (Z)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this, - jboolean stream) { - jobject fdObj, fd1Obj; - int fd, fd1; - - fdObj = (*env)->GetObjectField(env, this, psi_fdID); +static void socketCreate(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean stream) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "null fd object"); return; } fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); - if (fd == -1) { + if (fd == INVALID_SOCKET) { NET_ThrowCurrent(env, "create"); return; } else { /* Set socket attribute so it is not passed to any child process */ - SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); + //SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + fdObj.setSocket(fd); } if (ipv6_available()) { - fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); if (IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "null fd1 object"); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + fdObj.setSocket(null); NET_SocketClose(fd); return; } fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); - if (fd1 == -1) { + if (fd1 == INVALID_SOCKET) { NET_ThrowCurrent(env, "create"); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + fdObj.setSocket(null); NET_SocketClose(fd); return; } else { - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + fd1Obj.setSocket(fd1); } } else { - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + _this.fd1 = null; } } @@ -183,37 +210,35 @@ Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this, * Method: socketConnect * Signature: (Ljava/net/InetAddress;I)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, - jobject iaObj, jint port, - jint timeout) +static void socketConnect(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress iaObj, int port, int timeout) { - jint localport = (*env)->GetIntField(env, this, psi_localportID); + int localport = _this.localport; /* family and localport are int fields of iaObj */ int family; - jint fd, fd1=-1; - jint len; - int ipv6_supported = ipv6_available(); + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + boolean ipv6_supported = ipv6_available(); /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket * If we want to connect to IPv6 then we swap the two sockets/objects * This way, fd is always the connected socket, and fd1 always gets closed. */ - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; SOCKETADDRESS him; + him = new SOCKETADDRESS(); /* The result of the connection */ int connect_res; if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (ipv6_supported && !IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } if (IS_NULL(iaObj)) { @@ -221,67 +246,67 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, return; } - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, port, him, JNI_FALSE) != 0) { return; } family = him.him.sa_family; if (family == AF_INET6) { if (!ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol family not supported"); return; } else { - if (fd1 == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + if (fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Destination unreachable"); return; } /* close the v4 socket, and set fd to be the v6 socket */ - (*env)->SetObjectField(env, this, psi_fdID, fd1Obj); - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + _this.fd = fd1Obj; + _this.fd1 = null; NET_SocketClose(fd); fd = fd1; fdObj = fd1Obj; } } else { - if (fd1 != -1) { - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); + if (fd1 != null) { + fd1Obj.setSocket(null); NET_SocketClose(fd1); } - if (fd == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + if (fd == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Destination unreachable"); return; } } - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + _this.fd1 = null; if (timeout <= 0) { - connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him)); + connect_res = connect(fd, him); if (connect_res == SOCKET_ERROR) { connect_res = WSAGetLastError(); } } else { int optval; - int optlen = sizeof(optval); /* make socket non-blocking */ optval = 1; - ioctlsocket( fd, FIONBIO, &optval ); + ioctlsocket( fd, FIONBIO, optval ); /* initiate the connect */ - connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him)); + connect_res = connect(fd, him); if (connect_res == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { connect_res = WSAGetLastError(); } else { fd_set wr, ex; - struct timeval t; + wr = new fd_set(); ex = new fd_set(); + timeval t = new timeval(); - FD_ZERO(&wr); - FD_ZERO(&ex); - FD_SET(fd, &wr); - FD_SET(fd, &ex); + FD_ZERO(wr); + FD_ZERO(ex); + FD_SET(fd, wr); + FD_SET(fd, ex); t.tv_sec = timeout / 1000; t.tv_usec = (timeout % 1000) * 1000; @@ -289,7 +314,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, * Wait for timout, connection established or * connection failed. */ - connect_res = select(fd+1, 0, &wr, &ex, &t); + connect_res = select(null, wr, ex, t); /* * Timeout before connection is established/failed so @@ -298,13 +323,13 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, * The socket should be closed immediately by the caller. */ if (connect_res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "connect timed out"); shutdown( fd, SD_BOTH ); /* make socket blocking again - just in case */ optval = 0; - ioctlsocket( fd, FIONBIO, &optval ); + ioctlsocket( fd, FIONBIO, optval ); return; } @@ -317,21 +342,23 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, * yielding and retrying. As yielding is problematic in heavy * load conditions we attempt up to 3 times to get the error reason. */ - if (!FD_ISSET(fd, &ex)) { + if (!FD_ISSET(fd, ex)) { connect_res = 0; } else { int retry; for (retry=0; retry<3; retry++) { + int[] tmp = { 0 }; NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, - (char*)&connect_res, &optlen); - if (connect_res) { + tmp); + connect_res = tmp[0]; + if (connect_res != 0) { break; } Sleep(0); } if (connect_res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Unable to establish connection"); return; } @@ -341,12 +368,12 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, /* make socket blocking again */ optval = 0; - ioctlsocket(fd, FIONBIO, &optval); + ioctlsocket(fd, FIONBIO, optval); } - if (connect_res) { + if (connect_res != 0) { if (connect_res == WSAEADDRNOTAVAIL) { - JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"ConnectException", "connect: Address is invalid on local machine, or port is not valid on remote machine"); } else { NET_ThrowNew(env, connect_res, "connect"); @@ -354,11 +381,11 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, return; } - (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); + fdObj.setSocket(fd); /* set the remote peer address and port */ - (*env)->SetObjectField(env, this, psi_addressID, iaObj); - (*env)->SetIntField(env, this, psi_portID, port); + _this.address = iaObj; + _this.port = port; /* * we need to initialize the local port field if bind was called @@ -369,20 +396,18 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, /* Now that we're a connected socket, let's extract the port number * that the system chose for us and store it in the Socket object. */ - u_short port; - int len = SOCKETADDRESS_LEN(&him); - if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { + if (getsockname(fd, him) == -1) { if (WSAGetLastError() == WSAENOTSOCK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); } else { NET_ThrowCurrent(env, "getsockname failed"); } return; } - port = ntohs ((u_short)GET_PORT(&him)); - (*env)->SetIntField(env, this, psi_localportID, (int) port); + port = ntohs (GET_PORT(him)); + _this.localport = port; } } @@ -391,41 +416,36 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, * Method: socketBind * Signature: (Ljava/net/InetAddress;I)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, - jobject iaObj, jint localport) { - - /* fdObj is the FileDescriptor field on this */ - jobject fdObj, fd1Obj; - /* fd is an int field on fdObj */ - int fd, fd1, len; - int ipv6_supported = ipv6_available(); +static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress iaObj, int localport) { + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + boolean ipv6_supported = ipv6_available(); /* family is an int field of iaObj */ int family; int rv; SOCKETADDRESS him; + him = new SOCKETADDRESS(); - fdObj = (*env)->GetObjectField(env, this, psi_fdID); - fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - - family = (*env)->GetIntField(env, iaObj, ia_familyID); + family = iaObj.family; if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol family not supported"); return; } if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); if (ipv6_supported) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } } if (IS_NULL(iaObj)) { @@ -434,41 +454,41 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, } if (NET_InetAddressToSockaddr(env, iaObj, localport, - (struct sockaddr *)&him, &len, JNI_FALSE) != 0) { + him, JNI_FALSE) != 0) { return; } if (ipv6_supported) { - struct ipv6bind v6bind; - v6bind.addr = &him; + ipv6bind v6bind = new ipv6bind(); + v6bind.addr = him; v6bind.ipv4_fd = fd; v6bind.ipv6_fd = fd1; - rv = NET_BindV6(&v6bind); + rv = NET_BindV6(v6bind); if (rv != -1) { /* check if the fds have changed */ if (v6bind.ipv4_fd != fd) { fd = v6bind.ipv4_fd; - if (fd == -1) { + if (fd == null) { /* socket is closed. */ - (*env)->SetObjectField(env, this, psi_fdID, NULL); + _this.fd = null; } else { /* socket was re-created */ - (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); + fdObj.setSocket(fd); } } if (v6bind.ipv6_fd != fd1) { fd1 = v6bind.ipv6_fd; - if (fd1 == -1) { + if (fd1 == null) { /* socket is closed. */ - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + _this.fd1 = null; } else { /* socket was re-created */ - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + fd1Obj.setSocket(fd1); } } } } else { - rv = NET_Bind(fd, (struct sockaddr *)&him, len); + rv = NET_Bind(fd, him); } if (rv == -1) { @@ -477,26 +497,25 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, } /* set the address */ - (*env)->SetObjectField(env, this, psi_addressID, iaObj); + _this.address = iaObj; /* intialize the local port */ if (localport == 0) { /* Now that we're a bound socket, let's extract the port number * that the system chose for us and store it in the Socket object. */ - int len = SOCKETADDRESS_LEN(&him); - u_short port; + int port; fd = him.him.sa_family == AF_INET? fd: fd1; - if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { + if (getsockname(fd, him) == -1) { NET_ThrowCurrent(env, "getsockname in plain socketBind"); return; } - port = ntohs ((u_short) GET_PORT (&him)); + port = ntohs (GET_PORT (him)); - (*env)->SetIntField(env, this, psi_localportID, (int) port); + _this.localport = port; } else { - (*env)->SetIntField(env, this, psi_localportID, localport); + _this.localport = localport; } } @@ -505,52 +524,51 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, * Method: socketListen * Signature: (I)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketListen (JNIEnv *env, jobject this, - jint count) +static void socketListen (JNIEnv env, TwoStacksPlainSocketImpl _this, int count) { /* this FileDescriptor fd field */ - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - jobject address; + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + InetAddress address; /* fdObj's int fd field */ - int fd, fd1; - SOCKETADDRESS addr; int addrlen; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; + SOCKETADDRESS addr = new SOCKETADDRESS(); if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } /* Listen on V4 if address type is v4 or if v6 and address is ::0. * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0. * In cases, where we listen on one space only, we close the other socket. */ - address = (*env)->GetObjectField(env, this, psi_addressID); + address = _this.address; if (IS_NULL(address)) { JNU_ThrowNullPointerException(env, "socket address"); return; } - if (NET_InetAddressToSockaddr(env, address, 0, (struct sockaddr *)&addr, - &addrlen, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, address, 0, addr, + JNI_FALSE) != 0) { return; } - if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(&addr.him6)) { + if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(addr.him6)) { /* listen on v4 */ if (listen(fd, count) == -1) { NET_ThrowCurrent(env, "listen failed"); } } else { NET_SocketClose (fd); - (*env)->SetObjectField(env, this, psi_fdID, NULL); + _this.fd = null; } if (ipv6_available() && !IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); if (addr.him.sa_family == AF_INET6 || addr.him4.sin_addr.s_addr == INADDR_ANY) { /* listen on v6 */ if (listen(fd1, count) == -1) { @@ -558,7 +576,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen (JNIEnv *env, jobject this, } } else { NET_SocketClose (fd1); - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + _this.fd1 = null; } } } @@ -568,200 +586,139 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen (JNIEnv *env, jobject this, * Method: socketAccept * Signature: (Ljava/net/SocketImpl;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, - jobject socket) +static void socketAccept(JNIEnv env, TwoStacksPlainSocketImpl _this, SocketImpl socket) { /* fields on this */ - jint port; - jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + int port; + int timeout = _this.timeout; + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; /* the FileDescriptor field on socket */ - jobject socketFdObj; - - /* cache the Inet4/6Address classes */ - static jclass inet4Cls; - static jclass inet6Cls; + FileDescriptor socketFdObj; /* the InetAddress field on socket */ - jobject socketAddressObj; + InetAddress socketAddressObj; /* the fd int field on fdObj */ - jint fd=-1, fd1=-1; + cli.System.Net.Sockets.Socket fd=null, fd1=null; SOCKETADDRESS him; - jint len; + him = new SOCKETADDRESS(); if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } if (IS_NULL(socket)) { JNU_ThrowNullPointerException(env, "socket is null"); return; } else { - socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID); - socketAddressObj = (*env)->GetObjectField(env, socket, psi_addressID); + socketFdObj = socket.fd; + socketAddressObj = socket.address; } if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { JNU_ThrowNullPointerException(env, "socket address or fd obj"); return; } - if (fd != -1 && fd1 != -1) { - fd_set rfds; - struct timeval t, *tP=&t; - int lastfd, res, fd2; - FD_ZERO(&rfds); - FD_SET(fd,&rfds); - FD_SET(fd1,&rfds); - if (timeout) { + if (fd != null && fd1 != null) { + fd_set rfds = new fd_set(); + timeval t = new timeval(); + cli.System.Net.Sockets.Socket lastfd, fd2; + FD_ZERO(rfds); + FD_SET(fd,rfds); + FD_SET(fd1,rfds); + if (timeout != 0) { t.tv_sec = timeout/1000; t.tv_usec = (timeout%1000)*1000; } else { - tP = NULL; + t = null; } - res = select (fd, &rfds, NULL, NULL, tP); + int res = select (rfds, null, null, t); if (res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Accept timed out"); return; } else if (res == 1) { - fd2 = FD_ISSET(fd, &rfds)? fd: fd1; + fd2 = FD_ISSET(fd, rfds)? fd: fd1; } else if (res == 2) { /* avoid starvation */ - lastfd = (*env)->GetIntField(env, this, psi_lastfdID); - if (lastfd != -1) { + lastfd = _this.lastfd; + if (lastfd != null) { fd2 = lastfd==fd? fd1: fd; } else { fd2 = fd; } - (*env)->SetIntField(env, this, psi_lastfdID, fd2); + _this.lastfd = fd2; } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "select failed"); return; } - if (fd2 == fd) { /* v4 */ - len = sizeof (struct sockaddr_in); - } else { - len = sizeof (struct SOCKADDR_IN6); - } fd = fd2; } else { int ret; - if (fd1 != -1) { + if (fd1 != null) { fd = fd1; - len = sizeof (struct SOCKADDR_IN6); - } else { - len = sizeof (struct sockaddr_in); } - if (timeout) { + if (timeout != 0) { ret = NET_Timeout(fd, timeout); if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", "Accept timed out"); return; } else if (ret == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); /* REMIND: SOCKET CLOSED PROBLEM */ /* NET_ThrowCurrent(env, "Accept failed"); */ return; } else if (ret == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); return; } } } - fd = accept(fd, (struct sockaddr *)&him, &len); - if (fd < 0) { + fd = accept(fd, him); + if (fd == null) { /* REMIND: SOCKET CLOSED PROBLEM */ - if (fd == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + if (false) { + JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", "operation interrupted"); } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); } return; } - (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); + socketFdObj.setSocket(fd); if (him.him.sa_family == AF_INET) { - if (inet4Cls == NULL) { - jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); - if (c != NULL) { - inet4Cls = (*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - } - } /* * fill up the remote peer port and address in the new socket structure */ - if (inet4Cls != NULL) { - socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); - } else { - socketAddressObj = NULL; - } - if (socketAddressObj == NULL) { - /* - * FindClass or NewObject failed so close connection and - * exist (there will be a pending exception). - */ - NET_SocketClose(fd); - return; - } - - (*env)->SetIntField(env, socketAddressObj, ia_addressID, - ntohl(him.him4.sin_addr.s_addr)); - (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv4); - (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); + socketAddressObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); + socket.address = socketAddressObj; } else { - jbyteArray addr; /* AF_INET6 -> Inet6Address */ - if (inet6Cls == 0) { - jclass c = (*env)->FindClass(env, "java/net/Inet6Address"); - if (c != NULL) { - inet6Cls = (*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - } - } - if (inet6Cls != NULL) { - socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID); - } else { - socketAddressObj = NULL; - } - if (socketAddressObj == NULL) { - /* - * FindClass or NewObject failed so close connection and - * exist (there will be a pending exception). - */ - NET_SocketClose(fd); - return; - } - addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID); - (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr); - (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6); - (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id); + socketAddressObj = new Inet6Address(null, him.him6.sin6_addr, him.him6.sin6_scope_id); } /* fields common to AF_INET and AF_INET6 */ - port = ntohs ((u_short) GET_PORT (&him)); - (*env)->SetIntField(env, socket, psi_portID, (int)port); - port = (*env)->GetIntField(env, this, psi_localportID); - (*env)->SetIntField(env, socket, psi_localportID, port); - (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); + port = ntohs (GET_PORT (him)); + socket.port = port; + port = _this.localport; + socket.localport = port; + socket.address = socketAddressObj; } /* @@ -769,26 +726,25 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, * Method: socketAvailable * Signature: ()I */ -JNIEXPORT jint JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) { +static int socketAvailable(JNIEnv env, TwoStacksPlainSocketImpl _this) { - jint available = -1; - jint res; - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jint fd; + int[] available = { -1 }; + int res; + FileDescriptor fdObj = _this.fd; + cli.System.Net.Sockets.Socket fd; if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return -1; } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } - res = ioctlsocket(fd, FIONREAD, &available); + res = ioctlsocket(fd, FIONREAD, available); /* if result isn't 0, it means an error */ if (res != 0) { NET_ThrowNew(env, res, "socket available"); } - return available; + return available[0]; } /* @@ -796,31 +752,30 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAvailable(JNIEnv *env, jobject this * Method: socketClose * Signature: ()V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this, - jboolean useDeferredClose) { +static void socketClose0(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean useDeferredClose) { - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - jint fd=-1, fd1=-1; + FileDescriptor fdObj = _this.fd; + FileDescriptor fd1Obj = _this.fd1; + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket fd1 = null; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket already closed"); return; } if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + fd1 = fd1Obj.getSocket(); } - if (fd != -1) { - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + if (fd != null) { + fdObj.setSocket(null); NET_SocketClose(fd); } - if (fd1 != -1) { - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); + if (fd1 != null) { + fd1Obj.setSocket(null); NET_SocketClose(fd1); } } @@ -833,24 +788,19 @@ Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this, * Method: socketSetOption * Signature: (IZLjava/lang/Object;)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this, - jint cmd, jboolean on, - jobject value) { - int fd, fd1; - int level, optname, optlen; - union { - int i; - struct linger ling; - } optval; +static void socketSetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int cmd, boolean on, Object value) { + cli.System.Net.Sockets.Socket fd, fd1; + int[] level = new int[1]; + int[] optname = new int[1]; + Object optval; /* * Get SOCKET and check that it hasn't been closed */ - fd = getFD(env, this); - fd1 = getFD1(env, this); - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + fd = getFD(env, _this); + fd1 = getFD1(env, _this); + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return; } @@ -869,7 +819,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this * Don't enable the socket option on ServerSocket as it's * meaningless (we don't receive on a ServerSocket). */ - jobject ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID); + Object ssObj = _this.serverSocket; if (ssObj != NULL) { return; } @@ -881,14 +831,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this * select() -- see SocketInputStream.socketRead. */ if (isRcvTimeoutSupported) { - jclass iCls = (*env)->FindClass(env, "java/lang/Integer"); - jfieldID i_valueID; - jint timeout; - - CHECK_NULL(iCls); - i_valueID = (*env)->GetFieldID(env, iCls, "value", "I"); - CHECK_NULL(i_valueID); - timeout = (*env)->GetIntField(env, value, i_valueID); + int timeout = ((Integer)value).intValue(); /* * Disable SO_RCVTIMEO if timeout is <= 5 second. @@ -897,17 +840,15 @@ Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this timeout = 0; } - if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)) < 0) { + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, timeout) < 0) { if (WSAGetLastError() == WSAENOPROTOOPT) { isRcvTimeoutSupported = JNI_FALSE; } else { NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); } } - if (fd1 != -1) { - if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)) < 0) { + if (fd1 != null) { + if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, timeout) < 0) { NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); } } @@ -919,8 +860,8 @@ Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this * Map the Java level socket option to the platform specific * level */ - if (NET_MapSocketOption(cmd, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + if (NET_MapSocketOption(cmd, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); return; } @@ -931,62 +872,43 @@ Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this case java_net_SocketOptions_SO_OOBINLINE : case java_net_SocketOptions_SO_KEEPALIVE : case java_net_SocketOptions_SO_REUSEADDR : - optval.i = (on ? 1 : 0); - optlen = sizeof(optval.i); + optval = on; break; case java_net_SocketOptions_SO_SNDBUF : case java_net_SocketOptions_SO_RCVBUF : case java_net_SocketOptions_IP_TOS : - { - jclass cls; - jfieldID fid; - - cls = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "I"); - CHECK_NULL(fid); - - optval.i = (*env)->GetIntField(env, value, fid); - optlen = sizeof(optval.i); - } + optval = ((Integer)value).intValue(); break; case java_net_SocketOptions_SO_LINGER : { - jclass cls; - jfieldID fid; - - cls = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "I"); - CHECK_NULL(fid); - + linger ling = new linger(); if (on) { - optval.ling.l_onoff = 1; - optval.ling.l_linger = (*env)->GetIntField(env, value, fid); + ling.l_onoff = 1; + ling.l_linger = ((Integer)value).intValue(); } else { - optval.ling.l_onoff = 0; - optval.ling.l_linger = 0; + ling.l_onoff = 0; + ling.l_linger = 0; } - optlen = sizeof(optval.ling); + optval = ling; } break; default: /* shouldn't get here */ - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Option not supported by TwoStacksPlainSocketImpl"); return; } - if (fd != -1) { - if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) { + if (fd != null) { + if (NET_SetSockOpt(fd, level[0], optname[0], optval) < 0) { NET_ThrowCurrent(env, "setsockopt"); } } - if (fd1 != -1) { - if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) { + if (fd1 != null) { + if (NET_SetSockOpt(fd1, level[0], optname[0], optval) < 0) { NET_ThrowCurrent(env, "setsockopt"); } } @@ -998,28 +920,24 @@ Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this * Method: socketGetOption * Signature: (I)I */ -JNIEXPORT jint JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this, - jint opt, jobject iaContainerObj) { +static int socketGetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int opt, Object iaContainerObj) { - int fd, fd1; - int level, optname, optlen; - union { - int i; - struct linger ling; - } optval; + cli.System.Net.Sockets.Socket fd, fd1; + int[] level = new int[1]; + int[] optname = new int[1]; + Object optval; /* * Get SOCKET and check it hasn't been closed */ - fd = getFD(env, this); - fd1 = getFD1(env, this); + fd = getFD(env, _this); + fd1 = getFD1(env, _this); - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + if (fd == null && fd1 == null) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); return -1; } - if (fd < 0) { + if (fd == null) { fd = fd1; } @@ -1029,35 +947,25 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this * SO_BINDADDR isn't a socket option */ if (opt == java_net_SocketOptions_SO_BINDADDR) { - SOCKET_ADDRESS him; - int len; - int port; - jobject iaObj; - jclass iaCntrClass; - jfieldID iaFieldID; - - len = sizeof(struct sockaddr_in); + SOCKETADDRESS him; + him = new SOCKETADDRESS(); + int[] port = { 0 }; + InetAddress iaObj; - if (fd == -1) { + if (fd == null) { /* must be an IPV6 only socket. Case where both sockets are != -1 * is handled in java */ - fd = getFD1 (env, this); - len = sizeof(struct SOCKADDR_IN6); + fd = getFD1 (env, _this); } - if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + if (getsockname(fd, him) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", "Error getting socket name"); return -1; } - iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); - CHECK_NULL_RETURN(iaObj, -1); - - iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj); - iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(iaFieldID, -1); - (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); + iaObj = NET_SockaddrToInetAddress(him, port); + ((InetAddressContainer)iaContainerObj).addr = iaObj; return 0; /* notice change from before */ } @@ -1065,8 +973,8 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this * Map the Java level socket option to the platform specific * level and option name. */ - if (NET_MapSocketOption(opt, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + if (NET_MapSocketOption(opt, level, optname) != 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); return -1; } @@ -1074,34 +982,33 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this * Args are int except for SO_LINGER */ if (opt == java_net_SocketOptions_SO_LINGER) { - optlen = sizeof(optval.ling); + optval = new linger(); } else { - optlen = sizeof(optval.i); - optval.i = 0; + optval = new int[1]; } - if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { + if (NET_GetSockOpt(fd, level[0], optname[0], optval) < 0) { NET_ThrowCurrent(env, "getsockopt"); return -1; } switch (opt) { case java_net_SocketOptions_SO_LINGER: - return (optval.ling.l_onoff ? optval.ling.l_linger: -1); + return (((linger)optval).l_onoff != 0 ? ((linger)optval).l_linger: -1); case java_net_SocketOptions_SO_SNDBUF: case java_net_SocketOptions_SO_RCVBUF: case java_net_SocketOptions_IP_TOS: - return optval.i; + return ((int[])optval)[0]; case java_net_SocketOptions_TCP_NODELAY : case java_net_SocketOptions_SO_OOBINLINE : case java_net_SocketOptions_SO_KEEPALIVE : case java_net_SocketOptions_SO_REUSEADDR : - return (optval.i == 0) ? -1 : 1; + return (((int[])optval)[0] == 0) ? -1 : 1; default: /* shouldn't get here */ - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Option not supported by TwoStacksPlainSocketImpl"); return -1; } @@ -1112,24 +1019,22 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this * Method: socketShutdown * Signature: (I)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketShutdown(JNIEnv *env, jobject this, - jint howto) +static void socketShutdown(JNIEnv env, TwoStacksPlainSocketImpl _this, int howto) { - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jint fd; + FileDescriptor fdObj = _this.fd; + cli.System.Net.Sockets.Socket fd; /* * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being * -1 already? */ if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket already closed"); return; } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); } shutdown(fd, howto); } @@ -1139,35 +1044,34 @@ Java_java_net_TwoStacksPlainSocketImpl_socketShutdown(JNIEnv *env, jobject this, * Method: socketSendUrgentData * Signature: (B)V */ -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this, - jint data) { +static void socketSendUrgentData(JNIEnv env, TwoStacksPlainSocketImpl _this, int data) { /* The fd field */ - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - int n, fd; - unsigned char d = data & 0xff; + FileDescriptor fdObj = _this.fd; + int n; + cli.System.Net.Sockets.Socket fd; if (IS_NULL(fdObj)) { JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); return; } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + fd = fdObj.getSocket(); /* Bug 4086704 - If the Socket associated with this file descriptor * was closed (sysCloseFD), the the file descriptor is set to -1. */ - if (fd == -1) { + if (fd == null) { JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); return; } } - n = send(fd, (char *)&data, 1, MSG_OOB); + n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB); if (n == JVM_IO_ERR) { NET_ThrowCurrent(env, "send"); return; } if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); + JNU_ThrowByName(env, "java/io/InterruptedIOException", null); return; } } +} diff --git a/openjdk/java/net/net_util_md.java b/openjdk/java/net/net_util_md.java new file mode 100644 index 00000000..be3d368c --- /dev/null +++ b/openjdk/java/net/net_util_md.java @@ -0,0 +1,824 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.net; + +import cli.System.Net.IPAddress; +import cli.System.Net.IPEndPoint; +import static ikvm.internal.JNI.*; +import static ikvm.internal.Winsock.*; + +final class net_util_md +{ + private net_util_md() { } + + static final int INADDR_ANY = 0; + + static final int IPTOS_TOS_MASK = 0x1e; + static final int IPTOS_PREC_MASK = 0xe0; + + static boolean isRcvTimeoutSupported = true; + + /* + * Table of Windows Sockets errors, the specific exception we + * throw for the error, and the error text. + * + * Note that this table excludes OS dependent errors. + * + * Latest list of Windows Sockets errors can be found at :- + * http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm + */ + private static class WinsockError + { + final int errCode; + final int exc; + final String errString; + + WinsockError(int errCode, int exc, String errString) + { + this.errCode = errCode; + this.exc = exc; + this.errString = errString; + } + } + + private static final int Exception_BindException = 1; + private static final int Exception_ConnectException = 2; + private static final int Exception_NoRouteToHostException = 3; + + private static final WinsockError[] winsock_errors = { + new WinsockError(WSAEACCES, 0, "Permission denied"), + new WinsockError(WSAEADDRINUSE, Exception_BindException, "Address already in use"), + new WinsockError(WSAEADDRNOTAVAIL, Exception_BindException, "Cannot assign requested address"), + new WinsockError(WSAEAFNOSUPPORT, 0, "Address family not supported by protocol family"), + new WinsockError(WSAEALREADY, 0, "Operation already in progress"), + new WinsockError(WSAECONNABORTED, 0, "Software caused connection abort"), + new WinsockError(WSAECONNREFUSED, Exception_ConnectException, "Connection refused"), + new WinsockError(WSAECONNRESET, 0, "Connection reset by peer"), + new WinsockError(WSAEDESTADDRREQ, 0, "Destination address required"), + new WinsockError(WSAEFAULT, 0, "Bad address"), + new WinsockError(WSAEHOSTDOWN, 0, "Host is down"), + new WinsockError(WSAEHOSTUNREACH, Exception_NoRouteToHostException, "No route to host"), + new WinsockError(WSAEINPROGRESS, 0, "Operation now in progress"), + new WinsockError(WSAEINTR, 0, "Interrupted function call"), + new WinsockError(WSAEINVAL, 0, "Invalid argument"), + new WinsockError(WSAEISCONN, 0, "Socket is already connected"), + new WinsockError(WSAEMFILE, 0, "Too many open files"), + new WinsockError(WSAEMSGSIZE, 0, "The message is larger than the maximum supported by the underlying transport"), + new WinsockError(WSAENETDOWN, 0, "Network is down"), + new WinsockError(WSAENETRESET, 0, "Network dropped connection on reset"), + new WinsockError(WSAENETUNREACH, 0, "Network is unreachable"), + new WinsockError(WSAENOBUFS, 0, "No buffer space available (maximum connections reached?)"), + new WinsockError(WSAENOPROTOOPT, 0, "Bad protocol option"), + new WinsockError(WSAENOTCONN, 0, "Socket is not connected"), + new WinsockError(WSAENOTSOCK, 0, "Socket operation on nonsocket"), + new WinsockError(WSAEOPNOTSUPP, 0, "Operation not supported"), + new WinsockError(WSAEPFNOSUPPORT, 0, "Protocol family not supported"), + new WinsockError(WSAEPROCLIM, 0, "Too many processes"), + new WinsockError(WSAEPROTONOSUPPORT, 0, "Protocol not supported"), + new WinsockError(WSAEPROTOTYPE, 0, "Protocol wrong type for socket"), + new WinsockError(WSAESHUTDOWN, 0, "Cannot send after socket shutdown"), + new WinsockError(WSAESOCKTNOSUPPORT, 0, "Socket type not supported"), + new WinsockError(WSAETIMEDOUT, Exception_ConnectException, "Connection timed out"), + new WinsockError(WSATYPE_NOT_FOUND, 0, "Class type not found"), + new WinsockError(WSAEWOULDBLOCK, 0, "Resource temporarily unavailable"), + new WinsockError(WSAHOST_NOT_FOUND, 0, "Host not found"), + new WinsockError(WSA_NOT_ENOUGH_MEMORY, 0, "Insufficient memory available"), + new WinsockError(WSANOTINITIALISED, 0, "Successful WSAStartup not yet performed"), + new WinsockError(WSANO_DATA, 0, "Valid name, no data record of requested type"), + new WinsockError(WSANO_RECOVERY, 0, "This is a nonrecoverable error"), + new WinsockError(WSASYSNOTREADY, 0, "Network subsystem is unavailable"), + new WinsockError(WSATRY_AGAIN, 0, "Nonauthoritative host not found"), + new WinsockError(WSAVERNOTSUPPORTED, 0, "Winsock.dll version out of range"), + new WinsockError(WSAEDISCON, 0, "Graceful shutdown in progress"), + new WinsockError(WSA_OPERATION_ABORTED, 0, "Overlapped operation aborted") + }; + + /* + * Since winsock doesn't have the equivalent of strerror(errno) + * use table to lookup error text for the error. + */ + static SocketException NET_ThrowNew(int errorNum, String msg) + { + int i; + int table_size = winsock_errors.length; + int excP = 0; + String fullMsg; + + if (msg == null) { + msg = "no further information"; + } + + /* + * Check table for known winsock errors + */ + i=0; + while (i < table_size) { + if (errorNum == winsock_errors[i].errCode) { + break; + } + i++; + } + + /* + * If found get pick the specific exception and error + * message corresponding to this error. + */ + if (i < table_size) { + excP = winsock_errors[i].exc; + fullMsg = winsock_errors[i].errString + ": " + msg; + } else { + fullMsg = "Unrecognized Windows Sockets error: " + errorNum + ": " + msg; + } + + /* + * Throw SocketException if no specific exception for this + * error. + */ + switch (excP) { + case Exception_BindException: + return new BindException(fullMsg); + case Exception_ConnectException: + return new ConnectException(fullMsg); + case Exception_NoRouteToHostException: + return new NoRouteToHostException(fullMsg); + default: + return new SocketException(fullMsg); + } + } + + static void NET_ThrowNew(JNIEnv env, int errorNum, String msg) + { + env.Throw(NET_ThrowNew(errorNum, msg)); + } + + static SocketException NET_ThrowCurrent(String msg) + { + return NET_ThrowNew(WSAGetLastError(), msg); + } + + static void NET_ThrowCurrent(JNIEnv env, String msg) + { + env.Throw(NET_ThrowCurrent(msg)); + } + + /* + * Return the default TOS value + */ + static int NET_GetDefaultTOS() { + // we always use the "default" default... + return 0; + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + + private static final class sockopts { + int cmd; + int level; + int optname; + + sockopts(int cmd, int level, int optname) { + this.cmd = cmd; + this.level = level; + this.optname = optname; + } + } + + private static final sockopts opts[] = { + new sockopts(SocketOptions.TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY ), + new sockopts(SocketOptions.SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE ), + new sockopts(SocketOptions.SO_LINGER, SOL_SOCKET, SO_LINGER ), + new sockopts(SocketOptions.SO_SNDBUF, SOL_SOCKET, SO_SNDBUF ), + new sockopts(SocketOptions.SO_RCVBUF, SOL_SOCKET, SO_RCVBUF ), + new sockopts(SocketOptions.SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE ), + new sockopts(SocketOptions.SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR ), + new sockopts(SocketOptions.SO_BROADCAST, SOL_SOCKET, SO_BROADCAST ), + new sockopts(SocketOptions.IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF ), + new sockopts(SocketOptions.IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP ), + new sockopts(SocketOptions.IP_TOS, IPPROTO_IP, IP_TOS ), + + }; + + /* call NET_MapSocketOptionV6 for the IPv6 fd only + * and NET_MapSocketOption for the IPv4 fd + */ + static int NET_MapSocketOptionV6(int cmd, int[] level, int[] optname) { + + switch (cmd) { + case SocketOptions.IP_MULTICAST_IF: + case SocketOptions.IP_MULTICAST_IF2: + level[0] = IPPROTO_IPV6; + optname[0] = IPV6_MULTICAST_IF; + return 0; + + case SocketOptions.IP_MULTICAST_LOOP: + level[0] = IPPROTO_IPV6; + optname[0] = IPV6_MULTICAST_LOOP; + return 0; + } + return NET_MapSocketOption (cmd, level, optname); + } + + static int NET_MapSocketOption(int cmd, int[] level, int[] optname) { + /* + * Map the Java level option to the native level + */ + for (int i=0; i<opts.length; i++) { + if (cmd == opts[i].cmd) { + level[0] = opts[i].level; + optname[0] = opts[i].optname; + return 0; + } + } + + /* not found */ + return -1; + } + + static int NET_SetSockOpt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval) + { + int rv; + + if (level == IPPROTO_IP && optname == IP_TOS) { + int tos = (Integer)optval; + tos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK); + optval = tos; + } + + rv = setsockopt(s, level, optname, optval); + + if (rv == SOCKET_ERROR) { + /* + * IP_TOS & IP_MULTICAST_LOOP can't be set on some versions + * of Windows. + */ + if ((WSAGetLastError() == WSAENOPROTOOPT) && + (level == IPPROTO_IP) && + (optname == IP_TOS || optname == IP_MULTICAST_LOOP)) { + rv = 0; + } + + /* + * IP_TOS can't be set on unbound UDP sockets. + */ + if ((WSAGetLastError() == WSAEINVAL) && + (level == IPPROTO_IP) && + (optname == IP_TOS)) { + rv = 0; + } + } + + return rv; + } + + /* + * Wrapper for setsockopt dealing with Windows specific issues :- + * + * IP_TOS is not supported on some versions of Windows so + * instead return the default value for the OS. + */ + static int NET_GetSockOpt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval) + { + int rv; + + rv = getsockopt(s, level, optname, optval); + + + /* + * IPPROTO_IP/IP_TOS is not supported on some Windows + * editions so return the default type-of-service + * value. + */ + if (rv == SOCKET_ERROR) { + + if (WSAGetLastError() == WSAENOPROTOOPT && + level == IPPROTO_IP && optname == IP_TOS) { + + ((int[])optval)[0] = NET_GetDefaultTOS(); + + rv = 0; + } + } + + return rv; + } + + /* + * Wrapper for bind winsock call - transparent converts an + * error related to binding to a port that has exclusive access + * into an error indicating the port is in use (facilitates + * better error reporting). + */ + static int NET_Bind(cli.System.Net.Sockets.Socket s, SOCKETADDRESS him) + { + int rv = bind(s, him); + + if (rv == SOCKET_ERROR) { + /* + * If bind fails with WSAEACCES it means that a privileged + * process has done an exclusive bind (NT SP4/2000/XP only). + */ + if (WSAGetLastError() == WSAEACCES) { + WSASetLastError(WSAEADDRINUSE); + } + } + + return rv; + } + + static int NET_SocketClose(cli.System.Net.Sockets.Socket fd) { + linger l = new linger(); + int ret; + if (getsockopt(fd, SOL_SOCKET, SO_LINGER, l) == 0) { + if (l.l_onoff == 0) { + WSASendDisconnect(fd); + } + } + ret = closesocket (fd); + return ret; + } + + static int NET_Timeout(cli.System.Net.Sockets.Socket fd, long timeout) { + int ret; + fd_set tbl = new fd_set(); + timeval t = new timeval(); + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + FD_ZERO(tbl); + FD_SET(fd, tbl); + ret = select (tbl, null, null, t); + return ret; + } + + /* + * differs from NET_Timeout() as follows: + * + * If timeout = -1, it blocks forever. + * + * returns 1 or 2 depending if only one or both sockets + * fire at same time. + * + * *fdret is (one of) the active fds. If both sockets + * fire at same time, *fdret = fd always. + */ + static int NET_Timeout2(cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, long timeout, cli.System.Net.Sockets.Socket[] fdret) { + int ret; + fd_set tbl = new fd_set(); + timeval t = new timeval(); + if (timeout == -1) { + t = null; + } else { + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + } + FD_ZERO(tbl); + FD_SET(fd, tbl); + FD_SET(fd1, tbl); + ret = select (tbl, null, null, t); + switch (ret) { + case 0: + return 0; /* timeout */ + case 1: + if (FD_ISSET (fd, tbl)) { + fdret[0]= fd; + } else { + fdret[0]= fd1; + } + return 1; + case 2: + fdret[0]= fd; + return 2; + } + return -1; + } + + /* + * if ipv6 is available, call NET_BindV6 to bind to the required address/port. + * Because the same port number may need to be reserved in both v4 and v6 space, + * this may require socket(s) to be re-opened. Therefore, all of this information + * is passed in and returned through the ipv6bind structure. + * + * If the request is to bind to a specific address, then this (by definition) means + * only bind in either v4 or v6, and this is just the same as normal. ie. a single + * call to bind() will suffice. The other socket is closed in this case. + * + * The more complicated case is when the requested address is ::0 or 0.0.0.0. + * + * Two further cases: + * 2. If the reqeusted port is 0 (ie. any port) then we try to bind in v4 space + * first with a wild-card port argument. We then try to bind in v6 space + * using the returned port number. If this fails, we repeat the process + * until a free port common to both spaces becomes available. + * + * 3. If the requested port is a specific port, then we just try to get that + * port in both spaces, and if it is not free in both, then the bind fails. + * + * On failure, sockets are closed and an error returned with CLOSE_SOCKETS_AND_RETURN + */ + + static class ipv6bind { + SOCKETADDRESS addr; + cli.System.Net.Sockets.Socket ipv4_fd; + cli.System.Net.Sockets.Socket ipv6_fd; + } + + private static int CLOSE_SOCKETS_AND_RETURN( + cli.System.Net.Sockets.Socket fd, + cli.System.Net.Sockets.Socket ofd, + cli.System.Net.Sockets.Socket close_fd, + cli.System.Net.Sockets.Socket close_ofd, + ipv6bind b) { + if (fd != null) { + closesocket (fd); + } + if (ofd != null) { + closesocket (ofd); + } + if (close_fd != null) { + closesocket (close_fd); + } + if (close_ofd != null) { + closesocket (close_ofd); + } + b.ipv4_fd = b.ipv6_fd = null; + return SOCKET_ERROR; + } + + static int NET_BindV6(ipv6bind b) { + cli.System.Net.Sockets.Socket fd = null; + cli.System.Net.Sockets.Socket ofd = null; + int rv; + /* need to defer close until new sockets created */ + cli.System.Net.Sockets.Socket close_fd = null; + cli.System.Net.Sockets.Socket close_ofd = null; + + SOCKETADDRESS oaddr = new SOCKETADDRESS(); + int family = b.addr.him.sa_family; + int ofamily; + int port; + int bound_port; + + if (family == AF_INET && (b.addr.him4.sin_addr.s_addr != INADDR_ANY)) { + /* bind to v4 only */ + int ret; + ret = NET_Bind (b.ipv4_fd, b.addr); + if (ret == SOCKET_ERROR) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + closesocket (b.ipv6_fd); + b.ipv6_fd = null; + return 0; + } + if (family == AF_INET6 && (!IN6ADDR_ISANY(b.addr))) { + /* bind to v6 only */ + int ret; + ret = NET_Bind (b.ipv6_fd, b.addr); + if (ret == SOCKET_ERROR) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + closesocket (b.ipv4_fd); + b.ipv4_fd = null; + return 0; + } + + /* We need to bind on both stacks, with the same port number */ + + if (family == AF_INET) { + ofamily = AF_INET6; + fd = b.ipv4_fd; + ofd = b.ipv6_fd; + port = GET_PORT (b.addr); + oaddr.set(new IPEndPoint(IPAddress.IPv6Any, htons(port))); + } else { + ofamily = AF_INET; + ofd = b.ipv4_fd; + fd = b.ipv6_fd; + port = GET_PORT (b.addr); + oaddr.set(new IPEndPoint(IPAddress.Any, htons(port))); + } + + rv = NET_Bind (fd, b.addr); + if (rv == SOCKET_ERROR) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + + /* get the port and set it in the other address */ + if (getsockname(fd, b.addr) == -1) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + bound_port = b.addr.sin_port; + oaddr.sin_port = bound_port; + if ((rv=NET_Bind (ofd, oaddr)) == SOCKET_ERROR) { + + /* no retries unless, the request was for any free port */ + + if (port != 0) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + + int sotype = fd.get_SocketType().Value; + + /* 50 is an arbitrary limit, just to ensure that this + * cannot be an endless loop. Would expect socket creation to + * succeed sooner. + */ + for (int retries = 0; retries < 50 /*SOCK_RETRIES*/; retries ++) { + close_fd = fd; + fd = null; + close_ofd = ofd; + ofd = null; + b.ipv4_fd = null; + b.ipv6_fd = null; + + /* create two new sockets */ + fd = socket (family, sotype, 0); + if (fd == INVALID_SOCKET) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + ofd = socket (ofamily, sotype, 0); + if (ofd == INVALID_SOCKET) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + + /* bind random port on first socket */ + oaddr.sin_port = 0; + rv = NET_Bind (ofd, oaddr); + if (rv == SOCKET_ERROR) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + /* close the original pair of sockets before continuing */ + closesocket (close_fd); + closesocket (close_ofd); + close_fd = close_ofd = null; + + /* bind new port on second socket */ + if (getsockname(ofd, oaddr) == -1) { + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + bound_port = oaddr.sin_port; + b.addr.sin_port = bound_port; + rv = NET_Bind (fd, b.addr); + + if (rv != SOCKET_ERROR) { + if (family == AF_INET) { + b.ipv4_fd = fd; + b.ipv6_fd = ofd; + } else { + b.ipv4_fd = ofd; + b.ipv6_fd = fd; + } + return 0; + } + } + return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); + } + return 0; + } + + /* If address types is IPv6, then IPv6 must be available. Otherwise + * no address can be generated. In the case of an IPv4 Inetaddress this + * method will return an IPv4 mapped address where IPv6 is available and + * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in + * structure for an IPv4 InetAddress. + */ + static int NET_InetAddressToSockaddr(JNIEnv env, InetAddress iaObj, int port, SOCKETADDRESS him, boolean v4MappedAddress) { + if (iaObj.family == InetAddress.IPv4) { + him.set(new IPEndPoint(new IPAddress(htonl(iaObj.address) & 0xFFFFFFFFL), port)); + return 0; + } else { + Inet6Address v6addr = (Inet6Address)iaObj; + int scope = v6addr.getScopeId(); + if (scope == 0) { + him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress), port)); + return 0; + } else { + him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress, scope & 0xFFFFFFFFL), port)); + return 0; + } + } + } + + static int NET_GetPortFromSockaddr(SOCKETADDRESS him) { + return ntohs(GET_PORT(him)); + } + + static boolean NET_IsIPv4Mapped(byte[] caddr) { + int i; + for (i = 0; i < 10; i++) { + if (caddr[i] != 0x00) { + return false; + } + } + + if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) { + return true; + } + return false; + } + + static int NET_IPv4MappedToIPv4(byte[] caddr) { + return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8) + | (caddr[15] & 0xff); + } + + static boolean NET_IsEqual(byte[] caddr1, byte[] caddr2) { + int i; + for (i = 0; i < 16; i++) { + if (caddr1[i] != caddr2[i]) { + return false; + } + } + return true; + } + + static int getScopeID (SOCKETADDRESS him) { + return him.him6.sin6_scope_id; + } + + static boolean cmpScopeID (int scope, SOCKETADDRESS him) { + return him.him6.sin6_scope_id == scope; + } + + /* these methods are not from net_util_md.c */ + + static boolean ipv6_available() { + return InetAddressImplFactory.isIPv6Supported(); + } + + static boolean IS_NULL(Object obj) { + return obj == null; + } + + static boolean IN6ADDR_ISANY(SOCKETADDRESS him) { + if (him.sa_family != AF_INET6) { + return false; + } + byte[] addr = him.him6.sin6_addr; + byte b = 0; + for (int i = 0; i < addr.length; i++) { + b |= addr[i]; + } + return b == 0; + } + + static boolean NET_SockaddrEqualsInetAddress(SOCKETADDRESS him, InetAddress iaObj) { + int family = iaObj.family == InetAddress.IPv4 ? AF_INET : AF_INET6; + + if (him.sa_family == AF_INET6) { + byte[] caddrNew = him.him6.sin6_addr; + if (NET_IsIPv4Mapped(caddrNew)) { + int addrNew; + int addrCur; + if (family == AF_INET6) { + return false; + } + addrNew = NET_IPv4MappedToIPv4(caddrNew); + addrCur = iaObj.address; + if (addrNew == addrCur) { + return true; + } else { + return false; + } + } else { + byte[] caddrCur; + int scope; + + if (family == AF_INET) { + return false; + } + scope = ((Inet6Address)iaObj).getScopeId(); + caddrCur = ((Inet6Address)iaObj).ipaddress; + if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) { + return true; + } else { + return false; + } + } + } else { + int addrNew, addrCur; + if (family != AF_INET) { + return false; + } + addrNew = ntohl(him.him4.sin_addr.s_addr); + addrCur = iaObj.address; + if (addrNew == addrCur) { + return true; + } else { + return false; + } + } + } + + static InetAddress NET_SockaddrToInetAddress(SOCKETADDRESS him, int[] port) { + InetAddress iaObj; + if (him.sa_family == AF_INET6) { + byte[] caddr = him.him6.sin6_addr; + if (NET_IsIPv4Mapped(caddr)) { + iaObj = new Inet4Address(null, NET_IPv4MappedToIPv4(caddr)); + } else { + iaObj = new Inet6Address(null, caddr, getScopeID(him)); + } + port[0] = ntohs(him.him6.sin_port); + } else { + iaObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); + port[0] = ntohs(him.him4.sin_port); + } + return iaObj; + } + + static void NET_ThrowByNameWithLastError(JNIEnv env, String exceptionClass, String message) { + JNU_ThrowByName(env, exceptionClass, "errno: " + WSAGetLastError() + ", error: " + message + "\n"); + } + + static boolean IN_MULTICAST(int ipv4address) { + return ((ipv4address >> 24) & 0xf0) == 0xe0; + } + + static boolean IN6_IS_ADDR_MULTICAST(in6_addr address) { + return (address.s6_bytes()[0] & 0xff) == 0xff; + } + + static final class SOCKETADDRESS implements IIPEndPointWrapper { + final SOCKETADDRESS him = this; + final SOCKETADDRESS him4 = this; + final SOCKETADDRESS him6 = this; + final SOCKETADDRESS sin_addr = this; + int sa_family; + int sin_port; + int s_addr; + byte[] sin6_addr; + int sin6_scope_id; + + public void set(IPEndPoint ep) { + if (ep == null) { + sa_family = 0; + sin_port = 0; + s_addr = 0; + sin6_addr = null; + sin6_scope_id = 0; + } else { + sa_family = ep.get_AddressFamily().Value; + sin_port = htons(ep.get_Port()); + if (sa_family == AF_INET) { + s_addr = (int)ep.get_Address().get_Address(); + sin6_addr = null; + sin6_scope_id = 0; + } else { + s_addr = 0; + IPAddress addr = ep.get_Address(); + sin6_addr = addr.GetAddressBytes(); + sin6_scope_id = (int)addr.get_ScopeId(); + } + } + } + + public IPEndPoint get() { + if (sa_family == AF_INET) { + return new IPEndPoint(new IPAddress(s_addr & 0xFFFFFFFFL), ntohs(sin_port)); + } else if (sa_family == AF_INET6) { + IPAddress addr; + if (sin6_addr == null) { + addr = IPAddress.IPv6Any; + } else { + addr = new IPAddress(sin6_addr, sin6_scope_id & 0xFFFFFFFFL); + } + return new IPEndPoint(addr, ntohs(sin_port)); + } else { + return null; + } + } + } + + static int GET_PORT(SOCKETADDRESS sockaddr) { + return sockaddr.sin_port; + } + + static void Sleep(int ms) { + cli.System.Threading.Thread.Sleep(ms); + } +} |