private DNSResponse TcpRequest(DNSRequest request, List<IPEndPoint> dnsServers, int timeout)
{
//System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
//sw.Start();
byte[] responseMessage = new byte[512];
for (int intAttempts = 0; intAttempts < m_Retries; intAttempts++)
{
for (int intDnsServer = 0; intDnsServer < dnsServers.Count; intDnsServer++)
{
TcpClient tcpClient = new TcpClient();
tcpClient.ReceiveTimeout = timeout * 1000;
try
{
IAsyncResult result = tcpClient.BeginConnect(dnsServers[intDnsServer].Address, dnsServers[intDnsServer].Port, null, null);
bool success = result.AsyncWaitHandle.WaitOne(timeout * 1000, true);
if (!success || !tcpClient.Connected)
{
tcpClient.Close();
Verbose(string.Format(";; Connection to nameserver {0} failed", (intDnsServer + 1)));
continue;
}
BufferedStream bs = new BufferedStream(tcpClient.GetStream());
byte[] data = request.Data;
bs.WriteByte((byte)((data.Length >> 8) & 0xff));
bs.WriteByte((byte)(data.Length & 0xff));
bs.Write(data, 0, data.Length);
bs.Flush();
DNSResponse TransferResponse = new DNSResponse();
int intSoa = 0;
int intMessageSize = 0;
//Debug.WriteLine("Sending "+ (request.Length+2) + " bytes in "+ sw.ElapsedMilliseconds+" mS");
while (true)
{
int intLength = bs.ReadByte() << 8 | bs.ReadByte();
if (intLength <= 0)
{
tcpClient.Close();
Verbose(string.Format(";; Connection to nameserver {0} failed", (intDnsServer + 1)));
throw new SocketException(); // next try
}
intMessageSize += intLength;
data = new byte[intLength];
bs.Read(data, 0, intLength);
DNSResponse response = new DNSResponse(dnsServers[intDnsServer], data);
//Debug.WriteLine("Received "+ (intLength+2)+" bytes in "+sw.ElapsedMilliseconds +" mS");
if (response.header.RCODE != RCode.NOERROR)
return response;
if (response.Questions[0].QType != DNSQType.AXFR)
{
//AddToCache(response);
return response;
}
// Zone transfer!!
if (TransferResponse.Questions.Count == 0)
TransferResponse.Questions.AddRange(response.Questions);
TransferResponse.Answers.AddRange(response.Answers);
TransferResponse.Authorities.AddRange(response.Authorities);
TransferResponse.Additionals.AddRange(response.Additionals);
if (response.Answers[0].Type == DNSType.SOA)
intSoa++;
if (intSoa == 2)
{
TransferResponse.header.QDCOUNT = (ushort)TransferResponse.Questions.Count;
TransferResponse.header.ANCOUNT = (ushort)TransferResponse.Answers.Count;
TransferResponse.header.NSCOUNT = (ushort)TransferResponse.Authorities.Count;
TransferResponse.header.ARCOUNT = (ushort)TransferResponse.Additionals.Count;
TransferResponse.MessageSize = intMessageSize;
return TransferResponse;
}
}
} // try
catch (SocketException)
{
continue; // next try
}
finally
{
m_Unique++;
// close the socket
tcpClient.Close();
}
}
}
DNSResponse responseTimeout = new DNSResponse();
responseTimeout.Timedout = true;
return responseTimeout;
}