From a9b1f7904ad303b9946790e76bd863d8094090b3 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 5 Mar 2019 12:16:27 -0800 Subject: [PATCH] Fixing Error Handling for Peer Connections, Ack's now don't ack'd error'd messages. Also fixed 1 concurrent map access issue by moving to sync.Map --- go/characters/incominglistener.go | 6 ++-- go/gobjects/message.go | 1 + go/gothings/gcd.go | 17 +++++++---- go/gothings/uistate.go | 50 +++++++++++++++++++++++-------- go/the/globals.go | 1 + main.go | 2 +- qml/overlays/BulletinOverlay.qml | 2 +- qml/overlays/ChatOverlay.qml | 4 ++- qml/overlays/ListOverlay.qml | 2 +- qml/widgets/Message.qml | 2 -- 10 files changed, 61 insertions(+), 26 deletions(-) diff --git a/go/characters/incominglistener.go b/go/characters/incominglistener.go index 31b61e9a..2c1b10bd 100644 --- a/go/characters/incominglistener.go +++ b/go/characters/incominglistener.go @@ -11,7 +11,7 @@ import ( "time" ) -func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func(string,string)) { +func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func(string, string,string)) { q := event.NewEventQueue(1000) the.CwtchApp.EventBus().Subscribe(event.NewMessageFromPeer, q.EventChannel) the.CwtchApp.EventBus().Subscribe(event.NewMessageFromGroup, q.EventChannel) @@ -68,9 +68,9 @@ func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func( case event.NewGroupInvite: log.Debugf("got a group invite!") case event.SendMessageToGroupError: - groupErrorCallback(e.Data[event.Signature], e.Data[event.Error]) + groupErrorCallback(e.Data[event.GroupServer], e.Data[event.Signature], e.Data[event.Error]) case event.SendMessageToPeerError: - groupErrorCallback(e.Data[event.Signature], e.Data[event.Error]) + groupErrorCallback(e.Data[event.RemotePeer], e.Data[event.Signature], e.Data[event.Error]) } } } \ No newline at end of file diff --git a/go/gobjects/message.go b/go/gobjects/message.go index f7321f6e..8001dcad 100644 --- a/go/gobjects/message.go +++ b/go/gobjects/message.go @@ -12,4 +12,5 @@ type Message struct { MessageID string Timestamp time.Time Acknowledged bool + Error bool } diff --git a/go/gothings/gcd.go b/go/gothings/gcd.go index fdc687d6..43c91013 100644 --- a/go/gothings/gcd.go +++ b/go/gothings/gcd.go @@ -29,7 +29,7 @@ type GrandCentralDispatcher struct { _ func(handle, key, value string) `signal:"UpdateContactAttribute"` // messages pane stuff - _ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts string, ackd bool) `signal:"AppendMessage"` + _ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts string, ackd bool, error bool) `signal:"AppendMessage"` _ func() `signal:"ClearMessages"` _ func() `signal:"ResetMessagePane"` _ func(mID string) `signal:"Acknowledged"` @@ -99,6 +99,7 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { mID, time.Now(), false, + false, }) if err != nil { @@ -118,7 +119,7 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { mID = the.Peer.SendMessageToPeer(to, message) this.UIState.AddMessage(&gobjects.Message{ - this.CurrentOpenConversation(), + to, "me", "", message, @@ -127,6 +128,7 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { mID, time.Now(), false, + false, }) ackID := new(the.AckId) @@ -201,7 +203,8 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { tl[i].PeerID == the.Peer.GetProfile().Onion, tl[i].Timestamp.Format(constants.TIME_FORMAT), tl[i].Received.Equal(time.Unix(0,0)) == false, // If the received timestamp is epoch, we have not yet received this message through an active server - ) + false, + ) } return } // ELSE LOAD CONTACT @@ -222,6 +225,9 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { if messages[i].FromMe { from = "me" } + + log.Infof("Loading Message from Store %v", messages[i]) + this.AppendMessage( messages[i].Handle, from, @@ -231,10 +237,11 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { messages[i].MessageID, messages[i].FromMe, messages[i].Timestamp.Format(constants.TIME_FORMAT), - true, + false, + messages[i].Error, ) for _,id := range the.AcknowledgementIDs[messages[i].Handle] { - if id.ID == messages[i].MessageID && id.Ack{ + if id.ID == messages[i].MessageID && id.Ack && !id.Error { this.Acknowledged(id.ID) } } diff --git a/go/gothings/uistate.go b/go/gothings/uistate.go index 96c75ba1..2d06283c 100644 --- a/go/gothings/uistate.go +++ b/go/gothings/uistate.go @@ -9,16 +9,18 @@ import ( "git.openprivacy.ca/openprivacy/libricochet-go/log" "runtime/debug" "strings" + "sync" + "time" ) type InterfaceState struct { parentGcd *GrandCentralDispatcher contacts map[string]*gobjects.Contact - messages map[string][]*gobjects.Message + messages sync.Map } func NewUIState(gcd *GrandCentralDispatcher) (uis InterfaceState) { - uis = InterfaceState{gcd, make(map[string]*gobjects.Contact), make(map[string][]*gobjects.Message)} + uis = InterfaceState{gcd, make(map[string]*gobjects.Contact), sync.Map{}} return } @@ -86,16 +88,33 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact { return this.contacts[handle] } -func (this *InterfaceState) AddGroupError(signature string, err string) { +func (this *InterfaceState) AddSendMessageError(peer string, signature string, err string) { + acklist := the.AcknowledgementIDs[peer] + for _,ack := range acklist { + if ack.ID == signature { + ack.Error = true + } + } + messages,_ := this.messages.Load(peer) + messageList,_ := messages.([]*gobjects.Message) + + for _,message := range messageList { + if message.MessageID == signature { + message.Error = true + } + } + log.Debugf("Received Error Sending Message: %v %v", signature, err) + // FIXME: Sometimes, for the first Peer message we send our error beats our message to the UI + time.Sleep(time.Second*1) this.parentGcd.GroupSendError(signature, err) } func (this *InterfaceState) AddMessage(m *gobjects.Message) { this.GetContact(m.From) - _, found := this.messages[m.Handle] + _,found := this.messages.Load(m.Handle) if !found { - this.messages[m.Handle] = make([]*gobjects.Message, 0) + this.messages.Store(m.Handle, make([]*gobjects.Message, 0)) } // Ack message sent to group @@ -107,17 +126,22 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) { // If an ack, swallow the message and ack from the list. acklist := the.AcknowledgementIDs[m.From] for _,ack := range acklist { - ack.Ack = true - this.parentGcd.Acknowledged(ack.ID) + if ack.Error == false { + ack.Ack = true + this.parentGcd.Acknowledged(ack.ID) + } } } else { - this.messages[m.Handle] = append(this.messages[m.Handle], m) + + messages,_ := this.messages.Load(m.Handle) + messageList,_ := messages.([]*gobjects.Message) + this.messages.Store(m.Handle, append(messageList, m)) // If we have this group loaded already if this.parentGcd.CurrentOpenConversation() == m.Handle { // If the message is not from the user then add it, otherwise, just acknowledge. if !m.FromMe || !m.Acknowledged { - this.parentGcd.AppendMessage(m.Handle, m.From, m.DisplayName, m.Message, m.Image, m.MessageID, m.FromMe, m.Timestamp.Format(constants.TIME_FORMAT), m.Acknowledged) + this.parentGcd.AppendMessage(m.Handle, m.From, m.DisplayName, m.Message, m.Image, m.MessageID, m.FromMe, m.Timestamp.Format(constants.TIME_FORMAT), m.Acknowledged, m.Error) } else { this.parentGcd.Acknowledged(m.MessageID) } @@ -133,11 +157,13 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) { } func (this *InterfaceState) GetMessages(handle string) []*gobjects.Message { - _, found := this.messages[handle] + _,found := this.messages.Load(handle) if !found { - this.messages[handle] = make([]*gobjects.Message, 0) + this.messages.Store(handle, make([]*gobjects.Message, 0)) } - return this.messages[handle] + messages,found := this.messages.Load(handle) + messageList,_ := messages.([]*gobjects.Message) + return messageList } func (this *InterfaceState) UpdateContact(handle string) { diff --git a/go/the/globals.go b/go/the/globals.go index f55547f1..0b82bca7 100644 --- a/go/the/globals.go +++ b/go/the/globals.go @@ -12,6 +12,7 @@ var CwtchDir string type AckId struct { ID string Ack bool + Error bool } var AcknowledgementIDs map[string][]*AckId diff --git a/main.go b/main.go index 0b4ef326..5dc144aa 100644 --- a/main.go +++ b/main.go @@ -111,7 +111,7 @@ func main() { // these are long-lived pollers/listeners for incoming messages and status changes loadCwtchData(gcd, acn) - go characters.IncomingListener(gcd.UIState.AddMessage, gcd.UIState.AddGroupError) + go characters.IncomingListener(gcd.UIState.AddMessage, gcd.UIState.AddSendMessageError) go characters.TorStatusPoller(gcd.TorStatus, acn) go characters.PresencePoller(gcd.UIState.GetContact, gcd.UIState.AddContact, gcd.UIState.UpdateContact) go characters.GroupPoller(gcd.UIState.GetContact, gcd.UIState.UpdateContact) diff --git a/qml/overlays/BulletinOverlay.qml b/qml/overlays/BulletinOverlay.qml index 5ac875d5..640ff1a0 100644 --- a/qml/overlays/BulletinOverlay.qml +++ b/qml/overlays/BulletinOverlay.qml @@ -59,7 +59,7 @@ ColumnLayout { jsonModel4.clear() } - onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts) { + onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { var msg try { msg = JSON.parse(message) diff --git a/qml/overlays/ChatOverlay.qml b/qml/overlays/ChatOverlay.qml index ffc9f769..e3a58be9 100644 --- a/qml/overlays/ChatOverlay.qml +++ b/qml/overlays/ChatOverlay.qml @@ -32,7 +32,7 @@ ColumnLayout { txtMessage.text = "" } - onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ackd) { + onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ackd, error) { var msg try { msg = JSON.parse(message) @@ -52,6 +52,7 @@ ColumnLayout { "_fromMe": fromMe, "_ts": ts, "_ackd": ackd, + "_error": error == true ? "this message failed to send" : "", }) @@ -93,6 +94,7 @@ ColumnLayout { fromMe: _fromMe timestamp: _ts ackd: _ackd + error: _error } } } diff --git a/qml/overlays/ListOverlay.qml b/qml/overlays/ListOverlay.qml index 1e2fd252..46244360 100644 --- a/qml/overlays/ListOverlay.qml +++ b/qml/overlays/ListOverlay.qml @@ -58,7 +58,7 @@ ColumnLayout { jsonModel4.clear() } - onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts) { + onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { var msg try { msg = JSON.parse(message) diff --git a/qml/widgets/Message.qml b/qml/widgets/Message.qml index ad6d7851..4939a672 100644 --- a/qml/widgets/Message.qml +++ b/qml/widgets/Message.qml @@ -35,12 +35,10 @@ RowLayout { } onGroupSendError: function(mid, error) { - console.log("Error " + mid + " " + messageID) if (mid == messageID) { root.error = error } } - }