listener.go 2.3 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
	transport    tpt.Transport

	acceptQueue chan tpt.Conn
Marten Seemann's avatar
Marten Seemann committed
23

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

29
30
var _ tpt.Listener = &listener{}

31
func newListener(addr ma.Multiaddr, transport tpt.Transport, localPeer peer.ID, key ic.PrivKey, tlsConf *tls.Config) (tpt.Listener, error) {
32
	_, host, err := manet.DialArgs(addr)
Marten Seemann's avatar
Marten Seemann committed
33
34
35
	if err != nil {
		return nil, err
	}
36
	ln, err := quicListenAddr(host, tlsConf, quicConfig)
Marten Seemann's avatar
Marten Seemann committed
37
38
39
	if err != nil {
		return nil, err
	}
40
	localMultiaddr, err := quicMultiaddr(ln.Addr())
41
42
43
	if err != nil {
		return nil, err
	}
Marten Seemann's avatar
Marten Seemann committed
44
	return &listener{
45
46
47
48
49
		quicListener:   ln,
		transport:      transport,
		privKey:        key,
		localPeer:      localPeer,
		localMultiaddr: localMultiaddr,
Marten Seemann's avatar
Marten Seemann committed
50
51
	}, nil
}
Marten Seemann's avatar
Marten Seemann committed
52

53
54
// Accept accepts new connections.
// TODO(#2): don't accept a connection if the client's peer verification fails
Marten Seemann's avatar
Marten Seemann committed
55
func (l *listener) Accept() (tpt.Conn, error) {
56
	sess, err := l.quicListener.Accept()
Marten Seemann's avatar
Marten Seemann committed
57
58
59
	if err != nil {
		return nil, err
	}
60
	remotePubKey, err := getRemotePubKey(sess.ConnectionState().PeerCertificates)
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	if err != nil {
		return nil, err
	}
	remotePeerID, err := peer.IDFromPublicKey(remotePubKey)
	if err != nil {
		return nil, err
	}
	remoteMultiaddr, err := quicMultiaddr(sess.RemoteAddr())
	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
82
83
}

84
// Close closes the listener.
Marten Seemann's avatar
Marten Seemann committed
85
func (l *listener) Close() error {
Marten Seemann's avatar
Marten Seemann committed
86
	return l.quicListener.Close()
Marten Seemann's avatar
Marten Seemann committed
87
88
}

89
// Addr returns the address of this listener.
Marten Seemann's avatar
Marten Seemann committed
90
func (l *listener) Addr() net.Addr {
Marten Seemann's avatar
Marten Seemann committed
91
	return l.quicListener.Addr()
Marten Seemann's avatar
Marten Seemann committed
92
93
}

94
// Multiaddr returns the multiaddress of this listener.
Marten Seemann's avatar
Marten Seemann committed
95
func (l *listener) Multiaddr() ma.Multiaddr {
96
	return l.localMultiaddr
97
}