forked from cwtch.im/cwtch
111 lines
4.2 KiB
Go
111 lines
4.2 KiB
Go
|
package app
|
||
|
|
||
|
import (
|
||
|
"cwtch.im/cwtch/event"
|
||
|
"cwtch.im/cwtch/model"
|
||
|
"cwtch.im/cwtch/protocol/connections"
|
||
|
"cwtch.im/cwtch/storage"
|
||
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||
|
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||
|
"path"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// DestApp should be used as a destination for IPC messages that are for the application itself an not a peer
|
||
|
DestApp = "app"
|
||
|
)
|
||
|
|
||
|
type applicationService struct {
|
||
|
applicationBridge
|
||
|
|
||
|
storage map[string]storage.ProfileStore
|
||
|
engines map[string]connections.Engine
|
||
|
}
|
||
|
|
||
|
// ApplicationService is the back end of an application that manages engines and writing storage and communicates to an ApplicationClient by an IPCBridge
|
||
|
type ApplicationService interface {
|
||
|
Shutdown()
|
||
|
}
|
||
|
|
||
|
// NewAppService returns an ApplicationService that runs the backend of an app and communicates with a client by the supplied IPCBridge
|
||
|
func NewAppService(acn connectivity.ACN, appDirectory string, bridge event.IPCBridge) ApplicationService {
|
||
|
appService := &applicationService{storage: make(map[string]storage.ProfileStore), engines: make(map[string]connections.Engine), applicationBridge: applicationBridge{applicationCore: *newAppCore(acn, appDirectory), bridge: bridge}}
|
||
|
appService.handle = appService.handleEvent
|
||
|
|
||
|
// Set up IPC
|
||
|
|
||
|
// attach to listener
|
||
|
go appService.listen()
|
||
|
|
||
|
return appService
|
||
|
}
|
||
|
|
||
|
func (as *applicationService) handleEvent(ev *event.Event) {
|
||
|
log.Infof("app Service handleEvent %v\n", ev.EventType)
|
||
|
switch ev.EventType {
|
||
|
case event.CreatePeer:
|
||
|
profileName := ev.Data[event.ProfileName]
|
||
|
password := ev.Data[event.Password]
|
||
|
as.createPeer(profileName, password)
|
||
|
case event.LoadProfiles:
|
||
|
password := ev.Data[event.Password]
|
||
|
as.loadProfiles(password)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (as *applicationService) createPeer(name, password string) {
|
||
|
log.Infof("app Service create peer %v %v\n", name, password)
|
||
|
profile, err := as.applicationCore.CreatePeer(name, password)
|
||
|
as.eventBuses[profile.Onion] = event.IPCEventManagerFrom(as.bridge, profile.Onion, as.eventBuses[profile.Onion])
|
||
|
if err != nil {
|
||
|
log.Errorf("Could not create Peer: %v\n", err)
|
||
|
message := event.IPCMessage{Dest: DestApp, Message: event.NewEventList(event.PeerError, event.Error, err.Error())}
|
||
|
as.bridge.Write(&message)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
profileStore := storage.NewProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile)
|
||
|
|
||
|
blockedPeers := profile.BlockedPeers()
|
||
|
// TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key.
|
||
|
identity := identity.InitializeV3(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
||
|
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], blockedPeers)
|
||
|
|
||
|
as.storage[profile.Onion] = profileStore
|
||
|
as.engines[profile.Onion] = engine
|
||
|
|
||
|
message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.LocalID, event.Password: password})}
|
||
|
as.bridge.Write(&message)
|
||
|
}
|
||
|
|
||
|
func (as *applicationService) loadProfiles(password string) {
|
||
|
count := 0
|
||
|
as.applicationCore.LoadProfiles(password, func(profile *model.Profile, profileStore storage.ProfileStore) {
|
||
|
blockedPeers := profile.BlockedPeers()
|
||
|
identity := identity.InitializeV3(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
||
|
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], blockedPeers)
|
||
|
as.mutex.Lock()
|
||
|
as.storage[profile.Onion] = profileStore
|
||
|
as.engines[profile.Onion] = engine
|
||
|
as.mutex.Unlock()
|
||
|
message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.LocalID, event.Password: password})}
|
||
|
as.bridge.Write(&message)
|
||
|
count++
|
||
|
})
|
||
|
if count == 0 {
|
||
|
message := event.IPCMessage{Dest: DestApp, Message: event.NewEventList(event.AppError, event.Error, event.AppErrLoaded0)}
|
||
|
as.bridge.Write(&message)
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Shutdown shuts down the application Service and all peer related backend parts
|
||
|
func (as *applicationService) Shutdown() {
|
||
|
for id := range as.engines {
|
||
|
as.engines[id].Shutdown()
|
||
|
as.storage[id].Shutdown()
|
||
|
as.eventBuses[id].Shutdown()
|
||
|
}
|
||
|
}
|