Skip to content

Commit 473a8b4

Browse files
committed
☎️ conn: improve dialer API
- Add TFO method to expose actual TFO state. - Add DialUDPMmsgConn. - Return SocketInfo like the listen methods do.
1 parent 31c6eb5 commit 473a8b4

File tree

4 files changed

+50
-19
lines changed

4 files changed

+50
-19
lines changed

conn/conn.go

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -250,25 +250,38 @@ var (
250250
DefaultUDPClientListenConfig = DefaultUDPClientSocketOptions.ListenConfig()
251251
)
252252

253-
// Dialer is [tfo.Dialer] but provides a subjectively nicer API.
254-
type Dialer tfo.Dialer
253+
// Dialer wraps a [tfo.Dialer] and provides a subjectively nicer API.
254+
type Dialer struct {
255+
td tfo.Dialer
256+
fns setFuncSlice
257+
}
258+
259+
// TFO returns true if the next DialTCP call will attempt to enable TFO.
260+
func (d *Dialer) TFO() bool {
261+
return d.td.TFO()
262+
}
255263

256264
// DialTCP wraps [tfo.Dialer.DialContext] and returns a [*net.TCPConn] directly.
257-
func (d *Dialer) DialTCP(ctx context.Context, network, address string, b []byte) (*net.TCPConn, error) {
258-
c, err := (*tfo.Dialer)(d).DialContext(ctx, network, address, b)
265+
func (d *Dialer) DialTCP(ctx context.Context, network, address string, b []byte) (tc *net.TCPConn, info SocketInfo, err error) {
266+
td := d.td
267+
td.ControlContext = d.fns.controlContextFunc(&info)
268+
c, err := td.DialContext(ctx, network, address, b)
259269
if err != nil {
260-
return nil, err
270+
return nil, info, err
261271
}
262-
return c.(*net.TCPConn), nil
272+
return c.(*net.TCPConn), info, nil
263273
}
264274

265275
// DialUDP wraps [net.Dialer.DialContext] and returns a [*net.UDPConn] directly.
266-
func (d *Dialer) DialUDP(ctx context.Context, network, address string) (*net.UDPConn, error) {
267-
c, err := d.Dialer.DialContext(ctx, network, address)
276+
func (d *Dialer) DialUDP(ctx context.Context, network, address string) (uc *net.UDPConn, info SocketInfo, err error) {
277+
info.MaxUDPGSOSegments = 1
278+
nd := d.td.Dialer
279+
nd.ControlContext = d.fns.controlContextFunc(&info)
280+
c, err := nd.DialContext(ctx, network, address)
268281
if err != nil {
269-
return nil, err
282+
return nil, info, err
270283
}
271-
return c.(*net.UDPConn), nil
284+
return c.(*net.UDPConn), info, nil
272285
}
273286

274287
// DialerSocketOptions contains dialer-specific socket options.
@@ -311,13 +324,13 @@ type DialerSocketOptions struct {
311324
// Dialer returns a [Dialer] with a control function that sets the socket options.
312325
func (dso DialerSocketOptions) Dialer() Dialer {
313326
d := Dialer{
314-
Dialer: net.Dialer{
315-
ControlContext: dso.buildSetFns().controlContextFunc(nil),
327+
td: tfo.Dialer{
328+
DisableTFO: !dso.TCPFastOpen,
329+
Fallback: dso.TCPFastOpenFallback,
316330
},
317-
DisableTFO: !dso.TCPFastOpen,
318-
Fallback: dso.TCPFastOpenFallback,
331+
fns: dso.buildSetFns(),
319332
}
320-
d.SetMultipathTCP(dso.MultipathTCP)
333+
d.td.SetMultipathTCP(dso.MultipathTCP)
321334
return d
322335
}
323336

conn/conn_mmsg.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,17 @@ func (lc *ListenConfig) ListenUDPMmsgConn(ctx context.Context, network, address
2020
c, err = NewMmsgConn(pc.(*net.UDPConn))
2121
return c, info, err
2222
}
23+
24+
// DialUDPMmsgConn is like [DialUDP] but wraps the [*net.UDPConn] in a [MmsgConn] for
25+
// reading and writing multiple messages using the recvmmsg(2) and sendmmsg(2) system calls.
26+
func (d *Dialer) DialUDPMmsgConn(ctx context.Context, network, address string) (c MmsgConn, info SocketInfo, err error) {
27+
info.MaxUDPGSOSegments = 1
28+
nd := d.td.Dialer
29+
nd.ControlContext = d.fns.controlContextFunc(&info)
30+
nc, err := nd.DialContext(ctx, network, address)
31+
if err != nil {
32+
return MmsgConn{}, info, err
33+
}
34+
c, err = NewMmsgConn(nc.(*net.UDPConn))
35+
return c, info, err
36+
}

direct/udp.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func (c *Socks5UDPClient) Info() zerocopy.UDPClientInfo {
184184

185185
// NewSession implements [zerocopy.UDPClient.NewSession].
186186
func (c *Socks5UDPClient) NewSession(ctx context.Context) (zerocopy.UDPClientSessionInfo, zerocopy.UDPClientSession, error) {
187-
tc, err := c.dialer.DialTCP(ctx, c.networkTCP, c.address, nil)
187+
tc, _, err := c.dialer.DialTCP(ctx, c.networkTCP, c.address, nil)
188188
if err != nil {
189189
return c.info, zerocopy.UDPClientSession{}, fmt.Errorf("failed to dial SOCKS5 server: %w", err)
190190
}
@@ -244,7 +244,7 @@ func (c *Socks5AuthUDPClient) Info() zerocopy.UDPClientInfo {
244244

245245
// NewSession implements [zerocopy.UDPClient.NewSession].
246246
func (c *Socks5AuthUDPClient) NewSession(ctx context.Context) (zerocopy.UDPClientSessionInfo, zerocopy.UDPClientSession, error) {
247-
tc, err := c.plainClient.dialer.DialTCP(ctx, c.plainClient.networkTCP, c.plainClient.address, nil)
247+
tc, _, err := c.plainClient.dialer.DialTCP(ctx, c.plainClient.networkTCP, c.plainClient.address, nil)
248248
if err != nil {
249249
return c.plainClient.info, zerocopy.UDPClientSession{}, fmt.Errorf("failed to dial SOCKS5 server: %w", err)
250250
}

netio/tcp.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,17 @@ var (
4949
func (c *TCPClient) NewStreamDialer() (StreamDialer, StreamDialerInfo) {
5050
return c, StreamDialerInfo{
5151
Name: c.name,
52-
NativeInitialPayload: !c.dialer.DisableTFO,
52+
NativeInitialPayload: c.dialer.TFO(),
5353
}
5454
}
5555

5656
// DialStream implements [StreamDialer.DialStream].
5757
func (c *TCPClient) DialStream(ctx context.Context, addr conn.Addr, payload []byte) (Conn, error) {
58-
return c.dialer.DialTCP(ctx, c.network, addr.String(), payload)
58+
tc, _, err := c.dialer.DialTCP(ctx, c.network, addr.String(), payload)
59+
if err != nil {
60+
return nil, err
61+
}
62+
return tc, nil
5963
}
6064

6165
// NewTCPTransparentProxyServer returns a new TCP transparent proxy server.

0 commit comments

Comments
 (0)