Skip to content
Snippets Groups Projects
Commit 63d977da authored by Jake Taylor's avatar Jake Taylor
Browse files

refactor group chat receive.go

parent 174bc622
Branches
Tags
4 merge requests!510Release,!207WIP: Client Restructure,!203Symmetric broadcast,!194refactor send group chat code
...@@ -16,7 +16,6 @@ import ( ...@@ -16,7 +16,6 @@ import (
"gitlab.com/elixxir/crypto/group" "gitlab.com/elixxir/crypto/group"
"gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/format"
"gitlab.com/elixxir/primitives/states" "gitlab.com/elixxir/primitives/states"
"gitlab.com/xx_network/primitives/id"
"time" "time"
) )
...@@ -42,71 +41,70 @@ func (p *receptionProcessor) Process(message format.Message, receptionID recepti ...@@ -42,71 +41,70 @@ func (p *receptionProcessor) Process(message format.Message, receptionID recepti
jww.TRACE.Print("Group message reception received cMix message.") jww.TRACE.Print("Group message reception received cMix message.")
// Attempt to read the message // Attempt to read the message
roundTimeStamp := round.Timestamps[states.QUEUED] roundTimestamp := round.Timestamps[states.QUEUED]
msgID, timestamp, senderID, msg, err := decryptMessage(p.g, message, roundTimeStamp)
// Unmarshal cMix message contents to get public message format
pubMsg, err := unmarshalPublicMsg(message.GetContents())
if err != nil {
jww.WARN.Printf("Failed to unmarshal: %+v", errors.Errorf(unmarshalPublicMsgErr, err))
}
// Obtain the cryptKey for the public message
key, err := getCryptKey(p.g.Key, pubMsg.GetSalt(), message.GetMac(),
pubMsg.GetPayload(), p.g.DhKeys, roundTimestamp)
if err != nil {
jww.WARN.Printf("Unable to getCryptKey: %+v", err)
return
}
// Decrypt the message payload using the cryptKey
result, err := decryptMessage(p.g, message.GetKeyFP(), key, pubMsg.GetPayload())
if err != nil { if err != nil {
jww.WARN.Printf("Group message reception failed to read "+ jww.WARN.Printf("Group message reception failed to read "+
"cMix message: %+v", err) "cMix message: %+v", err)
return return
} }
// Populate remaining fields from the top level
result.GroupID = p.g.ID
result.RecipientID = receptionID.Source
result.EphemeralID = receptionID.EphId
result.RoundID = round.ID
result.RoundTimestamp = roundTimestamp
jww.DEBUG.Printf("Received group message with ID %s from sender "+ jww.DEBUG.Printf("Received group message with ID %s from sender "+
"%s in group %s with ID %s at %s.", msgID, senderID, p.g.Name, "%s in group %s with ID %s at %s.", result.ID, result.SenderID, p.g.Name,
p.g.ID, timestamp) p.g.ID, result.Timestamp)
// If the message was read correctly, send it to the callback // If the message was read correctly, send it to the callback
go p.m.receiveFunc(MessageReceive{ go p.m.receiveFunc(result)
GroupID: p.g.ID,
ID: msgID,
Payload: msg,
SenderID: senderID,
RecipientID: receptionID.Source,
EphemeralID: receptionID.EphId,
Timestamp: timestamp,
RoundID: round.ID,
RoundTimestamp: roundTimeStamp,
})
} }
// decryptMessage decrypts the group message payload and returns its message ID, // decryptMessage decrypts the group message payload and returns its message ID,
// timestamp, sender ID, and message contents. // timestamp, sender ID, and message contents.
func decryptMessage(g gs.Group, cMixMsg format.Message, roundTimestamp time.Time) ( func decryptMessage(g gs.Group, fingerprint format.Fingerprint, key group.CryptKey, payload []byte) (
group.MessageID, time.Time, *id.ID, []byte, error) { MessageReceive, error) {
// Unmarshal cMix message contents to get public message format
pubMsg, err := unmarshalPublicMsg(cMixMsg.GetContents())
if err != nil {
return group.MessageID{}, time.Time{}, nil, nil,
errors.Errorf(unmarshalPublicMsgErr, err)
}
key, err := getCryptKey(g.Key, pubMsg.GetSalt(), cMixMsg.GetMac(),
pubMsg.GetPayload(), g.DhKeys, roundTimestamp)
if err != nil {
return group.MessageID{}, time.Time{}, nil, nil, err
}
// Decrypt internal message // Decrypt internal message
decryptedPayload := group.Decrypt(key, cMixMsg.GetKeyFP(), decryptedPayload := group.Decrypt(key, fingerprint, payload)
pubMsg.GetPayload())
// Unmarshal internal message // Unmarshal internal message
intlMsg, err := unmarshalInternalMsg(decryptedPayload) intlMsg, err := unmarshalInternalMsg(decryptedPayload)
if err != nil { if err != nil {
return group.MessageID{}, time.Time{}, nil, nil, return MessageReceive{}, errors.Errorf(unmarshalInternalMsgErr, err)
errors.Errorf(unmarshalInternalMsgErr, err)
} }
// Unmarshal sender ID // Unmarshal sender ID
senderID, err := intlMsg.GetSenderID() senderID, err := intlMsg.GetSenderID()
if err != nil { if err != nil {
return group.MessageID{}, time.Time{}, nil, nil, return MessageReceive{}, errors.Errorf(unmarshalSenderIdErr, err)
errors.Errorf(unmarshalSenderIdErr, err)
} }
messageID := group.NewMessageID(g.ID, intlMsg.Marshal()) return MessageReceive{
ID: group.NewMessageID(g.ID, intlMsg.Marshal()),
return messageID, intlMsg.GetTimestamp(), senderID, intlMsg.GetPayload(), nil Payload: intlMsg.GetPayload(),
SenderID: senderID,
Timestamp: intlMsg.GetTimestamp(),
}, nil
} }
// getCryptKey generates the decryption key for a group internal message. The // getCryptKey generates the decryption key for a group internal message. The
...@@ -117,6 +115,7 @@ func decryptMessage(g gs.Group, cMixMsg format.Message, roundTimestamp time.Time ...@@ -117,6 +115,7 @@ func decryptMessage(g gs.Group, cMixMsg format.Message, roundTimestamp time.Time
// DH key is tried until there is a match. // DH key is tried until there is a match.
func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte, func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte,
dhKeys gs.DhKeyList, roundTimestamp time.Time) (group.CryptKey, error) { dhKeys gs.DhKeyList, roundTimestamp time.Time) (group.CryptKey, error) {
// Compute the current epoch // Compute the current epoch
epoch := group.ComputeEpoch(roundTimestamp) epoch := group.ComputeEpoch(roundTimestamp)
......
...@@ -37,8 +37,8 @@ const ( ...@@ -37,8 +37,8 @@ const (
saltReadLengthErr = "length of generated salt %d != %d required" saltReadLengthErr = "length of generated salt %d != %d required"
) )
// Send sends a message to all group members using Client.SendManyCMIX. The // Send sends a message to all group members using Client.SendManyCMIX.
// send fails if the message is too long. // The send fails if the message is too long.
func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time, group.MessageID, error) { func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time, group.MessageID, error) {
// Get the relevant group // Get the relevant group
...@@ -69,7 +69,7 @@ func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time, gro ...@@ -69,7 +69,7 @@ func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time, gro
rid, _, err := m.net.SendManyCMIX(groupMessages, param) rid, _, err := m.net.SendManyCMIX(groupMessages, param)
if err != nil { if err != nil {
return 0, time.Time{}, group.MessageID{}, return 0, time.Time{}, group.MessageID{},
errors.Errorf(sendManyCmixErr, m.gs.GetUser().ID, groupID, err) errors.Errorf(sendManyCmixErr, m.receptionId, groupID, err)
} }
jww.DEBUG.Printf("Sent message to %d members in group %s at %s.", jww.DEBUG.Printf("Sent message to %d members in group %s at %s.",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment