Для начал у вас не правильно работает function ReplaceSpecSymbol, она оставляет спецсимволы в конце строки. Вот накидал правильно работающую:
function ReplaceSpecSymbol(S: String): String;
var Count : Integer;
begin
Count:=0;
Result:='';
while True do
begin
Count:=Ord(S.Chars[0]);
Result:=Result+S.Substring(1,Count)+'.';
S:=S.Remove(0,Count+1);
if Ord(S.Chars[0])=0 Then
break;
end;
Result:=Result.TrimRight(['.']);
end;
После этого в вашем проекте нормально все ресолвится, но что отсылать в ответ на lookup я не имею представления. Не знаю как заставить IdDNSResolver отдать данные в сыром формате, надо искать и читать документацию.
Вот код процедуры, но надо разобраться что слать:
procedure TMainForm.IdUDPServerUDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var S, Domain: String;
I : Integer;
ABuffer : TIdBytes;
begin
S:=ReplaceSpecSymbol(BytesToString(AData,12));
Memo_Log.Lines.Add(S);
if Pos('in-addr.arpa',S)=0 then
begin
IdDNSResolver.Resolve(S);
for I := 0 to IdDNSResolver.QueryResult.Count-1 do
if IdDNSResolver.QueryResult[I].RecType = qtA then
begin
S:=TARecord(IdDNSResolver.QueryResult[I]).IPAddress;
Memo_Log.Lines.Add('IdDNSResolver: '+S);
end;
// Вот дальше не знаю что именно пересылать
// ABuffer:=DNSHeader.GenerateBinaryHeader;
// ABuffer:=IdDNSResolver.PlainTextResult;
// ABuffer:=ABuffer+IdDNSResolver.InternalQuery;
// ABuffer:=IdDNSResolver.InternalQuery;
ABinding.Send(ABuffer);
end;
Вы можете поразбираться с помощью простейшего DNS прокси, по крайней мере будете видеть что идет в запросе и что в ответе. Код ниже, только пропишите глобальную переменную ALocalPort : Integer, для запоминания забинденного порта на 127.0.0.1
procedure TMainForm.IdUDPServerUDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
Const ExternalDNSHost = '8.8.8.8';
LocalHost = '127.0.0.1';
begin
if ABinding.PeerIP.Equals(LocalHost) then // если запрос с локального, пересылаем на внешний dns
begin
ALocalPort:=ABinding.PeerPort;
IdUDPServer.SendBuffer(ExternalDNSHost,53,AData);
end;
if ABinding.PeerIP.Equals(ExternalDNSHost) then // если с внешнего, пересылаем на локальный
IdUDPServer.SendBuffer(LocalHost,ALocalPort,AData);
exit;
end;
в коммандной строке используйте "nslookup -retry=1 -timeout=30 google.ru 127.0.0.1 " (один повтор запроса, чтоб не засирать отладку и таймаут сколько нужно секунд, что не отвалился запрос пока будете разбираться)
Все правильно получаете, кодировка тут не при чем. Согласно спецификации "DNS Packet Structure", вы получаете не строку, а пакет который нужно разобрать. К примеру если запрос будет "nslookup www.google.ru 127.0.0.1", то там где вы получаете имя хоста будет строка "''#3'www'#6'google'#2'ru'#0#0#1#0#1".
Парсинг простейший:
#3 - означает что далее идут 3 символа хоста
'www' - вот ожидаемые 3 символа
#6 - далее идут еще 6 символов хоста
'google' - ага, вот они
#2 - ну и еще 2 символа
'ru' - ура, они здесь
#0 - конец имени хоста, складываем в кучу, перемежая точками и получаем www.google.ru
#0 - дальше у нас служебная информация...
#1
#0
#1
Вот как то так.
P.S. А зачем вам на таком низком уровне работать? Может использовать IdDNSServer : TIdDNSServer ?
P.P.S. Правильно Memo1.Lines.Add(BytesToString(AData,12)); //(12, а не 13)