# HG changeset patch # User mchung # Date 1276204897 25200 # Node ID cee4951cdec7f312348ad9b16801cb101efa0fad # Parent ca3811dc046d123998ccbe948e936d0336cbd9a4# Parent 1c86018749bda6a1ebd3515047c4871e6b2e6250 Merge diff -r ca3811dc046d -r cee4951cdec7 jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c --- a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Thu Jun 10 14:14:17 2010 -0700 +++ b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Thu Jun 10 14:21:37 2010 -0700 @@ -120,6 +120,12 @@ rv = connect((SOCKET)fd, (struct sockaddr *)&sa, sa_len); if (rv == SOCKET_ERROR) { handleSocketError(env, WSAGetLastError()); + } else { + /* Disable WSAECONNRESET errors as socket is no longer connected */ + BOOL enable = FALSE; + DWORD bytesReturned = 0; + WSAIoctl((SOCKET)fd, SIO_UDP_CONNRESET, &enable, sizeof(enable), + NULL, 0, &bytesReturned, NULL, NULL); } } diff -r ca3811dc046d -r cee4951cdec7 jdk/src/windows/native/sun/nio/ch/Net.c --- a/jdk/src/windows/native/sun/nio/ch/Net.c Thu Jun 10 14:14:17 2010 -0700 +++ b/jdk/src/windows/native/sun/nio/ch/Net.c Thu Jun 10 14:21:37 2010 -0700 @@ -67,6 +67,14 @@ #define COPY_INET6_ADDRESS(env, source, target) \ (*env)->GetByteArrayRegion(env, source, 0, 16, target) +/** + * Enable or disable receipt of WSAECONNRESET errors. + */ +static void setConnectionReset(SOCKET s, BOOL enable) { + DWORD bytesReturned = 0; + WSAIoctl(s, SIO_UDP_CONNRESET, &enable, sizeof(enable), + NULL, 0, &bytesReturned, NULL, NULL); +} JNIEXPORT void JNICALL @@ -109,6 +117,12 @@ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&opt, sizeof(opt)); } + + /* Disable WSAECONNRESET errors for initially unconnected UDP sockets */ + if (!stream) { + setConnectionReset(s, FALSE); + } + } else { NET_ThrowNew(env, WSAGetLastError(), "socket"); } @@ -149,12 +163,13 @@ SOCKETADDRESS sa; int rv; int sa_len; + SOCKET s = (SOCKET)fdval(env, fdo); if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { return IOS_THROWN; } - rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); + rv = connect(s, (struct sockaddr *)&sa, sa_len); if (rv != 0) { int err = WSAGetLastError(); if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) { @@ -162,6 +177,13 @@ } NET_ThrowNew(env, err, "connect"); return IOS_THROWN; + } else { + /* Enable WSAECONNRESET errors when a UDP socket is connected */ + int type = 0, optlen = sizeof(type); + rv = getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&type, &optlen); + if (rv == 0 && type == SOCK_DGRAM) { + setConnectionReset(s, TRUE); + } } return 1; } diff -r ca3811dc046d -r cee4951cdec7 jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Thu Jun 10 14:21:37 2010 -0700 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. 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. + * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6935563 + * @summary Test that Selector does not select an unconnected DatagramChannel when + * ICMP port unreachable received + */ + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.*; +import java.io.IOException; + +public class SelectWhenRefused { + + public static void main(String[] args) throws IOException { + DatagramChannel dc = DatagramChannel.open().bind(new InetSocketAddress(0)); + int port = dc.socket().getLocalPort(); + dc.close(); + + // datagram sent to this address should be refused + SocketAddress refuser = new InetSocketAddress(InetAddress.getLocalHost(), port); + + dc = DatagramChannel.open().bind(new InetSocketAddress(0)); + try { + dc.configureBlocking(false); + Selector sel = Selector.open(); + dc.register(sel, SelectionKey.OP_READ); + + /* Test 1: not connected so ICMP port unreachable should not be received */ + sendDatagram(dc, refuser); + int n = sel.select(2000); + if (n > 0) { + throw new RuntimeException("Unexpected wakeup"); + } + + /* Test 2: connected so ICMP port unreachable may be received */ + dc.connect(refuser); + try { + sendDatagram(dc, refuser); + n = sel.select(2000); + if (n > 0) { + sel.selectedKeys().clear(); + try { + n = dc.read(ByteBuffer.allocate(100)); + throw new RuntimeException("Unexpected datagram received"); + } catch (PortUnreachableException pue) { + // expected + } + } + } finally { + dc.disconnect(); + } + + /* Test 3: not connected so ICMP port unreachable should not be received */ + sendDatagram(dc, refuser); + n = sel.select(2000); + if (n > 0) { + throw new RuntimeException("Unexpected wakeup after disconnect"); + } + + } finally { + dc.close(); + } + } + + static void sendDatagram(DatagramChannel dc, SocketAddress remote) + throws IOException + { + ByteBuffer bb = ByteBuffer.wrap("Greetings!".getBytes()); + dc.send(bb, remote); + } +}