Fix the UDP/TCP handling for the responder
This commit is contained in:
parent
8582967bab
commit
ea68b035e9
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue