diff options
author | jfrijters <jfrijters> | 2008-06-15 13:42:37 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2008-06-15 13:42:37 +0400 |
commit | 41691f00525a12bf1a88261ac60049f77c0ac01a (patch) | |
tree | e0f095cf6cc4cd2a0357f5b1621d2c4f943c53bd /openjdk/sun/nio/ch | |
parent | 1ce49f3525efe6b2dff22c1c44bab9d477e84bab (diff) |
- Implemented connect/disconnect with .NET 2.0 Connect/Disconnect API.
- Throw PortUnreachableException from receive() if we receive WSAECONNRESET while connected.
- Use Socket.IOControl() .NET 2.0 API to disable WSAECONNRESET while not connected.
Diffstat (limited to 'openjdk/sun/nio/ch')
-rw-r--r-- | openjdk/sun/nio/ch/DatagramChannelImpl.java | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java index ce343494..99e928de 100644 --- a/openjdk/sun/nio/ch/DatagramChannelImpl.java +++ b/openjdk/sun/nio/ch/DatagramChannelImpl.java @@ -42,6 +42,13 @@ class DatagramChannelImpl extends DatagramChannel implements SelChImpl { + // 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; + // Our file descriptor FileDescriptor fd = null; @@ -92,6 +99,15 @@ class DatagramChannelImpl super(sp); this.fd = Net.socket(false); this.state = ST_UNCONNECTED; + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw PlainSocketImpl.convertSocketExceptionToIOException(x); + } } public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) @@ -448,18 +464,21 @@ class DatagramChannelImpl if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - // We simulate connectedness, so we don't call connect here, - // but if we're not yet bound, we should bind here. - if (!isBound()) + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + fd.getSocket().Connect(PlainSocketImpl.getAddressFromInetAddress(isa.getAddress()), isa.getPort()); + fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 1 }, null); + } + catch (cli.System.Net.Sockets.SocketException x) { - socket().bind(null); + throw new SocketException(x.getMessage()); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); } - //int n = Net.connect(fd, - // isa.getAddress(), - // isa.getPort(), - // trafficClass); - //if (n <= 0) - // throw new Error(); // Can't happen // Connection succeeded; disallow further invocation state = ST_CONNECTED; @@ -609,7 +628,21 @@ class DatagramChannelImpl private static void disconnect0(FileDescriptor fd) throws IOException { - // since we simulate connectedness, we don't need to do anything here + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + fd.getSocket().Disconnect(true); + fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw PlainSocketImpl.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } } private int receive0(ByteBuffer bb) throws IOException @@ -637,7 +670,13 @@ class DatagramChannelImpl if (x.get_ErrorCode() == Net.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 don't care so we just retry the receive. + // 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 (isConnected()) + { + throw new PortUnreachableException(); + } continue; } if (x.get_ErrorCode() == Net.WSAEMSGSIZE) |