Responder channel is now os.Error

to make it possible to send errors back
This commit is contained in:
Miek Gieben 2011-01-27 20:16:58 +01:00
parent 44c00e1b57
commit 896df96f94
5 changed files with 124 additions and 119 deletions

View File

@ -223,7 +223,7 @@ func main() {
s.Address = addr
s.Port = port
var srv *server
rs := make(chan bool)
rs := make(chan os.Error)
go s.NewResponder(srv, rs)
forever:
@ -236,7 +236,7 @@ forever:
break forever
}
}
rs <- true // shutdown responder
rs <- nil // shutdown responder
<-rs // wait for confirmation
// And the resolvers
for _, q := range qr {

View File

@ -17,115 +17,118 @@
package main
import (
"os"
"net"
"strconv"
"dns"
"dns/responder"
"runtime"
"os/signal"
"strconv"
"dns/responder"
"runtime"
"os/signal"
)
type server responder.Server
func reply(a net.Addr, in []byte, tcp bool) *dns.Msg {
inmsg := new(dns.Msg)
if !inmsg.Unpack(in) {
println("Unpacking failed")
return nil
}
if inmsg.MsgHdr.Response == true {
return nil // Don't answer responses
}
m := new(dns.Msg)
m.MsgHdr.Id = inmsg.MsgHdr.Id
m.MsgHdr.Authoritative = true
m.MsgHdr.Response = true
m.MsgHdr.Opcode = dns.OpcodeQuery
inmsg := new(dns.Msg)
if !inmsg.Unpack(in) {
println("Unpacking failed")
return nil
}
if inmsg.MsgHdr.Response == true {
return nil // Don't answer responses
}
m := new(dns.Msg)
m.MsgHdr.Id = inmsg.MsgHdr.Id
m.MsgHdr.Authoritative = true
m.MsgHdr.Response = true
m.MsgHdr.Opcode = dns.OpcodeQuery
m.MsgHdr.Rcode = dns.RcodeSuccess
m.Question = make([]dns.Question, 1)
m.Answer = make([]dns.RR, 1)
m.Extra = make([]dns.RR, 1)
m.MsgHdr.Rcode = dns.RcodeSuccess
m.Question = make([]dns.Question, 1)
m.Answer = make([]dns.RR, 1)
m.Extra = make([]dns.RR, 1)
r := new(dns.RR_A)
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
ip, _ := net.ResolveUDPAddr(a.String()) // No general variant for both upd and tcp
r.A = ip.IP.To4() // To4 very important
r := new(dns.RR_A)
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
ip, _ := net.ResolveUDPAddr(a.String()) // No general variant for both upd and tcp
r.A = ip.IP.To4() // To4 very important
t := new(dns.RR_TXT)
t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
if tcp {
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
} else {
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
}
t := new(dns.RR_TXT)
t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
if tcp {
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
} else {
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
}
m.Question[0] = inmsg.Question[0]
m.Answer[0] = r
m.Extra[0] = t
m.Question[0] = inmsg.Question[0]
m.Answer[0] = r
m.Extra[0] = t
return m
return m
}
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) {
m := reply(a, in, false)
if m == nil {
return
}
out, ok := m.Pack()
if !ok {
println("Failed to pack")
return
}
responder.SendUDP(out, c, a)
m := reply(a, in, false)
if m == nil {
return
}
out, ok := m.Pack()
if !ok {
println("Failed to pack")
return
}
responder.SendUDP(out, c, a)
}
func (s *server) ResponderTCP(c *net.TCPConn, in []byte) {
m := reply(c.RemoteAddr(), in, true)
if m == nil {
return
}
out, ok := m.Pack()
if !ok {
println("Failed to pack")
return
}
responder.SendTCP(out, c)
m := reply(c.RemoteAddr(), in, true)
if m == nil {
return
}
out, ok := m.Pack()
if !ok {
println("Failed to pack")
return
}
responder.SendTCP(out, c)
}
func main() {
runtime.GOMAXPROCS(10) // Be bold
runtime.GOMAXPROCS(10) // Be bold
s := new(responder.Server)
s.Address = "127.0.0.1"
s.Port = "8053"
var srv *server
ch := make(chan bool)
go s.NewResponder(srv, ch)
s := new(responder.Server)
s.Address = "127.0.0.1"
s.Port = "8053"
var srv *server
ch := make(chan os.Error)
go s.NewResponder(srv, ch)
t := new(responder.Server)
t.Address = "127.0.0.1"
t.Port = "8053"
t.Tcp = true
var srvt *server
cht := make(chan bool)
go t.NewResponder(srvt, cht)
t := new(responder.Server)
t.Address = "127.0.0.1"
t.Port = "8053"
t.Tcp = true
var srvt *server
cht := make(chan os.Error)
go t.NewResponder(srvt, cht)
forever:
for {
// Wait for a signal to stop
select {
case <-signal.Incoming:
println("Signal received, stopping")
ch <- true
cht <- true
break forever
case <-cht:
// last message from tcp channel
case <-ch:
// last message from udp channel
}
}
close(cht)
close(ch)
for {
// Wait for a signal to stop
select {
case <-signal.Incoming:
println("Signal received, stopping")
ch <- nil
cht <- nil
break forever
case e := <-cht:
// last message from tcp channel
println(e.String())
case e := <-ch:
// last message from udp channel
println(e.String())
}
}
close(cht)
close(ch)
}

View File

@ -10,7 +10,8 @@
package main
import (
"net"
"os"
"net"
"dns"
"dns/responder"
"os/signal"
@ -25,9 +26,9 @@ func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) {
// NXdomain 'n stuff
println("Unpacking failed")
}
if inmsg.MsgHdr.Response == true {
return // don't answer responses
}
if inmsg.MsgHdr.Response == true {
return // don't answer responses
}
m := new(dns.Msg)
m.MsgHdr.Id = inmsg.MsgHdr.Id
m.MsgHdr.Response = true
@ -52,7 +53,7 @@ func main() {
s.Address = "127.0.0.1"
s.Port = "8053"
var srv *server
ch := make(chan bool)
ch := make(chan os.Error)
go s.NewResponder(srv, ch)
forever:
@ -61,9 +62,13 @@ forever:
select {
case <-signal.Incoming:
println("Signal received, stopping")
ch <- true
<-ch
ch <- nil
<-ch
break forever
case e := <-cht:
println(e.String())
case e := <-ch:
println(e.String())
}
}
}

View File

@ -59,12 +59,12 @@ type Responder interface {
ResponderTCP(c *net.TCPConn, in []byte)
}
// Start a new responder. The returned channel is only used to stop the responder.
// Send 'true' to make it stop
func (res *Server) NewResponder(h Responder, stop chan bool) {
// Start a new responder. The returned channel is used to stop the responder.
// Send 'nil' to make it stop. It can also return error via the channel.
func (res *Server) NewResponder(h Responder, stop chan os.Error) {
var port string
if len(res.Address) == 0 {
// We cannot start responding without an addresss
stop <- &dns.Error{Error: "No addresses"}
return
}
if res.Port == "" {
@ -83,14 +83,12 @@ func (res *Server) NewResponder(h Responder, stop chan bool) {
for {
select {
case <-stop:
stop <- true
stop <- nil
listener.Close()
break foreverTCP
case s := <-tch:
if s.err != nil {
// always fatal??
stop <- false
println(s.err.String())
stop <- s.err
} else {
go h.ResponderTCP(s.tcp, s.msg)
}
@ -105,13 +103,11 @@ func (res *Server) NewResponder(h Responder, stop chan bool) {
for {
select {
case <-stop:
stop <- true
stop <- nil
break foreverUDP
case s := <-uch:
if s.err != nil {
//continue
stop <- false
println(s.err.String())
stop <- s.err
} else {
go h.ResponderUDP(s.udp, s.addr, s.msg)
}

View File

@ -1,6 +1,7 @@
package responder
import (
"os"
"testing"
"fmt"
"dns"
@ -66,7 +67,7 @@ func TestResponder(t *testing.T) {
su.Address = "127.0.0.1"
su.Port = "8053"
var us *myserv
uch := make(chan bool)
uch := make(chan os.Error)
go su.NewResponder(us, uch)
/* tcp servertje */
@ -75,23 +76,23 @@ func TestResponder(t *testing.T) {
st.Port = "8053"
st.Tcp = true
var ts *myserv
tch := make(chan bool)
tch := make(chan os.Error)
go st.NewResponder(ts, tch)
time.Sleep(1 * 1e9)
uch <- true
tch <- true
uch <- nil
tch <- nil
<-uch
<-tch
}
/*
func TestReflectorResponder(t *testing.T) {
stop := make(chan bool)
stop := make(chan os.Error)
s := new(Server)
s.Port = "8053"
s.Address = "127.0.0.1"
stoptcp := make(chan bool)
stoptcp := make(chan os.Error)
stcp := new(Server)
stcp.Port = "8053"
stcp.Address = "127.0.0.1"
@ -101,8 +102,8 @@ func TestReflectorResponder(t *testing.T) {
go s.NewResponder(Reflector, stop)
time.Sleep(1 * 1e9)
stop <- true
stoptcp <- true
stop <- nil
stoptcp <- nil
<-stop
<-stoptcp
}
@ -175,7 +176,7 @@ func TestResponderTsig(t *testing.T) {
su.Address = "127.0.0.1"
su.Port = "8053"
var us *servtsig
uch := make(chan bool)
uch := make(chan os.Error)
go su.NewResponder(us, uch)
/* tcp servertje */
@ -184,11 +185,11 @@ func TestResponderTsig(t *testing.T) {
st.Port = "8053"
st.Tcp = true
var ts *servtsig
tch := make(chan bool)
tch := make(chan os.Error)
go st.NewResponder(ts, tch)
time.Sleep(1 * 1e9)
uch <- true
tch <- true
uch <- nil
tch <- nil
<-uch
<-tch
}