1package mocknet
2
3import (
4	"sync"
5	"time"
6
7	"github.com/libp2p/go-libp2p-core/network"
8	"github.com/libp2p/go-libp2p-core/peer"
9
10	process "github.com/jbenet/goprocess"
11)
12
13// link implements mocknet.Link
14// and, for simplicity, network.Conn
15type link struct {
16	mock        *mocknet
17	nets        []*peernet
18	opts        LinkOptions
19	ratelimiter *RateLimiter
20	// this could have addresses on both sides.
21
22	sync.RWMutex
23}
24
25func newLink(mn *mocknet, opts LinkOptions) *link {
26	l := &link{mock: mn,
27		opts:        opts,
28		ratelimiter: NewRateLimiter(opts.Bandwidth)}
29	return l
30}
31
32func (l *link) newConnPair(dialer *peernet) (*conn, *conn) {
33	l.RLock()
34	defer l.RUnlock()
35
36	parent := process.WithTeardown(func() error { return nil })
37	target := l.nets[0]
38	if target == dialer {
39		target = l.nets[1]
40	}
41	dc := newConn(parent, dialer, target, l, network.DirOutbound)
42	tc := newConn(parent, target, dialer, l, network.DirInbound)
43	dc.rconn = tc
44	tc.rconn = dc
45	return dc, tc
46}
47
48func (l *link) Networks() []network.Network {
49	l.RLock()
50	defer l.RUnlock()
51
52	cp := make([]network.Network, len(l.nets))
53	for i, n := range l.nets {
54		cp[i] = n
55	}
56	return cp
57}
58
59func (l *link) Peers() []peer.ID {
60	l.RLock()
61	defer l.RUnlock()
62
63	cp := make([]peer.ID, len(l.nets))
64	for i, n := range l.nets {
65		cp[i] = n.peer
66	}
67	return cp
68}
69
70func (l *link) SetOptions(o LinkOptions) {
71	l.Lock()
72	defer l.Unlock()
73	l.opts = o
74	l.ratelimiter.UpdateBandwidth(l.opts.Bandwidth)
75}
76
77func (l *link) Options() LinkOptions {
78	l.RLock()
79	defer l.RUnlock()
80	return l.opts
81}
82
83func (l *link) GetLatency() time.Duration {
84	l.RLock()
85	defer l.RUnlock()
86	return l.opts.Latency
87}
88
89func (l *link) RateLimit(dataSize int) time.Duration {
90	return l.ratelimiter.Limit(dataSize)
91}
92