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

import (
4
	"crypto/tls"
Marten Seemann's avatar
Marten Seemann committed
5
6
	"net"

7
8
	ic "github.com/libp2p/go-libp2p-crypto"
	peer "github.com/libp2p/go-libp2p-peer"
Marten Seemann's avatar
Marten Seemann committed
9
	tpt "github.com/libp2p/go-libp2p-transport"
10
	quic "github.com/lucas-clemente/quic-go"
Marten Seemann's avatar
Marten Seemann committed
11
	ma "github.com/multiformats/go-multiaddr"
Marten Seemann's avatar
Marten Seemann committed
12
	manet "github.com/multiformats/go-multiaddr-net"
Marten Seemann's avatar
Marten Seemann committed
13
14
)

15
16
17
var quicListenAddr = quic.ListenAddr

// A listener listens for QUIC connections.
Marten Seemann's avatar
Marten Seemann committed
18
type listener struct {
19
	quicListener quic.Listener
20
21
22
23
24
	transport    tpt.Transport

	privKey        ic.PrivKey
	localPeer      peer.ID
	localMultiaddr ma.Multiaddr
Marten Seemann's avatar
Marten Seemann committed
25
26
}

27
28
var _ tpt.Listener = &listener{}

29
func newListener(addr ma.Multiaddr, transport tpt.Transport, localPeer peer.ID, key ic.PrivKey, tlsConf *tls.Config) (tpt.Listener, error) {
30
	lnet, host, err := manet.DialArgs(addr)
Marten Seemann's avatar
Marten Seemann committed
31
32
33
	if err != nil {
		return nil, err
	}
34
35
36
37
38
39
40
41
42
	laddr, err := net.ResolveUDPAddr(lnet, host)
	if err != nil {
		return nil, err
	}
	conn, err := net.ListenUDP(lnet, laddr)
	if err != nil {
		return nil, err
	}
	ln, err := quic.Listen(conn, tlsConf, quicConfig)
Marten Seemann's avatar
Marten Seemann committed
43
44
45
	if err != nil {
		return nil, err
	}
46
	localMultiaddr, err := toQuicMultiaddr(ln.Addr())
47
48
49
	if err != nil {
		return nil, err
	}
Marten Seemann's avatar
Marten Seemann committed
50
	return &listener{
51
52
53
54
55
		quicListener:   ln,
		transport:      transport,
		privKey:        key,
		localPeer:      localPeer,
		localMultiaddr: localMultiaddr,
Marten Seemann's avatar
Marten Seemann committed
56
57
	}, nil
}
Marten Seemann's avatar
Marten Seemann committed
58

59
// Accept accepts new connections.
Marten Seemann's avatar
Marten Seemann committed
60
func (l *listener) Accept() (tpt.Conn, error) {
61
62
63
64
65
66
67
68
69
70
71
	for {
		sess, err := l.quicListener.Accept()
		if err != nil {
			return nil, err
		}
		conn, err := l.setupConn(sess)
		if err != nil {
			sess.Close(err)
			continue
		}
		return conn, nil
Marten Seemann's avatar
Marten Seemann committed
72
	}
73
74
75
}

func (l *listener) setupConn(sess quic.Session) (tpt.Conn, error) {
76
	remotePubKey, err := getRemotePubKey(sess.ConnectionState().PeerCertificates)
77
78
79
80
81
82
83
	if err != nil {
		return nil, err
	}
	remotePeerID, err := peer.IDFromPublicKey(remotePubKey)
	if err != nil {
		return nil, err
	}
84
	remoteMultiaddr, err := toQuicMultiaddr(sess.RemoteAddr())
85
86
87
88
89
90
91
92
93
94
95
96
97
	if err != nil {
		return nil, err
	}
	return &conn{
		sess:            sess,
		transport:       l.transport,
		localPeer:       l.localPeer,
		localMultiaddr:  l.localMultiaddr,
		privKey:         l.privKey,
		remoteMultiaddr: remoteMultiaddr,
		remotePeerID:    remotePeerID,
		remotePubKey:    remotePubKey,
	}, nil
Marten Seemann's avatar
Marten Seemann committed
98
99
}

100
// Close closes the listener.
Marten Seemann's avatar
Marten Seemann committed
101
func (l *listener) Close() error {
Marten Seemann's avatar
Marten Seemann committed
102
	return l.quicListener.Close()
Marten Seemann's avatar
Marten Seemann committed
103
104
}

105
// Addr returns the address of this listener.
Marten Seemann's avatar
Marten Seemann committed
106
func (l *listener) Addr() net.Addr {
Marten Seemann's avatar
Marten Seemann committed
107
	return l.quicListener.Addr()
Marten Seemann's avatar
Marten Seemann committed
108
109
}

110
// Multiaddr returns the multiaddress of this listener.
Marten Seemann's avatar
Marten Seemann committed
111
func (l *listener) Multiaddr() ma.Multiaddr {
112
	return l.localMultiaddr
113
}