Skip to content

Commit 84fbb75

Browse files
committed
2026-05-28 16:37:01
1 parent cf1b795 commit 84fbb75

1 file changed

Lines changed: 17 additions & 51 deletions

File tree

protocol/etch/engine.go

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"math"
1414
"math/big"
1515
"net"
16-
"sync"
1716
"time"
1817

1918
"github.com/libraries/daze"
@@ -107,7 +106,7 @@ func (s *Stream) Write(p []byte) (int, error) {
107106
// Server implemented the ashe-over-quic protocol.
108107
type Server struct {
109108
Cipher []byte
110-
Ep *quic.Endpoint
109+
EpQuic *quic.Endpoint
111110
Limits *rate.Limits
112111
Listen string
113112
}
@@ -120,25 +119,25 @@ func (s *Server) Serve(ctx *daze.Context, cli io.ReadWriteCloser) error {
120119

121120
// Close listener. Established connections will not be closed.
122121
func (s *Server) Close() error {
123-
if s.Ep != nil {
124-
return s.Ep.Close(context.Background())
122+
if s.EpQuic != nil {
123+
return s.EpQuic.Close(context.Background())
125124
}
126125
return nil
127126
}
128127

129128
// Run it.
130129
func (s *Server) Run() error {
131-
ep, err := quic.Listen("udp", s.Listen, ServerConfig.Do())
130+
l, err := quic.Listen("udp", s.Listen, ServerConfig.Do())
132131
if err != nil {
133132
return err
134133
}
135-
s.Ep = ep
134+
s.EpQuic = l
136135
log.Println("main: listen and serve on", s.Listen)
137136

138137
go func() {
139138
idx := uint32(math.MaxUint32)
140139
for {
141-
con, err := ep.Accept(context.Background())
140+
con, err := l.Accept(context.Background())
142141
if err != nil {
143142
if !errors.Is(err, context.Canceled) && !errors.Is(err, net.ErrClosed) {
144143
log.Println("main:", err)
@@ -147,16 +146,16 @@ func (s *Server) Run() error {
147146
}
148147
go func(con *quic.Conn) {
149148
defer con.Close()
150-
peer := net.UDPAddrFromAddrPort(con.RemoteAddr())
149+
rem := net.UDPAddrFromAddrPort(con.RemoteAddr())
151150
for {
152151
stm, err := con.AcceptStream(context.Background())
153152
if err != nil {
154153
return
155154
}
156155
idx++
157156
ctx := &daze.Context{Cid: idx}
158-
cli := &Stream{rem: peer, stm: stm}
159-
log.Printf("conn: %08x accept remote=%s", ctx.Cid, peer)
157+
cli := &Stream{rem: rem, stm: stm}
158+
log.Printf("conn: %08x accept remote=%s", ctx.Cid, rem)
160159
rtc := &daze.ReadWriteCloser{
161160
Reader: io.TeeReader(cli, rate.NewLimitsWriter(s.Limits)),
162161
Writer: io.MultiWriter(cli, rate.NewLimitsWriter(s.Limits)),
@@ -189,56 +188,27 @@ func NewServer(listen string, cipher string) *Server {
189188
// Client implemented the ashe-over-quic protocol.
190189
type Client struct {
191190
Cipher []byte
191+
EpQuic *quic.Endpoint
192192
Server string
193-
194-
mu sync.Mutex
195-
ep *quic.Endpoint
196-
}
197-
198-
// endpoint lazily creates the shared quic endpoint that originates outbound connections. A single endpoint can
199-
// originate many connections, so reusing it avoids burning a new udp socket for every Dial.
200-
func (c *Client) endpoint() (*quic.Endpoint, error) {
201-
c.mu.Lock()
202-
defer c.mu.Unlock()
203-
if c.ep != nil {
204-
return c.ep, nil
205-
}
206-
// The client endpoint also needs a tls config that satisfies the "certificate or GetCertificate" requirement of
207-
// quic.Listen even though the endpoint never accepts inbound connections.
208-
ep, err := quic.Listen("udp", ":0", ClientConfig.Do())
209-
if err != nil {
210-
return nil, err
211-
}
212-
c.ep = ep
213-
return ep, nil
214193
}
215194

216-
// Estab dials the etch server and establishes an ashe channel over it. It is the caller's responsibility to close the
217-
// returned conn.
218-
func (c *Client) Estab(ctx *daze.Context, network string, address string) (io.ReadWriteCloser, error) {
219-
ep, err := c.endpoint()
220-
if err != nil {
221-
return nil, err
222-
}
223-
dialCtx, cancel := context.WithTimeout(context.Background(), daze.Conf.DialerTimeout)
224-
defer cancel()
225-
con, err := ep.Dial(dialCtx, "udp", c.Server, ClientConfig.Do())
195+
// Dial connects to the address on the named network.
196+
func (c *Client) Dial(ctx *daze.Context, network string, address string) (io.ReadWriteCloser, error) {
197+
con, err := c.EpQuic.Dial(context.Background(), "udp", c.Server, ClientConfig.Do())
226198
if err != nil {
227199
return nil, err
228200
}
229-
stm, err := con.NewStream(dialCtx)
201+
stm, err := con.NewStream(context.Background())
230202
if err != nil {
231203
con.Close()
232204
return nil, err
233205
}
234-
// NewStream is lazy: the peer does not see the stream until the first byte is written. Force a flush so the
235-
// server's AcceptStream returns promptly even if the ashe client decides to read before writing.
236206
if err := stm.Flush(); err != nil {
237207
con.Close()
238208
return nil, err
239209
}
240-
addr := net.UDPAddrFromAddrPort(con.RemoteAddr())
241-
srv := &Stream{con: con, rem: addr, stm: stm}
210+
rem := net.UDPAddrFromAddrPort(con.RemoteAddr())
211+
srv := &Stream{con: con, rem: rem, stm: stm}
242212
spy := &ashe.Client{Cipher: c.Cipher}
243213
out, err := spy.Estab(ctx, srv, network, address)
244214
if err != nil {
@@ -248,15 +218,11 @@ func (c *Client) Estab(ctx *daze.Context, network string, address string) (io.Re
248218
return out, nil
249219
}
250220

251-
// Dial connects to the address on the named network.
252-
func (c *Client) Dial(ctx *daze.Context, network string, address string) (io.ReadWriteCloser, error) {
253-
return c.Estab(ctx, network, address)
254-
}
255-
256221
// NewClient returns a new Client. Cipher is a password in string form, with no length limit.
257222
func NewClient(server string, cipher string) *Client {
258223
return &Client{
259224
Cipher: daze.Salt(cipher),
225+
EpQuic: doa.Try(quic.Listen("udp", ":0", ClientConfig.Do())),
260226
Server: server,
261227
}
262228
}

0 commit comments

Comments
 (0)