github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/core/link_quic.go (about) 1 package core 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "net" 8 "net/url" 9 "time" 10 11 "github.com/Arceliar/phony" 12 "github.com/quic-go/quic-go" 13 ) 14 15 type linkQUIC struct { 16 phony.Inbox 17 *links 18 tlsconfig *tls.Config 19 quicconfig *quic.Config 20 } 21 22 type linkQUICStream struct { 23 quic.Connection 24 quic.Stream 25 } 26 27 type linkQUICListener struct { 28 *quic.Listener 29 ch <-chan *linkQUICStream 30 } 31 32 func (l *linkQUICListener) Accept() (net.Conn, error) { 33 qs := <-l.ch 34 if qs == nil { 35 return nil, context.Canceled 36 } 37 return qs, nil 38 } 39 40 func (l *links) newLinkQUIC() *linkQUIC { 41 lt := &linkQUIC{ 42 links: l, 43 tlsconfig: l.core.config.tls.Clone(), 44 quicconfig: &quic.Config{ 45 MaxIdleTimeout: time.Minute, 46 KeepAlivePeriod: time.Second * 20, 47 TokenStore: quic.NewLRUTokenStore(255, 255), 48 }, 49 } 50 return lt 51 } 52 53 func (l *linkQUIC) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) { 54 qc, err := quic.DialAddr(ctx, url.Host, l.tlsconfig, l.quicconfig) 55 if err != nil { 56 return nil, err 57 } 58 qs, err := qc.OpenStreamSync(ctx) 59 if err != nil { 60 return nil, err 61 } 62 return &linkQUICStream{ 63 Connection: qc, 64 Stream: qs, 65 }, nil 66 } 67 68 func (l *linkQUIC) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) { 69 ql, err := quic.ListenAddr(url.Host, l.tlsconfig, l.quicconfig) 70 if err != nil { 71 return nil, err 72 } 73 ch := make(chan *linkQUICStream) 74 lql := &linkQUICListener{ 75 Listener: ql, 76 ch: ch, 77 } 78 go func() { 79 for { 80 qc, err := ql.Accept(ctx) 81 switch err { 82 case context.Canceled, context.DeadlineExceeded: 83 ql.Close() 84 fallthrough 85 case quic.ErrServerClosed: 86 return 87 case nil: 88 qs, err := qc.AcceptStream(ctx) 89 if err != nil { 90 _ = qc.CloseWithError(1, fmt.Sprintf("stream error: %s", err)) 91 continue 92 } 93 ch <- &linkQUICStream{ 94 Connection: qc, 95 Stream: qs, 96 } 97 } 98 } 99 }() 100 return lql, nil 101 }