Skip to content
File

Blob: overlay/quic.go

go71 lines
1package overlay
2 
3import (
4 "net"
5 "time"
6 
7 "go.miragespace.co/specter/spec/protocol"
8 "go.miragespace.co/specter/spec/transport"
9 "go.miragespace.co/specter/timing"
10 
11 "github.com/quic-go/quic-go"
12)
13 
14var (
15 quicConfig = &quic.Config{
16 KeepAlivePeriod: time.Second * 5,
17 HandshakeIdleTimeout: timing.TLSHandshakeTimeout,
18 MaxIdleTimeout: time.Second * 30,
19 MaxIncomingStreams: 500,
20 EnableDatagrams: true,
21 }
22)
23 
24type quicConn struct {
25 *quic.Stream
26 q *quic.Conn
27}
28 
29var _ net.Conn = (*quicConn)(nil)
30 
31func (q *quicConn) LocalAddr() net.Addr {
32 return q.q.LocalAddr()
33}
34 
35func (q *quicConn) RemoteAddr() net.Addr {
36 return q.q.RemoteAddr()
37}
38 
39func (q *quicConn) Close() error {
40 go func() {
41 time.Sleep(time.Second)
42 q.Stream.CancelWrite(409)
43 }()
44 q.Stream.CancelRead(409)
45 return q.Stream.Close()
46}
47 
48func WrapQuicConnection(s *quic.Stream, q *quic.Conn) net.Conn {
49 return &quicConn{
50 Stream: s,
51 q: q,
52 }
53}
54 
55// attachment identifies the QUIC connection itself, not its reusable cache key.
56type attachment struct {
57 q *quic.Conn
58}
59 
60func (a attachment) Done() <-chan struct{} { return a.q.Context().Done() }
61 
62func (a attachment) Err() error { return a.q.Context().Err() }
63 
64func (a attachment) Close(reason string) error { return a.q.CloseWithError(410, reason) }
65 
66func (a attachment) OpenStream(kind protocol.Stream_Type) (net.Conn, error) {
67 return openStream(a.q, &protocol.Stream{Type: kind})
68}
69 
70func (c *quicConn) PhysicalConn() transport.PhysicalConn { return attachment{c.q} }