131 lines
2.8 KiB
Go
131 lines
2.8 KiB
Go
// Copyright 2011 Miek Gieben. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// DNS server implementation
|
|
|
|
package dns
|
|
|
|
import (
|
|
"os"
|
|
"net"
|
|
)
|
|
|
|
func ServeUDP(l *net.UDPConn, f func(*net.UDPConn, net.Addr, *Msg)) os.Error {
|
|
for {
|
|
m := make([]byte, DefaultMsgSize)
|
|
n, radd, e := l.ReadFromUDP(m)
|
|
if e != nil {
|
|
continue
|
|
}
|
|
m = m[:n]
|
|
msg := new(Msg)
|
|
if ! msg.Unpack(m) {
|
|
continue
|
|
}
|
|
go f(l, radd, msg)
|
|
}
|
|
panic("not reached")
|
|
}
|
|
|
|
func ServeTCP(l *net.TCPListener, f func(*net.TCPConn, net.Addr, *Msg)) os.Error {
|
|
b := make([]byte, 2)
|
|
for {
|
|
c, e := l.AcceptTCP()
|
|
if e != nil {
|
|
return e
|
|
}
|
|
n, e := c.Read(b)
|
|
if e != nil {
|
|
continue
|
|
}
|
|
|
|
length := uint16(b[0])<<8 | uint16(b[1])
|
|
if length == 0 {
|
|
return &Error{Error: "received nil msg length"}
|
|
}
|
|
m := make([]byte, length)
|
|
|
|
n, e = c.Read(m)
|
|
if e != nil {
|
|
continue
|
|
}
|
|
i := n
|
|
if i < int(length) {
|
|
n, e = c.Read(m[i:])
|
|
if e != nil {
|
|
continue
|
|
}
|
|
i += n
|
|
}
|
|
msg := new(Msg)
|
|
if ! msg.Unpack(m) {
|
|
continue
|
|
}
|
|
go f(c, c.RemoteAddr(), msg)
|
|
}
|
|
panic("not reached")
|
|
}
|
|
|
|
func ListenAndServeTCP(addr string, f func(*net.TCPConn, net.Addr, *Msg)) os.Error {
|
|
a, err := net.ResolveTCPAddr(addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
l, err := net.ListenTCP("tcp", a)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ServeTCP(l, f)
|
|
return err
|
|
}
|
|
|
|
func ListenAndServeUDP(addr string, f func(*net.UDPConn, net.Addr, *Msg)) os.Error {
|
|
a, err := net.ResolveUDPAddr(addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
l, err := net.ListenUDP("udp", a)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ServeUDP(l, f)
|
|
return err
|
|
}
|
|
|
|
// Send a buffer on the TCP connection.
|
|
func SendTCP(m []byte, c *net.TCPConn, a net.Addr) os.Error {
|
|
l := make([]byte, 2)
|
|
l[0] = byte(len(m) >> 8)
|
|
l[1] = byte(len(m))
|
|
// First we send the length
|
|
n, err := c.Write(l)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// And the the message
|
|
n, err = c.Write(m)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
i := n
|
|
for i < len(m) {
|
|
n, err = c.Write(m)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
i += n
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Send a buffer to the remove address. Only here because
|
|
// of the symmetry with SendTCP().
|
|
func SendUDP(m []byte, c *net.UDPConn, a net.Addr) os.Error {
|
|
_, err := c.WriteTo(m, a)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|