BUG: W5100 cannot use socket as UDP after using it as TCP

I am still having this bug. Upon significant back and forth, we have not been able to reproduce it on Tim's setup (thanks Tim!), but it's very firmly repeatable on mine. I'd love to see if someone else could give it a shot.

Here's the easiest to use code:

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <utility/w5100.h>
#include "Dns.h"

void ShowSockStatus()
{
	for (int i = 0; i < MAX_SOCK_NUM; i++) {
		Serial.print("Socket#");
		Serial.print(i);
		uint8_t s = W5100.readSnSR(i);
		Serial.print(":0x");
		Serial.print(s,16);
		Serial.print(" ");
		Serial.print(W5100.readSnPORT(i));
		Serial.print(" D:");
		uint8_t dip[4];
		W5100.readSnDIPR(i, dip);
		for (int j=0; j<4; j++) {
			Serial.print(dip[j],10);
			if (j<3) Serial.print(".");
		}
		Serial.print("(");
		Serial.print(W5100.readSnDPORT(i));
		Serial.println(")");
	}
}

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

EthernetServer server(80);
IPAddress dnsserver(4,2,2,1);
IPAddress ip(192,168,10,20);
IPAddress gateway(192,168,10, 2);
IPAddress subnet(255, 255, 255, 0);

long timer;

void DoDNS()
{
	DNSClient dns;
	IPAddress remote_addr;
	dns.begin(dnsserver);
	if (dns.getHostByName("www.yahoo.com", remote_addr) == 1)
	{
		for (int i=0; i<4; i++) {
			Serial.print(remote_addr[i]);
			if (i!=3)
				Serial.print('.');
			else
				Serial.println("");
		}
	}
	else
		Serial.println("DNS FAIL!");
	ShowSockStatus();
}

void setup() {
	Serial.begin(9600);
	Ethernet.begin(mac, ip, dnsserver, gateway, subnet);
	delay(500);

	Serial.println("Start!");
	DoDNS();
	server.begin();
	timer = millis();
}


void loop()
{ 
	//Check if a web client has attached.
	EthernetClient client = server.available();
	if (client) {
		Serial.println("new Client");
		ShowSockStatus();
		boolean currentLineIsBlank = true;
		while (client.connected()) {
			if (client.available()) {
				char c = client.read();
				Serial.print(c);
				if (c == '\n' && currentLineIsBlank) {
					client.stop();
				}
				if (c == '\n') {
					// you're starting a new line
					currentLineIsBlank = true;
				} 
				else if (c != '\r') {
					// you've gotten a character on the current line
					currentLineIsBlank = false;
				}
			}
		}
		// give the web browser time to receive the data
		delay(1);
		// close the connection:
		client.stop();
		Serial.println("client disconnected");
	}

	if ((millis() - timer) > 5000) {
		DoDNS();
		timer = millis();
	}
}

If you start this, let it do a couple of DNS lookups and then browse to the Arduino with a web browser (or wget) you should start getting DNS failure messages.

Here's an output:

Start!
98.139.183.24
Socket#0:0x0 1039 D:4.2.2.1(53)
Socket#1:0x0 0 D:0.0.0.0(0)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)
new Client
Socket#0:0x17 80 D:192.168.10.1(58210)
Socket#1:0x14 80 D:0.0.0.0(0)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)
GET / HTTP/1.1
Host: 192.168.10.20
User-Agent: Wget

client disconnected
DNS FAIL!
Socket#0:0x0 1032 D:4.2.2.1(53)
Socket#1:0x14 80 D:0.0.0.0(0)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)
DNS FAIL!
Socket#0:0x0 1037 D:4.2.2.1(53)
Socket#1:0x14 80 D:0.0.0.0(0)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Note that the full secnario to get it to fail is for a specific socket (in this run above, it's Socket 0) goes from UDP transaction to TCP transaction and then you try and use it for UDP again. In that scenario it won't work (for me)...