listener.go 2.28 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
	_, host, err := manet.DialArgs(addr)
Marten Seemann's avatar
Marten Seemann committed
31
32
33
	if err != nil {
		return nil, err
	}
34
	ln, err := quicListenAddr(host, tlsConf, quicConfig)
Marten Seemann's avatar
Marten Seemann committed
35
36
37
	if err != nil {
		return nil, err
	}
38
	localMultiaddr, err := quicMultiaddr(ln.Addr())
39
40
41
	if err != nil {
		return nil, err
	}
Marten Seemann's avatar
Marten Seemann committed
42
	return &listener{
43
44
45
46
47
		quicListener:   ln,
		transport:      transport,
		privKey:        key,
		localPeer:      localPeer,
		localMultiaddr: localMultiaddr,
Marten Seemann's avatar
Marten Seemann committed
48
49
	}, nil
}
Marten Seemann's avatar
Marten Seemann committed
50

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

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

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

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