Merge pull request 'full gomobile and ffi support + new GetMessages' (#3) from gomobile into trunk

Reviewed-on: #3
This commit is contained in:
Dan Ballard 2021-01-28 12:25:39 -08:00
commit 5d0bcf0846
3 changed files with 154 additions and 46 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.idea
cwtch-sources.jar
cwtch.aar
libCwtch.h
libCwtch.so

View File

@ -1,6 +1,14 @@
# Build Instructions... # Build Instructions...
go build -buildmode c-shared -o libCwtch.so make linux
make android
# Using # Using
LD_LIBRARY_PATH set to point to libCwtch.so ## Linux Desktop:
- `LD_LIBRARY_PATH` set to point to `libCwtch.so`
- or drop a symlink into `/usr/lib`
## Android
- copy `cwtch.aar` into `flutter_app/android/cwtch`

183
lib.go
View File

@ -21,19 +21,21 @@ import (
) )
var application app.Application var application app.Application
var appBusQueue event.Queue
var acnQueue event.Queue var acnQueue event.Queue
var contactEventsQueue event.Queue var contactEventsQueue event.Queue
//export HelloWorld //export c_StartCwtch
func HelloWorld(a C.int, b C.int) C.int { func c_StartCwtch(dir_c *C.char, len C.int, tor_c *C.char, torLen C.int) {
return a+b dir := C.GoStringN(dir_c, len)
tor := C.GoStringN(tor_c, torLen)
StartCwtch(dir, tor)
} }
//export StartCwtch func StartCwtch(appDir string, torPath string) {
func StartCwtch(dir_c *C.char, len C.int) {
dir := C.GoStringN(dir_c, len)
log.SetLevel(log.LevelDebug) log.SetLevel(log.LevelDebug)
log.Infof("Loading Cwtch Directory %v", dir)
log.Infof("Loading Cwtch Directory %v and tor path: %v", appDir, torPath)
mrand.Seed(int64(time.Now().Nanosecond())) mrand.Seed(int64(time.Now().Nanosecond()))
port := mrand.Intn(1000) + 9600 port := mrand.Intn(1000) + 9600
@ -46,20 +48,28 @@ func StartCwtch(dir_c *C.char, len C.int) {
panic(err) panic(err)
} }
log.Infof("making directory %v", dir) log.Infof("making directory %v", appDir)
os.MkdirAll(path.Join(dir, "/.tor","tor"),0700) os.MkdirAll(path.Join(appDir, "/.tor", "tor"), 0700)
tor.NewTorrc().WithSocksPort(port).WithOnionTrafficOnly().WithControlPort(controlPort).WithHashedPassword(base64.StdEncoding.EncodeToString(key)).Build(filepath.Join(dir, ".tor", "tor", "torrc")) tor.NewTorrc().WithSocksPort(port).WithOnionTrafficOnly().WithControlPort(controlPort).WithHashedPassword(base64.StdEncoding.EncodeToString(key)).Build(filepath.Join(appDir, ".tor", "tor", "torrc"))
acn, err := tor.NewTorACNWithAuth(path.Join(dir, "/.tor"), "", controlPort, tor.HashedPasswordAuthenticator{base64.StdEncoding.EncodeToString(key)}) acn, err := tor.NewTorACNWithAuth(path.Join(appDir, "/.tor"), torPath, controlPort, tor.HashedPasswordAuthenticator{base64.StdEncoding.EncodeToString(key)})
if err != nil { if err != nil {
log.Errorf("\nError connecting to Tor: %v\n", err) log.Errorf("\nError connecting to Tor: %v\n", err)
} }
//acn.WaitTillBootstrapped() //acn.WaitTillBootstrapped()
newApp := app.NewApp(acn, appDir)
newApp := app.NewApp(acn, dir)
id := mrand.Int31()
acnQueue = event.NewQueue() acnQueue = event.NewQueue()
newApp.GetPrimaryBus().Subscribe(event.ACNStatus, acnQueue) newApp.GetPrimaryBus().Subscribe(event.ACNStatus, acnQueue)
appBusQueue = event.NewQueue()
newApp.GetPrimaryBus().Subscribe(event.NewPeer, appBusQueue)
newApp.GetPrimaryBus().Subscribe(event.PeerError, appBusQueue)
newApp.GetPrimaryBus().Subscribe(event.AppError, appBusQueue)
newApp.GetPrimaryBus().Subscribe(event.ACNStatus, appBusQueue)
newApp.GetPrimaryBus().Subscribe(event.ReloadDone, appBusQueue)
newApp.GetPrimaryBus().Subscribe(event.ACNVersion, appBusQueue)
// Lol this wasn't an intended use
peer.DefaultEventsToHandle = []event.Type{ peer.DefaultEventsToHandle = []event.Type{
event.EncryptedGroupMessage, event.EncryptedGroupMessage,
event.NewMessageFromPeer, event.NewMessageFromPeer,
@ -73,41 +83,81 @@ func StartCwtch(dir_c *C.char, len C.int) {
newApp.LoadProfiles("be gay do crime") newApp.LoadProfiles("be gay do crime")
newApp.LaunchPeers() newApp.LaunchPeers()
application = newApp application = newApp
log.Infof("Providing Handle %v", id) log.Infof("libcwtch-go application SET\n")
} }
//export ACNEvents //export c_ACNEvents
func ACNEvents() *C.char { func c_ACNEvents() *C.char {
return C.CString(ACNEvents())
}
func ACNEvents() string {
select { select {
case myevent := <- acnQueue.OutChan(): case myevent := <- acnQueue.OutChan():
return C.CString(fmt.Sprintf("%v", myevent)) return fmt.Sprintf("%v", myevent)
default: default:
return C.CString("") return ""
} }
} }
//export NextEvent //export c_AppBusEvent
func NextEvent() { func c_AppBusEvent() *C.char {
return C.CString(GetAppBusEvent())
} }
//export GetProfiles
func GetProfiles() *C.char { // GetAppBusEvent blocks until an event
profiles := application.ListPeers() func GetAppBusEvent() string {
select {
case myevent := <- acnQueue.OutChan():
return fmt.Sprintf("%v", myevent)
default:
return ""
}
event := appBusQueue.Next()
return fmt.Sprintf("%v", event)
}
type Profile struct {
Name string `json:"name"`
Onion string `json:"onion"`
ImagePath string `json:"imagePath"`
}
//export c_GetProfiles
func c_GetProfiles() *C.char {
return C.CString(GetProfiles())
}
func GetProfiles() string {
peerList := application.ListPeers()
profiles := make([]Profile, len(peerList))
i := 0
for onion, name := range peerList {
profiles[i] = Profile{
Name: name,
Onion: onion,
ImagePath: "",
}
i += 1
}
jsonBytes,_ := json.Marshal(profiles) jsonBytes,_ := json.Marshal(profiles)
return C.CString(string(jsonBytes)) return string(jsonBytes)
} }
type Contact struct { type Contact struct {
Name string `json:"name"` Name string `json:"name"`
Onion string `json:"onion"` Onion string `json:"onion"`
Status string `json:"status"` Status string `json:"status"`
} }
//export GetContacts //export c_GetContacts
func GetContacts(onion_ptr *C.char, onion_len C.int) *C.char { func c_GetContacts(onion_ptr *C.char, onion_len C.int) *C.char {
return C.CString(GetContacts(C.GoStringN(onion_ptr, onion_len)))
}
onion := C.GoStringN(onion_ptr, onion_len) func GetContacts(onion string)string {
log.Infof("Get Contacts for %v", onion) log.Infof("Get Contacts for %v", onion)
mypeer := application.GetPeer(onion) mypeer := application.GetPeer(onion)
@ -122,47 +172,92 @@ func GetContacts(onion_ptr *C.char, onion_len C.int) *C.char {
} }
bytes,_ := json.Marshal(contacts) bytes,_ := json.Marshal(contacts)
return C.CString(string(bytes)) return string(bytes)
} }
//export c_CreateProfile
func c_CreateProfile(nick_ptr *C.char, nick_len C.int, pass_ptr *C.char, pass_len C.int) {
CreateProfile(C.GoStringN(nick_ptr, nick_len), C.GoStringN(pass_ptr, pass_len))
}
func CreateProfile(nick, pass string) {
application.CreatePeer(nick, pass)
}
//export SelectProfile //export c_SelectProfile
func SelectProfile(onion_ptr *C.char, onion_len C.int) *C.char { func c_SelectProfile(onion_ptr *C.char, onion_len C.int) *C.char {
onion := C.GoStringN(onion_ptr, onion_len) return C.CString(SelectProfile(C.GoStringN(onion_ptr, onion_len)))
}
func SelectProfile(onion string) string {
log.Infof("Select Profile: %v", onion) log.Infof("Select Profile: %v", onion)
contactEventsQueue = event.NewQueue() contactEventsQueue = event.NewQueue()
application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue) application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue)
return C.CString("") return ""
} }
//export ContactEvents //export c_LoadProfiles
func ContactEvents() *C.char { func c_LoadProfiles(passwordPtr *C.char, passwordLen C.int) {
LoadProfiles(C.GoStringN(passwordPtr, passwordLen))
}
func LoadProfiles(pass string) {
application.LoadProfiles(pass)
}
//export c_ContactEvents
func c_ContactEvents() *C.char {
return C.CString(ContactEvents())
}
func ContactEvents() string {
select { select {
case myevent := <- contactEventsQueue.OutChan(): case myevent := <- contactEventsQueue.OutChan():
return C.CString(fmt.Sprintf("%v", myevent)) return fmt.Sprintf("%v", myevent)
default: default:
return C.CString("") return ""
} }
} }
//export NumMessages //export c_NumMessages
func NumMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int) (n C.int) { func c_NumMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int) (n C.int) {
profile := C.GoStringN(profile_ptr, profile_len) profile := C.GoStringN(profile_ptr, profile_len)
handle := C.GoStringN(handle_ptr, handle_len) handle := C.GoStringN(handle_ptr, handle_len)
n = C.int(len(application.GetPeer(profile).GetContact(handle).Timeline.Messages)) return C.int(NumMessages(profile, handle))
}
func NumMessages(profile, handle string) (n int) {
n = len(application.GetPeer(profile).GetContact(handle).Timeline.Messages)
log.Infof("NumMessagse(%s, %s) = %d", profile, handle, n) log.Infof("NumMessagse(%s, %s) = %d", profile, handle, n)
return return
} }
//export GetMessage //export c_GetMessage
func GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char { func c_GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char {
profile := C.GoStringN(profile_ptr, profile_len) profile := C.GoStringN(profile_ptr, profile_len)
handle := C.GoStringN(handle_ptr, handle_len) handle := C.GoStringN(handle_ptr, handle_len)
return C.CString(GetMessage(profile, handle, int(message_index)))
}
// Deprecate - 2021.01.14 - not used
func GetMessage(profile, handle string, message_index int) string {
message := application.GetPeer(profile).GetContact(handle).Timeline.Messages[message_index] message := application.GetPeer(profile).GetContact(handle).Timeline.Messages[message_index]
bytes,_ := json.Marshal(message) bytes,_ := json.Marshal(message)
log.Infof("GetMessage(%s, %s, %d) = %s", profile, handle, message_index, string(bytes)) log.Infof("GetMessage(%s, %s, %d) = %s", profile, handle, message_index, string(bytes))
return C.CString(string(bytes)) return string(bytes)
}
//export c_GetMessages
func c_GetMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, start C.int, end C.int) *C.char {
profile := C.GoStringN(profile_ptr, profile_len)
handle := C.GoStringN(handle_ptr, handle_len)
return C.CString(GetMessages(profile, handle, int(start), int(end)))
}
func GetMessages(profile, handle string, start, end int) string {
messages := application.GetPeer(profile).GetContact(handle).Timeline.Messages[start:end]
bytes,_ := json.Marshal(messages)
return string(bytes)
} }
// Leave as is, needed by ffi // Leave as is, needed by ffi