diff --git a/templates/lib_template.go b/templates/lib_template.go index b3572f7..7f24d70 100644 --- a/templates/lib_template.go +++ b/templates/lib_template.go @@ -30,6 +30,7 @@ import ( _ "github.com/mutecomm/go-sqlcipher/v4" "cwtch.im/cwtch/app" "git.openprivacy.ca/openprivacy/connectivity" + "sync" {{IMPORTS}} ) @@ -193,20 +194,9 @@ func _startCwtch(appDir string, torPath string) { {{EXPERIMENT_REGISTER}} - // Finally attempt to set up a proper TOR - // NOTE: This can block until finishing, so we wrap it in a - // go routine... - go func() { - newACN, globalSettings := buildACN(application.ReadSettings(), globalTorPath, globalAppDir) - settingsFile.WriteGlobalSettings(globalSettings) - globalACN.ReplaceACN(newACN) - application.QueryACNVersion() - // Settings may have changed... - globalSettings = settingsFile.ReadGlobalSettings() - settingsJson, _ := json.Marshal(globalSettings) - application.UpdateSettings(globalSettings) - application.GetPrimaryBus().Publish(event.NewEvent(settings.UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)})) - }() + // Finally attempt to set up a proper Tor + // Note: ResetTor launches an internal goroutine so this is non-blocking... + ResetTor() } // the pointer returned from this function **must** be freed using c_Free @@ -405,21 +395,38 @@ func c_ResetTor() { ResetTor() } + +var torLock sync.Mutex + func ResetTor() { - log.Infof("Replacing ACN with new Tor...") - settings := application.ReadSettings() - - globalACN.Close() // we need to close first if dateDir is the same, otherwise buildACN can't launch tor. - newAcn, settings := buildACN(settings, globalTorPath, globalAppDir) - application.UpdateSettings(settings) - globalACN.ReplaceACN(newAcn) - application.QueryACNVersion() - - // We need to update settings on reset as buildACN can alter settings, otherwise the next reset will be broken... - settings = application.ReadSettings() - settingsJson, _ := json.Marshal(settings) - application.GetPrimaryBus().Publish(event.NewEvent(UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)})) - log.Infof("Restarted") + go func() { + // prevent concurrent calls to this method... + torLock.Lock() + defer torLock.Unlock() + log.Infof("Replacing ACN with new Tor...") + settings := application.ReadSettings() + + globalACN.Close() // we need to close first if dateDir is the same, otherwise buildACN can't launch tor. + newAcn, settings, err := buildACN(settings, globalTorPath, globalAppDir) + // only update settings if successful. + if err == nil { + // Only update Tor specific settings... + currentSettings := application.ReadSettings() + currentSettings.TorCacheDir = settings.TorCacheDir + currentSettings.CustomControlPort = settings.CustomControlPort + currentSettings.CustomSocksPort = settings.CustomSocksPort + currentSettings.CustomTorrc = settings.CustomTorrc + application.UpdateSettings(currentSettings) + globalACN.ReplaceACN(newAcn) + application.QueryACNVersion() + + // We need to update settings on reset as buildACN can alter settings, otherwise the next reset will be broken... + settings = application.ReadSettings() + settingsJson, _ := json.Marshal(settings) + application.GetPrimaryBus().Publish(event.NewEvent(UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)})) + } + log.Infof("Restarted") + }() } const ( @@ -428,7 +435,7 @@ const ( UpdateGlobalSettings = event.Type("UpdateGlobalSettings") ) -func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir string) (connectivity.ACN, settings.GlobalSettings) { +func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir string) (connectivity.ACN, settings.GlobalSettings, error) { mrand.Seed(int64(time.Now().Nanosecond())) socksPort := mrand.Intn(1000) + 9600 @@ -447,7 +454,7 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str if err != nil { log.Errorf("error creating tor data directory: %v. Aborting app start up", err) eventHandler.Push(event.NewEventList(CwtchStartError, event.Error, fmt.Sprintf("Error connecting to Tor: %v", err))) - return &connectivity.ErrorACN{}, globalSettings + return &connectivity.ErrorACN{}, globalSettings, err } if globalSettings.AllowAdvancedTorConfig { @@ -482,7 +489,7 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str if err != nil { log.Errorf("error constructing torrc: %v", err) eventHandler.Push(event.NewEventList(CwtchStartError, event.Error, fmt.Sprintf("Error connecting to Tor: %v", err))) - return &connectivity.ErrorACN{}, globalSettings + return &connectivity.ErrorACN{}, globalSettings, err } dataDir := globalSettings.TorCacheDir @@ -502,7 +509,7 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str if dataDir, err = os.MkdirTemp(torDir, "data-dir-"); err != nil { eventHandler.Push(event.NewEventList(CwtchStartError, event.Error, fmt.Sprintf("Error connecting to Tor: %v", err))) - return &connectivity.ErrorACN{}, globalSettings + return &connectivity.ErrorACN{}, globalSettings, err } } @@ -515,7 +522,7 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str eventHandler.Push(event.NewEventList(CwtchStartError, event.Error, fmt.Sprintf("Error connecting to Tor: %v", err))) acn = &connectivity.ErrorACN{} } - return acn, globalSettings + return acn, globalSettings, err }