package app import ( "cwtch.im/cwtch/connectivity/tor" "cwtch.im/cwtch/peer" "errors" "fmt" "log" "os" "path" ) // Application is a facade over a cwtchPeer that provides some wrapping logic. type Application struct { Peer peer.CwtchPeerInterface TorManager *tor.Manager directory string } // NewApp creates a new app with some environment awareness and initializes a Tor Manager func NewApp(appDirectory string, torPath string) (*Application, error) { log.Printf("NewApp(%v, %v)\n", appDirectory, torPath) app := &Application{Peer: nil, directory: appDirectory} os.MkdirAll(path.Join(appDirectory, "tor"), 0700) err := app.startTor(torPath) if err != nil { return nil, err } return app, nil } // NewProfile creates a new cwtchPeer with a given name. func (app *Application) NewProfile(name string, password string) error { log.Printf("NewProfile(%v, %v)\n", name, password) if app.Peer != nil { return errors.New("Profile already created") } app.Peer = peer.NewCwtchPeer(name, password, path.Join(app.directory, name+".json")) err := app.Peer.Save() if err == nil { err = app.startPeer() } return err } // startTor will create a local torrc if needed func (app *Application) startTor(torPath string) error { // Creating a local cwtch tor server config for the user // creating $app.directory/torrc file // SOCKSPort socksPort // ControlPort controlPort torrc := path.Join(app.directory, "tor", "torrc") if _, err := os.Stat(torrc); os.IsNotExist(err) { log.Printf("writing torrc to: %v\n", torrc) file, err := os.Create(torrc) if err != nil { return err } fmt.Fprintf(file, "SOCKSPort %d\nControlPort %d\nCookieAuthentication 0\nSafeSocks 1\n", 9050, 9051) file.Close() } tm, err := tor.NewTorManager(9050, 9051, torPath, torrc) if err != nil { return err } app.TorManager = tm return nil } // SetProfile loads an existing profile from the given filename. func (app *Application) SetProfile(filename string, password string) error { if app.Peer == nil { profile, err := peer.LoadCwtchPeer(path.Join(app.directory, filename), password) if err != nil { return err } app.Peer = profile return app.startPeer() } return errors.New("profile is already loaded, to load a different profile you will need to restart the application") } func (app *Application) startPeer() error { go func() { e := app.Peer.Listen() if e != nil { log.Panic(e) } }() return nil } // PeerRequest attempts to setup peer relationship with the given onion address.` func (app *Application) PeerRequest(onion string) { app.Peer.PeerWithOnion(onion) }