2018-04-30 21:47:21 +00:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
2022-10-03 20:05:36 +00:00
|
|
|
"cwtch.im/cwtch/app/plugins"
|
|
|
|
"cwtch.im/cwtch/event"
|
2023-01-05 21:52:43 +00:00
|
|
|
"cwtch.im/cwtch/extensions"
|
|
|
|
"cwtch.im/cwtch/functionality/filesharing"
|
2022-10-03 20:05:36 +00:00
|
|
|
"cwtch.im/cwtch/model"
|
|
|
|
"cwtch.im/cwtch/model/attr"
|
|
|
|
"cwtch.im/cwtch/model/constants"
|
|
|
|
"cwtch.im/cwtch/peer"
|
|
|
|
"cwtch.im/cwtch/protocol/connections"
|
|
|
|
"cwtch.im/cwtch/storage"
|
|
|
|
"git.openprivacy.ca/openprivacy/connectivity"
|
|
|
|
"git.openprivacy.ca/openprivacy/log"
|
|
|
|
"os"
|
|
|
|
path "path/filepath"
|
|
|
|
"strconv"
|
|
|
|
"sync"
|
2018-04-30 21:47:21 +00:00
|
|
|
)
|
|
|
|
|
2018-09-21 18:53:10 +00:00
|
|
|
type application struct {
|
2022-10-03 20:05:36 +00:00
|
|
|
eventBuses map[string]event.Manager
|
|
|
|
directory string
|
2022-08-29 01:19:32 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
peerLock sync.Mutex
|
|
|
|
peers map[string]peer.CwtchPeer
|
|
|
|
acn connectivity.ACN
|
|
|
|
plugins sync.Map //map[string] []plugins.Plugin
|
2022-08-29 01:19:32 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
engines map[string]connections.Engine
|
|
|
|
appBus event.Manager
|
|
|
|
appmutex sync.Mutex
|
2023-01-25 20:32:26 +00:00
|
|
|
|
|
|
|
settings *GlobalSettingsFile
|
2018-09-21 18:53:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Application is a full cwtch peer application. It allows management, usage and storage of multiple peers
|
|
|
|
type Application interface {
|
2022-10-03 20:05:36 +00:00
|
|
|
LoadProfiles(password string)
|
2023-02-21 23:55:14 +00:00
|
|
|
CreateProfile(name string, password string, autostart bool)
|
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
ImportProfile(exportedCwtchFile string, password string) (peer.CwtchPeer, error)
|
2023-02-21 23:55:14 +00:00
|
|
|
DeleteProfile(onion string, currentPassword string)
|
2022-10-03 20:05:36 +00:00
|
|
|
AddPeerPlugin(onion string, pluginID plugins.PluginID)
|
2018-09-21 18:53:10 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
GetPrimaryBus() event.Manager
|
|
|
|
GetEventBus(onion string) event.Manager
|
|
|
|
QueryACNStatus()
|
|
|
|
QueryACNVersion()
|
2019-06-05 20:40:55 +00:00
|
|
|
|
2022-12-03 23:48:09 +00:00
|
|
|
ActivateEngines(doListn, doPeers, doServers bool)
|
2023-02-21 23:55:14 +00:00
|
|
|
ActivatePeerEngine(onion string)
|
2022-10-03 20:05:36 +00:00
|
|
|
DeactivatePeerEngine(onion string)
|
2022-08-29 01:19:32 +00:00
|
|
|
|
2023-01-25 20:32:26 +00:00
|
|
|
ReadSettings() GlobalSettings
|
|
|
|
UpdateSettings(settings GlobalSettings)
|
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
ShutdownPeer(string)
|
|
|
|
Shutdown()
|
2019-06-05 20:40:55 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
GetPeer(onion string) peer.CwtchPeer
|
|
|
|
ListProfiles() []string
|
2019-06-05 20:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// LoadProfileFn is the function signature for a function in an app that loads a profile
|
2021-11-09 23:47:33 +00:00
|
|
|
type LoadProfileFn func(profile peer.CwtchPeer)
|
2019-06-05 20:40:55 +00:00
|
|
|
|
2023-02-21 23:55:14 +00:00
|
|
|
func InitApp(appDirectory string) *GlobalSettingsFile {
|
2022-10-03 20:05:36 +00:00
|
|
|
log.Debugf("NewApp(%v)\n", appDirectory)
|
|
|
|
os.MkdirAll(path.Join(appDirectory, "profiles"), 0700)
|
2021-12-17 19:42:55 +00:00
|
|
|
|
2023-01-25 20:32:26 +00:00
|
|
|
// Note: we basically presume this doesn't fail. If the file doesn't exist we create it, and as such the
|
|
|
|
// only plausible error conditions are related to file create e.g. low disk space. If that is the case then
|
|
|
|
// many other parts of Cwtch are likely to fail also.
|
|
|
|
settings, err := InitGlobalSettingsFile(appDirectory, DefactoPasswordForUnencryptedProfiles)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("error initializing global settings file %. Global settings might not be loaded or saves", err)
|
|
|
|
}
|
2023-02-21 23:55:14 +00:00
|
|
|
return settings
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewApp creates a new app with some environment awareness and initializes a Tor Manager
|
|
|
|
func NewApp(acn connectivity.ACN, appDirectory string, settings *GlobalSettingsFile) Application {
|
2023-01-25 20:32:26 +00:00
|
|
|
|
|
|
|
app := &application{engines: make(map[string]connections.Engine), eventBuses: make(map[string]event.Manager), directory: appDirectory, appBus: event.NewEventManager(), settings: settings}
|
2022-10-03 20:05:36 +00:00
|
|
|
app.peers = make(map[string]peer.CwtchPeer)
|
2022-08-29 01:19:32 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
app.acn = acn
|
|
|
|
statusHandler := app.getACNStatusHandler()
|
|
|
|
acn.SetStatusCallback(statusHandler)
|
|
|
|
acn.SetVersionCallback(app.getACNVersionHandler())
|
|
|
|
prog, status := acn.GetBootstrapStatus()
|
|
|
|
statusHandler(prog, status)
|
2019-07-10 20:30:24 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
return app
|
2018-04-30 21:47:21 +00:00
|
|
|
}
|
|
|
|
|
2023-01-25 20:32:26 +00:00
|
|
|
func (app *application) ReadSettings() GlobalSettings {
|
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
|
|
|
return app.settings.ReadGlobalSettings()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *application) UpdateSettings(settings GlobalSettings) {
|
|
|
|
// don't allow any other application changes while settings update
|
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
|
|
|
app.settings.WriteGlobalSettings(settings)
|
|
|
|
|
|
|
|
// we now need to propagate changes to all peers
|
|
|
|
app.peerLock.Lock()
|
|
|
|
defer app.peerLock.Unlock()
|
|
|
|
for _, profile := range app.peers {
|
|
|
|
profile.UpdateExperiments(settings.ExperimentsEnabled, settings.Experiments)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-29 01:19:32 +00:00
|
|
|
// ListProfiles returns a map of onions to their profile's Name
|
|
|
|
func (app *application) ListProfiles() []string {
|
2022-10-03 20:05:36 +00:00
|
|
|
var keys []string
|
|
|
|
|
|
|
|
app.peerLock.Lock()
|
|
|
|
defer app.peerLock.Unlock()
|
|
|
|
for handle := range app.peers {
|
|
|
|
keys = append(keys, handle)
|
|
|
|
}
|
|
|
|
return keys
|
2022-08-29 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetPeer returns a cwtchPeer for a given onion address
|
|
|
|
func (app *application) GetPeer(onion string) peer.CwtchPeer {
|
2022-10-03 20:05:36 +00:00
|
|
|
if peer, ok := app.peers[onion]; ok {
|
|
|
|
return peer
|
|
|
|
}
|
|
|
|
return nil
|
2022-08-29 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ap *application) AddPlugin(peerid string, id plugins.PluginID, bus event.Manager, acn connectivity.ACN) {
|
2022-10-03 20:05:36 +00:00
|
|
|
if _, exists := ap.plugins.Load(peerid); !exists {
|
|
|
|
ap.plugins.Store(peerid, []plugins.Plugin{})
|
|
|
|
}
|
|
|
|
|
|
|
|
pluginsinf, _ := ap.plugins.Load(peerid)
|
|
|
|
peerPlugins := pluginsinf.([]plugins.Plugin)
|
|
|
|
|
2022-12-03 00:23:11 +00:00
|
|
|
for _, plugin := range peerPlugins {
|
|
|
|
if plugin.Id() == id {
|
|
|
|
log.Errorf("trying to add second instance of plugin %v to peer %v", id, peerid)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
newp, err := plugins.Get(id, bus, acn, peerid)
|
|
|
|
if err == nil {
|
|
|
|
newp.Start()
|
|
|
|
peerPlugins = append(peerPlugins, newp)
|
|
|
|
log.Debugf("storing plugin for %v %v", peerid, peerPlugins)
|
|
|
|
ap.plugins.Store(peerid, peerPlugins)
|
|
|
|
} else {
|
|
|
|
log.Errorf("error adding plugin: %v", err)
|
|
|
|
}
|
2022-08-29 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
2023-02-21 23:55:14 +00:00
|
|
|
func (app *application) CreateProfile(name string, password string, autostart bool) {
|
|
|
|
autostartVal := constants.True
|
|
|
|
if !autostart {
|
|
|
|
autostartVal = constants.False
|
|
|
|
}
|
|
|
|
tagVal := constants.ProfileTypeV1Password
|
|
|
|
if password == DefactoPasswordForUnencryptedProfiles {
|
|
|
|
tagVal = constants.ProfileTypeV1DefaultPassword
|
|
|
|
}
|
|
|
|
|
|
|
|
app.CreatePeer(name, password, map[attr.ZonedPath]string{
|
|
|
|
attr.ProfileZone.ConstructZonedPath(constants.Tag): tagVal,
|
|
|
|
attr.ProfileZone.ConstructZonedPath(constants.PeerAutostart): autostartVal,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-12-10 19:50:22 +00:00
|
|
|
// Deprecated in 1.10
|
2019-12-10 23:45:43 +00:00
|
|
|
func (app *application) CreateTaggedPeer(name string, password string, tag string) {
|
2022-12-10 19:50:22 +00:00
|
|
|
app.CreatePeer(name, password, map[attr.ZonedPath]string{attr.ProfileZone.ConstructZonedPath(constants.Tag): tag})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *application) CreatePeer(name string, password string, attributes map[attr.ZonedPath]string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
2021-11-09 23:47:33 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
profileDirectory := path.Join(app.directory, "profiles", model.GenerateRandomID())
|
2021-11-09 23:47:33 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
profile, err := peer.CreateEncryptedStorePeer(profileDirectory, name, password)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Error Creating Peer: %v", err)
|
|
|
|
app.appBus.Publish(event.NewEventList(event.PeerError, event.Error, err.Error()))
|
|
|
|
return
|
|
|
|
}
|
2019-06-05 20:40:55 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
eventBus := event.NewEventManager()
|
|
|
|
app.eventBuses[profile.GetOnion()] = eventBus
|
|
|
|
profile.Init(app.eventBuses[profile.GetOnion()])
|
2023-01-05 21:52:43 +00:00
|
|
|
app.registerHooks(profile)
|
2022-10-03 20:05:36 +00:00
|
|
|
app.peers[profile.GetOnion()] = profile
|
2018-09-21 18:53:10 +00:00
|
|
|
|
2022-12-10 19:50:22 +00:00
|
|
|
for zp, val := range attributes {
|
|
|
|
zone, key := attr.ParseZone(zp.ToString())
|
|
|
|
profile.SetScopedZonedAttribute(attr.LocalScope, zone, key, val)
|
2022-10-03 20:05:36 +00:00
|
|
|
}
|
2022-12-10 19:50:22 +00:00
|
|
|
|
2022-12-03 00:23:11 +00:00
|
|
|
app.AddPeerPlugin(profile.GetOnion(), plugins.CONNECTIONRETRY) // Now Mandatory
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appBus.Publish(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.GetOnion(), event.Created: event.True}))
|
2019-12-10 23:45:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-21 23:55:14 +00:00
|
|
|
func (app *application) DeleteProfile(onion string, password string) {
|
|
|
|
log.Debugf("DeleteProfile called on %v\n", onion)
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
2019-12-10 23:45:43 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
if app.peers[onion].CheckPassword(password) {
|
2022-10-25 20:59:05 +00:00
|
|
|
// soft-shutdown
|
|
|
|
app.peers[onion].Shutdown()
|
|
|
|
// delete the underlying storage
|
2022-10-03 20:05:36 +00:00
|
|
|
app.peers[onion].Delete()
|
2022-10-25 20:59:05 +00:00
|
|
|
// hard shutdown / remove from app
|
|
|
|
app.shutdownPeer(onion)
|
2021-12-17 19:42:55 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
// Shutdown and Remove the Engine
|
|
|
|
log.Debugf("Delete peer for %v Done\n", onion)
|
|
|
|
app.appBus.Publish(event.NewEventList(event.PeerDeleted, event.Identity, onion))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
app.appBus.Publish(event.NewEventList(event.AppError, event.Error, event.PasswordMatchError, event.Identity, onion))
|
2019-12-10 23:45:43 +00:00
|
|
|
}
|
|
|
|
|
2019-08-02 01:09:01 +00:00
|
|
|
func (app *application) AddPeerPlugin(onion string, pluginID plugins.PluginID) {
|
2022-10-03 20:05:36 +00:00
|
|
|
app.AddPlugin(onion, pluginID, app.eventBuses[onion], app.acn)
|
2019-08-02 01:09:01 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 21:45:26 +00:00
|
|
|
func (app *application) ImportProfile(exportedCwtchFile string, password string) (peer.CwtchPeer, error) {
|
2022-10-03 20:05:36 +00:00
|
|
|
profileDirectory := path.Join(app.directory, "profiles")
|
|
|
|
profile, err := peer.ImportProfile(exportedCwtchFile, profileDirectory, password)
|
|
|
|
if profile != nil || err == nil {
|
|
|
|
app.installProfile(profile)
|
|
|
|
}
|
|
|
|
return profile, err
|
2022-03-08 21:45:26 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 20:40:55 +00:00
|
|
|
// LoadProfiles takes a password and attempts to load any profiles it can from storage with it and create Peers for them
|
2021-12-17 19:42:55 +00:00
|
|
|
func (app *application) LoadProfiles(password string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
count := 0
|
|
|
|
migrating := false
|
|
|
|
|
|
|
|
files, err := os.ReadDir(path.Join(app.directory, "profiles"))
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("error: cannot read profiles directory: %v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
// Attempt to load an encrypted database
|
|
|
|
profileDirectory := path.Join(app.directory, "profiles", file.Name())
|
|
|
|
profile, err := peer.FromEncryptedDatabase(profileDirectory, password)
|
|
|
|
loaded := false
|
|
|
|
if err == nil {
|
|
|
|
// return the load the profile...
|
|
|
|
log.Infof("loading profile from new-type storage database...")
|
|
|
|
loaded = app.installProfile(profile)
|
|
|
|
} else { // On failure attempt to load a legacy profile
|
|
|
|
profileStore, err := storage.LoadProfileWriterStore(profileDirectory, password)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Infof("found legacy profile. importing to new database structure...")
|
|
|
|
legacyProfile := profileStore.GetProfileCopy(true)
|
|
|
|
if !migrating {
|
|
|
|
migrating = true
|
|
|
|
app.appBus.Publish(event.NewEventList(event.StartingStorageMiragtion))
|
|
|
|
}
|
|
|
|
|
|
|
|
cps, err := peer.CreateEncryptedStore(profileDirectory, password)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("error creating encrypted store: %v", err)
|
|
|
|
}
|
|
|
|
profile := peer.ImportLegacyProfile(legacyProfile, cps)
|
|
|
|
loaded = app.installProfile(profile)
|
|
|
|
}
|
|
|
|
if loaded {
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if count == 0 {
|
|
|
|
message := event.NewEventList(event.AppError, event.Error, event.AppErrLoaded0)
|
|
|
|
app.appBus.Publish(message)
|
|
|
|
}
|
|
|
|
if migrating {
|
|
|
|
app.appBus.Publish(event.NewEventList(event.DoneStorageMigration))
|
|
|
|
}
|
2021-12-17 19:42:55 +00:00
|
|
|
}
|
|
|
|
|
2023-01-05 21:52:43 +00:00
|
|
|
func (app *application) registerHooks(profile peer.CwtchPeer) {
|
|
|
|
// Register Hooks
|
|
|
|
profile.RegisterHook(extensions.ProfileValueExtension{})
|
|
|
|
profile.RegisterHook(filesharing.Functionality{})
|
|
|
|
}
|
|
|
|
|
2021-12-17 19:42:55 +00:00
|
|
|
// installProfile takes a profile and if it isn't loaded in the app, installs it and returns true
|
|
|
|
func (app *application) installProfile(profile peer.CwtchPeer) bool {
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
|
|
|
|
|
|
|
// Only attempt to finalize the profile if we don't have one loaded...
|
|
|
|
if app.peers[profile.GetOnion()] == nil {
|
|
|
|
eventBus := event.NewEventManager()
|
|
|
|
app.eventBuses[profile.GetOnion()] = eventBus
|
|
|
|
profile.Init(app.eventBuses[profile.GetOnion()])
|
2023-01-05 21:52:43 +00:00
|
|
|
app.registerHooks(profile)
|
2022-10-03 20:05:36 +00:00
|
|
|
app.peers[profile.GetOnion()] = profile
|
2023-01-05 21:52:43 +00:00
|
|
|
|
2022-12-03 00:23:11 +00:00
|
|
|
app.AddPeerPlugin(profile.GetOnion(), plugins.CONNECTIONRETRY) // Now Mandatory
|
2023-01-05 21:52:43 +00:00
|
|
|
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appBus.Publish(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.GetOnion(), event.Created: event.False}))
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
// Otherwise shutdown the connections
|
|
|
|
profile.Shutdown()
|
|
|
|
return false
|
2019-06-05 20:40:55 +00:00
|
|
|
}
|
|
|
|
|
2022-12-03 23:48:09 +00:00
|
|
|
// ActivateEngines launches all peer engines
|
|
|
|
func (app *application) ActivateEngines(doListen, doPeers, doServers bool) {
|
|
|
|
log.Debugf("ActivateEngines")
|
2022-09-26 01:28:04 +00:00
|
|
|
|
|
|
|
for _, profile := range app.peers {
|
|
|
|
app.engines[profile.GetOnion()], _ = profile.GenerateProtocolEngine(app.acn, app.eventBuses[profile.GetOnion()])
|
2022-12-03 23:48:09 +00:00
|
|
|
app.eventBuses[profile.GetOnion()].Publish(event.NewEventList(event.ProtocolEngineCreated))
|
2022-09-26 01:28:04 +00:00
|
|
|
}
|
2022-12-03 23:48:09 +00:00
|
|
|
app.QueryACNStatus()
|
2022-09-26 01:28:04 +00:00
|
|
|
|
|
|
|
if doListen {
|
|
|
|
for _, profile := range app.peers {
|
2022-12-03 00:23:11 +00:00
|
|
|
log.Debugf(" Listen for %v", profile.GetOnion())
|
2022-09-26 01:28:04 +00:00
|
|
|
profile.Listen()
|
|
|
|
}
|
|
|
|
}
|
2022-12-03 00:23:11 +00:00
|
|
|
|
|
|
|
if doPeers || doServers {
|
2022-09-26 01:28:04 +00:00
|
|
|
for _, profile := range app.peers {
|
2022-12-03 00:23:11 +00:00
|
|
|
log.Debugf(" Start Connections for %v doPeers:%v doServers:%v", profile.GetOnion(), doPeers, doServers)
|
|
|
|
profile.StartConnections(doPeers, doServers)
|
2022-09-26 01:28:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-10 17:36:28 +00:00
|
|
|
// ActivePeerEngine creates a peer engine for use with an ACN, should be called once the underlying ACN is online
|
2023-02-21 23:55:14 +00:00
|
|
|
func (app *application) ActivatePeerEngine(onion string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
profile := app.GetPeer(onion)
|
|
|
|
if profile != nil {
|
2022-12-05 04:08:41 +00:00
|
|
|
if _, exists := app.engines[onion]; !exists {
|
|
|
|
app.engines[profile.GetOnion()], _ = profile.GenerateProtocolEngine(app.acn, app.eventBuses[profile.GetOnion()])
|
|
|
|
|
|
|
|
app.eventBuses[profile.GetOnion()].Publish(event.NewEventList(event.ProtocolEngineCreated))
|
|
|
|
app.QueryACNStatus()
|
2023-02-21 23:55:14 +00:00
|
|
|
if true {
|
2022-12-05 04:08:41 +00:00
|
|
|
profile.Listen()
|
|
|
|
}
|
2023-02-21 23:55:14 +00:00
|
|
|
profile.StartConnections(true, true)
|
2022-10-03 20:05:36 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-29 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
2022-09-10 17:36:28 +00:00
|
|
|
// DeactivatePeerEngine shutsdown and cleans up a peer engine, should be called when an underlying ACN goes offline
|
2022-08-29 01:19:32 +00:00
|
|
|
func (app *application) DeactivatePeerEngine(onion string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
if engine, exists := app.engines[onion]; exists {
|
|
|
|
engine.Shutdown()
|
|
|
|
delete(app.engines, onion)
|
|
|
|
}
|
2022-08-29 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 20:40:55 +00:00
|
|
|
// GetPrimaryBus returns the bus the Application uses for events that aren't peer specific
|
|
|
|
func (app *application) GetPrimaryBus() event.Manager {
|
2022-10-03 20:05:36 +00:00
|
|
|
return app.appBus
|
2018-04-30 21:47:21 +00:00
|
|
|
}
|
|
|
|
|
2019-05-15 20:12:11 +00:00
|
|
|
// GetEventBus returns a cwtchPeer's event bus
|
2021-12-17 19:42:55 +00:00
|
|
|
func (app *application) GetEventBus(onion string) event.Manager {
|
2022-10-03 20:05:36 +00:00
|
|
|
if manager, ok := app.eventBuses[onion]; ok {
|
|
|
|
return manager
|
|
|
|
}
|
|
|
|
return nil
|
2019-05-15 20:12:11 +00:00
|
|
|
}
|
2018-10-05 23:27:57 +00:00
|
|
|
|
2019-09-26 23:43:34 +00:00
|
|
|
func (app *application) getACNStatusHandler() func(int, string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
return func(progress int, status string) {
|
|
|
|
progStr := strconv.Itoa(progress)
|
|
|
|
app.appmutex.Lock()
|
|
|
|
app.appBus.Publish(event.NewEventList(event.ACNStatus, event.Progress, progStr, event.Status, status))
|
|
|
|
for _, bus := range app.eventBuses {
|
|
|
|
bus.Publish(event.NewEventList(event.ACNStatus, event.Progress, progStr, event.Status, status))
|
|
|
|
}
|
|
|
|
app.appmutex.Unlock()
|
|
|
|
}
|
2019-09-26 23:43:34 +00:00
|
|
|
}
|
|
|
|
|
2022-08-04 05:20:54 +00:00
|
|
|
func (app *application) getACNVersionHandler() func(string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
return func(version string) {
|
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
|
|
|
app.appBus.Publish(event.NewEventList(event.ACNVersion, event.Data, version))
|
|
|
|
}
|
2022-08-04 05:20:54 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 23:43:34 +00:00
|
|
|
func (app *application) QueryACNStatus() {
|
2022-10-03 20:05:36 +00:00
|
|
|
prog, status := app.acn.GetBootstrapStatus()
|
|
|
|
app.getACNStatusHandler()(prog, status)
|
2019-09-26 23:43:34 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 03:25:17 +00:00
|
|
|
func (app *application) QueryACNVersion() {
|
2022-10-03 20:05:36 +00:00
|
|
|
version := app.acn.GetVersion()
|
|
|
|
app.appBus.Publish(event.NewEventList(event.ACNVersion, event.Data, version))
|
2020-12-01 03:25:17 +00:00
|
|
|
}
|
|
|
|
|
2019-05-15 20:12:11 +00:00
|
|
|
// ShutdownPeer shuts down a peer and removes it from the app's management
|
|
|
|
func (app *application) ShutdownPeer(onion string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
|
|
|
app.shutdownPeer(onion)
|
2022-08-29 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
2022-09-10 17:36:28 +00:00
|
|
|
// shutdownPeer mutex unlocked helper shutdown peer
|
2022-08-29 01:19:32 +00:00
|
|
|
func (app *application) shutdownPeer(onion string) {
|
2022-10-03 20:05:36 +00:00
|
|
|
app.eventBuses[onion].Publish(event.NewEventList(event.ShutdownPeer, event.Identity, onion))
|
|
|
|
app.eventBuses[onion].Shutdown()
|
|
|
|
delete(app.eventBuses, onion)
|
|
|
|
app.peers[onion].Shutdown()
|
|
|
|
delete(app.peers, onion)
|
|
|
|
if _, ok := app.engines[onion]; ok {
|
|
|
|
app.engines[onion].Shutdown()
|
|
|
|
delete(app.engines, onion)
|
|
|
|
}
|
|
|
|
log.Debugf("shutting down plugins for %v", onion)
|
|
|
|
pluginsI, ok := app.plugins.Load(onion)
|
|
|
|
if ok {
|
|
|
|
plugins := pluginsI.([]plugins.Plugin)
|
|
|
|
for _, plugin := range plugins {
|
|
|
|
plugin.Shutdown()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
app.plugins.Delete(onion)
|
2019-01-19 23:16:38 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 01:19:32 +00:00
|
|
|
// Shutdown shutsdown all peers of an app
|
2018-09-21 18:53:10 +00:00
|
|
|
func (app *application) Shutdown() {
|
2022-10-03 20:05:36 +00:00
|
|
|
app.appmutex.Lock()
|
|
|
|
defer app.appmutex.Unlock()
|
|
|
|
for id := range app.peers {
|
|
|
|
log.Debugf("Shutting Down Peer %v", id)
|
|
|
|
app.shutdownPeer(id)
|
|
|
|
}
|
|
|
|
log.Debugf("Shutting Down App")
|
|
|
|
app.appBus.Shutdown()
|
|
|
|
log.Debugf("Shut Down Complete")
|
2018-04-30 21:47:21 +00:00
|
|
|
}
|