QUIC interface support

This commit is contained in:
Neil Alexander 2023-05-21 11:29:05 +01:00
parent 002b984c04
commit d8dc6b2670
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
5 changed files with 160 additions and 0 deletions

View file

@ -35,6 +35,7 @@ type links struct {
tls *linkTLS // TLS interface support
unix *linkUNIX // UNIX interface support
socks *linkSOCKS // SOCKS interface support
quic *linkQUIC // QUIC interface support
// _links can only be modified safely from within the links actor
_links map[linkInfo]*link // *link is nil if connection in progress
}
@ -90,6 +91,7 @@ func (l *links) init(c *Core) error {
l.tls = l.newLinkTLS(l.tcp)
l.unix = l.newLinkUNIX()
l.socks = l.newLinkSOCKS()
l.quic = l.newLinkQUIC()
l._links = make(map[linkInfo]*link)
var listeners []ListenAddress
@ -329,6 +331,8 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
protocol = l.tls
case "unix":
protocol = l.unix
case "quic":
protocol = l.quic
default:
cancel()
return nil, ErrLinkUnrecognisedSchema
@ -465,6 +469,8 @@ func (l *links) connect(u *url.URL, info linkInfo, options linkOptions) (net.Con
dialer = l.socks
case "unix":
dialer = l.unix
case "quic":
dialer = l.quic
default:
return nil, ErrLinkUnrecognisedSchema
}

96
src/core/link_quic.go Normal file
View file

@ -0,0 +1,96 @@
package core
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/url"
"github.com/Arceliar/phony"
"github.com/quic-go/quic-go"
)
type linkQUIC struct {
phony.Inbox
*links
tlsconfig *tls.Config
quicconfig *quic.Config
}
type linkQUICStream struct {
quic.Connection
quic.Stream
}
type linkQUICListener struct {
quic.EarlyListener
ch <-chan *linkQUICStream
}
func (l *linkQUICListener) Accept() (net.Conn, error) {
qs := <-l.ch
if qs == nil {
return nil, context.Canceled
}
return qs, nil
}
func (l *links) newLinkQUIC() *linkQUIC {
lt := &linkQUIC{
links: l,
tlsconfig: l.core.config.tls.Clone(),
quicconfig: &quic.Config{
KeepAlivePeriod: 0,
},
}
return lt
}
func (l *linkQUIC) dial(url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
qc, err := quic.DialAddrEarly(url.Host, l.tlsconfig, l.quicconfig)
if err != nil {
fmt.Println("Dial error:", err)
return nil, err
}
qs, err := qc.OpenStream()
if err != nil {
fmt.Println("Stream error:", err)
return nil, err
}
return &linkQUICStream{
Connection: qc,
Stream: qs,
}, nil
}
func (l *linkQUIC) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
ql, err := quic.ListenAddrEarly(url.Host, l.tlsconfig, l.quicconfig)
if err != nil {
return nil, err
}
ch := make(chan *linkQUICStream)
lql := &linkQUICListener{
EarlyListener: ql,
ch: ch,
}
go func() {
for {
qc, err := ql.Accept(ctx)
if err != nil {
ql.Close()
return
}
qs, err := qc.AcceptStream(ctx)
if err != nil {
ql.Close()
return
}
ch <- &linkQUICStream{
Connection: qc,
Stream: qs,
}
}
}()
return lql, nil
}

View file

@ -17,6 +17,7 @@ func (c *Core) generateTLSConfig(cert *tls.Certificate) (*tls.Config, error) {
VerifyConnection: c.verifyTLSConnection,
InsecureSkipVerify: true,
MinVersion: tls.VersionTLS13,
NextProtos: []string{"yggdrasil/0.5"},
}
return config, nil
}