github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/net/conn/dial_test.go (about)

     1  package conn
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	tu "github.com/ipfs/go-ipfs/util/testutil"
    12  
    13  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    14  )
    15  
    16  func echoListen(ctx context.Context, listener Listener) {
    17  	for {
    18  		c, err := listener.Accept()
    19  		if err != nil {
    20  
    21  			select {
    22  			case <-ctx.Done():
    23  				return
    24  			default:
    25  			}
    26  
    27  			if ne, ok := err.(net.Error); ok && ne.Temporary() {
    28  				<-time.After(time.Microsecond * 10)
    29  				continue
    30  			}
    31  
    32  			log.Debugf("echoListen: listener appears to be closing")
    33  			return
    34  		}
    35  
    36  		go echo(c.(Conn))
    37  	}
    38  }
    39  
    40  func echo(c Conn) {
    41  	io.Copy(c, c)
    42  }
    43  
    44  func setupSecureConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) {
    45  	return setupConn(t, ctx, true)
    46  }
    47  
    48  func setupSingleConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) {
    49  	return setupConn(t, ctx, false)
    50  }
    51  
    52  func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p2 tu.PeerNetParams) {
    53  
    54  	p1 = tu.RandPeerNetParamsOrFatal(t)
    55  	p2 = tu.RandPeerNetParamsOrFatal(t)
    56  
    57  	key1 := p1.PrivKey
    58  	key2 := p2.PrivKey
    59  	if !secure {
    60  		key1 = nil
    61  		key2 = nil
    62  	}
    63  	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.
    68  
    69  	d2 := &Dialer{
    70  		LocalPeer:  p2.ID,
    71  		PrivateKey: key2,
    72  	}
    73  
    74  	var c2 Conn
    75  
    76  	done := make(chan error)
    77  	go func() {
    78  		defer close(done)
    79  
    80  		var err error
    81  		c2, err = d2.Dial(ctx, p1.Addr, p1.ID)
    82  		if err != nil {
    83  			done <- err
    84  			return
    85  		}
    86  
    87  		// if secure, need to read + write, as that's what triggers the handshake.
    88  		if secure {
    89  			if err := sayHello(c2); err != nil {
    90  				done <- err
    91  			}
    92  		}
    93  	}()
    94  
    95  	c1, err := l1.Accept()
    96  	if err != nil {
    97  		t.Fatal("failed to accept", err)
    98  	}
    99  
   100  	// if secure, need to read + write, as that's what triggers the handshake.
   101  	if secure {
   102  		if err := sayHello(c1); err != nil {
   103  			done <- err
   104  		}
   105  	}
   106  
   107  	if err := <-done; err != nil {
   108  		t.Fatal(err)
   109  	}
   110  
   111  	return c1.(Conn), c2, p1, p2
   112  }
   113  
   114  func sayHello(c net.Conn) error {
   115  	h := []byte("hello")
   116  	if _, err := c.Write(h); err != nil {
   117  		return err
   118  	}
   119  	if _, err := c.Read(h); err != nil {
   120  		return err
   121  	}
   122  	if string(h) != "hello" {
   123  		return fmt.Errorf("did not get hello")
   124  	}
   125  	return nil
   126  }
   127  
   128  func testDialer(t *testing.T, secure bool) {
   129  	// t.Skip("Skipping in favor of another test")
   130  
   131  	p1 := tu.RandPeerNetParamsOrFatal(t)
   132  	p2 := tu.RandPeerNetParamsOrFatal(t)
   133  
   134  	key1 := p1.PrivKey
   135  	key2 := p2.PrivKey
   136  	if !secure {
   137  		key1 = nil
   138  		key2 = nil
   139  		t.Log("testing insecurely")
   140  	} else {
   141  		t.Log("testing securely")
   142  	}
   143  
   144  	ctx, cancel := context.WithCancel(context.Background())
   145  	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.
   150  
   151  	d2 := &Dialer{
   152  		LocalPeer:  p2.ID,
   153  		PrivateKey: key2,
   154  	}
   155  
   156  	go echoListen(ctx, l1)
   157  
   158  	c, err := d2.Dial(ctx, p1.Addr, p1.ID)
   159  	if err != nil {
   160  		t.Fatal("error dialing peer", err)
   161  	}
   162  
   163  	// fmt.Println("sending")
   164  	c.WriteMsg([]byte("beep"))
   165  	c.WriteMsg([]byte("boop"))
   166  
   167  	out, err := c.ReadMsg()
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  	// fmt.Println("recving", string(out))
   173  	data := string(out)
   174  	if data != "beep" {
   175  		t.Error("unexpected conn output", data)
   176  	}
   177  
   178  	out, err = c.ReadMsg()
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	data = string(out)
   184  	if string(out) != "boop" {
   185  		t.Error("unexpected conn output", data)
   186  	}
   187  
   188  	// fmt.Println("closing")
   189  	c.Close()
   190  	l1.Close()
   191  	cancel()
   192  }
   193  
   194  func TestDialerInsecure(t *testing.T) {
   195  	// t.Skip("Skipping in favor of another test")
   196  	testDialer(t, false)
   197  }
   198  
   199  func TestDialerSecure(t *testing.T) {
   200  	// t.Skip("Skipping in favor of another test")
   201  	testDialer(t, true)
   202  }
   203  
   204  func testDialerCloseEarly(t *testing.T, secure bool) {
   205  	// t.Skip("Skipping in favor of another test")
   206  
   207  	p1 := tu.RandPeerNetParamsOrFatal(t)
   208  	p2 := tu.RandPeerNetParamsOrFatal(t)
   209  
   210  	key1 := p1.PrivKey
   211  	if !secure {
   212  		key1 = nil
   213  		t.Log("testing insecurely")
   214  	} else {
   215  		t.Log("testing securely")
   216  	}
   217  
   218  	ctx, cancel := context.WithCancel(context.Background())
   219  	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
   220  	if err != nil {
   221  		t.Fatal(err)
   222  	}
   223  	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.
   224  
   225  	// lol nesting
   226  	d2 := &Dialer{
   227  		LocalPeer: p2.ID,
   228  		// PrivateKey: key2, -- dont give it key. we'll just close the conn.
   229  	}
   230  
   231  	errs := make(chan error, 100)
   232  	done := make(chan struct{}, 1)
   233  	gotclosed := make(chan struct{}, 1)
   234  	go func() {
   235  		defer func() { done <- struct{}{} }()
   236  
   237  		c, err := l1.Accept()
   238  		if err != nil {
   239  			if strings.Contains(err.Error(), "closed") {
   240  				gotclosed <- struct{}{}
   241  				return
   242  			}
   243  			errs <- err
   244  		}
   245  
   246  		if _, err := c.Write([]byte("hello")); err != nil {
   247  			gotclosed <- struct{}{}
   248  			return
   249  		}
   250  
   251  		errs <- fmt.Errorf("wrote to conn")
   252  	}()
   253  
   254  	c, err := d2.Dial(ctx, p1.Addr, p1.ID)
   255  	if err != nil {
   256  		errs <- err
   257  	}
   258  	c.Close() // close it early.
   259  
   260  	readerrs := func() {
   261  		for {
   262  			select {
   263  			case e := <-errs:
   264  				t.Error(e)
   265  			default:
   266  				return
   267  			}
   268  		}
   269  	}
   270  	readerrs()
   271  
   272  	l1.Close()
   273  	<-done
   274  	cancel()
   275  	readerrs()
   276  	close(errs)
   277  
   278  	select {
   279  	case <-gotclosed:
   280  	default:
   281  		t.Error("did not get closed")
   282  	}
   283  }
   284  
   285  // we dont do a handshake with singleConn, so cant "close early."
   286  // func TestDialerCloseEarlyInsecure(t *testing.T) {
   287  // 	// t.Skip("Skipping in favor of another test")
   288  // 	testDialerCloseEarly(t, false)
   289  // }
   290  
   291  func TestDialerCloseEarlySecure(t *testing.T) {
   292  	// t.Skip("Skipping in favor of another test")
   293  	testDialerCloseEarly(t, true)
   294  }