diff --git a/model/group.go b/model/group.go index dd59aef..f91ec63 100644 --- a/model/group.go +++ b/model/group.go @@ -17,19 +17,19 @@ import ( // Group defines and encapsulates Cwtch's conception of group chat. Which are sessions // tied to a server under a given group key. Each group has a set of Messages. type Group struct { - GroupID string - SignedGroupID []byte - GroupKey [32]byte - GroupServer string - Timeline Timeline - Accepted bool - Owner string - IsCompromised bool - InitialMessage []byte - Attributes map[string]string - lock sync.Mutex - NewMessage chan Message `json:"-"` - LocalID string + GroupID string + SignedGroupID []byte + GroupKey [32]byte + GroupServer string + Timeline Timeline + Accepted bool + Owner string + IsCompromised bool + InitialMessage []byte + Attributes map[string]string + lock sync.Mutex + LocalID string + unacknowledgedMessages []Message } // NewGroup initializes a new group associated with a given CwtchServer @@ -103,8 +103,36 @@ func (g *Group) Invite(initialMessage []byte) ([]byte, error) { return invite, err } +// AddSentMessage takes a DecryptedGroupMessage and adds it to the Groups Timeline +func (g *Group) AddSentMessage(message *protocol.DecryptedGroupMessage, sig []byte) Message { + g.lock.Lock() + defer g.lock.Unlock() + timelineMessage := Message{ + Message: message.GetText(), + Timestamp: time.Unix(int64(message.GetTimestamp()), 0), + Received: time.Unix(0, 0), + Signature: sig, + PeerID: message.GetOnion(), + PreviousMessageSig: message.GetPreviousMessageSig(), + } + g.unacknowledgedMessages = append(g.unacknowledgedMessages, timelineMessage) + return timelineMessage +} + // AddMessage takes a DecryptedGroupMessage and adds it to the Groups Timeline func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, sig []byte) (*Message, bool) { + + g.lock.Lock() + defer g.lock.Unlock() + + // Delete the message from the unack'd buffer if it exists + for i, unAckedMessage := range g.unacknowledgedMessages { + if compareSignatures(unAckedMessage.Signature, sig) { + g.unacknowledgedMessages = append(g.unacknowledgedMessages[:i], g.unacknowledgedMessages[i+1:]...) + break + } + } + timelineMessage := &Message{ Message: message.GetText(), Timestamp: time.Unix(int64(message.GetTimestamp()), 0), @@ -114,6 +142,7 @@ func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, sig []byte) PreviousMessageSig: message.GetPreviousMessageSig(), } seen := g.Timeline.Insert(timelineMessage) + return timelineMessage, seen } @@ -121,7 +150,7 @@ func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, sig []byte) func (g *Group) GetTimeline() (timeline []Message) { g.lock.Lock() defer g.lock.Unlock() - return g.Timeline.GetMessages() + return append(g.Timeline.GetMessages(), g.unacknowledgedMessages...) } //EncryptMessage takes a message and encrypts the message under the group key. diff --git a/model/profile.go b/model/profile.go index ef2e246..661adb5 100644 --- a/model/profile.go +++ b/model/profile.go @@ -365,6 +365,7 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte, return nil, nil, err } signature := p.SignMessage(groupID + group.GroupServer + string(ciphertext)) + group.AddSentMessage(dm, signature) return ciphertext, signature, nil } return nil, nil, errors.New("group does not exist")