Skip to content

Commit 9ca227b

Browse files
committed
ipn/proxies: do not transition to other states from TPU
must be a state machine, but for now, make sure if a proxy enters the TPU state (ie, paused state), it cannot transition out of it, unless resumed or ended. also, ignore reachability checks, dials, and health checks for paused proxies.
1 parent 928668f commit 9ca227b

13 files changed

Lines changed: 120 additions & 92 deletions

File tree

intra/ipn/auto.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ func (h *auto) DialBind(network, local, remote string) (protect.Conn, error) {
109109
}
110110

111111
func (h *auto) dial(network, laddr, raddr string) (protect.Conn, error) {
112-
if h.status.Load() == END {
113-
return nil, errProxyStopped
112+
if err := candial(h.status); err != nil {
113+
return nil, err
114114
}
115115

116116
exit, exerr := h.pxr.ProxyFor(Exit)
@@ -302,8 +302,8 @@ func (h *auto) dial(network, laddr, raddr string) (protect.Conn, error) {
302302

303303
// Announce implements Proxy.
304304
func (h *auto) Announce(network, local string) (protect.PacketConn, error) {
305-
if h.status.Load() == END {
306-
return nil, errProxyStopped
305+
if err := candial(h.status); err != nil {
306+
return nil, err
307307
}
308308

309309
exit, exerr := h.pxr.ProxyFor(Exit)
@@ -375,8 +375,8 @@ func (h *auto) Announce(network, local string) (protect.PacketConn, error) {
375375

376376
// Accept implements Proxy.
377377
func (h *auto) Accept(network, local string) (l protect.Listener, err error) {
378-
if h.status.Load() == END {
379-
return nil, errProxyStopped
378+
if err := candial(h.status); err != nil {
379+
return nil, err
380380
}
381381
if settings.AutoAlwaysRemote() {
382382
log.E("proxy: auto: accept(%s) on %s remote-dial unimplemented", network, local)
@@ -394,8 +394,8 @@ func (h *auto) Accept(network, local string) (l protect.Listener, err error) {
394394

395395
// Probe implements Proxy.
396396
func (h *auto) Probe(network, local string) (pc protect.PacketConn, err error) {
397-
if h.status.Load() == END {
398-
return nil, errProxyStopped
397+
if err := candial(h.status); err != nil {
398+
return nil, err
399399
}
400400
if settings.AutoAlwaysRemote() {
401401
log.E("proxy: auto: probe(%s) on %s remote-dial unimplemented", network, local)

intra/ipn/base.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ func (h *base) DialBind(network, local, remote string) (c protect.Conn, err erro
9494
}
9595

9696
func (h *base) dial(network, local, remote string) (c protect.Conn, err error) {
97-
if h.status.Load() == END {
98-
return nil, errProxyStopped
97+
if err := candial(h.status); err != nil {
98+
return nil, err
9999
}
100100

101101
who := idstr(h)
@@ -128,8 +128,8 @@ func (h *base) dial(network, local, remote string) (c protect.Conn, err error) {
128128

129129
// Announce implements Proxy.
130130
func (h *base) Announce(network, local string) (protect.PacketConn, error) {
131-
if h.status.Load() == END {
132-
return nil, errProxyStopped
131+
if err := candial(h.status); err != nil {
132+
return nil, err
133133
}
134134
c, err := dialers.ListenPacket(h.outbound, network, local)
135135
defer localDialStatus(h.status, err)
@@ -139,16 +139,16 @@ func (h *base) Announce(network, local string) (protect.PacketConn, error) {
139139

140140
// Accept implements Proxy.
141141
func (h *base) Accept(network, local string) (protect.Listener, error) {
142-
if h.status.Load() == END {
143-
return nil, errProxyStopped
142+
if err := candial(h.status); err != nil {
143+
return nil, err
144144
}
145145
return dialers.Listen(h.outbound, network, local)
146146
}
147147

148148
// Probe implements Proxy.
149149
func (h *base) Probe(network, local string) (protect.PacketConn, error) {
150-
if h.status.Load() == END {
151-
return nil, errProxyStopped
150+
if err := candial(h.status); err != nil {
151+
return nil, err
152152
}
153153
c, err := dialers.Probe(h.outbound, network, local)
154154
defer localDialStatus(h.status, err)

intra/ipn/exit.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ func (h *exit) DialBind(network, local, remote string) (protect.Conn, error) {
8888
}
8989

9090
func (h *exit) dial(network, local, remote string) (protect.Conn, error) {
91-
if h.status.Load() == END {
92-
return nil, errProxyStopped
91+
if err := candial(h.status); err != nil {
92+
return nil, err
9393
}
9494
// exit always splits
9595
c, err := localDialStrat(h.outbound, network, local, remote)
@@ -103,8 +103,8 @@ func (h *exit) dial(network, local, remote string) (protect.Conn, error) {
103103

104104
// Announce implements Proxy.
105105
func (h *exit) Announce(network, local string) (protect.PacketConn, error) {
106-
if h.status.Load() == END {
107-
return nil, errProxyStopped
106+
if err := candial(h.status); err != nil {
107+
return nil, err
108108
}
109109
c, err := dialers.ListenPacket(h.outbound, network, local)
110110
defer localDialStatus(h.status, err)
@@ -114,16 +114,16 @@ func (h *exit) Announce(network, local string) (protect.PacketConn, error) {
114114

115115
// Accept implements Proxy.
116116
func (h *exit) Accept(network, local string) (protect.Listener, error) {
117-
if h.status.Load() == END {
118-
return nil, errProxyStopped
117+
if err := candial(h.status); err != nil {
118+
return nil, err
119119
}
120120
return dialers.Listen(h.outbound, network, local)
121121
}
122122

123123
// Probe implements Proxy.
124124
func (h *exit) Probe(network, local string) (protect.PacketConn, error) {
125-
if h.status.Load() == END {
126-
return nil, errProxyStopped
125+
if err := candial(h.status); err != nil {
126+
return nil, err
127127
}
128128
c, err := dialers.Probe(h.outbound, network, local)
129129
defer localDialStatus(h.status, err)
@@ -174,15 +174,15 @@ func (h *exit) Stop() error {
174174
return nil
175175
}
176176

177-
func localDialStatus(status *core.Volatile[int], err error) {
178-
if status.Load() == END {
179-
return
177+
func localDialStatus(status *core.Volatile[int], err error) bool {
178+
cur := status.Load()
179+
if cur == END || cur == TPU {
180+
return false
180181
}
181182
if err != nil {
182-
status.Store(TKO)
183-
} else {
184-
status.Store(TOK)
183+
return status.Cas(cur, TKO)
185184
}
185+
return status.Cas(cur, TOK)
186186
}
187187

188188
func idhandle(p Proxy) string {

intra/ipn/exit64.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ func (h *exit64) DialBind(network, local, remote string) (protect.Conn, error) {
8282
}
8383

8484
func (h *exit64) dial(network, local, remote string) (protect.Conn, error) {
85-
if h.status.Load() == END {
86-
return nil, errProxyStopped
85+
if err := candial(h.status); err != nil {
86+
return nil, err
8787
}
8888

8989
addr64 := addr4to6(remote)
@@ -105,8 +105,8 @@ func (h *exit64) dial(network, local, remote string) (protect.Conn, error) {
105105

106106
// Announce implements Proxy.
107107
func (h *exit64) Announce(network, local string) (protect.PacketConn, error) {
108-
if h.status.Load() == END {
109-
return nil, errProxyStopped
108+
if err := candial(h.status); err != nil {
109+
return nil, err
110110
}
111111
var local64 string
112112
if ipp, _ := netip.ParseAddrPort(local); ipp.IsValid() {
@@ -129,8 +129,8 @@ func (h *exit64) Announce(network, local string) (protect.PacketConn, error) {
129129

130130
// Accept implements Proxy.
131131
func (h *exit64) Accept(network, local string) (protect.Listener, error) {
132-
if h.status.Load() == END {
133-
return nil, errProxyStopped
132+
if err := candial(h.status); err != nil {
133+
return nil, err
134134
}
135135
var local64 string
136136
if ipp, _ := netip.ParseAddrPort(local); ipp.IsValid() {
@@ -153,8 +153,8 @@ func (h *exit64) Accept(network, local string) (protect.Listener, error) {
153153

154154
// Probe implements Proxy.
155155
func (h *exit64) Probe(network, local string) (protect.PacketConn, error) {
156-
if h.status.Load() == END {
157-
return nil, errProxyStopped
156+
if err := candial(h.status); err != nil {
157+
return nil, err
158158
}
159159
var local64 string
160160
if ipp, _ := netip.ParseAddrPort(local); ipp.IsValid() {

intra/ipn/http1.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ func (h *http1) DialerHandle() uintptr {
106106

107107
// Dial implements Proxy.
108108
func (h *http1) Dial(network, addr string) (c protect.Conn, err error) {
109-
if h.status.Load() == END {
110-
return nil, errProxyStopped
109+
if err := candial(h.status); err != nil {
110+
return nil, err
111111
}
112112

113113
h.lastdial = time.Now()
@@ -244,7 +244,7 @@ func (h *http1) Stop() error {
244244

245245
// OnProtoChange implements Proxy.
246246
func (h *http1) OnProtoChange(_ LinkProps) (string, bool) {
247-
if h.status.Load() == END {
247+
if err := candial(h.status); err != nil {
248248
return "", false
249249
}
250250
return h.opts.FullUrl(), true

intra/ipn/piph2.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ func (t *piph2) DialBind(network, local, remote string) (protect.Conn, error) {
397397
}
398398

399399
func (t *piph2) forward(network, addr string) (protect.Conn, error) {
400-
if t.status.Load() == END {
400+
if err := candial(t.status); err != nil {
401401
return nil, errProxyStopped
402402
}
403403
if network != "tcp" {

intra/ipn/proxies.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ func (px *proxifier) ProxyTo(ipp netip.AddrPort, uid string, pids []string) (_ P
499499

500500
notokproxies := make([]string, 0)
501501
endproxies := make([]string, 0)
502+
pausedproxies := make([]string, 0)
502503
norouteproxies := make([]string, 0)
503504
missproxies := make([]string, 0)
504505
loproxies := make([]string, 0)
@@ -507,8 +508,8 @@ func (px *proxifier) ProxyTo(ipp netip.AddrPort, uid string, pids []string) (_ P
507508
}
508509

509510
defer func() {
510-
logev(err)("proxy: pin: %s+%s; stalled? %ds; miss: %v; notok: %v; noroute: %v; ended %v",
511-
uid, ipp, stalledSec, missproxies, notokproxies, norouteproxies, endproxies)
511+
logev(err)("proxy: pin: %s+%s; stalled? %ds; miss: %v; notok: %v; noroute: %v; paused %v; ended %v",
512+
uid, ipp, stalledSec, missproxies, notokproxies, norouteproxies, pausedproxies, endproxies)
512513
}()
513514

514515
for _, pid := range pids {
@@ -526,7 +527,11 @@ func (px *proxifier) ProxyTo(ipp netip.AddrPort, uid string, pids []string) (_ P
526527
continue
527528
}
528529

529-
if p.Status() == END {
530+
st := p.Status()
531+
if st == TPU {
532+
pausedproxies = append(pausedproxies, pid)
533+
continue
534+
} else if st == END {
530535
endproxies = append(endproxies, pid)
531536
continue
532537
}

intra/ipn/proxy.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,12 @@ func (pxr *proxifier) fromOpts(id string, opts *settings.ProxyOptions) (Proxy, e
262262
}
263263

264264
func Reaches(p Proxy, urlOrHostPortOrIPPortCsv string, protos ...string) bool {
265-
if p == nil || p.Status() == END {
265+
if p == nil {
266+
return false
267+
}
268+
st := p.Status()
269+
if err := candial2(st); err != nil {
270+
log.W("proxy: %s reaches: err %v, status(%s)", idstr(p), err, pxstatus(st))
266271
return false
267272
}
268273
if len(urlOrHostPortOrIPPortCsv) <= 0 {
@@ -639,8 +644,8 @@ func healthy(p Proxy) error {
639644
return nil
640645
}
641646

642-
if p.Status() == END {
643-
return errProxyStopped
647+
if err := candial2(p.Status()); err != nil {
648+
return err
644649
} // TODO: err on TNT, TKO?
645650

646651
stat := p.Router().Stat()
@@ -699,6 +704,20 @@ func ViaID(p Proxy) string {
699704
return vid
700705
}
701706

707+
func candial2(st int) error {
708+
if st == END {
709+
return errProxyStopped
710+
}
711+
if st == TPU {
712+
return errProxyPaused
713+
}
714+
return nil
715+
}
716+
717+
func candial(state *core.Volatile[int]) error {
718+
return candial2(state.Load())
719+
}
720+
702721
func usevia(viaID *core.Volatile[string]) bool {
703722
return viaID != nil && len(viaID.Load()) > 0
704723
}

intra/ipn/seproxy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ func (h *seproxy) Router() x.Router {
377377

378378
// Dial implements Proxy.
379379
func (h *seproxy) Dial(network, addr string) (protect.Conn, error) {
380-
if h.status.Load() == END {
381-
return nil, errProxyStopped
380+
if err := candial(h.status); err != nil {
381+
return nil, err
382382
}
383383

384384
defer h.maybeRefresh()

intra/ipn/socks5.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ func (h *socks5) DialBind(network, local, remote string) (c protect.Conn, err er
212212

213213
// todo: bind to local
214214
func (h *socks5) dial(network, _, remote string) (c protect.Conn, err error) {
215-
if h.status.Load() == END {
216-
return nil, errProxyStopped
215+
if err := candial(h.status); err != nil {
216+
return nil, err
217217
}
218218

219219
h.lastdial = time.Now()
@@ -244,13 +244,7 @@ func (h *socks5) dial(network, _, remote string) (c protect.Conn, err error) {
244244
log.W("proxy: socks5: %s dial(%s) failed %s => %s: %v",
245245
h.ID(), network, h.GetAddr(), remote, err)
246246
}
247-
if err == nil {
248-
log.I("proxy: socks5: %s dial(%s) from %s => %s",
249-
h.ID(), network, h.GetAddr(), remote)
250-
h.status.Store(TOK)
251-
} else {
252-
h.status.Store(TKO)
253-
}
247+
defer localDialStatus(h.status, err)
254248
return
255249
}
256250

@@ -357,7 +351,7 @@ func (h *socks5) Stop() error {
357351

358352
// OnProtoChange implements Proxy.
359353
func (h *socks5) OnProtoChange(_ LinkProps) (string, bool) {
360-
if h.status.Load() == END {
354+
if err := candial(h.status); err != nil {
361355
return "", false
362356
}
363357
return h.opts.FullUrl(), true

0 commit comments

Comments
 (0)