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

import (
	"net"

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

14
15
16
var quicListenAddr = quic.ListenAddr

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

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

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

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

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

56
57
// 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
58
func (l *listener) Accept() (tpt.Conn, error) {
59
	sess, err := l.quicListener.Accept()
Marten Seemann's avatar
Marten Seemann committed
60
61
62
	if err != nil {
		return nil, err
	}
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	remotePubKey, err := getRemotePubKey(sess)
	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
85
86
}

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

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

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