//package cwtch package main import "C" import ( "crypto/rand" "cwtch.im/cwtch/app" "cwtch.im/cwtch/event" "cwtch.im/cwtch/peer" "encoding/json" "fmt" "encoding/base64" "git.openprivacy.ca/openprivacy/connectivity/tor" "git.openprivacy.ca/openprivacy/log" mrand "math/rand" "os" "path" "path/filepath" "time" ) var application app.Application var acnQueue event.Queue var contactEventsQueue event.Queue //export HelloWorld func HelloWorld(a C.int, b C.int) C.int { return a+b } //export StartCwtch func StartCwtch(dir_c *C.char, len C.int) { dir := C.GoStringN(dir_c, len) log.SetLevel(log.LevelDebug) log.Infof("Loading Cwtch Directory %v", dir) mrand.Seed(int64(time.Now().Nanosecond())) port := mrand.Intn(1000) + 9600 controlPort := port + 1 // generate a random password (actually random, stored in memory, for the control port) key := make([]byte, 64) _, err := rand.Read(key) if err != nil { panic(err) } log.Infof("making directory %v", dir) os.MkdirAll(path.Join(dir, "/.tor","tor"),0700) tor.NewTorrc().WithSocksPort(port).WithOnionTrafficOnly().WithControlPort(controlPort).WithHashedPassword(base64.StdEncoding.EncodeToString(key)).Build(filepath.Join(dir, ".tor", "tor", "torrc")) acn, err := tor.NewTorACNWithAuth(path.Join(dir, "/.tor"), "", controlPort, tor.HashedPasswordAuthenticator{base64.StdEncoding.EncodeToString(key)}) if err != nil { log.Errorf("\nError connecting to Tor: %v\n", err) } //acn.WaitTillBootstrapped() newApp := app.NewApp(acn, dir) id := mrand.Int31() acnQueue = event.NewQueue() newApp.GetPrimaryBus().Subscribe(event.ACNStatus, acnQueue) peer.DefaultEventsToHandle = []event.Type{ event.EncryptedGroupMessage, event.NewMessageFromPeer, event.PeerAcknowledgement, event.NewGroupInvite, event.PeerError, event.SendMessageToGroupError, event.NewGetValMessageFromPeer, event.PeerStateChange, } newApp.LoadProfiles("be gay do crime") newApp.LaunchPeers() application = newApp log.Infof("Providing Handle %v", id) } //export ACNEvents func ACNEvents() *C.char { select { case myevent := <- acnQueue.OutChan(): return C.CString(fmt.Sprintf("%v", myevent)) default: return C.CString("") } } //export NextEvent func NextEvent() { } //export GetProfiles func GetProfiles() *C.char { profiles := application.ListPeers() jsonBytes,_ := json.Marshal(profiles) return C.CString(string(jsonBytes)) } type Contact struct { Name string `json:"name"` Onion string `json:"onion"` Status string `json:"status"` } //export GetContacts func GetContacts(onion_ptr *C.char, onion_len C.int) *C.char { onion := C.GoStringN(onion_ptr, onion_len) log.Infof("Get Contacts for %v", onion) mypeer := application.GetPeer(onion) contactEventsQueue = event.NewQueue() application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue) var contacts []Contact for _,contact := range mypeer.GetContacts() { contactInfo := mypeer.GetContact(contact) log.Infof("contactInfo %v", contactInfo) contacts = append(contacts, Contact{Name: contactInfo.Name, Onion: contactInfo.Onion, Status: contactInfo.State}) } bytes,_ := json.Marshal(contacts) return C.CString(string(bytes)) } //export SelectProfile func SelectProfile(onion_ptr *C.char, onion_len C.int) *C.char { onion := C.GoStringN(onion_ptr, onion_len) log.Infof("Select Profile: %v", onion) contactEventsQueue = event.NewQueue() application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue) return C.CString("") } //export ContactEvents func ContactEvents() *C.char { select { case myevent := <- contactEventsQueue.OutChan(): return C.CString(fmt.Sprintf("%v", myevent)) default: return C.CString("") } } //export NumMessages func 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) handle := C.GoStringN(handle_ptr, handle_len) n = C.int(len(application.GetPeer(profile).GetContact(handle).Timeline.Messages)) log.Infof("NumMessagse(%s, %s) = %d", profile, handle, n) return } //export 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 { profile := C.GoStringN(profile_ptr, profile_len) handle := C.GoStringN(handle_ptr, handle_len) message := application.GetPeer(profile).GetContact(handle).Timeline.Messages[message_index] bytes,_ := json.Marshal(message) log.Infof("GetMessage(%s, %s, %d) = %s", profile, handle, message_index, string(bytes)) return C.CString(string(bytes)) } // Leave as is, needed by ffi func main() {}