transport.go 1.61 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
	"sync"

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

Marten Seemann's avatar
Marten Seemann committed
12
13
// QuicTransport implements a QUIC Transport
type QuicTransport struct {
Marten Seemann's avatar
Marten Seemann committed
14
	lmutex    sync.Mutex
Marten Seemann's avatar
Marten Seemann committed
15
	listeners map[string]tpt.Listener
Marten Seemann's avatar
Marten Seemann committed
16
17
18

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

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

func (t *QuicTransport) Dialer(laddr ma.Multiaddr, opts ...tpt.DialOpt) (tpt.Dialer, error) {
Marten Seemann's avatar
Marten Seemann committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	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
52
53
}

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

Marten Seemann's avatar
Marten Seemann committed
60
61
	t.lmutex.Lock()
	defer t.lmutex.Unlock()
Marten Seemann's avatar
Marten Seemann committed
62
63
64
65
66
67

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

68
	ln, err := newListener(laddr, t)
Marten Seemann's avatar
Marten Seemann committed
69
70
71
72
73
74
	if err != nil {
		return nil, err
	}

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

Marten Seemann's avatar
Marten Seemann committed
77
78
func (t *QuicTransport) Matches(a ma.Multiaddr) bool {
	return mafmt.QUIC.Matches(a)
Marten Seemann's avatar
Marten Seemann committed
79
80
81
}

var _ tpt.Transport = &QuicTransport{}