Stuck on #GT1 - forwarded queries timeout

I’m stuck on Stage #GT1.

The queries that I forward to the custom resolver are timing out and I’m not getting a response. I’m not sure what I’m doing wrong.

Here are my logs:

[tester::#GT1] Running tests for Stage #GT1 (Forwarding Server)
[tester::#GT1] Starting DNS server on 127.0.0.1:2053
[tester::#GT1] Running program
[tester::#GT1] DNS resolver listening on 127.0.0.1:5354
[tester::#GT1] Connecting to 127.0.0.1:2053 using UDP
[your_program] Listening for incoming UDP packets on port 2053...
[your_program] Forwarding DNS queries to {127.0.0.1 5354 }
[your_program] domainName: codecrafters.io
[your_program] Forwarding A record query for: codecrafters.io
[tester::#GT1] Did not receive response from DNS server, retrying
[tester::#GT1] read udp 127.0.0.1:41447->127.0.0.1:2053: i/o timeout
[your_program] domainName: codecrafters.io
[your_program] Forwarding A record query for: codecrafters.io
[tester::#GT1] Did not receive response from DNS server, retrying
[tester::#GT1] read udp 127.0.0.1:60207->127.0.0.1:2053: i/o timeout
[tester::#GT1] read udp 127.0.0.1:35543->127.0.0.1:2053: i/o timeout
[tester::#GT1] Test failed
[tester::#GT1] Terminating program
[tester::#GT1] Shutting down DNS resolver server...
[tester::#GT1] Program terminated successfully

And here’s a snippet of my code:

	for {
		size, source, err := udpConn.ReadFromUDP(buf)
		if err != nil {
			fmt.Println("Error receiving data:", err)
			break
		}

		receivedData := buf[:size]
		receivedHeader := DeserializeHeader(receivedData[:12])
		offset := 12 // Start after the header
		header := NewHeader(receivedHeader.ID, receivedHeader.OPCODE, receivedHeader.RD, receivedHeader.QDCOUNT)
		questions := []Question{}
		answers := []Answer{}
		for i := uint16(0); i < receivedHeader.QDCOUNT; i++ {
			receivedQuestion, newOffset := DeserializeQuestion(receivedData[offset:])
			question := NewQuestion(receivedQuestion.Name, receivedQuestion.Type, receivedQuestion.Class)
			questions = append(questions, *question)
			offset += newOffset
			if *resolver != "" {
				fmt.Printf("Forwarding A record query for: %s\n", receivedQuestion.Name)
				questionBuf := question.SerializeQuestion()
				message := NewMessage(header, []Question{receivedQuestion}, []Answer{})
				forward := message.Serialize()
				_, err = udpConn.WriteToUDP(forward, udpResolverAddr)
				if err != nil {
					fmt.Println("failed to forward message: ", err)
				}
				resolverBuf := make([]byte, 512)
				_, _, err := udpConn.ReadFromUDP(resolverBuf)
				if err != nil {
					fmt.Println("Error receiving data:", err)
					break
				}
				offset := 12 + len(questionBuf)
				answer := DeserializeAnswer(resolverBuf, offset)
				answers = append(answers, answer)
			} else {
				answer := NewAnswer(questions[i].Name, questions[i].Type, questions[i].Class, 60, 4, "1.1.1.1")
				answers = append(answers, *answer)
			}
		}

		message := NewMessage(header, questions, answers)
		response := message.Serialize()

		_, err = udpConn.WriteToUDP(response, source)
		if err != nil {
			fmt.Println("Failed to send response:", err)
		}
	}

My code is split into multiple files so here’s the whole repo for reference: GitHub - 0xi4o/codecrafters-dns-server-go

Any help is appreciated. Thank you.

Hey @0xi4o, I logged the messages being forwarded to the resolver:

There were two main issues:

  1. The most significant bit of the flags, QR, was incorrect:

QR: A one bit field that specifies whether this message is a query (0), or a response (1).

  1. The ANCOUNT field was set to 1 when there shouldn’t be any answers.

Let me know if you’d like further clarification!

1 Like

@andy1li Yep. That was it.

Thank you so much!

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.