listener.go 2.4 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 := toQuicMultiaddr(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
// Accept accepts new connections.
Marten Seemann's avatar
Marten Seemann committed
52
func (l *listener) Accept() (tpt.Conn, error) {
53
54
55
56
57
58
59
	for {
		sess, err := l.quicListener.Accept()
		if err != nil {
			return nil, err
		}
		conn, err := l.setupConn(sess)
		if err != nil {
Marten Seemann's avatar
Marten Seemann committed
60
			sess.CloseWithError(0, err)
61
62
63
			continue
		}
		return conn, nil
Marten Seemann's avatar
Marten Seemann committed
64
	}
65
66
67
}

func (l *listener) setupConn(sess quic.Session) (tpt.Conn, error) {
68
	remotePubKey, err := getRemotePubKey(sess.ConnectionState().PeerCertificates)
69
70
71
72
73
74
75
	if err != nil {
		return nil, err
	}
	remotePeerID, err := peer.IDFromPublicKey(remotePubKey)
	if err != nil {
		return nil, err
	}
76
	remoteMultiaddr, err := toQuicMultiaddr(sess.RemoteAddr())
77
78
79
80
81
82
83
84
85
86
87
88
89
	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
90
91
}

92
// Close closes the listener.
Marten Seemann's avatar
Marten Seemann committed
93
func (l *listener) Close() error {
Marten Seemann's avatar
Marten Seemann committed
94
	return l.quicListener.Close()
Marten Seemann's avatar
Marten Seemann committed
95
96
}

97
// Addr returns the address of this listener.
Marten Seemann's avatar
Marten Seemann committed
98
func (l *listener) Addr() net.Addr {
Marten Seemann's avatar
Marten Seemann committed
99
	return l.quicListener.Addr()
Marten Seemann's avatar
Marten Seemann committed
100
101
}

102
// Multiaddr returns the multiaddress of this listener.
Marten Seemann's avatar
Marten Seemann committed
103
func (l *listener) Multiaddr() ma.Multiaddr {
104
	return l.localMultiaddr
105
}