github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/net/mock/mock_net.go (about) 1 package mocknet 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 8 ic "github.com/ipfs/go-ipfs/p2p/crypto" 9 host "github.com/ipfs/go-ipfs/p2p/host" 10 bhost "github.com/ipfs/go-ipfs/p2p/host/basic" 11 inet "github.com/ipfs/go-ipfs/p2p/net" 12 peer "github.com/ipfs/go-ipfs/p2p/peer" 13 p2putil "github.com/ipfs/go-ipfs/p2p/test/util" 14 testutil "github.com/ipfs/go-ipfs/util/testutil" 15 16 ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 17 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess" 18 goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context" 19 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 20 ) 21 22 // mocknet implements mocknet.Mocknet 23 type mocknet struct { 24 nets map[peer.ID]*peernet 25 hosts map[peer.ID]*bhost.BasicHost 26 27 // links make it possible to connect two peers. 28 // think of links as the physical medium. 29 // usually only one, but there could be multiple 30 // **links are shared between peers** 31 links map[peer.ID]map[peer.ID]map[*link]struct{} 32 33 linkDefaults LinkOptions 34 35 proc goprocess.Process // for Context closing 36 ctx context.Context 37 sync.RWMutex 38 } 39 40 func New(ctx context.Context) Mocknet { 41 return &mocknet{ 42 nets: map[peer.ID]*peernet{}, 43 hosts: map[peer.ID]*bhost.BasicHost{}, 44 links: map[peer.ID]map[peer.ID]map[*link]struct{}{}, 45 proc: goprocessctx.WithContext(ctx), 46 ctx: ctx, 47 } 48 } 49 50 func (mn *mocknet) GenPeer() (host.Host, error) { 51 sk, err := p2putil.RandTestBogusPrivateKey() 52 if err != nil { 53 return nil, err 54 } 55 56 a := testutil.RandLocalTCPAddress() 57 58 h, err := mn.AddPeer(sk, a) 59 if err != nil { 60 return nil, err 61 } 62 63 return h, nil 64 } 65 66 func (mn *mocknet) AddPeer(k ic.PrivKey, a ma.Multiaddr) (host.Host, error) { 67 p, err := peer.IDFromPublicKey(k.GetPublic()) 68 if err != nil { 69 return nil, err 70 } 71 72 ps := peer.NewPeerstore() 73 ps.AddAddr(p, a, peer.PermanentAddrTTL) 74 ps.AddPrivKey(p, k) 75 ps.AddPubKey(p, k.GetPublic()) 76 77 return mn.AddPeerWithPeerstore(p, ps) 78 } 79 80 func (mn *mocknet) AddPeerWithPeerstore(p peer.ID, ps peer.Peerstore) (host.Host, error) { 81 n, err := newPeernet(mn.ctx, mn, p, ps) 82 if err != nil { 83 return nil, err 84 } 85 86 h := bhost.New(n) 87 88 mn.proc.AddChild(n.proc) 89 90 mn.Lock() 91 mn.nets[n.peer] = n 92 mn.hosts[n.peer] = h 93 mn.Unlock() 94 return h, nil 95 } 96 97 func (mn *mocknet) Peers() []peer.ID { 98 mn.RLock() 99 defer mn.RUnlock() 100 101 cp := make([]peer.ID, 0, len(mn.nets)) 102 for _, n := range mn.nets { 103 cp = append(cp, n.peer) 104 } 105 sort.Sort(peer.IDSlice(cp)) 106 return cp 107 } 108 109 func (mn *mocknet) Host(pid peer.ID) host.Host { 110 mn.RLock() 111 host := mn.hosts[pid] 112 mn.RUnlock() 113 return host 114 } 115 116 func (mn *mocknet) Net(pid peer.ID) inet.Network { 117 mn.RLock() 118 n := mn.nets[pid] 119 mn.RUnlock() 120 return n 121 } 122 123 func (mn *mocknet) Hosts() []host.Host { 124 mn.RLock() 125 defer mn.RUnlock() 126 127 cp := make([]host.Host, 0, len(mn.hosts)) 128 for _, h := range mn.hosts { 129 cp = append(cp, h) 130 } 131 132 sort.Sort(hostSlice(cp)) 133 return cp 134 } 135 136 func (mn *mocknet) Nets() []inet.Network { 137 mn.RLock() 138 defer mn.RUnlock() 139 140 cp := make([]inet.Network, 0, len(mn.nets)) 141 for _, n := range mn.nets { 142 cp = append(cp, n) 143 } 144 sort.Sort(netSlice(cp)) 145 return cp 146 } 147 148 // Links returns a copy of the internal link state map. 149 // (wow, much map. so data structure. how compose. ahhh pointer) 150 func (mn *mocknet) Links() LinkMap { 151 mn.RLock() 152 defer mn.RUnlock() 153 154 links := map[string]map[string]map[Link]struct{}{} 155 for p1, lm := range mn.links { 156 sp1 := string(p1) 157 links[sp1] = map[string]map[Link]struct{}{} 158 for p2, ls := range lm { 159 sp2 := string(p2) 160 links[sp1][sp2] = map[Link]struct{}{} 161 for l := range ls { 162 links[sp1][sp2][l] = struct{}{} 163 } 164 } 165 } 166 return links 167 } 168 169 func (mn *mocknet) LinkAll() error { 170 nets := mn.Nets() 171 for _, n1 := range nets { 172 for _, n2 := range nets { 173 if _, err := mn.LinkNets(n1, n2); err != nil { 174 return err 175 } 176 } 177 } 178 return nil 179 } 180 181 func (mn *mocknet) LinkPeers(p1, p2 peer.ID) (Link, error) { 182 mn.RLock() 183 n1 := mn.nets[p1] 184 n2 := mn.nets[p2] 185 mn.RUnlock() 186 187 if n1 == nil { 188 return nil, fmt.Errorf("network for p1 not in mocknet") 189 } 190 191 if n2 == nil { 192 return nil, fmt.Errorf("network for p2 not in mocknet") 193 } 194 195 return mn.LinkNets(n1, n2) 196 } 197 198 func (mn *mocknet) validate(n inet.Network) (*peernet, error) { 199 // WARNING: assumes locks acquired 200 201 nr, ok := n.(*peernet) 202 if !ok { 203 return nil, fmt.Errorf("Network not supported (use mock package nets only)") 204 } 205 206 if _, found := mn.nets[nr.peer]; !found { 207 return nil, fmt.Errorf("Network not on mocknet. is it from another mocknet?") 208 } 209 210 return nr, nil 211 } 212 213 func (mn *mocknet) LinkNets(n1, n2 inet.Network) (Link, error) { 214 mn.RLock() 215 n1r, err1 := mn.validate(n1) 216 n2r, err2 := mn.validate(n2) 217 ld := mn.linkDefaults 218 mn.RUnlock() 219 220 if err1 != nil { 221 return nil, err1 222 } 223 if err2 != nil { 224 return nil, err2 225 } 226 227 l := newLink(mn, ld) 228 l.nets = append(l.nets, n1r, n2r) 229 mn.addLink(l) 230 return l, nil 231 } 232 233 func (mn *mocknet) Unlink(l2 Link) error { 234 235 l, ok := l2.(*link) 236 if !ok { 237 return fmt.Errorf("only links from mocknet are supported") 238 } 239 240 mn.removeLink(l) 241 return nil 242 } 243 244 func (mn *mocknet) UnlinkPeers(p1, p2 peer.ID) error { 245 ls := mn.LinksBetweenPeers(p1, p2) 246 if ls == nil { 247 return fmt.Errorf("no link between p1 and p2") 248 } 249 250 for _, l := range ls { 251 if err := mn.Unlink(l); err != nil { 252 return err 253 } 254 } 255 return nil 256 } 257 258 func (mn *mocknet) UnlinkNets(n1, n2 inet.Network) error { 259 return mn.UnlinkPeers(n1.LocalPeer(), n2.LocalPeer()) 260 } 261 262 // get from the links map. and lazily contruct. 263 func (mn *mocknet) linksMapGet(p1, p2 peer.ID) *map[*link]struct{} { 264 265 l1, found := mn.links[p1] 266 if !found { 267 mn.links[p1] = map[peer.ID]map[*link]struct{}{} 268 l1 = mn.links[p1] // so we make sure it's there. 269 } 270 271 l2, found := l1[p2] 272 if !found { 273 m := map[*link]struct{}{} 274 l1[p2] = m 275 l2 = l1[p2] 276 } 277 278 return &l2 279 } 280 281 func (mn *mocknet) addLink(l *link) { 282 mn.Lock() 283 defer mn.Unlock() 284 285 n1, n2 := l.nets[0], l.nets[1] 286 (*mn.linksMapGet(n1.peer, n2.peer))[l] = struct{}{} 287 (*mn.linksMapGet(n2.peer, n1.peer))[l] = struct{}{} 288 } 289 290 func (mn *mocknet) removeLink(l *link) { 291 mn.Lock() 292 defer mn.Unlock() 293 294 n1, n2 := l.nets[0], l.nets[1] 295 delete(*mn.linksMapGet(n1.peer, n2.peer), l) 296 delete(*mn.linksMapGet(n2.peer, n1.peer), l) 297 } 298 299 func (mn *mocknet) ConnectAllButSelf() error { 300 nets := mn.Nets() 301 for _, n1 := range nets { 302 for _, n2 := range nets { 303 if n1 == n2 { 304 continue 305 } 306 307 if _, err := mn.ConnectNets(n1, n2); err != nil { 308 return err 309 } 310 } 311 } 312 return nil 313 } 314 315 func (mn *mocknet) ConnectPeers(a, b peer.ID) (inet.Conn, error) { 316 return mn.Net(a).DialPeer(mn.ctx, b) 317 } 318 319 func (mn *mocknet) ConnectNets(a, b inet.Network) (inet.Conn, error) { 320 return a.DialPeer(mn.ctx, b.LocalPeer()) 321 } 322 323 func (mn *mocknet) DisconnectPeers(p1, p2 peer.ID) error { 324 return mn.Net(p1).ClosePeer(p2) 325 } 326 327 func (mn *mocknet) DisconnectNets(n1, n2 inet.Network) error { 328 return n1.ClosePeer(n2.LocalPeer()) 329 } 330 331 func (mn *mocknet) LinksBetweenPeers(p1, p2 peer.ID) []Link { 332 mn.RLock() 333 defer mn.RUnlock() 334 335 ls2 := *mn.linksMapGet(p1, p2) 336 cp := make([]Link, 0, len(ls2)) 337 for l := range ls2 { 338 cp = append(cp, l) 339 } 340 return cp 341 } 342 343 func (mn *mocknet) LinksBetweenNets(n1, n2 inet.Network) []Link { 344 return mn.LinksBetweenPeers(n1.LocalPeer(), n2.LocalPeer()) 345 } 346 347 func (mn *mocknet) SetLinkDefaults(o LinkOptions) { 348 mn.Lock() 349 mn.linkDefaults = o 350 mn.Unlock() 351 } 352 353 func (mn *mocknet) LinkDefaults() LinkOptions { 354 mn.RLock() 355 defer mn.RUnlock() 356 return mn.linkDefaults 357 } 358 359 // netSlice for sorting by peer 360 type netSlice []inet.Network 361 362 func (es netSlice) Len() int { return len(es) } 363 func (es netSlice) Swap(i, j int) { es[i], es[j] = es[j], es[i] } 364 func (es netSlice) Less(i, j int) bool { return string(es[i].LocalPeer()) < string(es[j].LocalPeer()) } 365 366 // hostSlice for sorting by peer 367 type hostSlice []host.Host 368 369 func (es hostSlice) Len() int { return len(es) } 370 func (es hostSlice) Swap(i, j int) { es[i], es[j] = es[j], es[i] } 371 func (es hostSlice) Less(i, j int) bool { return string(es[i].ID()) < string(es[j].ID()) }