diff -r c943ca4a3380 -r 39275d6a8cac jdk/src/java.base/share/classes/java/net/DatagramSocket.java --- a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java Tue May 27 08:56:59 2014 -0400 +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java Wed May 28 14:51:24 2014 +0100 @@ -85,6 +85,17 @@ */ boolean oldImpl = false; + /** + * Set when a socket is ST_CONNECTED until we are certain + * that any packets which might have been received prior + * to calling connect() but not read by the application + * have been read. During this time we check the source + * address of all packets received to be sure they are from + * the connected destination. Other packets are read but + * silently dropped. + */ + private boolean explicitFilter = false; + private int bytesLeftToFilter; /* * Connection state: * ST_NOT_CONNECTED = socket not connected @@ -144,6 +155,15 @@ // socket is now connected by the impl connectState = ST_CONNECTED; + // Do we need to filter some packets? + int avail = getImpl().dataAvailable(); + if (avail == -1) { + throw new SocketException(); + } + explicitFilter = avail > 0; + if (explicitFilter) { + bytesLeftToFilter = getReceiveBufferSize(); + } } catch (SocketException se) { // connection will be emulated by DatagramSocket @@ -492,6 +512,7 @@ connectedAddress = null; connectedPort = -1; connectState = ST_NOT_CONNECTED; + explicitFilter = false; } } @@ -750,10 +771,12 @@ } // end of while } } - if (connectState == ST_CONNECTED_NO_IMPL) { + if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) { // We have to do the filtering the old fashioned way since // the native impl doesn't support connect or the connect - // via the impl failed. + // via the impl failed, or .. "explicitFilter" may be set when + // a socket is connected via the impl, for a period of time + // when packets from other sources might be queued on socket. boolean stop = false; while (!stop) { InetAddress peekAddress = null; @@ -772,8 +795,12 @@ if ((!connectedAddress.equals(peekAddress)) || (connectedPort != peekPort)) { // throw the packet away and silently continue - DatagramPacket tmp = new DatagramPacket(new byte[1], 1); + DatagramPacket tmp = new DatagramPacket( + new byte[1024], 1024); getImpl().receive(tmp); + if (explicitFilter) { + bytesLeftToFilter -= tmp.getLength(); + } } else { stop = true; } @@ -782,6 +809,15 @@ // If the security check succeeds, or the datagram is // connected then receive the packet getImpl().receive(p); + if (explicitFilter) { + bytesLeftToFilter -= p.getLength(); + if (bytesLeftToFilter <= 0) { + explicitFilter = false; + } else { + // break out of filter, if there is no more data queued + explicitFilter = getImpl().dataAvailable() > 0; + } + } } }