diff --git a/dm/client.go b/dm/client.go index afdec340ab158f5eab2e907bf1e22856eeb3cab9..9672b1eb13c7a3d59a55209d75302dd5fda62d3b 100644 --- a/dm/client.go +++ b/dm/client.go @@ -81,19 +81,19 @@ func NewDMClient(myID *codename.PrivateIdentity, receiver EventModel, } // Register the listener - dmc.register(receiver, dmc.st.CheckIfSent) + dmc.register(receiver, dmc.st) return dmc } // Register registers a listener for direct messages. func (dc *dmClient) register(apiReceiver EventModel, - checkSent messageReceiveFunc) error { + tracker SendTracker) error { beginningOfTime := time.Time{} r := &receiver{ - c: dc, - api: apiReceiver, - checkSent: checkSent, + c: dc, + api: apiReceiver, + sendTracker: tracker, } // Initialize Send Tracking diff --git a/dm/interfaces.go b/dm/interfaces.go index 601e6e90308723cca5ff724d8240acb1c739f124..5d6f96406cfd49678b0d18c6ee570decb80f17d1 100644 --- a/dm/interfaces.go +++ b/dm/interfaces.go @@ -277,4 +277,10 @@ type SendTracker interface { //CheckIfSent checks if the given message was a sent message CheckIfSent(messageID cryptoMessage.ID, r rounds.Round) bool + + //Delivered marks a message delivered + Delivered(msgID cryptoMessage.ID, round rounds.Round) bool + + //StopTracking stops tracking a message + StopTracking(msgID cryptoMessage.ID, round rounds.Round) bool } diff --git a/dm/receiver.go b/dm/receiver.go index 9c1bc5822c81538c6bbed7eb85c2396f41928eb1..be677a00fe0abfc3f36f0aa9d346f73762cd8c06 100644 --- a/dm/receiver.go +++ b/dm/receiver.go @@ -29,9 +29,9 @@ import ( // receiver struct for message handling type receiver struct { - c *dmClient - api EventModel - checkSent messageReceiveFunc + c *dmClient + api EventModel + sendTracker SendTracker } type dmProcessor struct { @@ -78,7 +78,9 @@ func (dp *dmProcessor) Process(msg format.Message, msgID := message.DeriveDirectMessageID(myID, directMsg) // Check if we sent the message and ignore triggering if we sent - if dp.r.checkSent(msgID, round) { + // This will happen when DM'ing with oneself, but the receive self + // processor will update the status to delivered, so we do nothing here. + if dp.r.sendTracker.CheckIfSent(msgID, round) { return } @@ -172,8 +174,22 @@ func (sp *selfProcessor) Process(msg format.Message, msgID := message.DeriveDirectMessageID(partnerID, directMsg) - // Check if we sent the message and ignore triggering if we sent - if sp.r.checkSent(msgID, round) { + // Check if we sent the message and ignore triggering if we + // sent, but mark the message as delivered + if sp.r.sendTracker.CheckIfSent(msgID, round) { + go func() { + ok := sp.r.sendTracker.Delivered(msgID, round) + if !ok { + jww.WARN.Printf("[DM] Couldn't mark delivered"+ + ": %s %v)", + msgID, round) + } + sp.r.sendTracker.StopTracking(msgID, round) + if !ok { + jww.WARN.Printf("[DM] Coulnd't StopTracking: "+ + "%s, %v", msgID, round) + } + }() return } diff --git a/dm/sendTracker.go b/dm/sendTracker.go index 1c2fab0c08f8b3b037088da74af989a8997a018d..eb5a7e3ec72e9190f285c6079a3a51c3c124dcbb 100644 --- a/dm/sendTracker.go +++ b/dm/sendTracker.go @@ -319,20 +319,39 @@ func (st *sendTracker) handleSendFailed(uuid uint64) (*tracked, error) { } // CheckIfSent is used when a message is received to check if the message was -// sent by this user. If it was, the correct signal is sent to the event model -// and the function returns true, notifying the caller to not process the -// message. +// sent by this user. func (st *sendTracker) CheckIfSent( messageID message.ID, round rounds.Round) bool { st.mux.RLock() - - // Skip if already added + defer st.mux.RUnlock() _, existsMessage := st.byMessageID[messageID] - st.mux.RUnlock() + return existsMessage +} + +// Delivered calls the event model update function to tell it that this +// message was delivered. (after this is called successfully, it is safe to +// stop tracking this message). +// returns true if the update sent status func was called. +func (st *sendTracker) Delivered(messageID message.ID, + round rounds.Round) bool { + st.mux.RLock() + defer st.mux.RUnlock() + msgData, existsMessage := st.byMessageID[messageID] if !existsMessage { return false } + ts := message.MutateTimestamp(round.Timestamps[states.QUEUED], + messageID) + st.updateStatus(msgData.UUID, messageID, ts, + round, Sent) + return true +} + +// StopTracking deletes this message id/round combination from the +// send tracking. returns true if it was removed, false otherwise. +func (st *sendTracker) StopTracking(messageID message.ID, + round rounds.Round) bool { st.mux.Lock() defer st.mux.Unlock() msgData, existsMessage := st.byMessageID[messageID] @@ -359,11 +378,6 @@ func (st *sendTracker) CheckIfSent( } } - ts := message.MutateTimestamp(round.Timestamps[states.QUEUED], - messageID) - go st.updateStatus(msgData.UUID, messageID, ts, - round, Sent) - if err := st.storeSent(); err != nil { jww.FATAL.Panicf("failed to store the updated sent list: %+v", err) diff --git a/dm/sendTracker_test.go b/dm/sendTracker_test.go index 7d7c07f03c173023a09c07548bd28a8ca9c22aa1..ad9a6804592dcbbf2d159cb87dce20e8f030e1c5 100644 --- a/dm/sendTracker_test.go +++ b/dm/sendTracker_test.go @@ -84,6 +84,8 @@ func TestSendTracker_MessageReceive(t *testing.T) { require.NoError(t, err) process = st.CheckIfSent(mid, r) + st.Delivered(mid, r) + st.StopTracking(mid, r) require.True(t, process) directMessage2 := &DirectMessage{ @@ -102,6 +104,8 @@ func TestSendTracker_MessageReceive(t *testing.T) { require.NoError(t, err) process = st.CheckIfSent(mid, r) require.True(t, process) + st.Delivered(mid, r) + st.StopTracking(mid, r) } // Test failedSend function, confirming that data is stored appropriately and