Official cwtch.im peer and server implementations. https://cwtch.im
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

appService.go 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package app
  2. import (
  3. "cwtch.im/cwtch/event"
  4. "cwtch.im/cwtch/model"
  5. "cwtch.im/cwtch/protocol/connections"
  6. "cwtch.im/cwtch/storage"
  7. "git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
  8. "git.openprivacy.ca/openprivacy/libricochet-go/identity"
  9. "git.openprivacy.ca/openprivacy/libricochet-go/log"
  10. "path"
  11. )
  12. const (
  13. // DestApp should be used as a destination for IPC messages that are for the application itself an not a peer
  14. DestApp = "app"
  15. )
  16. type applicationService struct {
  17. applicationBridge
  18. storage map[string]storage.ProfileStore
  19. engines map[string]connections.Engine
  20. }
  21. // ApplicationService is the back end of an application that manages engines and writing storage and communicates to an ApplicationClient by an IPCBridge
  22. type ApplicationService interface {
  23. Shutdown()
  24. }
  25. // NewAppService returns an ApplicationService that runs the backend of an app and communicates with a client by the supplied IPCBridge
  26. func NewAppService(acn connectivity.ACN, appDirectory string, bridge event.IPCBridge) ApplicationService {
  27. appService := &applicationService{storage: make(map[string]storage.ProfileStore), engines: make(map[string]connections.Engine), applicationBridge: applicationBridge{applicationCore: *newAppCore(acn, appDirectory), bridge: bridge}}
  28. appService.handle = appService.handleEvent
  29. // Set up IPC
  30. // attach to listener
  31. go appService.listen()
  32. return appService
  33. }
  34. func (as *applicationService) handleEvent(ev *event.Event) {
  35. log.Infof("app Service handleEvent %v\n", ev.EventType)
  36. switch ev.EventType {
  37. case event.CreatePeer:
  38. profileName := ev.Data[event.ProfileName]
  39. password := ev.Data[event.Password]
  40. as.createPeer(profileName, password)
  41. case event.LoadProfiles:
  42. password := ev.Data[event.Password]
  43. as.loadProfiles(password)
  44. }
  45. }
  46. func (as *applicationService) createPeer(name, password string) {
  47. log.Infof("app Service create peer %v %v\n", name, password)
  48. profile, err := as.applicationCore.CreatePeer(name, password)
  49. as.eventBuses[profile.Onion] = event.IPCEventManagerFrom(as.bridge, profile.Onion, as.eventBuses[profile.Onion])
  50. if err != nil {
  51. log.Errorf("Could not create Peer: %v\n", err)
  52. message := event.IPCMessage{Dest: DestApp, Message: event.NewEventList(event.PeerError, event.Error, err.Error())}
  53. as.bridge.Write(&message)
  54. return
  55. }
  56. profileStore := storage.NewProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile)
  57. blockedPeers := profile.BlockedPeers()
  58. // TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key.
  59. identity := identity.InitializeV3(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
  60. engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], blockedPeers)
  61. as.storage[profile.Onion] = profileStore
  62. as.engines[profile.Onion] = engine
  63. message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.LocalID, event.Password: password})}
  64. as.bridge.Write(&message)
  65. }
  66. func (as *applicationService) loadProfiles(password string) {
  67. count := 0
  68. as.applicationCore.LoadProfiles(password, func(profile *model.Profile, profileStore storage.ProfileStore) {
  69. blockedPeers := profile.BlockedPeers()
  70. identity := identity.InitializeV3(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
  71. engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], blockedPeers)
  72. as.mutex.Lock()
  73. as.storage[profile.Onion] = profileStore
  74. as.engines[profile.Onion] = engine
  75. as.mutex.Unlock()
  76. message := event.IPCMessage{Dest: DestApp, Message: event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.LocalID, event.Password: password})}
  77. as.bridge.Write(&message)
  78. count++
  79. })
  80. if count == 0 {
  81. message := event.IPCMessage{Dest: DestApp, Message: event.NewEventList(event.AppError, event.Error, event.AppErrLoaded0)}
  82. as.bridge.Write(&message)
  83. }
  84. }
  85. // Shutdown shuts down the application Service and all peer related backend parts
  86. func (as *applicationService) Shutdown() {
  87. for id := range as.engines {
  88. as.engines[id].Shutdown()
  89. as.storage[id].Shutdown()
  90. as.eventBuses[id].Shutdown()
  91. }
  92. }