transport.go 1.73 KB
Newer Older
Marten Seemann's avatar
Marten Seemann committed
1
2
3
package libp2pquic

import (
4
	"fmt"
Marten Seemann's avatar
Marten Seemann committed
5
6
7
	"sync"

	pstore "github.com/libp2p/go-libp2p-peerstore"
Marten Seemann's avatar
Marten Seemann committed
8
9
	tpt "github.com/libp2p/go-libp2p-transport"
	ma "github.com/multiformats/go-multiaddr"
Marten Seemann's avatar
Marten Seemann committed
10
	"github.com/whyrusleeping/mafmt"
Marten Seemann's avatar
Marten Seemann committed
11
12
)

Marten Seemann's avatar
Marten Seemann committed
13
14
15
16
// QuicTransport implements a QUIC Transport
type QuicTransport struct {
	peers pstore.Peerstore

Marten Seemann's avatar
Marten Seemann committed
17
	lmutex    sync.Mutex
Marten Seemann's avatar
Marten Seemann committed
18
	listeners map[string]tpt.Listener
Marten Seemann's avatar
Marten Seemann committed
19
20
21

	dmutex  sync.Mutex
	dialers map[string]tpt.Dialer
Marten Seemann's avatar
Marten Seemann committed
22
}
Marten Seemann's avatar
Marten Seemann committed
23

Marten Seemann's avatar
Marten Seemann committed
24
25
26
// NewQuicTransport creates a new QUIC Transport
// it tracks dialers and listeners created
func NewQuicTransport(peers pstore.Peerstore) *QuicTransport {
Marten Seemann's avatar
Marten Seemann committed
27
	// utils.SetLogLevel(utils.LogLevelDebug)
Marten Seemann's avatar
Marten Seemann committed
28
29
30
	return &QuicTransport{
		peers:     peers,
		listeners: make(map[string]tpt.Listener),
Marten Seemann's avatar
Marten Seemann committed
31
		dialers:   make(map[string]tpt.Dialer),
Marten Seemann's avatar
Marten Seemann committed
32
	}
Marten Seemann's avatar
Marten Seemann committed
33
34
35
}

func (t *QuicTransport) Dialer(laddr ma.Multiaddr, opts ...tpt.DialOpt) (tpt.Dialer, error) {
Marten Seemann's avatar
Marten Seemann committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
	if !t.Matches(laddr) {
		return nil, fmt.Errorf("quic transport cannot dial %q", laddr)
	}

	t.dmutex.Lock()
	defer t.dmutex.Unlock()

	s := laddr.String()
	d, ok := t.dialers[s]
	if ok {
		return d, nil
	}

	// TODO: read opts
	quicd, err := newDialer(t)
	if err != nil {
		return nil, err
	}
	t.dialers[s] = quicd
	return quicd, nil
Marten Seemann's avatar
Marten Seemann committed
56
57
}

Marten Seemann's avatar
Marten Seemann committed
58
// Listen starts listening on laddr
Marten Seemann's avatar
Marten Seemann committed
59
func (t *QuicTransport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {
60
61
62
63
	if !t.Matches(laddr) {
		return nil, fmt.Errorf("quic transport cannot listen on %q", laddr)
	}

Marten Seemann's avatar
Marten Seemann committed
64
65
	t.lmutex.Lock()
	defer t.lmutex.Unlock()
Marten Seemann's avatar
Marten Seemann committed
66
67
68
69
70
71
72
73
74
75
76
77
78

	l, ok := t.listeners[laddr.String()]
	if ok {
		return l, nil
	}

	ln, err := newListener(laddr, t.peers, t)
	if err != nil {
		return nil, err
	}

	t.listeners[laddr.String()] = ln
	return ln, nil
Marten Seemann's avatar
Marten Seemann committed
79
80
}

Marten Seemann's avatar
Marten Seemann committed
81
82
func (t *QuicTransport) Matches(a ma.Multiaddr) bool {
	return mafmt.QUIC.Matches(a)
Marten Seemann's avatar
Marten Seemann committed
83
84
85
}

var _ tpt.Transport = &QuicTransport{}