github.com/Finschia/ostracon@v1.1.5/p2p/transport_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"net"
     8  	"reflect"
     9  	"runtime"
    10  	"strconv"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p"
    16  
    17  	"github.com/Finschia/ostracon/crypto/ed25519"
    18  	"github.com/Finschia/ostracon/libs/protoio"
    19  	"github.com/Finschia/ostracon/p2p/conn"
    20  	"github.com/miekg/dns"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  var defaultNodeName = "host_peer"
    25  
    26  func emptyNodeInfo() NodeInfo {
    27  	return DefaultNodeInfo{}
    28  }
    29  
    30  // newMultiplexTransport returns a tcp connected multiplexed peer
    31  // using the default MConnConfig. It's a convenience function used
    32  // for testing.
    33  func newMultiplexTransport(
    34  	nodeInfo NodeInfo,
    35  	nodeKey NodeKey,
    36  ) *MultiplexTransport {
    37  	return NewMultiplexTransport(
    38  		nodeInfo, nodeKey, conn.DefaultMConnConfig(),
    39  	)
    40  }
    41  
    42  func TestTransportMultiplexConnFilter(t *testing.T) {
    43  	mt := newMultiplexTransport(
    44  		emptyNodeInfo(),
    45  		NodeKey{
    46  			PrivKey: ed25519.GenPrivKey(),
    47  		},
    48  	)
    49  	id := mt.nodeKey.ID()
    50  
    51  	MultiplexTransportConnFilters(
    52  		func(_ ConnSet, _ net.Conn, _ []net.IP) error { return nil },
    53  		func(_ ConnSet, _ net.Conn, _ []net.IP) error { return nil },
    54  		func(_ ConnSet, _ net.Conn, _ []net.IP) error {
    55  			return fmt.Errorf("rejected")
    56  		},
    57  	)(mt)
    58  
    59  	addr, err := NewNetAddressString(IDAddressString(id, "127.0.0.1:0"))
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  
    64  	if err := mt.Listen(*addr); err != nil {
    65  		t.Fatal(err)
    66  	}
    67  
    68  	errc := make(chan error)
    69  
    70  	go func() {
    71  		addr := NewNetAddress(id, mt.listener.Addr())
    72  
    73  		_, err := addr.Dial()
    74  		if err != nil {
    75  			errc <- err
    76  			return
    77  		}
    78  
    79  		close(errc)
    80  	}()
    81  
    82  	if err := <-errc; err != nil {
    83  		t.Errorf("connection failed: %v", err)
    84  	}
    85  
    86  	_, err = mt.Accept(peerConfig{})
    87  	if e, ok := err.(ErrRejected); ok {
    88  		if !e.IsFiltered() {
    89  			t.Errorf("expected peer to be filtered, got %v", e)
    90  		}
    91  	} else {
    92  		t.Errorf("expected ErrRejected, got %v", err)
    93  	}
    94  }
    95  
    96  func TestTransportMultiplexConnFilterTimeout(t *testing.T) {
    97  	mt := newMultiplexTransport(
    98  		emptyNodeInfo(),
    99  		NodeKey{
   100  			PrivKey: ed25519.GenPrivKey(),
   101  		},
   102  	)
   103  	id := mt.nodeKey.ID()
   104  
   105  	MultiplexTransportFilterTimeout(5 * time.Millisecond)(mt)
   106  	MultiplexTransportConnFilters(
   107  		func(_ ConnSet, _ net.Conn, _ []net.IP) error {
   108  			time.Sleep(1 * time.Second)
   109  			return nil
   110  		},
   111  	)(mt)
   112  
   113  	addr, err := NewNetAddressString(IDAddressString(id, "127.0.0.1:0"))
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	if err := mt.Listen(*addr); err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	errc := make(chan error)
   123  	go func() {
   124  		addr := NewNetAddress(id, mt.listener.Addr())
   125  
   126  		_, err := addr.Dial()
   127  		if err != nil {
   128  			errc <- err
   129  			return
   130  		}
   131  
   132  		close(errc)
   133  	}()
   134  
   135  	if err := <-errc; err != nil {
   136  		t.Errorf("connection failed: %v", err)
   137  	}
   138  
   139  	_, err = mt.Accept(peerConfig{})
   140  	if _, ok := err.(ErrFilterTimeout); !ok {
   141  		t.Errorf("expected ErrFilterTimeout, got %v", err)
   142  	}
   143  }
   144  
   145  func TestTransportMultiplexMaxIncomingConnections(t *testing.T) {
   146  	pv := ed25519.GenPrivKey()
   147  	id := PubKeyToID(pv.PubKey())
   148  	mt := newMultiplexTransport(
   149  		testNodeInfo(
   150  			id, "transport",
   151  		),
   152  		NodeKey{
   153  			PrivKey: pv,
   154  		},
   155  	)
   156  
   157  	MultiplexTransportMaxIncomingConnections(0)(mt)
   158  
   159  	addr, err := NewNetAddressString(IDAddressString(id, "127.0.0.1:0"))
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	const maxIncomingConns = 2
   164  	MultiplexTransportMaxIncomingConnections(maxIncomingConns)(mt)
   165  	if err := mt.Listen(*addr); err != nil {
   166  		t.Fatal(err)
   167  	}
   168  
   169  	laddr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   170  
   171  	// Connect more peers than max
   172  	for i := 0; i <= maxIncomingConns; i++ {
   173  		errc := make(chan error)
   174  		go testDialer(*laddr, errc)
   175  
   176  		err = <-errc
   177  		if i < maxIncomingConns {
   178  			if err != nil {
   179  				t.Errorf("dialer connection failed: %v", err)
   180  			}
   181  			_, err = mt.Accept(peerConfig{})
   182  			if err != nil {
   183  				t.Errorf("connection failed: %v", err)
   184  			}
   185  		} else if err == nil || !strings.Contains(err.Error(), "i/o timeout") {
   186  			// mt actually blocks forever on trying to accept a new peer into a full channel so
   187  			// expect the dialer to encounter a timeout error. Calling mt.Accept will block until
   188  			// mt is closed.
   189  			t.Errorf("expected i/o timeout error, got %v", err)
   190  		}
   191  	}
   192  }
   193  
   194  func TestTransportMultiplexAcceptMultiple(t *testing.T) {
   195  	mt := testSetupMultiplexTransport(t)
   196  	laddr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   197  
   198  	var (
   199  		seed     = rand.New(rand.NewSource(time.Now().UnixNano()))
   200  		nDialers = seed.Intn(64) + 64
   201  		errc     = make(chan error, nDialers)
   202  	)
   203  
   204  	// Setup dialers.
   205  	for i := 0; i < nDialers; i++ {
   206  		go testDialer(*laddr, errc)
   207  	}
   208  
   209  	// Catch connection errors.
   210  	for i := 0; i < nDialers; i++ {
   211  		if err := <-errc; err != nil {
   212  			t.Fatal(err)
   213  		}
   214  	}
   215  
   216  	ps := []Peer{}
   217  
   218  	// Accept all peers.
   219  	for i := 0; i < cap(errc); i++ {
   220  		p, err := mt.Accept(peerConfig{})
   221  		if err != nil {
   222  			t.Fatal(err)
   223  		}
   224  
   225  		if err := p.Start(); err != nil {
   226  			t.Fatal(err)
   227  		}
   228  
   229  		ps = append(ps, p)
   230  	}
   231  
   232  	if have, want := len(ps), cap(errc); have != want {
   233  		t.Errorf("have %v, want %v", have, want)
   234  	}
   235  
   236  	// Stop all peers.
   237  	for _, p := range ps {
   238  		if err := p.Stop(); err != nil {
   239  			t.Fatal(err)
   240  		}
   241  	}
   242  
   243  	if err := mt.Close(); err != nil {
   244  		t.Errorf("close errored: %v", err)
   245  	}
   246  }
   247  
   248  func testDialer(dialAddr NetAddress, errc chan error) {
   249  	var (
   250  		pv     = ed25519.GenPrivKey()
   251  		dialer = newMultiplexTransport(
   252  			testNodeInfo(PubKeyToID(pv.PubKey()), defaultNodeName),
   253  			NodeKey{
   254  				PrivKey: pv,
   255  			},
   256  		)
   257  	)
   258  
   259  	_, err := dialer.Dial(dialAddr, peerConfig{})
   260  	if err != nil {
   261  		errc <- err
   262  		return
   263  	}
   264  
   265  	// Signal that the connection was established.
   266  	errc <- nil
   267  }
   268  
   269  func TestTransportMultiplexAcceptNonBlocking(t *testing.T) {
   270  	mt := testSetupMultiplexTransport(t)
   271  
   272  	var (
   273  		fastNodePV   = ed25519.GenPrivKey()
   274  		fastNodeInfo = testNodeInfo(PubKeyToID(fastNodePV.PubKey()), "fastnode")
   275  		errc         = make(chan error)
   276  		fastc        = make(chan struct{})
   277  		slowc        = make(chan struct{})
   278  		slowdonec    = make(chan struct{})
   279  	)
   280  
   281  	// Simulate slow Peer.
   282  	go func() {
   283  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   284  
   285  		c, err := addr.Dial()
   286  		if err != nil {
   287  			errc <- err
   288  			return
   289  		}
   290  
   291  		close(slowc)
   292  		defer func() {
   293  			close(slowdonec)
   294  		}()
   295  
   296  		// Make sure we switch to fast peer goroutine.
   297  		runtime.Gosched()
   298  
   299  		select {
   300  		case <-fastc:
   301  			// Fast peer connected.
   302  		case <-time.After(200 * time.Millisecond):
   303  			// We error if the fast peer didn't succeed.
   304  			errc <- fmt.Errorf("fast peer timed out")
   305  		}
   306  
   307  		sc, err := upgradeSecretConn(c, 200*time.Millisecond, ed25519.GenPrivKey())
   308  		if err != nil {
   309  			errc <- err
   310  			return
   311  		}
   312  
   313  		_, err = handshake(sc, 200*time.Millisecond,
   314  			testNodeInfo(
   315  				PubKeyToID(ed25519.GenPrivKey().PubKey()),
   316  				"slow_peer",
   317  			))
   318  		if err != nil {
   319  			errc <- err
   320  		}
   321  	}()
   322  
   323  	// Simulate fast Peer.
   324  	go func() {
   325  		<-slowc
   326  
   327  		var (
   328  			dialer = newMultiplexTransport(
   329  				fastNodeInfo,
   330  				NodeKey{
   331  					PrivKey: fastNodePV,
   332  				},
   333  			)
   334  		)
   335  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   336  
   337  		_, err := dialer.Dial(*addr, peerConfig{})
   338  		if err != nil {
   339  			errc <- err
   340  			return
   341  		}
   342  
   343  		close(fastc)
   344  		<-slowdonec
   345  		close(errc)
   346  	}()
   347  
   348  	if err := <-errc; err != nil {
   349  		t.Logf("connection failed: %v", err)
   350  	}
   351  
   352  	p, err := mt.Accept(peerConfig{})
   353  	if err != nil {
   354  		t.Fatal(err)
   355  	}
   356  
   357  	if have, want := p.NodeInfo(), fastNodeInfo; !reflect.DeepEqual(have, want) {
   358  		t.Errorf("have %v, want %v", have, want)
   359  	}
   360  }
   361  
   362  func TestTransportMultiplexValidateNodeInfo(t *testing.T) {
   363  	mt := testSetupMultiplexTransport(t)
   364  
   365  	errc := make(chan error)
   366  
   367  	go func() {
   368  		var (
   369  			pv     = ed25519.GenPrivKey()
   370  			dialer = newMultiplexTransport(
   371  				testNodeInfo(PubKeyToID(pv.PubKey()), ""), // Should not be empty
   372  				NodeKey{
   373  					PrivKey: pv,
   374  				},
   375  			)
   376  		)
   377  
   378  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   379  
   380  		_, err := dialer.Dial(*addr, peerConfig{})
   381  		if err != nil {
   382  			errc <- err
   383  			return
   384  		}
   385  
   386  		close(errc)
   387  	}()
   388  
   389  	if err := <-errc; err != nil {
   390  		t.Errorf("connection failed: %v", err)
   391  	}
   392  
   393  	_, err := mt.Accept(peerConfig{})
   394  	if e, ok := err.(ErrRejected); ok {
   395  		if !e.IsNodeInfoInvalid() {
   396  			t.Errorf("expected NodeInfo to be invalid, got %v", e)
   397  		}
   398  	} else {
   399  		t.Errorf("expected ErrRejected, got %v", err)
   400  	}
   401  }
   402  
   403  func TestTransportMultiplexRejectMissmatchID(t *testing.T) {
   404  	mt := testSetupMultiplexTransport(t)
   405  
   406  	errc := make(chan error)
   407  
   408  	go func() {
   409  		dialer := newMultiplexTransport(
   410  			testNodeInfo(
   411  				PubKeyToID(ed25519.GenPrivKey().PubKey()), "dialer",
   412  			),
   413  			NodeKey{
   414  				PrivKey: ed25519.GenPrivKey(),
   415  			},
   416  		)
   417  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   418  
   419  		_, err := dialer.Dial(*addr, peerConfig{})
   420  		if err != nil {
   421  			errc <- err
   422  			return
   423  		}
   424  
   425  		close(errc)
   426  	}()
   427  
   428  	if err := <-errc; err != nil {
   429  		t.Errorf("connection failed: %v", err)
   430  	}
   431  
   432  	_, err := mt.Accept(peerConfig{})
   433  	if e, ok := err.(ErrRejected); ok {
   434  		if !e.IsAuthFailure() {
   435  			t.Errorf("expected auth failure, got %v", e)
   436  		}
   437  	} else {
   438  		t.Errorf("expected ErrRejected, got %v", err)
   439  	}
   440  }
   441  
   442  func TestTransportMultiplexDialRejectWrongID(t *testing.T) {
   443  	mt := testSetupMultiplexTransport(t)
   444  
   445  	var (
   446  		pv     = ed25519.GenPrivKey()
   447  		dialer = newMultiplexTransport(
   448  			testNodeInfo(PubKeyToID(pv.PubKey()), ""), // Should not be empty
   449  			NodeKey{
   450  				PrivKey: pv,
   451  			},
   452  		)
   453  	)
   454  
   455  	wrongID := PubKeyToID(ed25519.GenPrivKey().PubKey())
   456  	addr := NewNetAddress(wrongID, mt.listener.Addr())
   457  
   458  	_, err := dialer.Dial(*addr, peerConfig{})
   459  	if err != nil {
   460  		t.Logf("connection failed: %v", err)
   461  		if e, ok := err.(ErrRejected); ok {
   462  			if !e.IsAuthFailure() {
   463  				t.Errorf("expected auth failure, got %v", err)
   464  			}
   465  		} else {
   466  			t.Errorf("expected ErrRejected, got %v", err)
   467  		}
   468  	}
   469  }
   470  
   471  func TestTransportMultiplexRejectIncompatible(t *testing.T) {
   472  	mt := testSetupMultiplexTransport(t)
   473  
   474  	errc := make(chan error)
   475  
   476  	go func() {
   477  		var (
   478  			pv     = ed25519.GenPrivKey()
   479  			dialer = newMultiplexTransport(
   480  				testNodeInfoWithNetwork(PubKeyToID(pv.PubKey()), "dialer", "incompatible-network"),
   481  				NodeKey{
   482  					PrivKey: pv,
   483  				},
   484  			)
   485  		)
   486  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   487  
   488  		_, err := dialer.Dial(*addr, peerConfig{})
   489  		if err != nil {
   490  			errc <- err
   491  			return
   492  		}
   493  
   494  		close(errc)
   495  	}()
   496  
   497  	_, err := mt.Accept(peerConfig{})
   498  	if e, ok := err.(ErrRejected); ok {
   499  		if !e.IsIncompatible() {
   500  			t.Errorf("expected to reject incompatible, got %v", e)
   501  		}
   502  	} else {
   503  		t.Errorf("expected ErrRejected, got %v", err)
   504  	}
   505  }
   506  
   507  func TestTransportMultiplexRejectSelf(t *testing.T) {
   508  	mt := testSetupMultiplexTransport(t)
   509  
   510  	errc := make(chan error)
   511  
   512  	go func() {
   513  		addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr())
   514  
   515  		_, err := mt.Dial(*addr, peerConfig{})
   516  		if err != nil {
   517  			errc <- err
   518  			return
   519  		}
   520  
   521  		close(errc)
   522  	}()
   523  
   524  	if err := <-errc; err != nil {
   525  		if e, ok := err.(ErrRejected); ok {
   526  			if !e.IsSelf() {
   527  				t.Errorf("expected to reject self, got: %v", e)
   528  			}
   529  		} else {
   530  			t.Errorf("expected ErrRejected, got %v", err)
   531  		}
   532  	} else {
   533  		t.Errorf("expected connection failure")
   534  	}
   535  
   536  	_, err := mt.Accept(peerConfig{})
   537  	if e, ok := err.(ErrRejected); ok {
   538  		if !e.IsSelf() {
   539  			t.Errorf("expected to reject self, got: %v", e)
   540  		}
   541  	} else {
   542  		t.Errorf("expected ErrRejected, got %v", err)
   543  	}
   544  }
   545  
   546  func TestTransportConnDuplicateIPFilter(t *testing.T) {
   547  	filter := ConnDuplicateIPFilter()
   548  
   549  	if err := filter(nil, &testTransportConn{}, nil); err != nil {
   550  		t.Fatal(err)
   551  	}
   552  
   553  	var (
   554  		c  = &testTransportConn{}
   555  		cs = NewConnSet()
   556  	)
   557  
   558  	cs.Set(c, []net.IP{
   559  		{10, 0, 10, 1},
   560  		{10, 0, 10, 2},
   561  		{10, 0, 10, 3},
   562  	})
   563  
   564  	if err := filter(cs, c, []net.IP{
   565  		{10, 0, 10, 2},
   566  	}); err == nil {
   567  		t.Errorf("expected Peer to be rejected as duplicate")
   568  	}
   569  }
   570  
   571  func TestTransportHandshake(t *testing.T) {
   572  	ln, err := net.Listen("tcp", "127.0.0.1:0")
   573  	if err != nil {
   574  		t.Fatal(err)
   575  	}
   576  
   577  	var (
   578  		peerPV       = ed25519.GenPrivKey()
   579  		peerNodeInfo = testNodeInfo(PubKeyToID(peerPV.PubKey()), defaultNodeName)
   580  	)
   581  
   582  	go func() {
   583  		c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
   584  		if err != nil {
   585  			t.Error(err)
   586  			return
   587  		}
   588  
   589  		go func(c net.Conn) {
   590  			_, err := protoio.NewDelimitedWriter(c).WriteMsg(peerNodeInfo.(DefaultNodeInfo).ToProto())
   591  			if err != nil {
   592  				t.Error(err)
   593  			}
   594  		}(c)
   595  		go func(c net.Conn) {
   596  			var (
   597  				// ni   DefaultNodeInfo
   598  				pbni tmp2p.DefaultNodeInfo
   599  			)
   600  
   601  			protoReader := protoio.NewDelimitedReader(c, MaxNodeInfoSize())
   602  			_, err := protoReader.ReadMsg(&pbni)
   603  			if err != nil {
   604  				t.Error(err)
   605  			}
   606  
   607  			_, err = DefaultNodeInfoFromToProto(&pbni)
   608  			if err != nil {
   609  				t.Error(err)
   610  			}
   611  		}(c)
   612  	}()
   613  
   614  	c, err := ln.Accept()
   615  	if err != nil {
   616  		t.Fatal(err)
   617  	}
   618  
   619  	ni, err := handshake(c, 50*time.Millisecond, emptyNodeInfo())
   620  	if err != nil {
   621  		t.Fatal(err)
   622  	}
   623  
   624  	if have, want := ni, peerNodeInfo; !reflect.DeepEqual(have, want) {
   625  		t.Errorf("have %v, want %v", have, want)
   626  	}
   627  }
   628  
   629  func TestTransportAddChannel(t *testing.T) {
   630  	mt := newMultiplexTransport(
   631  		emptyNodeInfo(),
   632  		NodeKey{
   633  			PrivKey: ed25519.GenPrivKey(),
   634  		},
   635  	)
   636  	testChannel := byte(0x01)
   637  
   638  	err := mt.AddChannel(testChannel)
   639  	require.NoError(t, err)
   640  	if !mt.nodeInfo.(DefaultNodeInfo).HasChannel(testChannel) {
   641  		t.Errorf("missing added channel %v. Got %v", testChannel, mt.nodeInfo.(DefaultNodeInfo).Channels)
   642  	}
   643  }
   644  
   645  func TestTransportResolveIPs(t *testing.T) {
   646  	server := startFakeDNS()
   647  	defer func() {
   648  		err := server.Shutdown()
   649  		require.NoError(t, err)
   650  	}()
   651  
   652  	r := &net.Resolver{
   653  		PreferGo: true,
   654  		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
   655  			d := net.Dialer{
   656  				Timeout: time.Millisecond * time.Duration(500),
   657  			}
   658  			return d.DialContext(ctx, network, "127.0.0.1:5355")
   659  		},
   660  	}
   661  	_, err := resolveIPs(r, &testTransportConn{})
   662  	require.Contains(t, err.Error(), "lookup test.local: i/o timeout")
   663  }
   664  
   665  // create listener
   666  func testSetupMultiplexTransport(t *testing.T) *MultiplexTransport {
   667  	var (
   668  		pv = ed25519.GenPrivKey()
   669  		id = PubKeyToID(pv.PubKey())
   670  		mt = newMultiplexTransport(
   671  			testNodeInfo(
   672  				id, "transport",
   673  			),
   674  			NodeKey{
   675  				PrivKey: pv,
   676  			},
   677  		)
   678  	)
   679  
   680  	addr, err := NewNetAddressString(IDAddressString(id, "127.0.0.1:0"))
   681  	if err != nil {
   682  		t.Fatal(err)
   683  	}
   684  
   685  	if err := mt.Listen(*addr); err != nil {
   686  		t.Fatal(err)
   687  	}
   688  
   689  	// give the listener some time to get ready
   690  	time.Sleep(20 * time.Millisecond)
   691  
   692  	return mt
   693  }
   694  
   695  type testTransportAddr struct{}
   696  
   697  func (a *testTransportAddr) Network() string { return "tcp" }
   698  func (a *testTransportAddr) String() string  { return "test.local:1234" }
   699  
   700  type testTransportConn struct{}
   701  
   702  func (c *testTransportConn) Close() error {
   703  	return fmt.Errorf("close() not implemented")
   704  }
   705  
   706  func (c *testTransportConn) LocalAddr() net.Addr {
   707  	return &testTransportAddr{}
   708  }
   709  
   710  func (c *testTransportConn) RemoteAddr() net.Addr {
   711  	return &testTransportAddr{}
   712  }
   713  
   714  func (c *testTransportConn) Read(_ []byte) (int, error) {
   715  	return -1, fmt.Errorf("read() not implemented")
   716  }
   717  
   718  func (c *testTransportConn) SetDeadline(_ time.Time) error {
   719  	return fmt.Errorf("setDeadline() not implemented")
   720  }
   721  
   722  func (c *testTransportConn) SetReadDeadline(_ time.Time) error {
   723  	return fmt.Errorf("setReadDeadline() not implemented")
   724  }
   725  
   726  func (c *testTransportConn) SetWriteDeadline(_ time.Time) error {
   727  	return fmt.Errorf("setWriteDeadline() not implemented")
   728  }
   729  
   730  func (c *testTransportConn) Write(_ []byte) (int, error) {
   731  	return -1, fmt.Errorf("write() not implemented")
   732  }
   733  
   734  // fake dns server
   735  var records = map[string]string{
   736  	"test.local.": "192.168.0.2",
   737  }
   738  
   739  func parseQuery(m *dns.Msg) {
   740  	time.Sleep(5 * time.Second)
   741  	for _, q := range m.Question {
   742  		switch q.Qtype {
   743  		case dns.TypeA:
   744  			ip := records[q.Name]
   745  			if ip != "" {
   746  				rr, err := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, ip))
   747  				if err == nil {
   748  					m.Answer = append(m.Answer, rr)
   749  				}
   750  			}
   751  		}
   752  	}
   753  }
   754  
   755  func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
   756  	m := new(dns.Msg)
   757  	m.SetReply(r)
   758  	m.Compress = false
   759  	switch r.Opcode {
   760  	case dns.OpcodeQuery:
   761  		parseQuery(m)
   762  	}
   763  	_ = w.WriteMsg(m)
   764  }
   765  
   766  func startFakeDNS() *dns.Server {
   767  	// attach request handler func
   768  	dns.HandleFunc("local.", handleDnsRequest)
   769  
   770  	// start server
   771  	port := 5355
   772  	server := &dns.Server{Addr: ":" + strconv.Itoa(port), Net: "udp"}
   773  	go func() {
   774  		err := server.ListenAndServe()
   775  		if err != nil {
   776  			panic(err.Error())
   777  		}
   778  	}()
   779  	return server
   780  }