Revert all yggquic changes

This reverts commit 4ab9007abe.
This commit is contained in:
Neil Alexander
2023-12-10 11:00:27 +00:00
parent 9c0f9f68bb
commit 767f9b8c5d
8 changed files with 182 additions and 23 deletions

View File

@@ -32,4 +32,4 @@ jobs:
platforms: ${{ env.PLATFORMS }}
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/yggmail:${{ github.ref_name == 'main' && 'latest' || github.ref_name }}
ghcr.io/${{ github.repository_owner }}/yggmail:${{ github.ref_name }}

View File

@@ -1,4 +1,4 @@
FROM docker.io/golang:alpine3.18 as builder
FROM docker.io/golang:alpine as builder
COPY . /src
WORKDIR /src
@@ -6,7 +6,7 @@ WORKDIR /src
RUN apk add --no-cache --update go gcc g++
RUN go build -o /src/yggmail ./cmd/yggmail
FROM docker.io/alpine:3.18
FROM docker.io/alpine
LABEL org.opencontainers.image.source=https://github.com/neilalexander/yggmail
LABEL org.opencontainers.image.description=Yggmail

View File

@@ -207,7 +207,7 @@ func main() {
overlayServer.MaxRecipients = 50
overlayServer.AuthDisabled = true
if err := overlayServer.Serve(transport); err != nil {
if err := overlayServer.Serve(transport.Listener()); err != nil {
log.Fatal(err)
}
}()

9
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/neilalexander/yggmail
go 1.20
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
@@ -10,16 +11,15 @@ require (
github.com/emersion/go-smtp v0.15.0
github.com/fatih/color v1.15.0
github.com/gologme/log v1.3.0
github.com/mattn/go-sqlite3 v1.14.18
github.com/yggdrasil-network/yggdrasil-go v0.5.4
github.com/yggdrasil-network/yggquic v0.0.0-20231209220136-b412fc6f0d7e
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
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-20231127131626-465b82dfb5bd // 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,7 +31,6 @@ 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

14
go.sum
View File

@@ -1,5 +1,5 @@
github.com/Arceliar/ironwood v0.0.0-20231127131626-465b82dfb5bd h1:458tnmZ4zM2gbLtefdYbaxyAJevDNEWu6tLKEqbK4wg=
github.com/Arceliar/ironwood v0.0.0-20231127131626-465b82dfb5bd/go.mod h1:5x7fWW0mshe9WQ1lvSMmmHBYC3BeHH9gpwW5tz7cbfw=
github.com/Arceliar/ironwood v0.0.0-20231104025256-ec84c695fc44 h1:u328GAZGtL0W4oFWQs4YWHZT215LL6Lw9aYJxx76UVs=
github.com/Arceliar/ironwood v0.0.0-20231104025256-ec84c695fc44/go.mod h1:5x7fWW0mshe9WQ1lvSMmmHBYC3BeHH9gpwW5tz7cbfw=
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d h1:UK9fsWbWqwIQkMCz1CP+v5pGbsGoWAw6g4AyvMpm1EM=
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q=
github.com/bits-and-blooms/bitset v1.3.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
@@ -49,8 +49,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
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=
@@ -67,10 +67,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.4 h1:A7ZFmxkkbZhtqJgQXBVDw5sHsi25aUawLlJCCHnNsAs=
github.com/yggdrasil-network/yggdrasil-go v0.5.4/go.mod h1:TLmU4X0nfzCY9t5xABtFQ6GLoOtCae8xVatC9JwjD5I=
github.com/yggdrasil-network/yggquic v0.0.0-20231209220136-b412fc6f0d7e h1:Ncp4P0jFiIJ+6o06a4PABcvWeJDdbUQSjMVaJVSOu2I=
github.com/yggdrasil-network/yggquic v0.0.0-20231209220136-b412fc6f0d7e/go.mod h1:XFL2wkUXrqdl4AYiJghA+wW9xAm4ISvUtNrHdWPXjsE=
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/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=

View File

@@ -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("yggdrasil", q.destination)
conn, err := q.queues.Transport.Dial(q.destination)
if err != nil {
return fmt.Errorf("q.queues.Transport.Dial: %w", err)
}

View File

@@ -13,6 +13,6 @@ import (
)
type Transport interface {
Dial(network, host string) (net.Conn, error)
net.Listener
Dial(host string) (net.Conn, error)
Listener() net.Listener
}

View File

@@ -9,21 +9,48 @@
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"
)
func NewYggdrasilTransport(log *log.Logger, sk ed25519.PrivateKey, pk ed25519.PublicKey, peers []string, mcast bool) (*yggquic.YggdrasilTransport, error) {
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) {
yellow := color.New(color.FgYellow).SprintfFunc()
glog := gologme.New(log.Writer(), fmt.Sprintf("[ %s ] ", yellow("Yggdrasil")), gologme.LstdFlags|gologme.Lmsgprefix)
glog.EnableLevel("warn")
@@ -69,5 +96,140 @@ func NewYggdrasilTransport(log *log.Logger, sk ed25519.PrivateKey, pk ed25519.Pu
}
}
return yggquic.New(ygg, *cfg.Certificate, nil)
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()
}