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 }