2011-07-05 17:49:13 +00:00
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
2018-09-13 13:36:28 +00:00
|
|
|
"context"
|
2016-01-08 13:26:13 +00:00
|
|
|
"crypto/tls"
|
2014-02-14 21:53:00 +00:00
|
|
|
"fmt"
|
2015-11-26 08:04:38 +00:00
|
|
|
"io"
|
2014-02-14 21:53:00 +00:00
|
|
|
"net"
|
2013-06-22 07:55:30 +00:00
|
|
|
"runtime"
|
2018-09-08 16:10:56 +00:00
|
|
|
"strings"
|
2014-02-28 15:57:10 +00:00
|
|
|
"sync"
|
2018-10-09 17:43:08 +00:00
|
|
|
"sync/atomic"
|
2011-07-05 17:49:13 +00:00
|
|
|
"testing"
|
2015-10-05 13:41:02 +00:00
|
|
|
"time"
|
2018-09-13 13:36:28 +00:00
|
|
|
|
|
|
|
"golang.org/x/sync/errgroup"
|
2011-07-05 17:49:13 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func HelloServer(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
2012-12-09 18:23:25 +00: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-19 15:15:03 +00:00
|
|
|
w.WriteMsg(m)
|
2011-07-05 17:49:13 +00:00
|
|
|
}
|
|
|
|
|
2017-02-15 20:40:16 +00:00
|
|
|
func HelloServerBadID(w ResponseWriter, req *Msg) {
|
2015-05-06 05:56:42 +00:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
2015-08-23 07:03:13 +00:00
|
|
|
m.Id++
|
2015-05-06 05:56:42 +00: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)
|
Ignore responses with unexpected IDs (#1155)
* Ignore replies with unexpected IDs
This fixes the following problem:
At time 0, we send a query with ID X from port P.
At time T, we time out the query due to lack of response, and then send
a different query with ID Y. By coincidence, the new query is sent from
the same port number P (since port numbers are only 16 bits, this can happen
with non-negligible probability when making queries at a high rate).
At time T+epsilon, we receive a response to the original query.
Since the ID in this response is X, not Y, we would previously return
ErrId, preventing the second query from succeeding.
With this commit, we simply ignore the response with the mismatched ID
and return once we receive the response with the correct ID.
* Update test for bad ID
The new test sends two replies: the first one has a bad ID, which should
be ignored, and the second one has the correct ID.
* Add test to ensure query times out when server returns bad ID
* Avoid use of error string matching in test case
* Check for mismatched query IDs when using TCP
* Reduce timeout in TestClientSyncBadID
2020-10-18 05:55:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func HelloServerBadThenGoodID(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
m.Id++
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
m.Id--
|
|
|
|
w.WriteMsg(m)
|
2015-05-06 05:56:42 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 09:52:01 +00: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-24 22:46:35 +00:00
|
|
|
func AnotherHelloServer(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
2012-12-09 18:23:25 +00: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-19 15:15:03 +00:00
|
|
|
w.WriteMsg(m)
|
2012-08-24 22:46:35 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
func RunLocalUDPServer(laddr string, opts ...func(*Server)) (*Server, string, chan error, error) {
|
2014-08-29 12:27:53 +00:00
|
|
|
pc, err := net.ListenPacket("udp", laddr)
|
2014-08-29 03:11:49 +00:00
|
|
|
if err != nil {
|
2015-12-01 22:15:42 +00:00
|
|
|
return nil, "", nil, err
|
2014-08-29 03:11:49 +00:00
|
|
|
}
|
2015-10-05 13:41:02 +00:00
|
|
|
server := &Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
2014-12-17 13:46:50 +00:00
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
|
2018-09-26 08:19:35 +00:00
|
|
|
for _, opt := range opts {
|
|
|
|
opt(server)
|
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
// fin must be buffered so the goroutine below won't block
|
|
|
|
// forever if fin is never read from. This always happens
|
|
|
|
// if the channel is discarded and can happen in TestShutdownUDP.
|
|
|
|
fin := make(chan error, 1)
|
|
|
|
|
2014-08-29 03:11:49 +00:00
|
|
|
go func() {
|
2018-02-28 01:38:12 +00:00
|
|
|
fin <- server.ActivateAndServe()
|
2014-08-29 03:11:49 +00:00
|
|
|
pc.Close()
|
|
|
|
}()
|
2014-12-06 02:33:35 +00:00
|
|
|
|
2014-12-17 13:46:50 +00:00
|
|
|
waitLock.Lock()
|
2015-12-01 22:15:42 +00:00
|
|
|
return server, pc.LocalAddr().String(), fin, nil
|
2014-08-29 03:11:49 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
func RunLocalPacketConnServer(laddr string, opts ...func(*Server)) (*Server, string, chan error, error) {
|
|
|
|
return RunLocalUDPServer(laddr, append(opts, func(srv *Server) {
|
|
|
|
// Make srv.PacketConn opaque to trigger the generic code paths.
|
|
|
|
srv.PacketConn = struct{ net.PacketConn }{srv.PacketConn}
|
|
|
|
})...)
|
2018-02-28 01:38:12 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
func RunLocalTCPServer(laddr string, opts ...func(*Server)) (*Server, string, chan error, error) {
|
2014-08-29 12:27:53 +00:00
|
|
|
l, err := net.Listen("tcp", laddr)
|
|
|
|
if err != nil {
|
2018-02-28 01:38:12 +00:00
|
|
|
return nil, "", nil, err
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
2014-12-17 13:46:50 +00:00
|
|
|
|
2015-10-05 13:41:02 +00:00
|
|
|
server := &Server{Listener: l, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
2014-12-17 13:46:50 +00:00
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
waitLock.Lock()
|
|
|
|
server.NotifyStartedFunc = waitLock.Unlock
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
for _, opt := range opts {
|
|
|
|
opt(server)
|
|
|
|
}
|
|
|
|
|
|
|
|
// See the comment in RunLocalUDPServer as to why fin must be buffered.
|
2018-02-28 01:38:12 +00:00
|
|
|
fin := make(chan error, 1)
|
|
|
|
|
2014-08-29 12:27:53 +00:00
|
|
|
go func() {
|
2018-02-28 01:38:12 +00:00
|
|
|
fin <- server.ActivateAndServe()
|
2014-08-29 12:27:53 +00:00
|
|
|
l.Close()
|
|
|
|
}()
|
2014-12-06 02:33:35 +00:00
|
|
|
|
2014-12-17 13:46:50 +00:00
|
|
|
waitLock.Lock()
|
2018-02-28 01:38:12 +00:00
|
|
|
return server, l.Addr().String(), fin, nil
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
func RunLocalTLSServer(laddr string, config *tls.Config) (*Server, string, chan error, error) {
|
|
|
|
return RunLocalTCPServer(laddr, func(srv *Server) {
|
|
|
|
srv.Listener = tls.NewListener(srv.Listener, config)
|
|
|
|
})
|
2016-01-08 13:26:13 +00:00
|
|
|
}
|
|
|
|
|
2011-07-05 17:49:13 +00:00
|
|
|
func TestServing(t *testing.T) {
|
2020-10-24 15:53:01 +00:00
|
|
|
for _, tc := range []struct {
|
|
|
|
name string
|
|
|
|
network string
|
|
|
|
runServer func(laddr string, opts ...func(*Server)) (*Server, string, chan error, error)
|
|
|
|
}{
|
|
|
|
{"udp", "udp", RunLocalUDPServer},
|
|
|
|
{"tcp", "tcp", RunLocalTCPServer},
|
|
|
|
{"PacketConn", "udp", RunLocalPacketConnServer},
|
|
|
|
} {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
|
|
|
defer HandleRemove("miek.nl.")
|
|
|
|
defer HandleRemove("example.com.")
|
|
|
|
|
|
|
|
s, addrstr, _, err := tc.runServer(":0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
2014-08-29 03:11:49 +00:00
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
c := &Client{
|
|
|
|
Net: tc.network,
|
|
|
|
}
|
|
|
|
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")
|
|
|
|
}
|
2014-07-17 10:14:50 +00:00
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
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")
|
|
|
|
}
|
2014-07-17 10:14:50 +00:00
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
// 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")
|
|
|
|
}
|
|
|
|
})
|
2013-07-25 06:55:59 +00:00
|
|
|
}
|
2011-07-05 17:49:13 +00:00
|
|
|
}
|
2011-07-06 17:21:19 +00:00
|
|
|
|
2019-06-13 06:24:10 +00:00
|
|
|
// Verify that the server responds to a query with Z flag on, ignoring the flag, and does not echoes it back
|
2019-05-23 19:54:24 +00:00
|
|
|
func TestServeIgnoresZFlag(t *testing.T) {
|
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0")
|
2019-05-23 19:54:24 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
2019-06-13 06:24:10 +00:00
|
|
|
|
2019-05-23 19:54:24 +00:00
|
|
|
// Test the Z flag is not echoed
|
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
|
|
|
m.Zero = true
|
|
|
|
r, _, err := c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("failed to exchange example.com with +zflag", err)
|
|
|
|
}
|
|
|
|
if r.Zero {
|
|
|
|
t.Error("the response should not have Z flag set - even for a query which does")
|
|
|
|
}
|
|
|
|
if r.Rcode != RcodeSuccess {
|
|
|
|
t.Errorf("expected rcode %v, got %v", RcodeSuccess, r.Rcode)
|
2019-06-17 15:13:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the server responds to a query with unsupported Opcode with a NotImplemented error and that Opcode is unchanged.
|
|
|
|
func TestServeNotImplemented(t *testing.T) {
|
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
|
|
|
opcode := 15
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0")
|
2019-06-17 15:13:02 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
|
2021-02-25 16:08:05 +00:00
|
|
|
// Test that Opcode is like the unchanged from request Opcode and that Rcode is set to NotImplemented
|
2019-06-17 15:13:02 +00:00
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
|
|
|
m.Opcode = opcode
|
|
|
|
r, _, err := c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("failed to exchange example.com with +zflag", err)
|
|
|
|
}
|
|
|
|
if r.Opcode != opcode {
|
|
|
|
t.Errorf("expected opcode %v, got %v", opcode, r.Opcode)
|
|
|
|
}
|
|
|
|
if r.Rcode != RcodeNotImplemented {
|
|
|
|
t.Errorf("expected rcode %v, got %v", RcodeNotImplemented, r.Rcode)
|
2019-05-23 19:54:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-08 13:26:13 +00: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},
|
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalTLSServer(":0", &config)
|
2016-01-08 13:26:13 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-22 17:34:55 +00:00
|
|
|
// TestServingTLSConnectionState tests that we only can access
|
|
|
|
// tls.ConnectionState under a DNS query handled by a TLS DNS server.
|
|
|
|
// This test will sequentially create a TLS, UDP and TCP server, attach a custom
|
|
|
|
// handler which will set a testing error if tls.ConnectionState is available
|
|
|
|
// when it is not expected, or the other way around.
|
|
|
|
func TestServingTLSConnectionState(t *testing.T) {
|
|
|
|
handlerResponse := "Hello example"
|
|
|
|
// tlsHandlerTLS is a HandlerFunc that can be set to expect or not TLS
|
|
|
|
// connection state.
|
|
|
|
tlsHandlerTLS := func(tlsExpected bool) func(ResponseWriter, *Msg) {
|
|
|
|
return func(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
tlsFound := true
|
|
|
|
if connState := w.(ConnectionStater).ConnectionState(); connState == nil {
|
|
|
|
tlsFound = false
|
|
|
|
}
|
|
|
|
if tlsFound != tlsExpected {
|
|
|
|
t.Errorf("TLS connection state available: %t, expected: %t", tlsFound, tlsExpected)
|
|
|
|
}
|
|
|
|
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{handlerResponse}}
|
|
|
|
w.WriteMsg(m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Question used in tests
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("tlsstate.example.net.", TypeTXT)
|
|
|
|
|
|
|
|
// TLS DNS server
|
|
|
|
HandleFunc(".", tlsHandlerTLS(true))
|
|
|
|
cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to build certificate: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
config := tls.Config{
|
|
|
|
Certificates: []tls.Certificate{cert},
|
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalTLSServer(":0", &config)
|
2018-09-22 17:34:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
|
|
|
// TLS DNS query
|
|
|
|
c := &Client{
|
|
|
|
Net: "tcp-tls",
|
|
|
|
TLSConfig: &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to exchange tlsstate.example.net", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
HandleRemove(".")
|
|
|
|
// UDP DNS Server
|
|
|
|
HandleFunc(".", tlsHandlerTLS(false))
|
|
|
|
defer HandleRemove(".")
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err = RunLocalUDPServer(":0")
|
2018-09-22 17:34:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
|
|
|
// UDP DNS query
|
|
|
|
c = new(Client)
|
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to exchange tlsstate.example.net", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP DNS Server
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err = RunLocalTCPServer(":0")
|
2018-09-22 17:34:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
|
|
|
// TCP DNS query
|
|
|
|
c = &Client{Net: "tcp"}
|
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to exchange tlsstate.example.net", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-10 10:11:23 +00:00
|
|
|
func TestServingListenAndServe(t *testing.T) {
|
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
|
|
|
defer HandleRemove("example.com.")
|
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
server := &Server{Addr: ":0", Net: "udp", ReadTimeout: time.Hour, WriteTimeout: time.Hour, NotifyStartedFunc: waitLock.Unlock}
|
|
|
|
waitLock.Lock()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
server.ListenAndServe()
|
|
|
|
}()
|
|
|
|
waitLock.Lock()
|
|
|
|
|
|
|
|
c, m := new(Client), new(Msg)
|
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
|
|
|
addr := server.PacketConn.LocalAddr().String() // Get address via the PacketConn that gets set.
|
|
|
|
r, _, err := c.Exchange(m, addr)
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
server.Shutdown()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestServingListenAndServeTLS(t *testing.T) {
|
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
|
|
|
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},
|
|
|
|
}
|
|
|
|
|
|
|
|
waitLock := sync.Mutex{}
|
|
|
|
server := &Server{Addr: ":0", Net: "tcp", TLSConfig: config, ReadTimeout: time.Hour, WriteTimeout: time.Hour, NotifyStartedFunc: waitLock.Unlock}
|
|
|
|
waitLock.Lock()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
server.ListenAndServe()
|
|
|
|
}()
|
|
|
|
waitLock.Lock()
|
|
|
|
|
|
|
|
c, m := new(Client), new(Msg)
|
|
|
|
c.Net = "tcp"
|
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
|
|
|
addr := server.Listener.Addr().String() // Get address via the Listener that gets set.
|
|
|
|
r, _, err := c.Exchange(m, addr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
txt := r.Extra[0].(*TXT).Txt[0]
|
|
|
|
if txt != "Hello example" {
|
|
|
|
t.Error("unexpected result for example.com", txt, "!= Hello example")
|
|
|
|
}
|
|
|
|
server.Shutdown()
|
|
|
|
}
|
|
|
|
|
2014-01-29 07:56:21 +00:00
|
|
|
func BenchmarkServe(b *testing.B) {
|
2011-07-23 21:43:43 +00:00
|
|
|
b.StopTimer()
|
2011-07-06 17:21:19 +00:00
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2014-08-30 13:45:30 +00:00
|
|
|
defer HandleRemove("miek.nl.")
|
2013-06-22 07:55:30 +00:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 12:27:53 +00:00
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0")
|
2014-08-29 12:27:53 +00:00
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
b.Fatalf("unable to run test server: %v", err)
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2012-05-26 08:28:32 +00:00
|
|
|
c := new(Client)
|
2011-07-23 21:43:43 +00:00
|
|
|
m := new(Msg)
|
2018-09-08 16:10:56 +00:00
|
|
|
m.SetQuestion("miek.nl.", TypeSOA)
|
2011-07-06 17:21:19 +00:00
|
|
|
|
2011-07-23 21:43:43 +00:00
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2018-09-08 16:10:56 +00:00
|
|
|
_, _, err := c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Exchange failed: %v", err)
|
|
|
|
}
|
2011-07-23 21:43:43 +00:00
|
|
|
}
|
2013-06-22 07:55:30 +00:00
|
|
|
runtime.GOMAXPROCS(a)
|
2011-07-06 17:21:19 +00:00
|
|
|
}
|
2012-09-17 06:56:27 +00:00
|
|
|
|
2018-09-08 16:10:56 +00:00
|
|
|
func BenchmarkServe6(b *testing.B) {
|
2014-07-08 14:15:08 +00:00
|
|
|
b.StopTimer()
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2014-08-30 13:45:30 +00:00
|
|
|
defer HandleRemove("miek.nl.")
|
2014-07-08 14:15:08 +00:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer("[::1]:0")
|
2014-08-29 12:27:53 +00:00
|
|
|
if err != nil {
|
2018-09-08 16:10:56 +00:00
|
|
|
if strings.Contains(err.Error(), "bind: cannot assign requested address") {
|
|
|
|
b.Skip("missing IPv6 support")
|
|
|
|
}
|
2015-11-26 14:12:38 +00:00
|
|
|
b.Fatalf("unable to run test server: %v", err)
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2014-07-08 14:15:08 +00:00
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
2018-09-08 16:10:56 +00:00
|
|
|
m.SetQuestion("miek.nl.", TypeSOA)
|
2014-07-08 14:15:08 +00:00
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2018-09-08 16:10:56 +00:00
|
|
|
_, _, err := c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Exchange failed: %v", err)
|
|
|
|
}
|
2014-07-08 14:15:08 +00:00
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(a)
|
|
|
|
}
|
|
|
|
|
2013-06-27 19:29:10 +00: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 07:52:23 +00:00
|
|
|
func BenchmarkServeCompress(b *testing.B) {
|
2013-06-27 19:29:10 +00:00
|
|
|
b.StopTimer()
|
|
|
|
HandleFunc("miek.nl.", HelloServerCompress)
|
2014-08-30 13:45:30 +00:00
|
|
|
defer HandleRemove("miek.nl.")
|
2013-06-27 19:29:10 +00:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0")
|
2014-08-29 12:27:53 +00:00
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
b.Fatalf("unable to run test server: %v", err)
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
2013-06-27 19:29:10 +00:00
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
2018-09-08 16:10:56 +00:00
|
|
|
m.SetQuestion("miek.nl.", TypeSOA)
|
2013-06-27 19:29:10 +00:00
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2018-09-08 16:10:56 +00:00
|
|
|
_, _, err := c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Exchange failed: %v", err)
|
|
|
|
}
|
2013-06-27 19:29:10 +00:00
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(a)
|
|
|
|
}
|
|
|
|
|
2014-02-28 15:57:10 +00:00
|
|
|
type maxRec struct {
|
|
|
|
max int
|
|
|
|
sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
var M = new(maxRec)
|
2014-02-14 21:53:00 +00:00
|
|
|
|
2014-02-15 08:03:40 +00:00
|
|
|
func HelloServerLargeResponse(resp ResponseWriter, req *Msg) {
|
2014-02-14 21:53:00 +00:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
m.Authoritative = true
|
2014-02-28 15:57:10 +00:00
|
|
|
m1 := 0
|
|
|
|
M.RLock()
|
|
|
|
m1 = M.max
|
|
|
|
M.RUnlock()
|
|
|
|
for i := 0; i < m1; i++ {
|
2014-02-14 21:53:00 +00: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-29 18:10:05 +00:00
|
|
|
HandleFunc("example.", HelloServerLargeResponse)
|
2014-08-30 13:45:30 +00:00
|
|
|
defer HandleRemove("example.")
|
2014-02-14 21:53:00 +00:00
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0")
|
2014-08-29 12:27:53 +00:00
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-02-14 21:53:00 +00:00
|
|
|
}
|
2014-08-29 12:27:53 +00:00
|
|
|
defer s.Shutdown()
|
2014-02-14 21:53:00 +00:00
|
|
|
|
|
|
|
// Create request
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("web.service.example.", TypeANY)
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
c.Net = "udp"
|
2014-02-28 15:57:10 +00:00
|
|
|
M.Lock()
|
|
|
|
M.max = 2
|
|
|
|
M.Unlock()
|
2014-08-29 12:27:53 +00:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-14 21:53:00 +00:00
|
|
|
if err != nil {
|
2015-02-26 06:14:21 +00:00
|
|
|
t.Errorf("failed to exchange: %v", err)
|
2014-02-14 21:53:00 +00:00
|
|
|
}
|
|
|
|
// This must fail
|
2014-02-28 15:57:10 +00:00
|
|
|
M.Lock()
|
|
|
|
M.max = 20
|
|
|
|
M.Unlock()
|
2014-08-29 12:27:53 +00:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-14 21:53:00 +00:00
|
|
|
if err == nil {
|
2015-02-21 05:03:02 +00:00
|
|
|
t.Error("failed to fail exchange, this should generate packet error")
|
2014-02-14 21:53:00 +00:00
|
|
|
}
|
2014-02-14 22:14:41 +00:00
|
|
|
// But this must work again
|
|
|
|
c.UDPSize = 7000
|
2014-08-29 12:27:53 +00:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-14 22:14:41 +00:00
|
|
|
if err != nil {
|
2015-02-26 06:14:21 +00:00
|
|
|
t.Errorf("failed to exchange: %v", err)
|
2014-02-14 22:14:41 +00:00
|
|
|
}
|
2014-02-14 21:53:00 +00:00
|
|
|
}
|
2014-08-19 08:39:04 +00:00
|
|
|
|
2014-10-19 09:36:26 +00:00
|
|
|
func TestServingResponse(t *testing.T) {
|
2014-11-12 10:19:20 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
2014-10-19 09:36:26 +00:00
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0")
|
2014-10-19 09:36:26 +00:00
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-10-19 09:36:26 +00:00
|
|
|
}
|
2018-11-27 10:43:01 +00:00
|
|
|
defer s.Shutdown()
|
2014-10-19 09:36:26 +00: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 05:03:02 +00:00
|
|
|
t.Fatal("failed to exchange", err)
|
2014-10-19 09:36:26 +00:00
|
|
|
}
|
2020-10-16 07:10:36 +00:00
|
|
|
m.Response = true // this holds up the reply, set short read time out to avoid waiting too long
|
|
|
|
c.ReadTimeout = 100 * time.Millisecond
|
2014-10-19 09:36:26 +00:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err == nil {
|
2015-02-21 05:03:02 +00:00
|
|
|
t.Fatal("exchanged response message")
|
2014-11-19 16:34:18 +00:00
|
|
|
}
|
2014-10-19 09:36:26 +00:00
|
|
|
}
|
|
|
|
|
2014-08-19 09:25:41 +00:00
|
|
|
func TestShutdownTCP(t *testing.T) {
|
2020-10-24 15:53:01 +00:00
|
|
|
s, _, fin, err := RunLocalTCPServer(":0")
|
2014-08-29 12:27:53 +00:00
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
2018-02-28 01:38:12 +00:00
|
|
|
t.Fatalf("could not shutdown test TCP server, %v", err)
|
|
|
|
}
|
|
|
|
select {
|
|
|
|
case err := <-fin:
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error returned from ActivateAndServe, %v", err)
|
|
|
|
}
|
|
|
|
case <-time.After(2 * time.Second):
|
|
|
|
t.Error("could not shutdown test TCP server. Gave up waiting")
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
2014-08-19 09:25:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-13 13:36:28 +00:00
|
|
|
func init() {
|
|
|
|
testShutdownNotify = &sync.Cond{
|
|
|
|
L: new(sync.Mutex),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkInProgressQueriesAtShutdownServer(t *testing.T, srv *Server, addr string, client *Client) {
|
2020-10-16 07:10:36 +00:00
|
|
|
const requests = 15 // enough to make this interesting? TODO: find a proper value
|
2018-09-13 13:36:28 +00:00
|
|
|
|
|
|
|
var errOnce sync.Once
|
2018-10-09 17:41:42 +00:00
|
|
|
// t.Fail will panic if it's called after the test function has
|
|
|
|
// finished. Burning the sync.Once with a defer will prevent the
|
|
|
|
// handler from calling t.Errorf after we've returned.
|
|
|
|
defer errOnce.Do(func() {})
|
2018-09-13 13:36:28 +00:00
|
|
|
|
2018-10-09 17:43:08 +00:00
|
|
|
toHandle := int32(requests)
|
2018-09-13 13:36:28 +00:00
|
|
|
HandleFunc("example.com.", func(w ResponseWriter, req *Msg) {
|
2018-10-09 17:43:08 +00:00
|
|
|
defer atomic.AddInt32(&toHandle, -1)
|
2018-09-13 13:36:28 +00:00
|
|
|
|
|
|
|
// Wait until ShutdownContext is called before replying.
|
|
|
|
testShutdownNotify.L.Lock()
|
|
|
|
testShutdownNotify.Wait()
|
|
|
|
testShutdownNotify.L.Unlock()
|
|
|
|
|
|
|
|
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"}}
|
|
|
|
|
|
|
|
if err := w.WriteMsg(m); err != nil {
|
|
|
|
errOnce.Do(func() {
|
|
|
|
t.Errorf("ResponseWriter.WriteMsg error: %s", err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
defer HandleRemove("example.com.")
|
|
|
|
|
2020-10-16 07:10:36 +00:00
|
|
|
client.Timeout = 1 * time.Second
|
2018-09-13 13:36:28 +00:00
|
|
|
|
|
|
|
conns := make([]*Conn, requests)
|
|
|
|
eg := new(errgroup.Group)
|
|
|
|
|
|
|
|
for i := range conns {
|
|
|
|
conn := &conns[i]
|
|
|
|
eg.Go(func() error {
|
|
|
|
var err error
|
|
|
|
*conn, err = client.Dial(addr)
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
if eg.Wait() != nil {
|
|
|
|
t.Fatalf("client.Dial error: %v", eg.Wait())
|
|
|
|
}
|
|
|
|
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
|
|
|
eg = new(errgroup.Group)
|
|
|
|
|
|
|
|
for _, conn := range conns {
|
|
|
|
conn := conn
|
|
|
|
eg.Go(func() error {
|
|
|
|
conn.SetWriteDeadline(time.Now().Add(client.Timeout))
|
|
|
|
|
|
|
|
return conn.WriteMsg(m)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
if eg.Wait() != nil {
|
|
|
|
t.Fatalf("conn.WriteMsg error: %v", eg.Wait())
|
|
|
|
}
|
|
|
|
|
|
|
|
// This sleep is needed to allow time for the requests to
|
|
|
|
// pass from the client through the kernel and back into
|
|
|
|
// the server. Without it, some requests may still be in
|
|
|
|
// the kernel's buffer when ShutdownContext is called.
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
eg = new(errgroup.Group)
|
|
|
|
|
|
|
|
for _, conn := range conns {
|
|
|
|
conn := conn
|
|
|
|
eg.Go(func() error {
|
|
|
|
conn.SetReadDeadline(time.Now().Add(client.Timeout))
|
|
|
|
|
|
|
|
_, err := conn.ReadMsg()
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
if err := srv.ShutdownContext(ctx); err != nil {
|
2018-10-09 17:43:08 +00:00
|
|
|
t.Errorf("could not shutdown test server: %v", err)
|
2018-09-13 13:36:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-09 17:43:08 +00:00
|
|
|
if left := atomic.LoadInt32(&toHandle); left != 0 {
|
|
|
|
t.Errorf("ShutdownContext returned before %d replies", left)
|
2018-09-13 13:36:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if eg.Wait() != nil {
|
2018-11-03 09:44:07 +00:00
|
|
|
t.Errorf("conn.ReadMsg error: %v", eg.Wait())
|
|
|
|
}
|
|
|
|
|
|
|
|
srv.lock.RLock()
|
|
|
|
defer srv.lock.RUnlock()
|
|
|
|
if len(srv.conns) != 0 {
|
|
|
|
t.Errorf("TCP connection tracking map not empty after ShutdownContext; map still contains %d connections", len(srv.conns))
|
2018-09-13 13:36:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInProgressQueriesAtShutdownTCP(t *testing.T) {
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addr, _, err := RunLocalTCPServer(":0")
|
2018-09-13 13:36:28 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c := &Client{Net: "tcp"}
|
|
|
|
checkInProgressQueriesAtShutdownServer(t, s, addr, c)
|
|
|
|
}
|
|
|
|
|
2016-01-08 13:26:13 +00: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},
|
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, _, _, err := RunLocalTLSServer(":0", &config)
|
2016-01-08 13:26:13 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:36:28 +00:00
|
|
|
func TestInProgressQueriesAtShutdownTLS(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},
|
|
|
|
}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addr, _, err := RunLocalTLSServer(":0", &config)
|
2018-09-13 13:36:28 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c := &Client{
|
|
|
|
Net: "tcp-tls",
|
|
|
|
TLSConfig: &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
checkInProgressQueriesAtShutdownServer(t, s, addr, c)
|
|
|
|
}
|
|
|
|
|
2015-11-26 08:04:38 +00:00
|
|
|
func TestHandlerCloseTCP(t *testing.T) {
|
2017-11-08 10:01:19 +00:00
|
|
|
ln, err := net.Listen("tcp", ":0")
|
2015-11-26 08:04:38 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
addr := ln.Addr().String()
|
|
|
|
|
|
|
|
server := &Server{Addr: addr, Net: "tcp", Listener: ln}
|
|
|
|
|
|
|
|
hname := "testhandlerclosetcp."
|
2018-09-26 20:04:11 +00:00
|
|
|
triggered := make(chan struct{})
|
2015-11-26 08:04:38 +00:00
|
|
|
HandleFunc(hname, func(w ResponseWriter, r *Msg) {
|
2018-09-26 20:04:11 +00:00
|
|
|
close(triggered)
|
2015-11-26 08:04:38 +00: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 {
|
2018-09-26 20:04:11 +00:00
|
|
|
t.Errorf("exchange failed: %v", err)
|
2015-11-26 08:04:38 +00:00
|
|
|
if tries == 3 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
time.Sleep(time.Second / 10)
|
2017-02-15 20:40:16 +00:00
|
|
|
tries++
|
2015-11-26 08:04:38 +00:00
|
|
|
goto exchange
|
|
|
|
}
|
|
|
|
}()
|
2018-09-26 20:04:11 +00:00
|
|
|
if err := server.ActivateAndServe(); err != nil {
|
|
|
|
t.Fatalf("ActivateAndServe failed: %v", err)
|
|
|
|
}
|
|
|
|
select {
|
|
|
|
case <-triggered:
|
|
|
|
default:
|
2015-11-26 14:03:51 +00:00
|
|
|
t.Fatalf("handler never called")
|
2015-11-26 08:04:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-19 09:25:41 +00:00
|
|
|
func TestShutdownUDP(t *testing.T) {
|
2020-10-24 15:53:01 +00:00
|
|
|
s, _, fin, err := RunLocalUDPServer(":0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("could not shutdown test UDP server, %v", err)
|
|
|
|
}
|
|
|
|
select {
|
|
|
|
case err := <-fin:
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error returned from ActivateAndServe, %v", err)
|
|
|
|
}
|
|
|
|
case <-time.After(2 * time.Second):
|
|
|
|
t.Error("could not shutdown test UDP server. Gave up waiting")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestShutdownPacketConn(t *testing.T) {
|
|
|
|
s, _, fin, err := RunLocalPacketConnServer(":0")
|
2014-08-29 12:27:53 +00:00
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
2015-11-26 14:12:38 +00:00
|
|
|
t.Errorf("could not shutdown test UDP server, %v", err)
|
2014-08-29 12:27:53 +00:00
|
|
|
}
|
2015-12-01 22:15:42 +00:00
|
|
|
select {
|
2018-02-28 01:38:12 +00:00
|
|
|
case err := <-fin:
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error returned from ActivateAndServe, %v", err)
|
|
|
|
}
|
2015-12-01 22:15:42 +00:00
|
|
|
case <-time.After(2 * time.Second):
|
2017-11-10 10:11:23 +00:00
|
|
|
t.Error("could not shutdown test UDP server. Gave up waiting")
|
2015-12-01 22:15:42 +00:00
|
|
|
}
|
2014-08-19 08:39:04 +00:00
|
|
|
}
|
2015-08-04 13:04:40 +00:00
|
|
|
|
2018-09-13 13:36:28 +00:00
|
|
|
func TestInProgressQueriesAtShutdownUDP(t *testing.T) {
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addr, _, err := RunLocalUDPServer(":0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c := &Client{Net: "udp"}
|
|
|
|
checkInProgressQueriesAtShutdownServer(t, s, addr, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInProgressQueriesAtShutdownPacketConn(t *testing.T) {
|
|
|
|
s, addr, _, err := RunLocalPacketConnServer(":0")
|
2018-09-13 13:36:28 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c := &Client{Net: "udp"}
|
|
|
|
checkInProgressQueriesAtShutdownServer(t, s, addr, c)
|
|
|
|
}
|
|
|
|
|
2017-11-10 10:33:17 +00:00
|
|
|
func TestServerStartStopRace(t *testing.T) {
|
2018-09-09 19:47:16 +00:00
|
|
|
var wg sync.WaitGroup
|
2017-11-10 10:33:17 +00:00
|
|
|
for i := 0; i < 10; i++ {
|
2018-09-09 19:47:16 +00:00
|
|
|
wg.Add(1)
|
2020-10-24 15:53:01 +00:00
|
|
|
s, _, _, err := RunLocalUDPServer(":0")
|
2017-11-10 10:33:17 +00:00
|
|
|
if err != nil {
|
2017-11-17 10:48:42 +00:00
|
|
|
t.Fatalf("could not start server: %s", err)
|
2017-11-10 10:33:17 +00:00
|
|
|
}
|
|
|
|
go func() {
|
2018-09-09 19:47:16 +00:00
|
|
|
defer wg.Done()
|
2017-11-10 10:33:17 +00:00
|
|
|
if err := s.Shutdown(); err != nil {
|
2018-09-09 19:47:16 +00:00
|
|
|
t.Errorf("could not stop server: %s", err)
|
2017-11-10 10:33:17 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2018-09-09 19:47:16 +00:00
|
|
|
wg.Wait()
|
2017-11-10 10:33:17 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 10:42:54 +00:00
|
|
|
func TestServerReuseport(t *testing.T) {
|
|
|
|
if !supportsReusePort {
|
|
|
|
t.Skip("reuseport is not supported")
|
|
|
|
}
|
|
|
|
|
|
|
|
startServer := func(addr string) (*Server, chan error) {
|
|
|
|
wait := make(chan struct{})
|
|
|
|
srv := &Server{
|
|
|
|
Net: "udp",
|
|
|
|
Addr: addr,
|
|
|
|
NotifyStartedFunc: func() { close(wait) },
|
|
|
|
ReusePort: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
fin := make(chan error, 1)
|
|
|
|
go func() {
|
|
|
|
fin <- srv.ListenAndServe()
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-wait:
|
|
|
|
case err := <-fin:
|
|
|
|
t.Fatalf("failed to start server: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return srv, fin
|
|
|
|
}
|
|
|
|
|
|
|
|
srv1, fin1 := startServer(":0") // :0 is resolved to a random free port by the kernel
|
|
|
|
srv2, fin2 := startServer(srv1.PacketConn.LocalAddr().String())
|
|
|
|
|
|
|
|
if err := srv1.Shutdown(); err != nil {
|
|
|
|
t.Fatalf("failed to shutdown first server: %v", err)
|
|
|
|
}
|
|
|
|
if err := srv2.Shutdown(); err != nil {
|
|
|
|
t.Fatalf("failed to shutdown second server: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := <-fin1; err != nil {
|
|
|
|
t.Fatalf("first ListenAndServe returned error after Shutdown: %v", err)
|
|
|
|
}
|
|
|
|
if err := <-fin2; err != nil {
|
|
|
|
t.Fatalf("second ListenAndServe returned error after Shutdown: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-26 08:19:35 +00:00
|
|
|
func TestServerRoundtripTsig(t *testing.T) {
|
|
|
|
secret := map[string]string{"test.": "so6ZGir4GPAqINNh9U5c3A=="}
|
|
|
|
|
2020-10-24 15:53:01 +00:00
|
|
|
s, addrstr, _, err := RunLocalUDPServer(":0", func(srv *Server) {
|
2018-09-26 08:19:35 +00:00
|
|
|
srv.TsigSecret = secret
|
2020-03-11 14:18:07 +00:00
|
|
|
srv.MsgAcceptFunc = func(dh Header) MsgAcceptAction {
|
|
|
|
// defaultMsgAcceptFunc does reject UPDATE queries
|
|
|
|
return MsgAccept
|
|
|
|
}
|
2018-09-26 08:19:35 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to run test server: %v", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2020-03-11 14:18:07 +00:00
|
|
|
handlerFired := make(chan struct{})
|
2018-09-26 08:19:35 +00:00
|
|
|
HandleFunc("example.com.", func(w ResponseWriter, r *Msg) {
|
2020-03-11 14:18:07 +00:00
|
|
|
close(handlerFired)
|
|
|
|
|
2018-09-26 08:19:35 +00:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(r)
|
|
|
|
if r.IsTsig() != nil {
|
|
|
|
status := w.TsigStatus()
|
|
|
|
if status == nil {
|
|
|
|
// *Msg r has an TSIG record and it was validated
|
2020-10-24 11:57:51 +00:00
|
|
|
m.SetTsig("test.", HmacSHA256, 300, time.Now().Unix())
|
2018-09-26 08:19:35 +00:00
|
|
|
} else {
|
2021-02-25 16:08:05 +00:00
|
|
|
// *Msg r has an TSIG records and it was not validated
|
2018-09-26 08:19:35 +00:00
|
|
|
t.Errorf("invalid TSIG: %v", status)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Error("missing TSIG")
|
|
|
|
}
|
2020-03-11 14:18:07 +00:00
|
|
|
if err := w.WriteMsg(m); err != nil {
|
|
|
|
t.Error("writemsg failed", err)
|
|
|
|
}
|
2018-09-26 08:19:35 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.Opcode = OpcodeUpdate
|
|
|
|
m.SetQuestion("example.com.", TypeSOA)
|
|
|
|
m.Ns = []RR{&CNAME{
|
|
|
|
Hdr: RR_Header{
|
2018-09-26 17:36:02 +00:00
|
|
|
Name: "foo.example.com.",
|
2018-09-26 08:19:35 +00:00
|
|
|
Rrtype: TypeCNAME,
|
2018-09-26 17:36:02 +00:00
|
|
|
Class: ClassINET,
|
|
|
|
Ttl: 300,
|
2018-09-26 08:19:35 +00:00
|
|
|
},
|
|
|
|
Target: "bar.example.com.",
|
|
|
|
}}
|
|
|
|
c.TsigSecret = secret
|
2020-10-24 11:57:51 +00:00
|
|
|
m.SetTsig("test.", HmacSHA256, 300, time.Now().Unix())
|
2018-09-26 08:19:35 +00:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("failed to exchange", err)
|
|
|
|
}
|
2020-03-11 14:18:07 +00:00
|
|
|
select {
|
|
|
|
case <-handlerFired:
|
|
|
|
// ok, handler was actually called
|
|
|
|
default:
|
|
|
|
t.Error("handler was not called")
|
|
|
|
}
|
2018-09-26 08:19:35 +00:00
|
|
|
}
|
|
|
|
|
2018-10-04 06:39:21 +00:00
|
|
|
func TestResponseAfterClose(t *testing.T) {
|
2018-11-03 09:44:07 +00:00
|
|
|
testError := func(name string, err error) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
expect := fmt.Sprintf("dns: %s called after Close", name)
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expected error from %s after Close", name)
|
|
|
|
} else if err.Error() != expect {
|
|
|
|
t.Errorf("expected explicit error from %s after Close, expected %q, got %q", name, expect, err)
|
|
|
|
}
|
2018-10-04 06:39:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rw := &response{
|
2018-11-03 09:44:07 +00:00
|
|
|
closed: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := rw.Write(make([]byte, 2))
|
|
|
|
testError("Write", err)
|
|
|
|
|
|
|
|
testError("WriteMsg", rw.WriteMsg(new(Msg)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResponseDoubleClose(t *testing.T) {
|
|
|
|
rw := &response{
|
|
|
|
closed: true,
|
|
|
|
}
|
|
|
|
if err, expect := rw.Close(), "dns: connection already closed"; err == nil || err.Error() != expect {
|
|
|
|
t.Errorf("Close did not return expected: error %q, got: %v", expect, err)
|
2018-10-04 06:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-13 18:49:02 +00:00
|
|
|
type countingConn struct {
|
|
|
|
net.Conn
|
|
|
|
writes int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *countingConn) Write(p []byte) (int, error) {
|
|
|
|
c.writes++
|
|
|
|
return len(p), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResponseWriteSinglePacket(t *testing.T) {
|
|
|
|
c := &countingConn{}
|
|
|
|
rw := &response{
|
|
|
|
tcp: c,
|
|
|
|
}
|
|
|
|
rw.writer = rw
|
|
|
|
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl.", TypeTXT)
|
|
|
|
m.Response = true
|
|
|
|
err := rw.WriteMsg(m)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to write: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.writes != 1 {
|
|
|
|
t.Fatalf("incorrect number of Write calls")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-04 13:04:40 +00:00
|
|
|
type ExampleFrameLengthWriter struct {
|
|
|
|
Writer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ExampleFrameLengthWriter) Write(m []byte) (int, error) {
|
2015-08-06 21:55:37 +00:00
|
|
|
fmt.Println("writing raw DNS message of length", len(m))
|
2015-08-04 13:04:40 +00:00
|
|
|
return e.Writer.Write(m)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ExampleDecorateWriter() {
|
2015-08-06 21:55:37 +00:00
|
|
|
// instrument raw DNS message writing
|
2015-08-04 13:04:40 +00:00
|
|
|
wf := DecorateWriter(func(w Writer) Writer {
|
|
|
|
return &ExampleFrameLengthWriter{w}
|
|
|
|
})
|
|
|
|
|
|
|
|
// simple UDP server
|
2017-11-08 10:01:19 +00:00
|
|
|
pc, err := net.ListenPacket("udp", ":0")
|
2015-08-04 13:04:40 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
server := &Server{
|
|
|
|
PacketConn: pc,
|
|
|
|
DecorateWriter: wf,
|
2015-10-05 13:41:02 +00:00
|
|
|
ReadTimeout: time.Hour, WriteTimeout: time.Hour,
|
2015-08-04 13:04:40 +00: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-06 21:55:37 +00:00
|
|
|
// Output: writing raw DNS message of length 56
|
2015-08-04 13:04:40 +00:00
|
|
|
}
|
2016-01-08 13:26:13 +00: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-----`)
|
|
|
|
)
|