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 (
"gitlab.com/elixxir/crypto/group"
"gitlab.com/elixxir/primitives/format"
"gitlab.com/elixxir/primitives/states"
"gitlab.com/xx_network/primitives/id"
"time"
)
......@@ -42,71 +41,70 @@ func (p *receptionProcessor) Process(message format.Message, receptionID recepti
jww.TRACE.Print("Group message reception received cMix message.")
// Attempt to read the message
roundTimeStamp := round.Timestamps[states.QUEUED]
msgID, timestamp, senderID, msg, err := decryptMessage(p.g, message, roundTimeStamp)
roundTimestamp := round.Timestamps[states.QUEUED]
// 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 {
jww.WARN.Printf("Group message reception failed to read "+
"cMix message: %+v", err)
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 "+
"%s in group %s with ID %s at %s.", msgID, senderID, p.g.Name,
p.g.ID, timestamp)
"%s in group %s with ID %s at %s.", result.ID, result.SenderID, p.g.Name,
p.g.ID, result.Timestamp)
// If the message was read correctly, send it to the callback
go p.m.receiveFunc(MessageReceive{
GroupID: p.g.ID,
ID: msgID,
Payload: msg,
SenderID: senderID,
RecipientID: receptionID.Source,
EphemeralID: receptionID.EphId,
Timestamp: timestamp,
RoundID: round.ID,
RoundTimestamp: roundTimeStamp,
})
go p.m.receiveFunc(result)
}
// decryptMessage decrypts the group message payload and returns its message ID,
// timestamp, sender ID, and message contents.
func decryptMessage(g gs.Group, cMixMsg format.Message, roundTimestamp time.Time) (
group.MessageID, time.Time, *id.ID, []byte, 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
}
func decryptMessage(g gs.Group, fingerprint format.Fingerprint, key group.CryptKey, payload []byte) (
MessageReceive, error) {
// Decrypt internal message
decryptedPayload := group.Decrypt(key, cMixMsg.GetKeyFP(),
pubMsg.GetPayload())
decryptedPayload := group.Decrypt(key, fingerprint, payload)
// Unmarshal internal message
intlMsg, err := unmarshalInternalMsg(decryptedPayload)
if err != nil {
return group.MessageID{}, time.Time{}, nil, nil,
errors.Errorf(unmarshalInternalMsgErr, err)
return MessageReceive{}, errors.Errorf(unmarshalInternalMsgErr, err)
}
// Unmarshal sender ID
senderID, err := intlMsg.GetSenderID()
if err != nil {
return group.MessageID{}, time.Time{}, nil, nil,
errors.Errorf(unmarshalSenderIdErr, err)
return MessageReceive{}, errors.Errorf(unmarshalSenderIdErr, err)
}
messageID := group.NewMessageID(g.ID, intlMsg.Marshal())
return messageID, intlMsg.GetTimestamp(), senderID, intlMsg.GetPayload(), nil
return MessageReceive{
ID: group.NewMessageID(g.ID, intlMsg.Marshal()),
Payload: intlMsg.GetPayload(),
SenderID: senderID,
Timestamp: intlMsg.GetTimestamp(),
}, nil
}
// 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
// DH key is tried until there is a match.
func getCryptKey(key group.Key, salt [group.SaltLen]byte, mac, payload []byte,
dhKeys gs.DhKeyList, roundTimestamp time.Time) (group.CryptKey, error) {
// Compute the current epoch
epoch := group.ComputeEpoch(roundTimestamp)
......
......@@ -37,8 +37,8 @@ const (
saltReadLengthErr = "length of generated salt %d != %d required"
)
// Send sends a message to all group members using Client.SendManyCMIX. The
// send fails if the message is too long.
// Send sends a message to all group members using Client.SendManyCMIX.
// 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) {
// Get the relevant group
......@@ -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)
if err != nil {
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.",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment