@@ -88,24 +88,26 @@ type Tunnel interface {
8888 // Get local services.
8989 GetServices () (x.Services , error )
9090
91- // Sets new default routes for the given engine, where engine is
92- // one of the constants (Ns4, Ns6, Ns46) defined in package settings.
93- SetRoute (engine int ) error
9491 // SetLinkAndRoutes sets the tun fd as link with mtu & engine as routes for the tunnel.
92+ // where engine is one of the constants (Ns4, Ns6, Ns46) defined in package settings.
9593 SetLinkAndRoutes (fd , mtu , engine int ) error
9694 // Restart restarts the tunnel with the given fd, mtu, and engine.
9795 Restart (fd , mtu , engine int ) error
9896
97+ // Close connections by pid, cid, uid.
98+ CloseConns (activecsv string ) (closedcsv string )
99+
99100 // Sets pcap output to fpcap which is the absolute filepath
100101 // to which a PCAP file will be written to.
101102 // If len(fpcap) is 0, no PCAP file will be written.
102103 // If len(fpcap) is 1, PCAP be written to stdout.
103104 SetPcap (fpcap string ) error
105+ // NIC, IP, TCP, UDP, and ICMP stats.
106+ Stat () (* x.NetStat , error )
104107}
105108
106109type rtunnel struct {
107- tunnel.Tunnel
108- tunmu sync.Mutex // serializes access to tunnel.Tunnel
110+ t * core.Volatile [tunnel.Tunnel ]
109111 ctx context.Context
110112 done context.CancelFunc
111113 handlers netstack.GConnHandler
@@ -116,6 +118,20 @@ type rtunnel struct {
116118 once sync.Once
117119}
118120
121+ var _ Tunnel = (* rtunnel )(nil )
122+
123+ type clogAdapter struct {
124+ b Bridge
125+ }
126+
127+ var _ log.Console = (* clogAdapter )(nil )
128+
129+ func (l * clogAdapter ) Log (lvl log.LogLevel , msg log.Logmsg ) {
130+ if bdg := l .b ; bdg != nil {
131+ bdg .Log (int32 (lvl ), x .StrOf (msg )) // adopt the log message
132+ }
133+ }
134+
119135func NewTunnel (fd , mtu int , fakedns string , dtr DefaultDNS , bdg Bridge ) (t Tunnel , err error ) {
120136 defer core .Recover (core .Exit11 , "i.newTunnel" )
121137
@@ -198,7 +214,7 @@ func NewTunnel(fd, mtu int, fakedns string, dtr DefaultDNS, bdg Bridge) (t Tunne
198214 rerr := proxies .Reverser (revhdl )
199215
200216 t = & rtunnel {
201- Tunnel : gt ,
217+ t : core. NewVolatile [tunnel. Tunnel ]( gt ) ,
202218 ctx : ctx ,
203219 done : cancel ,
204220 handlers : hdl ,
@@ -231,15 +247,15 @@ func (t *rtunnel) SetLinkAndRoutes(fd, mtu, engine int) error {
231247 return errClosed
232248 }
233249
234- t .tunmu .Lock ()
235- defer t .tunmu .Unlock ()
250+ tunnel := t .t .Load ()
236251
237- mtudiff := t . Tunnel .Mtu () != int32 (mtu )
252+ mtudiff := tunnel .Mtu () != int32 (mtu )
238253 l3 := settings .L3 (engine )
239254 l3diff := dialers .IPProtos (l3 )
240255
241- err := t . Tunnel . SetLink (fd , mtu ) // route is always dual-stack
256+ err := tunnel . SetLinkAndRoutes (fd , mtu , engine ) // route is always dual-stack
242257
258+ // TODO: skip refresh on err?
243259 core .Gx ("i.setLinkAndRoutesRefresh" , func () {
244260 if l3diff || mtudiff {
245261 // dialers.IPProtos must always preced calls to other refreshes
@@ -275,16 +291,16 @@ func (t *rtunnel) Restart(fd, mtu, engine int) error {
275291
276292 gt , revhdl , err := tunnel .NewGTunnel (t .ctx , fd , mtu , l3 , t .handlers )
277293
278- if gt == nil || err != nil {
279- log .W ("tun: <<< restart >>>; err(%v)" , err )
280- t .Tunnel .Disconnect ()
294+ old := t .t .Load ()
295+ old .Disconnect () // may hve been disconnected already
296+
297+ if err != nil || gt == nil || core .IsNil (gt ) {
298+ log .W ("tun: <<< restart >>>; new? %t; err(%v)" , gt != nil , err )
281299 return core .OneErr (err , errMakeTunnel )
282300 }
283301
284- t .tunmu .Lock ()
285- t .Tunnel .Disconnect ()
286- t .Tunnel = gt
287- t .tunmu .Unlock ()
302+ // TODO: CompareAndSwap
303+ t .t .Store (gt ) // gt never nil
288304
289305 // TODO: err on reverser errors too?
290306 rerr := t .proxies .Reverser (revhdl )
@@ -365,9 +381,9 @@ func (t *rtunnel) Stat() (*x.NetStat, error) {
365381}
366382
367383func (t * rtunnel ) stat () (* x.NetStat , error ) {
368- t . tunmu . Lock ()
369- out , err := t . Tunnel . Stat ()
370- t . tunmu . Unlock ()
384+ tunnel := t . t . Load ()
385+
386+ out , err := tunnel . Stat ()
371387
372388 if err != nil {
373389 return nil , err
@@ -455,6 +471,43 @@ func (t *rtunnel) stat() (*x.NetStat, error) {
455471 return out , nil
456472}
457473
474+ // CloseConns implements Tunnel.
475+ func (t * rtunnel ) CloseConns (activecsv string ) (closedcsv string ) {
476+ defer core .Recover (core .Exit11 , "i.CloseConns" )
477+
478+ return t .handlers .CloseConns (activecsv )
479+ }
480+
481+ // Enabled implements Tunnel.
482+ func (t * rtunnel ) Enabled () bool {
483+ tunnel := t .t .Load ()
484+ return tunnel .Enabled ()
485+ }
486+
487+ // IsConnected implements Tunnel.
488+ func (t * rtunnel ) IsConnected () bool {
489+ tunnel := t .t .Load ()
490+ return tunnel .IsConnected ()
491+ }
492+
493+ // Mtu implements Tunnel.
494+ func (t * rtunnel ) Mtu () int32 {
495+ tunnel := t .t .Load ()
496+ return tunnel .Mtu ()
497+ }
498+
499+ // SetPcap implements Tunnel.
500+ func (t * rtunnel ) SetPcap (fpcap string ) error {
501+ tunnel := t .t .Load ()
502+ return tunnel .SetPcap (fpcap )
503+ }
504+
505+ // Unlink implements Tunnel.
506+ func (t * rtunnel ) Unlink () error {
507+ tunnel := t .t .Load ()
508+ return tunnel .Unlink ()
509+ }
510+
458511func csv2ssv (csv string ) string {
459512 return strings .ReplaceAll (csv , "," , ";" )
460513}
@@ -481,15 +534,3 @@ func fetchDNSInfo(r dnsx.Resolver, id string) string {
481534 return rerr .Error ()
482535 }
483536}
484-
485- type clogAdapter struct {
486- b Bridge
487- }
488-
489- var _ log.Console = (* clogAdapter )(nil )
490-
491- func (l * clogAdapter ) Log (lvl log.LogLevel , msg log.Logmsg ) {
492- if bdg := l .b ; bdg != nil {
493- bdg .Log (int32 (lvl ), x .StrOf (msg )) // adopt the log message
494- }
495- }
0 commit comments