private void EndTcpReadData(IAsyncResult ar) { TcpClient client = null; NetworkStream stream = null; try { object[] state = (object[])ar.AsyncState; client = (TcpClient)state[0]; stream = (NetworkStream)state[1]; byte[] buffer = (byte[])state[2]; Timer timer = (Timer)state[3]; timer.Dispose(); stream.EndRead(ar); DnsMessageBase query; try { query = DnsMessageBase.Create(buffer, true, TsigKeySelector, null); } catch (Exception e) { throw new Exception("Error parsing dns query", e); } DnsMessageBase response = ProcessMessage(query, ((IPEndPoint)client.Client.RemoteEndPoint).Address, ProtocolType.Tcp); if (response == null) { response = query; query.IsQuery = false; query.ReturnCode = ReturnCode.ServerFailure; } int length = response.Encode(out buffer, true); timer = new Timer(TcpTimedOut, new object[] { client, stream }, 120000, System.Threading.Timeout.Infinite); stream.BeginWrite(buffer, 0, length, EndTcpSendData, new object[] { client, stream, timer }); } catch (Exception e) { try { if (stream != null) { stream.Close(); } } catch {} try { if (client != null) { client.Close(); } } catch {} OnExceptionThrown(e); } }
private void EndUdpReceive(IAsyncResult ar) { try { IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, _DNS_PORT); byte[] buffer = _udpClient.EndReceive(ar, ref endpoint); DnsMessageBase query; try { query = DnsMessageBase.Create(buffer, true, TsigKeySelector, null); } catch (Exception e) { throw new Exception("Error parsing dns query", e); } DnsMessageBase response = ProcessMessage(query, endpoint.Address, ProtocolType.Udp); if (response == null) { response = query; query.IsQuery = false; query.ReturnCode = ReturnCode.ServerFailure; } int length = response.Encode(out buffer, false); #region Truncating DnsMessage message = response as DnsMessage; if (message != null) { int maxLength = 512; if (query.IsEDnsEnabled && message.IsEDnsEnabled) { maxLength = Math.Max(512, (int)message.EDnsOptions.UpdPayloadSize); } while (length > maxLength) { // First step: remove data from additional records except the opt record if ((message.IsEDnsEnabled && (message.AdditionalRecords.Count > 1)) || (!message.IsEDnsEnabled && (message.AdditionalRecords.Count > 0))) { for (int i = message.AdditionalRecords.Count - 1; i >= 0; i--) { if (message.AdditionalRecords[i].RecordType != RecordType.Opt) { message.AdditionalRecords.RemoveAt(i); } } length = message.Encode(out buffer, false); continue; } int savedLength = 0; if (message.AuthorityRecords.Count > 0) { for (int i = message.AuthorityRecords.Count - 1; i >= 0; i--) { savedLength += message.AuthorityRecords[i].MaximumLength; message.AuthorityRecords.RemoveAt(i); if ((length - savedLength) < maxLength) { break; } } message.IsTruncated = true; length = message.Encode(out buffer, false); continue; } if (message.AnswerRecords.Count > 0) { for (int i = message.AnswerRecords.Count - 1; i >= 0; i--) { savedLength += message.AnswerRecords[i].MaximumLength; message.AnswerRecords.RemoveAt(i); if ((length - savedLength) < maxLength) { break; } } message.IsTruncated = true; length = message.Encode(out buffer, false); continue; } if (message.Questions.Count > 0) { for (int i = message.Questions.Count - 1; i >= 0; i--) { savedLength += message.Questions[i].MaximumLength; message.Questions.RemoveAt(i); if ((length - savedLength) < maxLength) { break; } } message.IsTruncated = true; length = message.Encode(out buffer, false); continue; } } } #endregion _udpClient.BeginSend(buffer, length, endpoint, EndUdpSend, null); } catch (Exception e) { OnExceptionThrown(e); } StartUdpListen(); }