Fix the UDP/TCP handling for the responder

This commit is contained in:
Miek Gieben 2011-01-13 15:14:27 +01:00
parent 8582967bab
commit ea68b035e9
2 changed files with 122 additions and 42 deletions

View File

@ -250,7 +250,7 @@ func exchangeUDP(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Err
}
for a := 0; a < attempts; a++ {
if send {
err := sendUDP(c, m)
err := sendUDP(m, c)
if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
@ -298,7 +298,7 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Err
for a := 0; a < attempts; a++ {
// only send something when told so
if send {
err := sendTCP(c, m)
err := sendTCP(m,c)
if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
@ -325,8 +325,7 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Err
return nil, &dns.Error{Error: servErr}
}
func sendUDP(c net.Conn, m []byte) os.Error {
func sendUDP(m []byte,c net.Conn) os.Error {
_, err := c.Write(m)
if err != nil {
return err
@ -344,7 +343,7 @@ func recvUDP(c net.Conn) ([]byte, os.Error) {
return m, nil
}
func sendTCP(c net.Conn, m []byte) os.Error {
func sendTCP(m []byte, c net.Conn) os.Error {
l := make([]byte, 2)
l[0] = byte(len(m) >> 8)
l[1] = byte(len(m))

View File

@ -12,10 +12,7 @@ import (
"os"
"net"
"dns"
"fmt"
)
// Some helper function for sending tcp/udp queries, like those
// in resolver.go, but then exported?
type Server struct {
Address string // interface to use, for multiple interfaces, use multiple servers
@ -25,12 +22,25 @@ type Server struct {
Mangle func([]byte) []byte // mangle the packet, before sending
}
type serverMsgUDP struct {
c *net.UDPConn // connection
addr *net.UDPAddr // remote address
msg []byte // raw dns message
err os.Error // any errors
}
type serverMsgTCP struct {
c *net.TCPConn // connection
msg []byte // raw dns message
err os.Error // any errors
}
// Every nameserver must implement the Handler interface.
type Responder interface {
// Receives the raw message content
ResponderUDP(c *net.UDPConn, raddr net.Addr, in []byte)
ResponderUDP(c *net.UDPConn, a *net.UDPAddr, in []byte)
// Receives the raw message content
ResponderTCP(c *net.TCPConn, raddr net.Addr, in []byte)
ResponderTCP(c *net.TCPConn, in []byte)
}
// This is a NAMESERVER
@ -50,49 +60,120 @@ func (res *Server) NewResponder(h Responder, ch chan bool) os.Error {
}
switch res.Tcp {
case true:
/* Todo tcp conn. */
tch := make(chan serverMsgTCP)
a, _ := net.ResolveTCPAddr(res.Address + ":" + port)
go listenerTCP(a, tch)
foreverTCP:
for {
select {
case <-ch:
ch <- true
break foreverTCP
case s := <-tch:
if s.err != nil {
//continue
}
go h.ResponderTCP(s.c, s.msg)
}
}
case false:
udpaddr, _ := net.ResolveUDPAddr(res.Address + ":" + port)
c, _ := net.ListenUDP("udp", udpaddr)
foreverudp:
uch := make(chan serverMsgUDP)
a, _ := net.ResolveUDPAddr(res.Address + ":" + port)
go listenerUDP(a, uch)
foreverUDP:
for {
select {
case <-ch:
ch <- true // last echo
c.Close()
break foreverudp
default:
m := make([]byte, 4096) // Can we take this out of this loop TODO(mg)
n, raddr, err := c.ReadFrom(m)
if err != nil {
break foreverUDP
case s := <-uch:
if s.err != nil {
//continue
}
m = m[:n]
go h.ResponderUDP(c, raddr, m)
go h.ResponderUDP(s.c, s.addr, s.msg)
}
}
}
return nil
}
// The raw packet
func handlerUDP(c *net.UDPConn, raddr net.Addr, i []byte) {
in := new(dns.Msg)
in.Unpack(i)
fmt.Printf("%v\n", in)
m := new(dns.Msg)
m.MsgHdr.Id = in.MsgHdr.Id // Copy the Id over
m.MsgHdr.Authoritative = true
m.MsgHdr.Response = true
m.MsgHdr.Rcode = dns.RcodeSuccess
m.Question = make([]dns.Question, 1)
m.Question[0] = dns.Question{"miek.nl.", dns.TypeTXT, dns.ClassINET}
m.Answer = make([]dns.RR, 1)
a := new(dns.RR_TXT)
a.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 3600}
a.Txt = "dit dan"
m.Answer[0] = a
out, _ := m.Pack()
c.WriteTo(out, raddr)
func listenerUDP(a *net.UDPAddr, ch chan serverMsgUDP) {
c, _ := net.ListenUDP("udp", a)
// check error TODO(mg)
for {
m := make([]byte, dns.DefaultMsgSize) // TODO(mg) out of this loop?
n, radd, err := c.ReadFromUDP(m)
if err != nil {
// hmm
}
m = m[:n]
// if closed(ch) c.Close() TODO(mg)
ch <- serverMsgUDP{c, radd, m, nil}
}
}
func listenerTCP(a *net.TCPAddr, ch chan serverMsgTCP) {
t, _ := net.ListenTCP("tcp", a)
for {
l := make([]byte, 2) // receiver length
c, err := t.AcceptTCP()
var _ = err // handle err TODO(mg)
n, cerr := c.Read(l)
if err != nil {
// Send err mesg
}
length := uint16(l[0])<<8 | uint16(l[1])
if length == 0 {
// Send err mesg
//return nil, &dns.Error{Error: "received nil msg length", Server: c.RemoteAddr(
}
m := make([]byte, length)
n, cerr = c.Read(m)
if cerr != nil {
//send msg TODO(mg)
//return nil, cerr
}
i := n
if i < int(length) {
n, err = c.Read(m[i:])
if err != nil {
//send err
//return nil, err
}
i += n
}
ch <- serverMsgTCP{c, m, nil}
}
}
// Send a raw msg over a TCP connection
func SendTCP(m []byte, c *net.TCPConn) os.Error {
l := make([]byte, 2)
l[0] = byte(len(m) >> 8)
l[1] = byte(len(m))
// First we send the length
_, err := c.Write(l)
if err != nil {
return err
}
// And the the message
_, err = c.Write(m)
if err != nil {
return err
}
return nil
}
// if we do tcp we should also provide an udp version
// First the message TODO(mg)
func SendUDP(m []byte, c *net.UDPConn, a *net.UDPAddr) os.Error {
_, err := c.WriteTo(m, a)
if err != nil {
return err
}
return nil
}