diff --git a/app/app.go b/app/app.go index 4984770..7245529 100644 --- a/app/app.go +++ b/app/app.go @@ -18,6 +18,8 @@ import ( "sync" ) +const AttributeTag = "tag" + type applicationCore struct { eventBuses map[string]event.Manager @@ -39,6 +41,8 @@ type application struct { type Application interface { LoadProfiles(password string) CreatePeer(name string, password string) + CreateTaggedPeer(name string, password string, tag string) + DeletePeer(onion string) AddPeerPlugin(onion string, pluginID plugins.PluginID) LaunchPeers() @@ -92,8 +96,15 @@ func (ac *applicationCore) CreatePeer(name string) (*model.Profile, error) { return profile, nil } -// CreatePeer creates a new Peer with the given name and required accessories (eventbus, storage, protocol engine) -func (app *application) CreatePeer(name string, password string) { +func (ac *applicationCore) DeletePeer(onion string) { + ac.mutex.Lock() + defer ac.mutex.Unlock() + + ac.eventBuses[onion].Shutdown() + delete(ac.eventBuses, onion) +} + +func (app *application) CreateTaggedPeer(name string, password string, tag string) { profile, err := app.applicationCore.CreatePeer(name) if err != nil { app.appBus.Publish(event.NewEventList(event.PeerError, event.Error, err.Error())) @@ -115,9 +126,43 @@ func (app *application) CreatePeer(name string, password string) { app.peers[profile.Onion] = peer app.engines[profile.Onion] = engine + if tag != "" { + peer.SetAttribute(AttributeTag, tag) + } + app.appBus.Publish(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.Onion})) } + +// CreatePeer creates a new Peer with the given name and required accessories (eventbus, storage, protocol engine) +func (app *application) CreatePeer(name string, password string) { + app.CreateTaggedPeer(name, password, "") +} + +func (app *application) DeletePeer(onion string) { + log.Infof("DeletePeer called on %v\n", onion) + app.mutex.Lock() + + app.appletPlugins.ShutdownPeer(onion) + app.plugins.Delete(onion) + + app.peers[onion].Shutdown() + delete(app.peers, onion) + + app.engines[onion].Shutdown() + delete(app.engines, onion) + + app.storage[onion].Shutdown() + app.storage[onion].Delete() + delete(app.storage, onion) + + app.eventBuses[onion].Publish(event.NewEventList(event.ShutdownPeer, event.Identity, onion)) + app.mutex.Unlock() + + app.applicationCore.DeletePeer(onion) + log.Debugf("Delete peer for %v Done\n", onion) +} + func (app *application) AddPeerPlugin(onion string, pluginID plugins.PluginID) { app.AddPlugin(onion, pluginID, app.eventBuses[onion], app.acn) } diff --git a/app/appClient.go b/app/appClient.go index 1117afc..800ba0b 100644 --- a/app/appClient.go +++ b/app/appClient.go @@ -43,6 +43,9 @@ func (ac *applicationClient) handleEvent(ev *event.Event) { password := ev.Data[event.Password] reload := ev.Data[event.Status] == "running" ac.newPeer(localID, password, reload) + case event.DeletePeer: + onion := ev.Data[event.Identity] + ac.handleDeletedPeer(onion) case event.PeerError: ac.appBus.Publish(*ev) case event.AppError: @@ -90,11 +93,31 @@ func (ac *applicationClient) newPeer(localID, password string, reload bool) { // CreatePeer messages the service to create a new Peer with the given name func (ac *applicationClient) CreatePeer(name string, password string) { + ac.CreateTaggedPeer(name, password, "") +} + +func (ac *applicationClient) CreateTaggedPeer(name, password, tag string) { log.Infof("appClient CreatePeer %v\n", name) - message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.CreatePeer, map[event.Field]string{event.ProfileName: name, event.Password: password})} + message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.CreatePeer, map[event.Field]string{event.ProfileName: name, event.Password: password, event.Data: tag})} ac.bridge.Write(&message) } +// DeletePeer messages tehe service to delete a peer +func (ac *applicationClient) DeletePeer(onion string) { + message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.DeletePeer, map[event.Field]string{event.Identity: onion})} + ac.bridge.Write(&message) +} + +func (ac *applicationClient) handleDeletedPeer(onion string) { + ac.mutex.Lock() + ac.peers[onion].Shutdown() + delete(ac.peers, onion) + ac.eventBuses[onion].Publish(event.NewEventList(event.ShutdownPeer, event.Identity, onion)) + ac.mutex.Unlock() + + ac.applicationCore.DeletePeer(onion) +} + func (ac *applicationClient) AddPeerPlugin(onion string, pluginID plugins.PluginID) { message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.AddPeerPlugin, map[event.Field]string{event.Identity: onion, event.Data: strconv.Itoa(int(pluginID))})} ac.bridge.Write(&message) diff --git a/app/appService.go b/app/appService.go index 03539e8..576d46b 100644 --- a/app/appService.go +++ b/app/appService.go @@ -46,7 +46,14 @@ func (as *applicationService) handleEvent(ev *event.Event) { case event.CreatePeer: profileName := ev.Data[event.ProfileName] password := ev.Data[event.Password] - as.createPeer(profileName, password) + tag := ev.Data[event.Data] + as.createPeer(profileName, password, tag) + case event.DeletePeer: + onion := ev.Data[event.Identity] + as.deletePeer(onion) + + message := event.IPCMessage{Dest: DestApp, Message: *ev} + as.bridge.Write(&message) case event.AddPeerPlugin: onion := ev.Data[event.Identity] pluginID, _ := strconv.Atoi(ev.Data[event.Data]) @@ -79,7 +86,7 @@ func (as *applicationService) handleEvent(ev *event.Event) { } } -func (as *applicationService) createPeer(name, password string) { +func (as *applicationService) createPeer(name, password, tag string) { log.Infof("app Service create peer %v %v\n", name, password) profile, err := as.applicationCore.CreatePeer(name) as.eventBuses[profile.Onion] = event.IPCEventManagerFrom(as.bridge, profile.Onion, as.eventBuses[profile.Onion]) @@ -90,6 +97,10 @@ func (as *applicationService) createPeer(name, password string) { return } + if tag != "" { + profile.SetAttribute(AttributeTag, tag) + } + profileStore := storage.NewProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile) blockedPeers := profile.BlockedPeers() @@ -136,6 +147,26 @@ func (as *applicationService) getACNStatusHandler() func(int, string) { } } +func (as *applicationService) deletePeer(onion string) { + as.mutex.Lock() + + as.appletPlugins.ShutdownPeer(onion) + as.plugins.Delete(onion) + + + + as.engines[onion].Shutdown() + delete(as.engines, onion) + + as.storage[onion].Shutdown() + as.storage[onion].Delete() + delete(as.storage, onion) + + as.mutex.Unlock() + + as.applicationCore.DeletePeer(onion) +} + func (as *applicationService) ShutdownPeer(onion string) { as.engines[onion].Shutdown() delete(as.engines, onion) diff --git a/event/common.go b/event/common.go index 443062a..6d0a475 100644 --- a/event/common.go +++ b/event/common.go @@ -129,13 +129,16 @@ const ( /***** Application client / service messages *****/ - // ProfileName, Password + // ProfileName, Password, Data(tag) CreatePeer = Type("CreatePeer") // service -> client: Identity(localId), Password, [Status(new/default=blank || from reload='running')] // app -> Identity(onion) NewPeer = Type("NewPeer") + // Identity(onion) + DeletePeer = Type("DeletePeer") + // Identity(onion), Data(pluginID) AddPeerPlugin = Type("AddPeerPlugin") diff --git a/storage/file_store.go b/storage/file_store.go index 7398ca5..ee802c6 100644 --- a/storage/file_store.go +++ b/storage/file_store.go @@ -2,6 +2,8 @@ package storage import ( "io/ioutil" + "git.openprivacy.ca/openprivacy/libricochet-go/log" + "os" "path" ) @@ -16,6 +18,7 @@ type fileStore struct { type FileStore interface { Save([]byte) error Load() ([]byte, error) + Delete() } // NewFileStore instantiates a fileStore given a filename and a password @@ -39,9 +42,15 @@ func (fps *fileStore) Save(data []byte) error { encryptedbytes = append(salt[:], encryptedbytes...) err = ioutil.WriteFile(path.Join(fps.directory, fps.filename), encryptedbytes, 0600) return err - } func (fps *fileStore) Load() ([]byte, error) { return readEncryptedFile(fps.directory, fps.filename, fps.password) } + +func (fps *fileStore) Delete() { + err := os.Remove(path.Join(fps.directory, fps.filename)) + if err != nil { + log.Errorf("Deleting file %v\n", err) + } +} \ No newline at end of file diff --git a/storage/profile_store.go b/storage/profile_store.go index a7954f8..27288ba 100644 --- a/storage/profile_store.go +++ b/storage/profile_store.go @@ -26,6 +26,7 @@ type profileStore struct { type ProfileStore interface { Load() error Shutdown() + Delete() GetProfileCopy(timeline bool) *model.Profile GetNewPeerMessage() *event.Event GetStatusMessages() []*event.Event @@ -265,3 +266,18 @@ func (ps *profileStore) Shutdown() { ps.queue.Shutdown() } } + +func (ps *profileStore) Delete() { + log.Debugf("Delete ProfileStore for %v\n", ps.profile.Onion) + + for _, ss := range ps.streamStores { + ss.Delete() + } + + ps.fs.Delete() + + err := os.RemoveAll(ps.directory) + if err != nil { + log.Errorf("ProfileStore Delete error on RemoveAll on %v was %v\n", ps.directory, err) + } +}