2011-07-06 03:49:13 +10:00
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
2016-01-09 00:26:13 +11:00
|
|
|
"crypto/tls"
|
2014-02-15 08:53:00 +11:00
|
|
|
"fmt"
|
2015-11-26 19:04:38 +11:00
|
|
|
"io"
|
2014-02-15 08:53:00 +11:00
|
|
|
"net"
|
2013-06-22 17:55:30 +10:00
|
|
|
"runtime"
|
2014-03-01 02:57:10 +11:00
|
|
|
"sync"
|
2011-07-06 03:49:13 +10:00
|
|
|
"testing"
|
2015-10-06 00:41:02 +11:00
|
|
|
"time"
|
2011-07-06 03:49:13 +10:00
|
|
|
)
|
|
|
|
|
|
|
|
func HelloServer(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
2012-12-10 05:23:25 +11:00
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
2012-11-20 02:15:03 +11:00
|
|
|
w.WriteMsg(m)
|
2011-07-06 03:49:13 +10:00
|
|
|
}
|
|
|
|
|
2017-02-16 07:40:16 +11:00
|
|
|
func HelloServerBadID(w ResponseWriter, req *Msg) {
|
2015-05-06 15:56:42 +10:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
2015-08-23 17:03:13 +10:00
|
|
|
m.Id++
|
2015-05-06 15:56:42 +10:00
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
|
|
w.WriteMsg(m)
|
|
|
|
}
|
|
|
|
|
2017-09-29 19:52:01 +10:00
|
|
|
func HelloServerEchoAddrPort(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
remoteAddr := w.RemoteAddr().String()
|
|
|
|
m.Extra = make([]RR, 1)
|
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{remoteAddr}}
|
|
|
|
w.WriteMsg(m)
|
|
|
|
}
|
|
|
|
|
2012-08-25 08:46:35 +10:00
|
|
|
func AnotherHelloServer(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
2012-12-10 05:23:25 +11:00
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello example"}}
|
2012-11-20 02:15:03 +11:00
|
|
|
w.WriteMsg(m)
|
2012-08-25 08:46:35 +10:00
|
|
|
}
|
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
func RunLocalUDPServer(laddr string) (*Server, string, error) {
|
2015-12-02 09:15:42 +11:00
|
|
|
server, l, _, err := RunLocalUDPServerWithFinChan(laddr)
|
|
|
|
|
|
|
|
return server, l, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func RunLocalUDPServerWithFinChan(laddr string) (*Server, string, chan struct{}, error) {
|
2014-08-29 22:27:53 +10:00
|
|
|
pc, err := net.ListenPacket("udp", laddr)
|
2014-08-29 13:11:49 +10:00
|
|
|
if err != nil {
|
2015-12-02 09:15:42 +11:00
|
|
|
return nil, "", nil, err
|
2014-08-29 13:11:49 +10:00
|
|
|
}
|
2015-10-06 00:41:02 +11:00
|
|
|
server := &Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
2014-12-18 00:46:50 +11:00
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
|
2015-12-02 09:15:42 +11:00
|
|
|
fin := make(chan struct{}, 0)
|
|
|
|
|
2014-08-29 13:11:49 +10:00
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
2015-12-02 09:15:42 +11:00
|
|
|
close(fin)
|
2014-08-29 13:11:49 +10:00
|
|
|
pc.Close()
|
|
|
|
}()
|
2014-12-06 13:33:35 +11:00
|
|
|
|
2014-12-18 00:46:50 +11:00
|
|
|
waitLock.Lock()
|
2015-12-02 09:15:42 +11:00
|
|
|
return server, pc.LocalAddr().String(), fin, nil
|
2014-08-29 13:11:49 +10:00
|
|
|
}
|
|
|
|
|
2014-12-06 13:59:02 +11:00
|
|
|
func RunLocalUDPServerUnsafe(laddr string) (*Server, string, error) {
|
|
|
|
pc, err := net.ListenPacket("udp", laddr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
2015-10-06 00:41:02 +11:00
|
|
|
server := &Server{PacketConn: pc, Unsafe: true,
|
|
|
|
ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
2014-12-18 00:46:50 +11:00
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
|
2014-12-06 13:59:02 +11:00
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
|
|
|
pc.Close()
|
|
|
|
}()
|
|
|
|
|
2014-12-18 00:46:50 +11:00
|
|
|
waitLock.Lock()
|
2014-12-06 13:59:02 +11:00
|
|
|
return server, pc.LocalAddr().String(), nil
|
|
|
|
}
|
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
func RunLocalTCPServer(laddr string) (*Server, string, error) {
|
|
|
|
l, err := net.Listen("tcp", laddr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
2014-12-18 00:46:50 +11:00
|
|
|
|
2015-10-06 00:41:02 +11:00
|
|
|
server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
2014-12-18 00:46:50 +11:00
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
|
|
|
l.Close()
|
|
|
|
}()
|
2014-12-06 13:33:35 +11:00
|
|
|
|
2014-12-18 00:46:50 +11:00
|
|
|
waitLock.Lock()
|
2014-08-29 22:27:53 +10:00
|
|
|
return server, l.Addr().String(), nil
|
|
|
|
}
|
|
|
|
|
2016-01-09 00:26:13 +11:00
|
|
|
func RunLocalTLSServer(laddr string, config *tls.Config) (*Server, string, error) {
|
|
|
|
l, err := tls.Listen("tcp", laddr, config)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
|
|
|
l.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
waitLock.Lock()
|
|
|
|
return server, l.Addr().String(), nil
|
|
|
|
}
|
|
|
|
|
2011-07-06 03:49:13 +10:00
|
|
|
func TestServing(t *testing.T) {
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2012-08-25 08:46:35 +10:00
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
2014-08-30 23:45:30 +10:00
|
|
|
defer HandleRemove("miek.nl.")
|
|
|
|
defer HandleRemove("example.com.")
|
2014-08-29 13:11:49 +10:00
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
2014-08-29 13:11:49 +10:00
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-08-29 13:11:49 +10:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2012-08-25 08:46:35 +10:00
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl.", TypeTXT)
|
2014-08-29 13:11:49 +10:00
|
|
|
r, _, err := c.Exchange(m, addrstr)
|
2014-11-10 03:09:49 +11:00
|
|
|
if err != nil || len(r.Extra) == 0 {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Fatal("failed to exchange miek.nl", err)
|
2014-07-17 20:14:50 +10:00
|
|
|
}
|
2012-12-10 05:23:25 +11:00
|
|
|
txt := r.Extra[0].(*TXT).Txt[0]
|
2012-08-25 08:46:35 +10:00
|
|
|
if txt != "Hello world" {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Error("unexpected result for miek.nl", txt, "!= Hello world")
|
2012-08-25 08:46:35 +10:00
|
|
|
}
|
2014-07-17 20:14:50 +10:00
|
|
|
|
2012-08-25 08:46:35 +10:00
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
2014-08-29 13:11:49 +10:00
|
|
|
r, _, err = c.Exchange(m, addrstr)
|
2014-07-17 20:14:50 +10:00
|
|
|
if err != nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Fatal("failed to exchange example.com", err)
|
2014-07-17 20:14:50 +10:00
|
|
|
}
|
2012-12-10 05:23:25 +11:00
|
|
|
txt = r.Extra[0].(*TXT).Txt[0]
|
2012-08-25 08:46:35 +10:00
|
|
|
if txt != "Hello example" {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Error("unexpected result for example.com", txt, "!= Hello example")
|
2012-08-25 08:46:35 +10:00
|
|
|
}
|
2014-07-17 20:14:50 +10:00
|
|
|
|
2013-10-19 21:52:15 +11:00
|
|
|
// Test Mixes cased as noticed by Ask.
|
2013-07-25 16:55:59 +10:00
|
|
|
m.SetQuestion("eXaMplE.cOm.", TypeTXT)
|
2014-08-29 13:11:49 +10:00
|
|
|
r, _, err = c.Exchange(m, addrstr)
|
2014-07-17 20:14:50 +10:00
|
|
|
if err != nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Error("failed to exchange eXaMplE.cOm", err)
|
2014-07-17 20:14:50 +10:00
|
|
|
}
|
2013-07-25 16:55:59 +10:00
|
|
|
txt = r.Extra[0].(*TXT).Txt[0]
|
|
|
|
if txt != "Hello example" {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Error("unexpected result for example.com", txt, "!= Hello example")
|
2013-07-25 16:55:59 +10:00
|
|
|
}
|
2011-07-06 03:49:13 +10:00
|
|
|
}
|
2011-07-07 03:21:19 +10:00
|
|
|
|
2016-01-09 00:26:13 +11:00
|
|
|
func TestServingTLS(t *testing.T) {
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
|
|
|
defer HandleRemove("miek.nl.")
|
|
|
|
defer HandleRemove("example.com.")
|
|
|
|
|
|
|
|
cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to build certificate: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
config := tls.Config{
|
|
|
|
Certificates: []tls.Certificate{cert},
|
|
|
|
}
|
|
|
|
|
|
|
|
s, addrstr, err := RunLocalTLSServer("127.0.0.1:0", &config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
c.Net = "tcp-tls"
|
|
|
|
c.TLSConfig = &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl.", TypeTXT)
|
|
|
|
r, _, err := c.Exchange(m, addrstr)
|
|
|
|
if err != nil || len(r.Extra) == 0 {
|
|
|
|
t.Fatal("failed to exchange miek.nl", err)
|
|
|
|
}
|
|
|
|
txt := r.Extra[0].(*TXT).Txt[0]
|
|
|
|
if txt != "Hello world" {
|
|
|
|
t.Error("unexpected result for miek.nl", txt, "!= Hello world")
|
|
|
|
}
|
|
|
|
|
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
|
|
|
r, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("failed to exchange example.com", err)
|
|
|
|
}
|
|
|
|
txt = r.Extra[0].(*TXT).Txt[0]
|
|
|
|
if txt != "Hello example" {
|
|
|
|
t.Error("unexpected result for example.com", txt, "!= Hello example")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test Mixes cased as noticed by Ask.
|
|
|
|
m.SetQuestion("eXaMplE.cOm.", TypeTXT)
|
|
|
|
r, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to exchange eXaMplE.cOm", err)
|
|
|
|
}
|
|
|
|
txt = r.Extra[0].(*TXT).Txt[0]
|
|
|
|
if txt != "Hello example" {
|
|
|
|
t.Error("unexpected result for example.com", txt, "!= Hello example")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-29 18:56:21 +11:00
|
|
|
func BenchmarkServe(b *testing.B) {
|
2011-07-24 07:43:43 +10:00
|
|
|
b.StopTimer()
|
2011-07-07 03:21:19 +10:00
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2014-08-30 23:45:30 +10:00
|
|
|
defer HandleRemove("miek.nl.")
|
2013-06-22 17:55:30 +10:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 22:27:53 +10:00
|
|
|
|
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
b.Fatalf("unable to run test server: %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2012-05-26 18:28:32 +10:00
|
|
|
c := new(Client)
|
2011-07-24 07:43:43 +10:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl", TypeSOA)
|
2011-07-07 03:21:19 +10:00
|
|
|
|
2011-07-24 07:43:43 +10:00
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2014-08-29 22:27:53 +10:00
|
|
|
c.Exchange(m, addrstr)
|
2011-07-24 07:43:43 +10:00
|
|
|
}
|
2013-06-22 17:55:30 +10:00
|
|
|
runtime.GOMAXPROCS(a)
|
2011-07-07 03:21:19 +10:00
|
|
|
}
|
2012-09-17 16:56:27 +10:00
|
|
|
|
2014-07-09 16:23:54 +10:00
|
|
|
func benchmarkServe6(b *testing.B) {
|
2014-07-09 00:15:08 +10:00
|
|
|
b.StopTimer()
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2014-08-30 23:45:30 +10:00
|
|
|
defer HandleRemove("miek.nl.")
|
2014-07-09 00:15:08 +10:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("[::1]:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
b.Fatalf("unable to run test server: %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2014-07-09 00:15:08 +10:00
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl", TypeSOA)
|
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2014-08-29 22:27:53 +10:00
|
|
|
c.Exchange(m, addrstr)
|
2014-07-09 00:15:08 +10:00
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(a)
|
|
|
|
}
|
|
|
|
|
2013-06-28 05:29:10 +10:00
|
|
|
func HelloServerCompress(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
m.Extra = make([]RR, 1)
|
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
|
|
m.Compress = true
|
|
|
|
w.WriteMsg(m)
|
|
|
|
}
|
|
|
|
|
2014-01-29 18:52:23 +11:00
|
|
|
func BenchmarkServeCompress(b *testing.B) {
|
2013-06-28 05:29:10 +10:00
|
|
|
b.StopTimer()
|
|
|
|
HandleFunc("miek.nl.", HelloServerCompress)
|
2014-08-30 23:45:30 +10:00
|
|
|
defer HandleRemove("miek.nl.")
|
2013-06-28 05:29:10 +10:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
b.Fatalf("unable to run test server: %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
2013-06-28 05:29:10 +10:00
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl", TypeSOA)
|
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2014-08-29 22:27:53 +10:00
|
|
|
c.Exchange(m, addrstr)
|
2013-06-28 05:29:10 +10:00
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(a)
|
|
|
|
}
|
|
|
|
|
2012-09-17 16:56:27 +10:00
|
|
|
func TestDotAsCatchAllWildcard(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
|
|
|
mux.Handle(".", HandlerFunc(HelloServer))
|
|
|
|
mux.Handle("example.com.", HandlerFunc(AnotherHelloServer))
|
|
|
|
|
2012-09-18 16:19:06 +10:00
|
|
|
handler := mux.match("www.miek.nl.", TypeTXT)
|
2012-09-17 16:56:27 +10:00
|
|
|
if handler == nil {
|
|
|
|
t.Error("wildcard match failed")
|
|
|
|
}
|
|
|
|
|
2012-09-18 16:19:06 +10:00
|
|
|
handler = mux.match("www.example.com.", TypeTXT)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("example.com match failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = mux.match("a.www.example.com.", TypeTXT)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("a.www.example.com match failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = mux.match("boe.", TypeTXT)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("boe. match failed")
|
2012-09-17 16:56:27 +10:00
|
|
|
}
|
|
|
|
}
|
2013-05-12 23:56:12 +10:00
|
|
|
|
2013-12-14 20:37:53 +11:00
|
|
|
func TestCaseFolding(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
|
|
|
mux.Handle("_udp.example.com.", HandlerFunc(HelloServer))
|
|
|
|
|
|
|
|
handler := mux.match("_dns._udp.example.com.", TypeSRV)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("case sensitive characters folded")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = mux.match("_DNS._UDP.EXAMPLE.COM.", TypeSRV)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("case insensitive characters not folded")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-12 23:56:12 +10:00
|
|
|
func TestRootServer(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
|
|
|
mux.Handle(".", HandlerFunc(HelloServer))
|
|
|
|
|
|
|
|
handler := mux.match(".", TypeNS)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("root match failed")
|
|
|
|
}
|
|
|
|
}
|
2014-02-15 08:53:00 +11:00
|
|
|
|
2014-03-01 02:57:10 +11:00
|
|
|
type maxRec struct {
|
|
|
|
max int
|
|
|
|
sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
var M = new(maxRec)
|
2014-02-15 08:53:00 +11:00
|
|
|
|
2014-02-15 19:03:40 +11:00
|
|
|
func HelloServerLargeResponse(resp ResponseWriter, req *Msg) {
|
2014-02-15 08:53:00 +11:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
m.Authoritative = true
|
2014-03-01 02:57:10 +11:00
|
|
|
m1 := 0
|
|
|
|
M.RLock()
|
|
|
|
m1 = M.max
|
|
|
|
M.RUnlock()
|
|
|
|
for i := 0; i < m1; i++ {
|
2014-02-15 08:53:00 +11:00
|
|
|
aRec := &A{
|
|
|
|
Hdr: RR_Header{
|
|
|
|
Name: req.Question[0].Name,
|
|
|
|
Rrtype: TypeA,
|
|
|
|
Class: ClassINET,
|
|
|
|
Ttl: 0,
|
|
|
|
},
|
|
|
|
A: net.ParseIP(fmt.Sprintf("127.0.0.%d", i+1)).To4(),
|
|
|
|
}
|
|
|
|
m.Answer = append(m.Answer, aRec)
|
|
|
|
}
|
|
|
|
resp.WriteMsg(m)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestServingLargeResponses(t *testing.T) {
|
2014-08-30 04:10:05 +10:00
|
|
|
HandleFunc("example.", HelloServerLargeResponse)
|
2014-08-30 23:45:30 +10:00
|
|
|
defer HandleRemove("example.")
|
2014-02-15 08:53:00 +11:00
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
2014-08-29 22:27:53 +10:00
|
|
|
defer s.Shutdown()
|
2014-02-15 08:53:00 +11:00
|
|
|
|
|
|
|
// Create request
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("web.service.example.", TypeANY)
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
c.Net = "udp"
|
2014-03-01 02:57:10 +11:00
|
|
|
M.Lock()
|
|
|
|
M.max = 2
|
|
|
|
M.Unlock()
|
2014-08-29 22:27:53 +10:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-15 08:53:00 +11:00
|
|
|
if err != nil {
|
2015-02-26 17:14:21 +11:00
|
|
|
t.Errorf("failed to exchange: %v", err)
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
|
|
|
// This must fail
|
2014-03-01 02:57:10 +11:00
|
|
|
M.Lock()
|
|
|
|
M.max = 20
|
|
|
|
M.Unlock()
|
2014-08-29 22:27:53 +10:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-15 08:53:00 +11:00
|
|
|
if err == nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Error("failed to fail exchange, this should generate packet error")
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
2014-02-15 09:14:41 +11:00
|
|
|
// But this must work again
|
|
|
|
c.UDPSize = 7000
|
2014-08-29 22:27:53 +10:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-15 09:14:41 +11:00
|
|
|
if err != nil {
|
2015-02-26 17:14:21 +11:00
|
|
|
t.Errorf("failed to exchange: %v", err)
|
2014-02-15 09:14:41 +11:00
|
|
|
}
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
2014-08-19 18:39:04 +10:00
|
|
|
|
2014-10-19 20:36:26 +11:00
|
|
|
func TestServingResponse(t *testing.T) {
|
2014-11-12 21:19:20 +11:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
2014-10-19 20:36:26 +11:00
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-10-19 20:36:26 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl.", TypeTXT)
|
|
|
|
m.Response = false
|
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Fatal("failed to exchange", err)
|
2014-10-19 20:36:26 +11:00
|
|
|
}
|
|
|
|
m.Response = true
|
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err == nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Fatal("exchanged response message")
|
2014-11-20 03:34:18 +11:00
|
|
|
}
|
2014-12-06 13:59:02 +11:00
|
|
|
|
|
|
|
s.Shutdown()
|
|
|
|
s, addrstr, err = RunLocalUDPServerUnsafe("127.0.0.1:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-12-06 13:59:02 +11:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2014-11-20 03:34:18 +11:00
|
|
|
m.Response = true
|
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
2015-02-21 16:03:02 +11:00
|
|
|
t.Fatal("could exchanged response message in Unsafe mode")
|
2014-10-19 20:36:26 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-19 19:25:41 +10:00
|
|
|
func TestShutdownTCP(t *testing.T) {
|
2014-08-29 22:27:53 +10:00
|
|
|
s, _, err := RunLocalTCPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Errorf("could not shutdown test TCP server, %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
2014-08-19 19:25:41 +10:00
|
|
|
}
|
|
|
|
|
2016-01-09 00:26:13 +11:00
|
|
|
func TestShutdownTLS(t *testing.T) {
|
|
|
|
cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to build certificate: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
config := tls.Config{
|
|
|
|
Certificates: []tls.Certificate{cert},
|
|
|
|
}
|
|
|
|
|
|
|
|
s, _, err := RunLocalTLSServer("127.0.0.1:0", &config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("could not shutdown test TLS server, %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-27 01:03:51 +11:00
|
|
|
type trigger struct {
|
|
|
|
done bool
|
|
|
|
sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *trigger) Set() {
|
|
|
|
t.Lock()
|
|
|
|
defer t.Unlock()
|
|
|
|
t.done = true
|
|
|
|
}
|
|
|
|
func (t *trigger) Get() bool {
|
|
|
|
t.RLock()
|
|
|
|
defer t.RUnlock()
|
|
|
|
return t.done
|
|
|
|
}
|
|
|
|
|
2015-11-26 19:04:38 +11:00
|
|
|
func TestHandlerCloseTCP(t *testing.T) {
|
2015-11-27 01:03:51 +11:00
|
|
|
|
2015-11-26 19:04:38 +11:00
|
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
addr := ln.Addr().String()
|
|
|
|
|
|
|
|
server := &Server{Addr: addr, Net: "tcp", Listener: ln}
|
|
|
|
|
|
|
|
hname := "testhandlerclosetcp."
|
2015-11-27 01:03:51 +11:00
|
|
|
triggered := &trigger{}
|
2015-11-26 19:04:38 +11:00
|
|
|
HandleFunc(hname, func(w ResponseWriter, r *Msg) {
|
2015-11-27 01:03:51 +11:00
|
|
|
triggered.Set()
|
2015-11-26 19:04:38 +11:00
|
|
|
w.Close()
|
|
|
|
})
|
|
|
|
defer HandleRemove(hname)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer server.Shutdown()
|
|
|
|
c := &Client{Net: "tcp"}
|
|
|
|
m := new(Msg).SetQuestion(hname, 1)
|
|
|
|
tries := 0
|
|
|
|
exchange:
|
|
|
|
_, _, err := c.Exchange(m, addr)
|
|
|
|
if err != nil && err != io.EOF {
|
2015-11-27 01:03:51 +11:00
|
|
|
t.Logf("exchange failed: %s\n", err)
|
2015-11-26 19:04:38 +11:00
|
|
|
if tries == 3 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
time.Sleep(time.Second / 10)
|
2017-02-16 07:40:16 +11:00
|
|
|
tries++
|
2015-11-26 19:04:38 +11:00
|
|
|
goto exchange
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
server.ActivateAndServe()
|
2015-11-27 01:03:51 +11:00
|
|
|
if !triggered.Get() {
|
|
|
|
t.Fatalf("handler never called")
|
2015-11-26 19:04:38 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-19 19:25:41 +10:00
|
|
|
func TestShutdownUDP(t *testing.T) {
|
2015-12-02 09:15:42 +11:00
|
|
|
s, _, fin, err := RunLocalUDPServerWithFinChan("127.0.0.1:0")
|
2014-08-29 22:27:53 +10:00
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
2015-11-27 01:12:38 +11:00
|
|
|
t.Errorf("could not shutdown test UDP server, %v", err)
|
2014-08-29 22:27:53 +10:00
|
|
|
}
|
2015-12-02 09:15:42 +11:00
|
|
|
select {
|
|
|
|
case <-fin:
|
|
|
|
case <-time.After(2 * time.Second):
|
|
|
|
t.Error("Could not shutdown test UDP server. Gave up waiting")
|
|
|
|
}
|
2014-08-19 18:39:04 +10:00
|
|
|
}
|
2015-08-04 23:04:40 +10:00
|
|
|
|
|
|
|
type ExampleFrameLengthWriter struct {
|
|
|
|
Writer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ExampleFrameLengthWriter) Write(m []byte) (int, error) {
|
2015-08-07 07:55:37 +10:00
|
|
|
fmt.Println("writing raw DNS message of length", len(m))
|
2015-08-04 23:04:40 +10:00
|
|
|
return e.Writer.Write(m)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ExampleDecorateWriter() {
|
2015-08-07 07:55:37 +10:00
|
|
|
// instrument raw DNS message writing
|
2015-08-04 23:04:40 +10:00
|
|
|
wf := DecorateWriter(func(w Writer) Writer {
|
|
|
|
return &ExampleFrameLengthWriter{w}
|
|
|
|
})
|
|
|
|
|
|
|
|
// simple UDP server
|
|
|
|
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
server := &Server{
|
|
|
|
PacketConn: pc,
|
|
|
|
DecorateWriter: wf,
|
2015-10-06 00:41:02 +11:00
|
|
|
ReadTimeout: time.Hour, WriteTimeout: time.Hour,
|
2015-08-04 23:04:40 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
defer server.Shutdown()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
|
|
|
pc.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
waitLock.Lock()
|
|
|
|
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl.", TypeTXT)
|
|
|
|
_, _, err = c.Exchange(m, pc.LocalAddr().String())
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("failed to exchange", err.Error())
|
|
|
|
return
|
|
|
|
}
|
2015-08-07 07:55:37 +10:00
|
|
|
// Output: writing raw DNS message of length 56
|
2015-08-04 23:04:40 +10:00
|
|
|
}
|
2016-01-09 00:26:13 +11:00
|
|
|
|
|
|
|
var (
|
|
|
|
// CertPEMBlock is a X509 data used to test TLS servers (used with tls.X509KeyPair)
|
|
|
|
CertPEMBlock = []byte(`-----BEGIN CERTIFICATE-----
|
|
|
|
MIIDAzCCAeugAwIBAgIRAJFYMkcn+b8dpU15wjf++GgwDQYJKoZIhvcNAQELBQAw
|
|
|
|
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjAxMDgxMjAzNTNaFw0xNzAxMDcxMjAz
|
|
|
|
NTNaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
|
|
|
ggEKAoIBAQDXjqO6skvP03k58CNjQggd9G/mt+Wa+xRU+WXiKCCHttawM8x+slq5
|
|
|
|
yfsHCwxlwsGn79HmJqecNqgHb2GWBXAvVVokFDTcC1hUP4+gp2gu9Ny27UHTjlLm
|
|
|
|
O0l/xZ5MN8tfKyYlFw18tXu3fkaPyHj8v/D1RDkuo4ARdFvGSe8TqisbhLk2+9ow
|
|
|
|
xfIGbEM9Fdiw8qByC2+d+FfvzIKz3GfQVwn0VoRom8L6NBIANq1IGrB5JefZB6nv
|
|
|
|
DnfuxkBmY7F1513HKuEJ8KsLWWZWV9OPU4j4I4Rt+WJNlKjbD2srHxyrS2RDsr91
|
|
|
|
8nCkNoWVNO3sZq0XkWKecdc921vL4ginAgMBAAGjVDBSMA4GA1UdDwEB/wQEAwIC
|
|
|
|
pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBoGA1UdEQQT
|
|
|
|
MBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGcU3iyLBIVZj
|
|
|
|
aDzSvEDHUd1bnLBl1C58Xu/CyKlPqVU7mLfK0JcgEaYQTSX6fCJVNLbbCrcGLsPJ
|
|
|
|
fbjlBbyeLjTV413fxPVuona62pBFjqdtbli2Qe8FRH2KBdm41JUJGdo+SdsFu7nc
|
|
|
|
BFOcubdw6LLIXvsTvwndKcHWx1rMX709QU1Vn1GAIsbJV/DWI231Jyyb+lxAUx/C
|
|
|
|
8vce5uVxiKcGS+g6OjsN3D3TtiEQGSXLh013W6Wsih8td8yMCMZ3w8LQ38br1GUe
|
|
|
|
ahLIgUJ9l6HDguM17R7kGqxNvbElsMUHfTtXXP7UDQUiYXDakg8xDP6n9DCDhJ8Y
|
|
|
|
bSt7OLB7NQ==
|
|
|
|
-----END CERTIFICATE-----`)
|
|
|
|
|
|
|
|
// KeyPEMBlock is a X509 data used to test TLS servers (used with tls.X509KeyPair)
|
|
|
|
KeyPEMBlock = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
|
|
|
MIIEpQIBAAKCAQEA146jurJLz9N5OfAjY0IIHfRv5rflmvsUVPll4iggh7bWsDPM
|
|
|
|
frJaucn7BwsMZcLBp+/R5iannDaoB29hlgVwL1VaJBQ03AtYVD+PoKdoLvTctu1B
|
|
|
|
045S5jtJf8WeTDfLXysmJRcNfLV7t35Gj8h4/L/w9UQ5LqOAEXRbxknvE6orG4S5
|
|
|
|
NvvaMMXyBmxDPRXYsPKgcgtvnfhX78yCs9xn0FcJ9FaEaJvC+jQSADatSBqweSXn
|
|
|
|
2Qep7w537sZAZmOxdeddxyrhCfCrC1lmVlfTj1OI+COEbfliTZSo2w9rKx8cq0tk
|
|
|
|
Q7K/dfJwpDaFlTTt7GatF5FinnHXPdtby+IIpwIDAQABAoIBAAJK4RDmPooqTJrC
|
|
|
|
JA41MJLo+5uvjwCT9QZmVKAQHzByUFw1YNJkITTiognUI0CdzqNzmH7jIFs39ZeG
|
|
|
|
proKusO2G6xQjrNcZ4cV2fgyb5g4QHStl0qhs94A+WojduiGm2IaumAgm6Mc5wDv
|
|
|
|
ld6HmknN3Mku/ZCyanVFEIjOVn2WB7ZQLTBs6ZYaebTJG2Xv6p9t2YJW7pPQ9Xce
|
|
|
|
s9ohAWohyM4X/OvfnfnLtQp2YLw/BxwehBsCR5SXM3ibTKpFNtxJC8hIfTuWtxZu
|
|
|
|
2ywrmXShYBRB1WgtZt5k04bY/HFncvvcHK3YfI1+w4URKtwdaQgPUQRbVwDwuyBn
|
|
|
|
flfkCJECgYEA/eWt01iEyE/lXkGn6V9lCocUU7lCU6yk5UT8VXVUc5If4KZKPfCk
|
|
|
|
p4zJDOqwn2eM673aWz/mG9mtvAvmnugaGjcaVCyXOp/D/GDmKSoYcvW5B/yjfkLy
|
|
|
|
dK6Yaa5LDRVYlYgyzcdCT5/9Qc626NzFwKCZNI4ncIU8g7ViATRxWJ8CgYEA2Ver
|
|
|
|
vZ0M606sfgC0H3NtwNBxmuJ+lIF5LNp/wDi07lDfxRR1rnZMX5dnxjcpDr/zvm8J
|
|
|
|
WtJJX3xMgqjtHuWKL3yKKony9J5ZPjichSbSbhrzfovgYIRZLxLLDy4MP9L3+CX/
|
|
|
|
yBXnqMWuSnFX+M5fVGxdDWiYF3V+wmeOv9JvavkCgYEAiXAPDFzaY+R78O3xiu7M
|
|
|
|
r0o3wqqCMPE/wav6O/hrYrQy9VSO08C0IM6g9pEEUwWmzuXSkZqhYWoQFb8Lc/GI
|
|
|
|
T7CMXAxXQLDDUpbRgG79FR3Wr3AewHZU8LyiXHKwxcBMV4WGmsXGK3wbh8fyU1NO
|
|
|
|
6NsGk+BvkQVOoK1LBAPzZ1kCgYEAsBSmD8U33T9s4dxiEYTrqyV0lH3g/SFz8ZHH
|
|
|
|
pAyNEPI2iC1ONhyjPWKlcWHpAokiyOqeUpVBWnmSZtzC1qAydsxYB6ShT+sl9BHb
|
|
|
|
RMix/QAauzBJhQhUVJ3OIys0Q1UBDmqCsjCE8SfOT4NKOUnA093C+YT+iyrmmktZ
|
|
|
|
zDCJkckCgYEAndqM5KXGk5xYo+MAA1paZcbTUXwaWwjLU+XSRSSoyBEi5xMtfvUb
|
|
|
|
7+a1OMhLwWbuz+pl64wFKrbSUyimMOYQpjVE/1vk/kb99pxbgol27hdKyTH1d+ov
|
|
|
|
kFsxKCqxAnBVGEWAvVZAiiTOxleQFjz5RnL0BQp9Lg2cQe+dvuUmIAA=
|
|
|
|
-----END RSA PRIVATE KEY-----`)
|
|
|
|
)
|
2016-12-16 03:20:35 +11:00
|
|
|
|
|
|
|
func testShutdownBindPort(t *testing.T, protocol string, port string) {
|
|
|
|
handler := NewServeMux()
|
|
|
|
handler.HandleFunc(".", func(w ResponseWriter, r *Msg) {})
|
|
|
|
startedCh := make(chan struct{})
|
|
|
|
s := &Server{
|
|
|
|
Addr: net.JoinHostPort("127.0.0.1", port),
|
|
|
|
Net: protocol,
|
|
|
|
Handler: handler,
|
|
|
|
NotifyStartedFunc: func() {
|
|
|
|
startedCh <- struct{}{}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
if err := s.ListenAndServe(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
<-startedCh
|
|
|
|
t.Logf("DNS server is started on: %s", s.Addr)
|
|
|
|
if err := s.Shutdown(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
go func() {
|
|
|
|
if err := s.ListenAndServe(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
<-startedCh
|
|
|
|
t.Logf("DNS server is started on: %s", s.Addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestShutdownBindPortUDP(t *testing.T) {
|
|
|
|
testShutdownBindPort(t, "udp", "1153")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestShutdownBindPortTCP(t *testing.T) {
|
|
|
|
testShutdownBindPort(t, "tcp", "1154")
|
|
|
|
}
|