GRONG: A small authoritative DNS name server written in Go

Skip to first unread message

Stéphane Bortzmeyer

Feb 11, 2010, 9:25:32 AM2/11/10
to golang-nuts
It is a not a serious production-ready name server (for instance, it
is very brittle when invalid packets come in) but I wrote it to learn
Go. Comments most welcome. Techniques used: goroutines, binary
protocol reading and writing.

(That's also why I don't use the dns* modules in package net.)

Russ Cox

Feb 19, 2010, 3:42:03 AM2/19/10
to Stéphane Bortzmeyer, golang-nuts
It's pretty nice looking code. A bunch of small comments below.
The most important one is please don't use runtime.Semacquire
when a channel will do just as well.

Nice use of net.Addr.
Qdcount etc should be implied by the length of the
corresponding slices.

Qsection and Asection might be clearer as Question and Answer,
with also NS and Extra added as the last two sections.
There's no reason to misspell Type.
ToTXT and Encode both allocate buffers.
Instead you could pass in the slice to write to and let the
marshaller have a single buffer instead of the small
allocations. That sidesteps the "what a waste" issue.
Another way would be to pass in a small bufio.Writer.
for i := 0; i < len(s); i++ {
c := s[i]
instead of
for i, c := range strings.Bytes(s) {
will avoid an allocation.

You might be interested to look at packDomainName in
It's probably cleaner to write to a bytes.Buffer than to
repeatedly call bytes.Add.
typical Go style is to uppercase the whole acronym
when camelcasing, so defaultTTL not defaultTtl
good place for a composite literal:

result[i] = types.RR{
Name: domain,
TTL: defaultTTL,
Type: types.NS,
Class: types.IN,
Data: types.Encode(text),

all the RR initializations could use them.
The upper bounds are not relevant.
PutUint16(result[12+last+1:], ...)
most programs shouldn't need to import "runtime".
there is no guarantee that Semacquire will stay as it is.
it's really a low-level thing, and in fact it might get
hidden again. on the other hand, channels are here to stay.

runtime.Semacquire instead of a channel may in fact
have less overhead but it almost never matters,
especially when the goal is to "sleep forever".

<-make(chan int) "case
true" is more idiomatically written "default"
the switches would be more idiomatic if they
switched on the value on the left of all the ==.
(e.g., switch query.Qtype {, case types.NS, case types.SOA, default)
if all the cases that finished the result did "return result"
then you wouldn't need to set SERVFAIL in multiple places,
just once at the end of the function, unconditionally.

Reply all
Reply to author
0 new messages