add caching and filtering of contact state change events; change logic from contact auth to approved/blocked
continuous-integration/drone/pr Build is pending Details

This commit is contained in:
Dan Ballard 2022-01-06 16:31:21 -05:00
parent a1e06a868f
commit 86dfe63a8f
5 changed files with 83 additions and 59 deletions

3
go.mod
View File

@ -3,7 +3,7 @@ module git.openprivacy.ca/cwtch.im/libcwtch-go
go 1.15
require (
cwtch.im/cwtch v0.14.9
cwtch.im/cwtch v0.14.10
git.openprivacy.ca/cwtch.im/server v1.4.2
git.openprivacy.ca/openprivacy/connectivity v1.5.0
git.openprivacy.ca/openprivacy/log v1.0.3
@ -12,4 +12,3 @@ require (
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.7 // indirect
)

9
go.sum
View File

@ -10,17 +10,12 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cwtch.im/cwtch v0.14.1/go.mod h1:/fLuoYLY/7JHw6RojFojpd245CiOcU24QpWqzh9FRDI=
cwtch.im/cwtch v0.14.1/go.mod h1:/fLuoYLY/7JHw6RojFojpd245CiOcU24QpWqzh9FRDI=
cwtch.im/cwtch v0.14.8 h1:bybtnnCTp7utGvfIbQvdeffKmJQgGrkfgijrAfS8SQw=
cwtch.im/cwtch v0.14.8/go.mod h1:/fLuoYLY/7JHw6RojFojpd245CiOcU24QpWqzh9FRDI=
cwtch.im/cwtch v0.14.9 h1:VYXbQG6f41fCoLpLEYDAeiJSG+9Gxstl1DOk1Hv4tjM=
cwtch.im/cwtch v0.14.9/go.mod h1:/fLuoYLY/7JHw6RojFojpd245CiOcU24QpWqzh9FRDI=
cwtch.im/cwtch v0.14.10 h1:RA/hehCxeAE+J6YkUuEvS6n8blEAK2ixGnKbq23bN10=
cwtch.im/cwtch v0.14.10/go.mod h1:/fLuoYLY/7JHw6RojFojpd245CiOcU24QpWqzh9FRDI=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
git.openprivacy.ca/cwtch.im/server v1.4.1 h1:ZCySCYxt7rvCLdf2INFWK1xDoSexJD6sJRZ2yZ9iYHU=
git.openprivacy.ca/cwtch.im/server v1.4.1/go.mod h1:gJ57TXx0cnnKN7FZSzr210KNq+WtDtBUo1zHFZ/FbTw=
git.openprivacy.ca/cwtch.im/server v1.4.2 h1:ZcRK1XuWvJzNjYdAvAISD8HcEITPwWbvRiIZGkMKu1k=
git.openprivacy.ca/cwtch.im/server v1.4.2/go.mod h1:CeE/bThy2UVQ+gx+3ctNt65H9xvELDfcwBS9qJwOsOg=
git.openprivacy.ca/cwtch.im/tapir v0.4.9 h1:LXonlztwvI1F1++0IyomIcDH1/Bxzo+oN8YjGonNvjM=

17
lib.go
View File

@ -10,16 +10,15 @@ import (
"crypto/rand"
"encoding/json"
"fmt"
"strconv"
constants2 "cwtch.im/cwtch/model/constants"
"git.openprivacy.ca/cwtch.im/libcwtch-go/features"
// Import SQL Cipher
"os/user"
"runtime"
"strconv"
"strings"
"unsafe"
@ -252,7 +251,7 @@ func ReconnectCwtchForeground() {
// populate profile list
peerList := application.ListProfiles()
for _, onion := range peerList {
eventHandler.Push(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: onion, event.Created: event.False, "Reload": event.True}))
eventHandler.Push(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: onion}))
}
settings := utils.ReadGlobalSettings()
@ -489,6 +488,16 @@ func BlockContact(profileOnion string, conversationID int) {
profile.BlockConversation(conversationID)
}
//export c_UnblockContact
func c_UnblockContact(profilePtr *C.char, profileLen C.int, conversation_id C.int) {
UnblockContact(C.GoStringN(profilePtr, profileLen), int(conversation_id))
}
func UnblockContact(profileOnion string, conversationID int) {
profile := application.GetPeer(profileOnion)
profile.UnblockConversation(conversationID)
}
//export c_GetMessage
// the pointer returned from this function **must** be Freed by c_Free
func c_GetMessage(profile_ptr *C.char, profile_len C.int, conversation_id C.int, message_index C.int) *C.char {
@ -886,7 +895,7 @@ func SetMessageAttribute(profileOnion string, conversationID int, channelID int,
}
//export c_ChangePassword
func c_ChangePassword(profile_ptr *C.char, profile_len C.int, oldpassword_ptr *C.char, oldpassword_len C.int, newpassword_ptr *C.char, newpassword_len C.int, newpassword_again_ptr *C.char, newpassword_again_len C.int) {
func c_ChangePassword(profile_ptr *C.char, profile_len C.int, oldpassword_ptr *C.char, oldpassword_len C.int, newpassword_ptr *C.char, newpassword_len C.int, newpassword_again_ptr *C.char, newpassword_again_len C.int) {
profileOnion := C.GoStringN(profile_ptr, profile_len)
oldPassword := C.GoStringN(oldpassword_ptr, oldpassword_len)
newPassword := C.GoStringN(newpassword_ptr, newpassword_len)

View File

@ -1,17 +1,18 @@
package utils
type Contact struct {
Name string `json:"name"`
Onion string `json:"onion"`
Status string `json:"status"`
Picture string `json:"picture"`
Authorization string `json:"authorization"`
SaveHistory string `json:"saveConversationHistory"`
Messages int `json:"numMessages"`
Unread int `json:"numUnread"`
LastMessage string `json:"lastMsgTime"`
IsGroup bool `json:"isGroup"`
GroupServer string `json:"groupServer"`
IsArchived bool `json:"isArchived"`
Identifier int `json:"identifier"`
Name string `json:"name"`
Onion string `json:"onion"`
Status string `json:"status"`
Picture string `json:"picture"`
Accepted bool `json:"accepted"`
Blocked bool `json:"blocked"`
SaveHistory string `json:"saveConversationHistory"`
Messages int `json:"numMessages"`
Unread int `json:"numUnread"`
LastMessage string `json:"lastMsgTime"`
IsGroup bool `json:"isGroup"`
GroupServer string `json:"groupServer"`
IsArchived bool `json:"isArchived"`
Identifier int `json:"identifier"`
}

View File

@ -184,16 +184,9 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
state = connections.DISCONNECTED
}
// Resolve Conversation Auth State
// TODO: Align this with ACLs
authorization := model.AuthUnknown
if conversationInfo.Accepted {
authorization = model.AuthApproved
}
// If ACL has blocked conversation then hide them...
if acl, exists := conversationInfo.ACL[conversationInfo.Handle]; exists && acl.Blocked {
authorization = model.AuthBlocked
blocked := false
if conversationInfo.ACL[conversationInfo.Handle].Blocked {
blocked = true
}
// Check if we are a server...
@ -208,19 +201,20 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
lastMessage, _ := profile.GetMostRecentMessages(conversationInfo.ID, 0, 0, 1)
contacts = append(contacts, Contact{
Name: name,
Identifier: conversationInfo.ID,
Onion: conversationInfo.Handle,
Status: connections.ConnectionStateName[state],
Picture: cpicPath,
Authorization: string(authorization),
SaveHistory: saveHistory,
Messages: count,
Unread: 0,
LastMessage: strconv.Itoa(getLastMessageTime(lastMessage)),
IsGroup: conversationInfo.IsGroup(),
GroupServer: groupServer,
IsArchived: isArchived == event.True,
Name: name,
Identifier: conversationInfo.ID,
Onion: conversationInfo.Handle,
Status: connections.ConnectionStateName[state],
Picture: cpicPath,
Accepted: conversationInfo.Accepted,
Blocked: blocked,
SaveHistory: saveHistory,
Messages: count,
Unread: 0,
LastMessage: strconv.Itoa(getLastMessageTime(lastMessage)),
IsGroup: conversationInfo.IsGroup(),
GroupServer: groupServer,
IsArchived: isArchived == event.True,
})
}
}
@ -242,6 +236,9 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
// handleProfileEvent enriches Profile events so they are usable with out further data fetches
func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
// cache of contact states to use to filter out events repeating known states
var contactStateCache = make(map[string]connections.ConnectionState)
if eh.app == nil {
log.Errorf("eh.app == nil in handleProfileEvent... this shouldnt happen?")
} else {
@ -312,16 +309,14 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
}
// Resolve Conversation Auth State
// TODO: Align this with ACLs
authorization := model.AuthUnknown
if conversationInfo.Accepted {
authorization = model.AuthApproved
blocked := constants.False
if conversationInfo.ACL[conversationInfo.Handle].Blocked {
blocked = constants.True
}
// If ACL has blocked conversation then hide them...
if acl, exists := conversationInfo.ACL[conversationInfo.Handle]; exists && acl.Blocked {
authorization = model.AuthBlocked
accepted := constants.False
if conversationInfo.Accepted {
accepted = constants.True
}
lastMessage, _ := profile.GetMostRecentMessages(conversationID, 0, 0, 1)
@ -330,7 +325,8 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
ev.Event.Data["numMessages"] = strconv.Itoa(count)
ev.Event.Data["nick"] = conversationInfo.Handle
ev.Event.Data["status"] = connections.ConnectionStateName[profile.GetPeerState(conversationInfo.Handle)]
ev.Event.Data["authorization"] = string(authorization)
ev.Event.Data["accepted"] = accepted
ev.Event.Data["blocked"] = blocked
ev.Event.Data["loading"] = "false"
ev.Event.Data["lastMsgTime"] = strconv.Itoa(getLastMessageTime(lastMessage))
case event.GroupCreated:
@ -351,6 +347,12 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
}
case event.PeerStateChange:
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
// skip events the UI doesn't act on
if cxnState == connections.CONNECTING || cxnState == connections.CONNECTED {
return ""
}
contact, _ := profile.FetchConversationInfo(ev.Event.Data[event.RemotePeer])
if ev.Event.Data[event.RemotePeer] == profile.GetOnion() {
@ -363,15 +365,33 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
return ""
}
// if we already know this state, suppress
if knownState, exists := contactStateCache[ev.Event.Data[event.RemotePeer]]; exists && cxnState == knownState {
return ""
}
contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState
if contact != nil {
// No enrichment needed
//uiManager.UpdateContactStatus(contact.Onion, int(cxnState), false)
if cxnState == connections.AUTHENTICATED {
// if known and authed, get vars
profile.SendScopedZonedGetValToContact(contact.ID, attr.PublicScope, attr.ProfileZone, constants.Name)
profile.SendScopedZonedGetValToContact(contact.ID, attr.PublicScope, attr.ProfileZone, constants2.Picture)
}
}
case event.ServerStateChange:
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
// skip events the UI doesn't act on
if cxnState == connections.CONNECTING || cxnState == connections.CONNECTED {
return ""
}
// if we already know this state, suppress
if knownState, exists := contactStateCache[ev.Event.Data[event.RemotePeer]]; exists && cxnState == knownState {
return ""
}
contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState
case event.NewRetValMessageFromPeer:
// auto handled event means the setting is already done, we're just deciding if we need to tell the UI