From 9992edadbafca3a5d48c2a4f43a4cb3845efea03 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Tue, 2 Aug 2022 19:45:44 -0700 Subject: [PATCH] add testing to versionCallback, fix versionCallback --- tor/torProvider.go | 52 ++++++++++++++++++++++++----------------- tor/torProvider_test.go | 16 +++++++++++++ 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/tor/torProvider.go b/tor/torProvider.go index 8cbd191..1e30ec2 100644 --- a/tor/torProvider.go +++ b/tor/torProvider.go @@ -75,6 +75,7 @@ type torProvider struct { authenticator tor.Authenticator isClosed bool dataDir string + version string } func (ols *onionListenService) AddressFull() string { @@ -210,6 +211,12 @@ func (tp *torProvider) GetBootstrapStatus() (int, string) { func (tp *torProvider) GetVersion() string { tp.lock.Lock() defer tp.lock.Unlock() + return tp.version +} + +func (tp *torProvider) getVersionFromControlPort() string { + tp.lock.Lock() + defer tp.lock.Unlock() if tp.t == nil { return "No Tor" @@ -325,6 +332,7 @@ func (tp *torProvider) restart() { // preserve status callback after shutdown statusCallback := tp.statusCallback + versionCallback := tp.versionCallback tp.t = nil log.Debugf("Restarting Tor Process") @@ -335,6 +343,10 @@ func (tp *torProvider) restart() { tp.t = newTp.t tp.dialer = newTp.dialer tp.statusCallback = statusCallback + tp.versionCallback = versionCallback + if tp.versionCallback != nil { + tp.versionCallback(tp.version) + } tp.lastRestartTime = time.Now() tp.isClosed = false go tp.monitorRestart() @@ -412,14 +424,6 @@ func (tp *torProvider) callStatusCallback(prog int, status string) { } } -func (tp *torProvider) callVersionCallback(version string) { - tp.lock.Lock() - defer tp.lock.Unlock() - if tp.versionCallback != nil { - tp.versionCallback(version) - } -} - // NewTorACNWithAuth creates/starts a Tor ACN and returns a usable ACN object func NewTorACNWithAuth(appDirectory string, bundledTorPath string, dataDir string, controlPort int, authenticator tor.Authenticator) (connectivity.ACN, error) { tp, err := startTor(appDirectory, bundledTorPath, dataDir, controlPort, authenticator) @@ -444,7 +448,7 @@ func newHideCmd(exePath string) process.Creator { }) } -func (tp *torProvider) checkVersion() error { +func (tp *torProvider) checkVersion() (string, error) { // attempt connect to system tor log.Debugf("dialing tor control port") controlport, err := dialControlPort(tp.controlPort) @@ -457,13 +461,13 @@ func (tp *torProvider) checkVersion() error { if err == nil { if minTorVersionReqs(pinfo.TorVersion) { log.Debugln("OK version " + pinfo.TorVersion) - return nil + return pinfo.TorVersion, nil } - return fmt.Errorf("tor version not supported: %v", pinfo.TorVersion) + return pinfo.TorVersion, fmt.Errorf("tor version not supported: %v", pinfo.TorVersion) } } } - return err + return "", err } func startTor(appDirectory string, bundledTorPath string, dataDir string, controlPort int, authenticator tor.Authenticator) (*torProvider, error) { @@ -471,10 +475,11 @@ func startTor(appDirectory string, bundledTorPath string, dataDir string, contro os.MkdirAll(torDir, 0700) - tp := &torProvider{authenticator: authenticator, controlPort: controlPort, appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool, 1), statusCallback: nil, lastRestartTime: time.Now().Add(-restartCooldown)} + tp := &torProvider{authenticator: authenticator, controlPort: controlPort, appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool, 1), statusCallback: nil, versionCallback: nil, lastRestartTime: time.Now().Add(-restartCooldown)} log.Debugf("checking if there is a running system tor") - if err := tp.checkVersion(); err == nil { + if version, err := tp.checkVersion(); err == nil { + tp.version = version controlport, err := dialControlPort(tp.controlPort) if err == nil { log.Debugf("creating tor handler from system tor") @@ -493,7 +498,7 @@ func startTor(appDirectory string, bundledTorPath string, dataDir string, contro // if not, try bundled tor, then running system tor log.Debugln("checking if we can run bundled tor or system installed tor") - if bundledTorPath != "" && checkCmdlineTorVersion(bundledTorPath) { + if version, pass := checkCmdlineTorVersion(bundledTorPath); pass { log.Debugln("bundled tor appears viable, attempting to use '" + bundledTorPath + "'") t, err := tor.Start(context.TODO(), &tor.StartConf{ControlPort: tp.controlPort, DisableCookieAuth: true, UseEmbeddedControlConn: false, DisableEagerAuth: true, EnableNetwork: true, DataDir: dataDir, TorrcFile: path.Join(torDir, "torrc"), ExePath: bundledTorPath, DebugWriter: nil, ProcessCreator: newHideCmd(bundledTorPath)}) if err != nil { @@ -501,23 +506,25 @@ func startTor(appDirectory string, bundledTorPath string, dataDir string, contro return nil, err } tp.t = t - } else if checkCmdlineTorVersion("tor") { + tp.version = version + } else if version, pass := checkCmdlineTorVersion("tor"); pass { t, err := tor.Start(context.TODO(), &tor.StartConf{ControlPort: tp.controlPort, DisableCookieAuth: true, UseEmbeddedControlConn: false, DisableEagerAuth: true, EnableNetwork: true, DataDir: dataDir, TorrcFile: path.Join(torDir, "torrc"), DebugWriter: nil, ProcessCreator: newHideCmd("tor")}) if err != nil { log.Debugf("Error connecting to self-run system tor: %v\n", err) return nil, err } tp.t = t + tp.version = version } else { log.Debugln("Could not find a viable tor running or to run") return nil, fmt.Errorf("could not connect to or start Tor that met requirements (min Tor version 0.3.5.x)") } - err := tp.checkVersion() + version, err := tp.checkVersion() if err == nil { tp.t.DeleteDataDirOnClose = false // caller is responsible for dealing with cached information... tp.dialer, err = tp.t.Dialer(context.TODO(), &tor.DialConf{Authenticator: tp.authenticator}) - tp.callVersionCallback(tp.GetVersion()) + tp.version = version return tp, err } return nil, fmt.Errorf("could not connect to running tor: %v", err) @@ -588,7 +595,10 @@ func createFromExisting(controlport *control.Conn, datadir string) *tor.Tor { return t } -func checkCmdlineTorVersion(torCmd string) bool { +func checkCmdlineTorVersion(torCmd string) (string, bool) { + if torCmd == "" { + return "", false + } // ideally we would use CommandContext with Timeout here // but it doesn't work with programs that may launch other processes via scripts e.g. exec // and the workout is more complex than just implementing the logic ourselves... @@ -615,13 +625,13 @@ func checkCmdlineTorVersion(torCmd string) bool { if err != nil { log.Debugf("tor process timed out") - return false + return "", false } re := regexp.MustCompile(`[0-1]\.[0-9]\.[0-9]\.[0-9]`) sysTorVersion := re.Find(outb.Bytes()) log.Infof("tor version: %v", string(sysTorVersion)) - return minTorVersionReqs(string(sysTorVersion)) + return string(sysTorVersion), minTorVersionReqs(string(sysTorVersion)) } // returns true if supplied version meets our min requirments diff --git a/tor/torProvider_test.go b/tor/torProvider_test.go index 5827eb3..38dd726 100644 --- a/tor/torProvider_test.go +++ b/tor/torProvider_test.go @@ -19,11 +19,19 @@ func getStatusCallback(progChan chan int) func(int, string) { } } +func getVersionCallback(verChan chan string) func(string) { + return func(version string) { + fmt.Printf("version: %v\n", version) + verChan <- version + } +} + func TestTorProvider(t *testing.T) { goRoutineStart := runtime.NumGoroutine() progChan := make(chan int, 10) + verChan := make(chan string, 10) log.SetLevel(log.LevelDebug) torpath := path.Join("..", "tmp/tor") @@ -43,6 +51,7 @@ func TestTorProvider(t *testing.T) { return } acn.SetStatusCallback(getStatusCallback(progChan)) + acn.SetVersionCallback(getVersionCallback(verChan)) progress := 0 for progress < 100 { @@ -57,6 +66,13 @@ func TestTorProvider(t *testing.T) { progress = <-progChan t.Logf("progress: %v", progress) } + log.Debugf("Pulling tor version from version callback chan...\n") + version := <-verChan + if version == "" { + t.Errorf("failed to get tor version, got empty string\n") + } else { + log.Debugf("Tor version: %v\n", version) + } // Test opening the OP Server _, _, err = acn.Open("isbr2t6bflul2zyi6hjtnuezb2xvfr42svzjg2q3gyqfgg3wmnrbkkqd")