diff --git a/lib.go b/lib.go index 866700a..200d6ac 100644 --- a/lib.go +++ b/lib.go @@ -58,12 +58,21 @@ type ChatMessage struct { func c_StartCwtch(dir_c *C.char, len C.int, tor_c *C.char, torLen C.int) int8 { dir := C.GoStringN(dir_c, len) tor := C.GoStringN(tor_c, torLen) - return StartCwtch(dir, tor) + return int8(StartCwtch(dir, tor)) } -func StartCwtch(appDir string, torPath string) int8 { +// StartCwtch starts cwtch in the library and initlaizes all data structures +// GetAppbusEvents is always safe to use +// the rest of functions are unsafe until the CwtchStarted event has been received indicating StartCwtch has completed +// returns: +// message: CwtchStarted when start up is complete and app is safe to use +// CwtchStartError message when start up fails (includes event.Error data field) +func StartCwtch(appDir string, torPath string) int { + eventHandler = utils.NewEventHandler() log.SetLevel(log.LevelInfo) + // Quick hack check that we're being called with the correct params + // On android a stale worker could be calling us with "last apps" directory. Best to abort fast so the app can make a new worker if runtime.GOOS == "android" { fh, err := os.Open(torPath) if err != nil { @@ -73,7 +82,11 @@ func StartCwtch(appDir string, torPath string) int8 { } _ = fh.Close() } + go _startCwtch(appDir, torPath) + return 0 +} +func _startCwtch(appDir string, torPath string) { // Exclude Tapir wire Messages (We need a TRACE level) log.ExcludeFromPattern("service.go") @@ -100,8 +113,8 @@ func StartCwtch(appDir string, torPath string) int8 { acn, err := tor.NewTorACNWithAuth(path.Join(appDir, "/.tor"), torPath, controlPort, tor.HashedPasswordAuthenticator{Password: base64.StdEncoding.EncodeToString(key)}) if err != nil { log.Errorf("\nError connecting to Tor replacing with ErrorACN: %v\n", err) - // Replace the nil acn with a stub that will do nothing but report this error to the user... - acn = new(utils.ErrorACN) + eventHandler.PublishAppEvent(event.NewEventList(utils.CwtchStartError, event.Error, err)) + return } globalACN = acn newApp := app.NewApp(acn, appDir) @@ -111,7 +124,7 @@ func StartCwtch(appDir string, torPath string) int8 { newApp.GetPrimaryBus().Subscribe(utils.SetLoggingLevel, acnQueue) newApp.GetPrimaryBus().Subscribe(event.AppError, acnQueue) - eventHandler = utils.NewEventHandler(newApp) + eventHandler.HandleApp(newApp) peer.DefaultEventsToHandle = []event.Type{ event.EncryptedGroupMessage, @@ -137,7 +150,7 @@ func StartCwtch(appDir string, torPath string) int8 { // Send global settings to the UI... application.GetPrimaryBus().Publish(event.NewEvent(utils.UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)})) log.Infof("libcwtch-go application launched") - return 0 + application.GetPrimaryBus().Publish(event.NewEvent(utils.CwtchStarted, map[event.Field]string{})) } //export c_ReconnectCwtchForeground @@ -154,20 +167,7 @@ func ReconnectCwtchForeground() { } } -//export c_ACNEvents -func c_ACNEvents() *C.char { - return C.CString(ACNEvents()) -} - -func ACNEvents() string { - select { - case myevent := <-acnQueue.OutChan(): - return fmt.Sprintf("%v", myevent) - default: - return "" - } -} - +//export c_SendAppEvent //export c_SendAppEvent // A generic method for Rebroadcasting App Events from a UI func c_SendAppEvent(json_ptr *C.char, json_len C.int) { @@ -305,20 +305,6 @@ func GetAppBusEvent() string { return json } -//export c_GetProfileRepaintEvent -func c_GetProfileRepaintEvent() int8 { - if GetProfileRepaintEvent() { - return 1 - } else { - return 0 - } -} - -func GetProfileRepaintEvent() bool { - <-acnQueue.OutChan() - return true -} - type Profile struct { Name string `json:"name"` Onion string `json:"onion"` @@ -355,7 +341,7 @@ func c_CreateProfile(nick_ptr *C.char, nick_len C.int, pass_ptr *C.char, pass_le func CreateProfile(nick, pass string) { application.CreatePeer(nick, pass) } - +/* //export c_SelectProfile func c_SelectProfile(onion_ptr *C.char, onion_len C.int) *C.char { return C.CString(SelectProfile(C.GoStringN(onion_ptr, onion_len))) @@ -365,7 +351,7 @@ func SelectProfile(onion string) string { contactEventsQueue = event.NewQueue() application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue) return "" -} +}*/ //export c_LoadProfiles func c_LoadProfiles(passwordPtr *C.char, passwordLen C.int) { diff --git a/utils/errorACN.go b/utils/errorACN.go deleted file mode 100644 index b7ca14f..0000000 --- a/utils/errorACN.go +++ /dev/null @@ -1,50 +0,0 @@ -package utils - -import ( - "errors" - "git.openprivacy.ca/openprivacy/connectivity" - "git.openprivacy.ca/openprivacy/log" - "net" -) - -// ErrorACN is a stub ACN handler used when no other valid ACN can be found. This is a critical error and as such -// this is only used when the only course of action is to close Cwtch and fix the underlying discovery problem... -type ErrorACN struct { -} - -func (e ErrorACN) GetBootstrapStatus() (int, string) { - return -1, "could not find tor" -} - -func (e ErrorACN) WaitTillBootstrapped() { - // instant -} - -func (e ErrorACN) SetStatusCallback(callback func(int, string)) { - callback(-1, "could not find tor please restart cwtch with an active Tor in path") -} - -func (e ErrorACN) Restart() { - // does nothing - log.Errorf("Called Restart() on ErrorACN, which does nothing") -} - -func (e ErrorACN) Open(hostname string) (net.Conn, string, error) { - return nil, "", errors.New("could not find tor") -} - -func (e ErrorACN) Listen(identity connectivity.PrivateKey, port int) (connectivity.ListenService, error) { - return nil, errors.New("could not find tor") -} - -func (e ErrorACN) GetPID() (int, error) { - return 0, errors.New("could not find tor") -} - -func (e ErrorACN) GetVersion() string { - return "could not find tor" -} - -func (e ErrorACN) Close() { - // does nothing -} diff --git a/utils/eventHandler.go b/utils/eventHandler.go index 6a919a5..c00c37b 100644 --- a/utils/eventHandler.go +++ b/utils/eventHandler.go @@ -23,21 +23,32 @@ type EventHandler struct { app app.Application appBusQueue event.Queue profileEvents chan EventProfileEnvelope - profileQueues map[string]event.Queue } -func NewEventHandler(application app.Application) *EventHandler { - appBusQueue := event.NewQueue() - application.GetPrimaryBus().Subscribe(event.NewPeer, appBusQueue) - application.GetPrimaryBus().Subscribe(event.PeerError, appBusQueue) - application.GetPrimaryBus().Subscribe(event.PeerDeleted, appBusQueue) - application.GetPrimaryBus().Subscribe(event.AppError, appBusQueue) - application.GetPrimaryBus().Subscribe(event.ACNStatus, appBusQueue) - application.GetPrimaryBus().Subscribe(event.ReloadDone, appBusQueue) - application.GetPrimaryBus().Subscribe(event.ACNVersion, appBusQueue) - application.GetPrimaryBus().Subscribe(UpdateGlobalSettings, appBusQueue) - return &EventHandler{app: application, appBusQueue: appBusQueue, profileQueues: make(map[string]event.Queue), profileEvents: make(chan EventProfileEnvelope)} +func NewEventHandler() *EventHandler { + eh := &EventHandler{app: nil, appBusQueue: event.NewQueue(), profileQueues: make(map[string]event.Queue), profileEvents: make(chan EventProfileEnvelope)} + return eh +} + +// PublishAppEvent is a way for libCwtch-go to publish an event for consumption by a UI before a Cwtch app has been initalized +// Main use: to signal an error before a cwtch app could be created +func (eh *EventHandler) PublishAppEvent(event event.Event) { + log.Infof("PublishAppEvent %v\n", event) + eh.appBusQueue.Publish(event) +} + +func (eh *EventHandler) HandleApp(application app.Application) { + eh.app = application + application.GetPrimaryBus().Subscribe(event.NewPeer, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(event.PeerError, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(event.PeerDeleted, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(event.AppError, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(event.ACNStatus, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(event.ReloadDone, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(event.ACNVersion, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(UpdateGlobalSettings, eh.appBusQueue) + application.GetPrimaryBus().Subscribe(CwtchStarted, eh.appBusQueue) } func (eh *EventHandler) GetNextEvent() string { diff --git a/utils/settings.go b/utils/settings.go index b068571..e76a8a0 100644 --- a/utils/settings.go +++ b/utils/settings.go @@ -12,6 +12,8 @@ import ( ) const ( + CwtchStarted = event.Type("CwtchStarted") + CwtchStartError = event.Type("CwtchStartError") UpdateGlobalSettings = event.Type("UpdateGlobalSettings") )