From 4ab9007abee8cf9547c4dd6f3ab1d5eec6ea446c Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 26 Nov 2023 16:08:21 +0000 Subject: [PATCH] Use `yggquic` --- cmd/yggmail/main.go | 2 +- go.mod | 7 +- go.sum | 8 ++ internal/smtpsender/sender.go | 2 +- internal/transport/transport.go | 4 +- internal/transport/yggdrasil.go | 168 +------------------------------- 6 files changed, 19 insertions(+), 172 deletions(-) diff --git a/cmd/yggmail/main.go b/cmd/yggmail/main.go index fac50ba..e9d1e94 100644 --- a/cmd/yggmail/main.go +++ b/cmd/yggmail/main.go @@ -207,7 +207,7 @@ func main() { overlayServer.MaxRecipients = 50 overlayServer.AuthDisabled = true - if err := overlayServer.Serve(transport.Listener()); err != nil { + if err := overlayServer.Serve(transport); err != nil { log.Fatal(err) } }() diff --git a/go.mod b/go.mod index 6d9ac41..7d383d8 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,8 @@ module github.com/neilalexander/yggmail -go 1.20 +go 1.21.0 require ( - github.com/Arceliar/ironwood v0.0.0-20231104025256-ec84c695fc44 github.com/emersion/go-imap v1.2.1 github.com/emersion/go-imap-idle v0.0.0-20210907174914-db2568431445 github.com/emersion/go-message v0.17.0 @@ -12,14 +11,15 @@ require ( github.com/fatih/color v1.15.0 github.com/gologme/log v1.3.0 github.com/mattn/go-sqlite3 v1.14.17 - github.com/quic-go/quic-go v0.40.0 github.com/yggdrasil-network/yggdrasil-go v0.5.2 + github.com/yggdrasil-network/yggquic v0.0.0-20231126155506-966e783e183d go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.14.0 golang.org/x/term v0.13.0 ) require ( + github.com/Arceliar/ironwood v0.0.0-20231104025256-ec84c695fc44 // indirect github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.6.0 // indirect @@ -31,6 +31,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/onsi/ginkgo/v2 v2.13.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect + github.com/quic-go/quic-go v0.40.0 // indirect github.com/stretchr/testify v1.7.0 // indirect go.uber.org/mock v0.3.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect diff --git a/go.sum b/go.sum index 984cb2f..1951ce7 100644 --- a/go.sum +++ b/go.sum @@ -33,12 +33,15 @@ github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1: github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/gologme/log v1.3.0 h1:l781G4dE+pbigClDSDzSaaYKtiueHCILUa/qSDsmHAo= github.com/gologme/log v1.3.0/go.mod h1:yKT+DvIPdDdDoPtqFrFxheooyVmoqi0BAsw+erN3wA4= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/hjson/hjson-go/v4 v4.3.1 h1:wfmDwHGxjzmYKXRFL0Qr9nonY/Xxe5y7IalwjlY7ekA= @@ -54,6 +57,7 @@ github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= @@ -69,6 +73,8 @@ github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/yggdrasil-network/yggdrasil-go v0.5.2 h1:OEt5xi5iQDhK4yGjp0Bq9B0uZyQz741WIlorE8oVW1c= github.com/yggdrasil-network/yggdrasil-go v0.5.2/go.mod h1:oATGHx91oFqq3h3RKFU9qADFcO27TCf3CbQqrG2wzvU= +github.com/yggdrasil-network/yggquic v0.0.0-20231126155506-966e783e183d h1:4sK8R6zUDo8jD7Rph5lMV3mhbIfAh60ihpfpB4kASJU= +github.com/yggdrasil-network/yggquic v0.0.0-20231126155506-966e783e183d/go.mod h1:gv+bkfk5XSTignK4PJNOKCiwbQX5QA+TCxxYYOVkEpw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -130,6 +136,8 @@ golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/smtpsender/sender.go b/internal/smtpsender/sender.go index bdf0e5b..ed960c5 100644 --- a/internal/smtpsender/sender.go +++ b/internal/smtpsender/sender.go @@ -123,7 +123,7 @@ func (q *Queue) run() { q.queues.Log.Println("Sending mail from", ref.From, "to", q.destination) if err := func() error { - conn, err := q.queues.Transport.Dial(q.destination) + conn, err := q.queues.Transport.Dial("yggdrasil", q.destination) if err != nil { return fmt.Errorf("q.queues.Transport.Dial: %w", err) } diff --git a/internal/transport/transport.go b/internal/transport/transport.go index 461903e..f193c2b 100644 --- a/internal/transport/transport.go +++ b/internal/transport/transport.go @@ -13,6 +13,6 @@ import ( ) type Transport interface { - Dial(host string) (net.Conn, error) - Listener() net.Listener + Dial(network, host string) (net.Conn, error) + net.Listener } diff --git a/internal/transport/yggdrasil.go b/internal/transport/yggdrasil.go index 7a50bca..3245943 100644 --- a/internal/transport/yggdrasil.go +++ b/internal/transport/yggdrasil.go @@ -9,48 +9,21 @@ package transport import ( - "context" "crypto/ed25519" - "crypto/tls" "encoding/hex" "fmt" "log" - "net" "regexp" - "sync" - "time" - iwt "github.com/Arceliar/ironwood/types" "github.com/fatih/color" gologme "github.com/gologme/log" - "github.com/quic-go/quic-go" "github.com/yggdrasil-network/yggdrasil-go/src/config" "github.com/yggdrasil-network/yggdrasil-go/src/core" "github.com/yggdrasil-network/yggdrasil-go/src/multicast" + "github.com/yggdrasil-network/yggquic" ) -type YggdrasilTransport struct { - listener *quic.Listener - yggdrasil net.PacketConn - transport *quic.Transport - tlsConfig *tls.Config - quicConfig *quic.Config - incoming chan *yggdrasilSession - sessions sync.Map // string -> quic.Connection - dials sync.Map // string -> *yggdrasilDial -} - -type yggdrasilSession struct { - quic.Connection - quic.Stream -} - -type yggdrasilDial struct { - context.Context - context.CancelFunc -} - -func NewYggdrasilTransport(log *log.Logger, sk ed25519.PrivateKey, pk ed25519.PublicKey, peers []string, mcast bool) (*YggdrasilTransport, error) { +func NewYggdrasilTransport(log *log.Logger, sk ed25519.PrivateKey, pk ed25519.PublicKey, peers []string, mcast bool) (*yggquic.YggdrasilTransport, error) { yellow := color.New(color.FgYellow).SprintfFunc() glog := gologme.New(log.Writer(), fmt.Sprintf("[ %s ] ", yellow("Yggdrasil")), gologme.LstdFlags|gologme.Lmsgprefix) glog.EnableLevel("warn") @@ -96,140 +69,5 @@ func NewYggdrasilTransport(log *log.Logger, sk ed25519.PrivateKey, pk ed25519.Pu } } - tr := &YggdrasilTransport{ - tlsConfig: &tls.Config{ - ServerName: hex.EncodeToString(ygg.PublicKey()), - Certificates: []tls.Certificate{ - *cfg.Certificate, - }, - InsecureSkipVerify: true, - }, - quicConfig: &quic.Config{ - HandshakeIdleTimeout: time.Second * 5, - MaxIdleTimeout: time.Second * 60, - }, - transport: &quic.Transport{ - Conn: ygg, - }, - yggdrasil: ygg, - incoming: make(chan *yggdrasilSession, 1), - } - - if tr.listener, err = tr.transport.Listen(tr.tlsConfig, tr.quicConfig); err != nil { - return nil, fmt.Errorf("quic.Listen: %w", err) - } - - go tr.connectionAcceptLoop() - return tr, nil -} - -func (t *YggdrasilTransport) connectionAcceptLoop() { - for { - qc, err := t.listener.Accept(context.TODO()) - if err != nil { - return - } - - host := qc.RemoteAddr().String() - if eqc, ok := t.sessions.LoadAndDelete(host); ok { - eqc := eqc.(quic.Connection) - _ = eqc.CloseWithError(0, "Connection replaced") - } - t.sessions.Store(host, qc) - if dial, ok := t.dials.LoadAndDelete(host); ok { - dial := dial.(*yggdrasilDial) - dial.CancelFunc() - } - - go t.streamAcceptLoop(qc) - } -} - -func (t *YggdrasilTransport) streamAcceptLoop(qc quic.Connection) { - host := qc.RemoteAddr().String() - - defer qc.CloseWithError(0, "Timed out") // nolint:errcheck - defer t.sessions.Delete(host) - - for { - qs, err := qc.AcceptStream(context.Background()) - if err != nil { - break - } - t.incoming <- &yggdrasilSession{qc, qs} - } -} - -func (t *YggdrasilTransport) Dial(host string) (net.Conn, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - var retry bool -retry: - qc, ok := t.sessions.Load(host) - if !ok { - if dial, ok := t.dials.Load(host); ok { - <-dial.(*yggdrasilDial).Done() - } - if qc, ok = t.sessions.Load(host); !ok { - dialctx, dialcancel := context.WithCancel(ctx) - defer dialcancel() - - t.dials.Store(host, &yggdrasilDial{dialctx, dialcancel}) - defer t.dials.Delete(host) - - addr := make(iwt.Addr, ed25519.PublicKeySize) - k, err := hex.DecodeString(host) - if err != nil { - return nil, err - } - copy(addr, k) - - if qc, err = t.transport.Dial(dialctx, addr, t.tlsConfig, t.quicConfig); err != nil { - return nil, err - } - - qc := qc.(quic.Connection) - t.sessions.Store(host, qc) - go t.streamAcceptLoop(qc) - } - } - if qc == nil { - return nil, net.ErrClosed - } else { - qc := qc.(quic.Connection) - qs, err := qc.OpenStreamSync(ctx) - if err != nil { - if !retry { - retry = true - goto retry - } - return nil, err - } - // For some reason this is needed to kick the stream - _, err = qs.Write([]byte(" ")) - return &yggdrasilSession{qc, qs}, err - } -} - -func (t *YggdrasilTransport) Listener() net.Listener { - return &yggdrasilListener{t} -} - -type yggdrasilListener struct { - *YggdrasilTransport -} - -func (t *yggdrasilListener) Accept() (net.Conn, error) { - return <-t.incoming, nil -} - -func (t *yggdrasilListener) Addr() net.Addr { - return t.listener.Addr() -} - -func (t *yggdrasilListener) Close() error { - if err := t.listener.Close(); err != nil { - return err - } - return t.yggdrasil.Close() + return yggquic.New(ygg, *cfg.Certificate) }