diff --git a/listener/sing_tun/server.go b/listener/sing_tun/server.go index f948320a..44824b75 100644 --- a/listener/sing_tun/server.go +++ b/listener/sing_tun/server.go @@ -182,7 +182,7 @@ func New(options config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P err = E.Cause(err, "build android rules") return } - tunIf, err := tun.Open(tunOptions) + tunIf, err := tunOpen(tunOptions) if err != nil { err = E.Cause(err, "configure tun interface") return diff --git a/listener/sing_tun/server_other.go b/listener/sing_tun/server_notandroid.go similarity index 100% rename from listener/sing_tun/server_other.go rename to listener/sing_tun/server_notandroid.go diff --git a/listener/sing_tun/server_notwindows.go b/listener/sing_tun/server_notwindows.go new file mode 100644 index 00000000..27872d8e --- /dev/null +++ b/listener/sing_tun/server_notwindows.go @@ -0,0 +1,11 @@ +//go:build !windows + +package sing_tun + +import ( + tun "github.com/sagernet/sing-tun" +) + +func tunOpen(options tun.Options) (tun.Tun, error) { + return tun.Open(options) +} diff --git a/listener/sing_tun/server_windows.go b/listener/sing_tun/server_windows.go index 33f3ff19..20fc7031 100644 --- a/listener/sing_tun/server_windows.go +++ b/listener/sing_tun/server_windows.go @@ -1,6 +1,29 @@ package sing_tun -import tun "github.com/sagernet/sing-tun" +import ( + "time" + + "github.com/Dreamacro/clash/log" + + tun "github.com/sagernet/sing-tun" +) + +func tunOpen(options tun.Options) (tunIf tun.Tun, err error) { + maxRetry := 3 + for i := 0; i < maxRetry; i++ { + timeBegin := time.Now() + tunIf, err = tun.Open(options) + if err == nil { + return + } + timeEnd := time.Now() + if timeEnd.Sub(timeBegin) < 1*time.Second { // retrying for "Cannot create a file when that file already exists." + return + } + log.Warnln("Start Tun interface timeout: %s [retrying %d/%d]", err, i+1, maxRetry) + } + return +} func init() { tun.TunnelType = InterfaceName