cwtch/app/app.go

171 lines
4.4 KiB
Go
Raw Normal View History

2018-04-30 21:47:21 +00:00
package app
import (
"crypto/rand"
2019-01-04 21:44:21 +00:00
"cwtch.im/cwtch/event"
2018-05-28 18:05:06 +00:00
"cwtch.im/cwtch/peer"
2018-10-06 03:50:55 +00:00
"cwtch.im/cwtch/storage"
"encoding/hex"
2018-07-01 18:43:05 +00:00
"fmt"
2018-10-06 03:50:55 +00:00
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
2018-12-04 02:52:11 +00:00
"git.openprivacy.ca/openprivacy/libricochet-go/log"
"io/ioutil"
2018-07-01 18:43:05 +00:00
"os"
"path"
"path/filepath"
"sync"
2018-04-30 21:47:21 +00:00
)
type application struct {
2018-10-04 19:15:03 +00:00
peers map[string]peer.CwtchPeer
2018-11-22 18:01:04 +00:00
acn connectivity.ACN
2018-10-04 19:15:03 +00:00
directory string
mutex sync.Mutex
2018-10-04 04:35:30 +00:00
primaryonion string
2018-10-06 03:50:55 +00:00
storage map[string]storage.ProfileStore
EventBus *event.Manager
}
// Application is a full cwtch peer application. It allows management, usage and storage of multiple peers
type Application interface {
2018-10-06 03:50:55 +00:00
SaveProfile(cwtchPeer peer.CwtchPeer)
LoadProfiles(password string) error
CreatePeer(name string, password string) (peer.CwtchPeer, error)
2018-10-04 04:35:30 +00:00
PrimaryIdentity() peer.CwtchPeer
GetPeer(onion string) peer.CwtchPeer
ListPeers() map[string]string
2018-11-22 00:08:47 +00:00
LaunchPeers()
//GetTorStatus() (map[string]string, error)
2018-10-05 23:27:57 +00:00
Shutdown()
}
// NewApp creates a new app with some environment awareness and initializes a Tor Manager
2018-11-22 18:01:04 +00:00
func NewApp(acn connectivity.ACN, appDirectory string) Application {
2018-12-04 02:52:11 +00:00
log.Debugf("NewApp(%v)\n", appDirectory)
2018-11-22 18:01:04 +00:00
app := &application{peers: make(map[string]peer.CwtchPeer), storage: make(map[string]storage.ProfileStore), directory: appDirectory, acn: acn}
os.Mkdir(path.Join(app.directory, "profiles"), 0700)
app.EventBus = new(event.Manager)
app.EventBus.Initialize()
return app
2018-04-30 21:47:21 +00:00
}
func generateRandomFilename() string {
randBytes := make([]byte, 16)
rand.Read(randBytes)
return filepath.Join(hex.EncodeToString(randBytes))
}
2018-10-06 03:50:55 +00:00
func (app *application) SaveProfile(p peer.CwtchPeer) {
app.mutex.Lock()
defer app.mutex.Unlock()
app.peers[p.GetProfile().Onion] = p
app.storage[p.GetProfile().Onion].Save(p)
}
// NewProfile creates a new cwtchPeer with a given name.
func (app *application) CreatePeer(name string, password string) (peer.CwtchPeer, error) {
2018-12-04 02:52:11 +00:00
log.Debugf("CreatePeer(%v)\n", name)
randomFileName := generateRandomFilename()
2018-10-06 03:50:55 +00:00
fileStore := storage.CreateFileProfileStore(path.Join(app.directory, "profiles", randomFileName), password)
p := peer.NewCwtchPeer(name)
err := fileStore.Save(p)
if err != nil {
return nil, err
}
p.Init(app.acn, app.EventBus)
_, exists := app.peers[p.GetProfile().Onion]
if exists {
p.Shutdown()
return nil, fmt.Errorf("Error: profile for onion %v already exists", p.GetProfile().Onion)
}
app.mutex.Lock()
app.peers[p.GetProfile().Onion] = p
2018-10-06 03:50:55 +00:00
app.storage[p.GetProfile().Onion] = fileStore
app.mutex.Unlock()
return p, nil
}
func (app *application) LoadProfiles(password string) error {
files, err := ioutil.ReadDir(path.Join(app.directory, "profiles"))
if err != nil {
return fmt.Errorf("Error: cannot read profiles directory: %v", err)
}
for _, file := range files {
2018-10-06 03:50:55 +00:00
fileStore := storage.CreateFileProfileStore(path.Join(app.directory, "profiles", file.Name()), password)
p, err := fileStore.Load()
if err != nil {
continue
}
2018-10-06 03:50:55 +00:00
_, exists := app.peers[p.GetProfile().Onion]
if exists {
p.Shutdown()
2018-12-04 02:52:11 +00:00
log.Errorf("profile for onion %v already exists", p.GetProfile().Onion)
continue
}
2018-11-22 00:08:47 +00:00
p.Init(app.acn, app.EventBus)
2018-11-22 00:08:47 +00:00
app.mutex.Lock()
app.peers[p.GetProfile().Onion] = p
2018-10-06 03:50:55 +00:00
app.storage[p.GetProfile().Onion] = fileStore
2018-10-04 04:35:30 +00:00
if app.primaryonion == "" {
app.primaryonion = p.GetProfile().Onion
}
app.mutex.Unlock()
}
return nil
2018-04-30 21:47:21 +00:00
}
2018-11-22 00:08:47 +00:00
func (app *application) LaunchPeers() {
for _, p := range app.peers {
if !p.IsStarted() {
2018-11-26 22:06:26 +00:00
p.Listen()
2018-11-22 00:08:47 +00:00
}
}
}
// ListPeers returns a map of onions to their profile's Name
func (app *application) ListPeers() map[string]string {
keys := map[string]string{}
for k, p := range app.peers {
keys[k] = p.GetProfile().Name
}
return keys
}
2018-10-06 03:50:55 +00:00
// PrimaryIdentity returns a cwtchPeer for a given onion address
2018-10-04 04:35:30 +00:00
func (app *application) PrimaryIdentity() peer.CwtchPeer {
return app.peers[app.primaryonion]
}
2018-10-06 03:50:55 +00:00
// GetPeer returns a cwtchPeer for a given onion address
func (app *application) GetPeer(onion string) peer.CwtchPeer {
if peer, ok := app.peers[onion]; ok {
return peer
}
return nil
2018-04-30 21:47:21 +00:00
}
/*
2018-10-05 23:27:57 +00:00
// GetTorStatus returns tor control port bootstrap-phase status info in a map
func (app *application) GetTorStatus() (map[string]string, error) {
return app.torManager.GetStatus()
}*/
2018-10-05 23:27:57 +00:00
// Shutdown shutsdown all peers of an app and then the tormanager
func (app *application) Shutdown() {
for _, peer := range app.peers {
peer.Shutdown()
}
2018-04-30 21:47:21 +00:00
}