2019-06-05 20:40:55 +00:00
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"
2019-07-10 20:30:24 +00:00
"strconv"
2019-06-05 20:40:55 +00:00
)
type applicationService struct {
applicationBridge
2019-07-10 20:30:24 +00:00
appletACN
2019-06-05 20:40:55 +00:00
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 {
2019-07-10 20:30:24 +00:00
appService := & applicationService { storage : make ( map [ string ] storage . ProfileStore ) , engines : make ( map [ string ] connections . Engine ) , applicationBridge : applicationBridge { applicationCore : * newAppCore ( appDirectory ) , bridge : bridge } }
2019-07-19 17:27:50 +00:00
2019-07-10 20:30:24 +00:00
fn := func ( progress int , status string ) {
progStr := strconv . Itoa ( progress )
appService . bridge . Write ( & event . IPCMessage { Dest : DestApp , Message : event . NewEventList ( event . ACNStatus , event . Progreess , progStr , event . Status , status ) } )
}
appService . appletACN . init ( acn , fn )
2019-06-05 20:40:55 +00:00
appService . handle = appService . handleEvent
go appService . listen ( )
2019-06-21 21:50:43 +00:00
log . Infoln ( "Created new App Service" )
2019-06-05 20:40:55 +00:00
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 )
2019-07-19 17:27:50 +00:00
case event . ReloadClient :
for _ , storage := range as . storage {
message := event . IPCMessage { Dest : DestApp , Message : * storage . GetNewPeerMessage ( ) }
as . bridge . Write ( & message )
}
message := event . IPCMessage { Dest : DestApp , Message : event . NewEventList ( event . ReloadDone ) }
as . bridge . Write ( & message )
case event . ReloadPeer :
onion := ev . Data [ event . Identity ]
events := as . storage [ onion ] . GetStatusMessages ( )
for _ , ev := range events {
message := event . IPCMessage { Dest : onion , Message : * ev }
as . bridge . Write ( & message )
}
case event . ShutdownPeer :
onion := ev . Data [ event . Identity ]
as . ShutdownPeer ( onion )
2019-06-05 20:40:55 +00:00
}
}
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
2019-07-19 17:27:50 +00:00
as . applicationCore . LoadProfiles ( password , false , func ( profile * model . Profile , profileStore storage . ProfileStore ) {
2019-07-06 00:46:51 +00:00
as . eventBuses [ profile . Onion ] = event . IPCEventManagerFrom ( as . bridge , profile . Onion , as . eventBuses [ profile . Onion ] )
2019-07-19 17:27:50 +00:00
2019-06-05 20:40:55 +00:00
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 )
}
}
2019-07-19 17:27:50 +00:00
func ( as * applicationService ) ShutdownPeer ( onion string ) {
as . engines [ onion ] . Shutdown ( )
delete ( as . engines , onion )
as . storage [ onion ] . Shutdown ( )
delete ( as . storage , onion )
as . eventBuses [ onion ] . Shutdown ( )
delete ( as . eventBuses , onion )
}
2019-06-05 20:40:55 +00:00
// Shutdown shuts down the application Service and all peer related backend parts
func ( as * applicationService ) Shutdown ( ) {
for id := range as . engines {
2019-07-19 17:27:50 +00:00
as . ShutdownPeer ( id )
2019-06-05 20:40:55 +00:00
}
}