Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
client
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
elixxir
client
Commits
174bc622
Commit
174bc622
authored
Apr 4, 2022
by
Jake Taylor
Browse files
Options
Downloads
Patches
Plain Diff
refactor send group chat code
parent
df41ca21
No related branches found
No related tags found
4 merge requests
!510
Release
,
!207
WIP: Client Restructure
,
!203
Symmetric broadcast
,
!194
refactor send group chat code
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
groupChat/send.go
+58
-64
58 additions, 64 deletions
groupChat/send.go
with
58 additions
and
64 deletions
groupChat/send.go
+
58
−
64
View file @
174bc622
...
...
@@ -14,6 +14,7 @@ import (
gs
"gitlab.com/elixxir/client/groupChat/groupStore"
"gitlab.com/elixxir/client/network"
"gitlab.com/elixxir/client/network/message"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/group"
"gitlab.com/elixxir/primitives/format"
"gitlab.com/xx_network/primitives/id"
...
...
@@ -38,75 +39,55 @@ const (
// 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
)
{
func
(
m
*
Manager
)
Send
(
groupID
*
id
.
ID
,
message
[]
byte
)
(
id
.
Round
,
time
.
Time
,
group
.
MessageID
,
error
)
{
// Get the relevant group
g
,
exists
:=
m
.
GetGroup
(
groupID
)
if
!
exists
{
return
0
,
time
.
Time
{},
group
.
MessageID
{},
errors
.
Errorf
(
newNoGroupErr
,
groupID
)
}
// get the current time stripped of the monotonic clock
timeNow
:=
netTime
.
Now
()
.
Round
(
0
)
// Create a cMix message for each group member
m
essages
,
msgID
,
err
:=
m
.
create
Messages
(
g
roupID
,
message
,
timeNow
)
groupM
essages
,
err
:=
m
.
new
Messages
(
g
,
message
,
timeNow
)
if
err
!=
nil
{
return
0
,
time
.
Time
{},
group
.
MessageID
{},
errors
.
Errorf
(
newCmixMsgErr
,
err
)
}
// Obtain message ID
msgId
,
err
:=
getGroupMessageId
(
m
.
grp
,
groupID
,
m
.
receptionId
,
timeNow
,
message
)
if
err
!=
nil
{
return
0
,
time
.
Time
{},
group
.
MessageID
{},
err
}
// Send all the groupMessages
param
:=
network
.
GetDefaultCMIXParams
()
param
.
DebugTag
=
"group.Message"
rid
,
_
,
err
:=
m
.
net
.
SendManyCMIX
(
messages
,
param
)
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
)
}
jww
.
DEBUG
.
Printf
(
"Sent message to %d members in group %s at %s."
,
len
(
messages
),
groupID
,
timeNow
)
return
rid
,
timeNow
,
msgID
,
nil
len
(
groupMessages
),
groupID
,
timeNow
)
return
rid
,
timeNow
,
msgId
,
nil
}
// createMessages generates a list of cMix messages and a list of corresponding
// recipient IDs.
func
(
m
*
Manager
)
createMessages
(
groupID
*
id
.
ID
,
msg
[]
byte
,
timestamp
time
.
Time
)
(
[]
network
.
TargetedCmixMessage
,
group
.
MessageID
,
error
)
{
//make the message ID
cmixMsg
:=
format
.
NewMessage
(
m
.
grp
.
GetP
()
.
ByteLen
())
_
,
intlMsg
,
err
:=
newMessageParts
(
cmixMsg
.
ContentsSize
())
if
err
!=
nil
{
return
nil
,
group
.
MessageID
{},
errors
.
WithMessage
(
err
,
"Failed to make message parts for message ID"
)
}
messageID
:=
group
.
NewMessageID
(
groupID
,
setInternalPayload
(
intlMsg
,
timestamp
,
m
.
gs
.
GetUser
()
.
ID
,
msg
))
g
,
exists
:=
m
.
gs
.
Get
(
groupID
)
if
!
exists
{
return
[]
network
.
TargetedCmixMessage
{},
group
.
MessageID
{},
errors
.
Errorf
(
newNoGroupErr
,
groupID
)
}
NewMessages
,
err
:=
m
.
newMessages
(
g
,
msg
,
timestamp
)
return
NewMessages
,
messageID
,
err
}
// newMessages is a private function that allows the passing in of a timestamp
// and streamGen instead of a fastRNG.StreamGenerator for easier testing.
// newMessages quickly builds messages for all group chat members in multiple threads
func
(
m
*
Manager
)
newMessages
(
g
gs
.
Group
,
msg
[]
byte
,
timestamp
time
.
Time
)
(
[]
network
.
TargetedCmixMessage
,
error
)
{
// Create list of cMix messages
messages
:=
make
([]
network
.
TargetedCmixMessage
,
0
,
len
(
g
.
Members
))
// Create channels to receive messages and errors on
type
msgInfo
struct
{
msg
format
.
Message
id
*
id
.
ID
}
msgChan
:=
make
(
chan
network
.
TargetedCmixMessage
,
len
(
g
.
Members
)
-
1
)
errChan
:=
make
(
chan
error
,
len
(
g
.
Members
)
-
1
)
// Create cMix messages in parallel
for
i
,
member
:=
range
g
.
Members
{
// Do not send to the sender
if
m
.
gs
.
GetUser
()
.
ID
.
Cmp
(
member
.
ID
)
{
if
m
.
receptionId
.
Cmp
(
member
.
ID
)
{
continue
}
...
...
@@ -117,19 +98,18 @@ func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
defer
rng
.
Close
()
// Add cMix message to list
msgChan
<-
network
.
TargetedCmixMessage
{
Recipient
:
member
.
ID
,
Payload
:
msg
,
Service
:
message
.
Service
{
Identifier
:
g
.
ID
[
:
],
Tag
:
catalog
.
Group
,
Metadata
:
g
.
ID
[
:
],
},
cMixMsg
,
err
:=
newCmixMsg
(
g
,
msg
,
timestamp
,
member
,
rng
,
m
.
receptionId
,
m
.
grp
)
if
err
!=
nil
{
errChan
<-
errors
.
Errorf
(
newCmixErr
,
i
,
member
.
ID
,
g
.
ID
,
err
)
}
msgChan
<-
cMixMsg
}(
member
,
i
)
}
// Create list of cMix messages
messages
:=
make
([]
network
.
TargetedCmixMessage
,
0
,
len
(
g
.
Members
))
// Wait for messages or errors
for
len
(
messages
)
<
len
(
g
.
Members
)
-
1
{
select
{
...
...
@@ -145,12 +125,21 @@ func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
}
// newCmixMsg generates a new cMix message to be sent to a group member.
func
(
m
*
Manager
)
newCmixMsg
(
g
gs
.
Group
,
msg
[]
byte
,
timestamp
time
.
Time
,
mem
group
.
Member
,
rng
io
.
Reader
)
(
format
.
Message
,
error
)
{
func
newCmixMsg
(
g
gs
.
Group
,
msg
[]
byte
,
timestamp
time
.
Time
,
mem
group
.
Member
,
rng
io
.
Reader
,
senderId
*
id
.
ID
,
grp
*
cyclic
.
Group
)
(
network
.
TargetedCmixMessage
,
error
)
{
// Initialize targeted message
cmixMsg
:=
network
.
TargetedCmixMessage
{
Recipient
:
mem
.
ID
,
Service
:
message
.
Service
{
Identifier
:
g
.
ID
[
:
],
Tag
:
catalog
.
Group
,
Metadata
:
g
.
ID
[
:
],
},
}
// Create three message layers
cmixMsg
:=
format
.
NewMessage
(
m
.
grp
.
GetP
()
.
ByteLen
())
pubMsg
,
intlMsg
,
err
:=
newMessageParts
(
cmixMsg
.
ContentsSize
())
pubMsg
,
intlMsg
,
err
:=
newMessageParts
(
grp
.
GetP
()
.
ByteLen
())
if
err
!=
nil
{
return
cmixMsg
,
err
}
...
...
@@ -168,7 +157,7 @@ func (m *Manager) newCmixMsg(g gs.Group, msg []byte, timestamp time.Time,
}
// Generate key fingerprint
keyFp
:
=
group
.
NewKeyFingerprint
(
g
.
Key
,
salt
,
mem
.
ID
)
cmixMsg
.
Fingerprint
=
group
.
NewKeyFingerprint
(
g
.
Key
,
salt
,
mem
.
ID
)
// Generate key
key
,
err
:=
group
.
NewKdfKey
(
g
.
Key
,
group
.
ComputeEpoch
(
timestamp
),
salt
)
...
...
@@ -177,25 +166,30 @@ func (m *Manager) newCmixMsg(g gs.Group, msg []byte, timestamp time.Time,
}
// Generate internal message
payload
:=
setInternalPayload
(
intlMsg
,
timestamp
,
m
.
gs
.
GetUser
()
.
ID
,
msg
)
payload
:=
setInternalPayload
(
intlMsg
,
timestamp
,
senderId
,
msg
)
// Encrypt internal message
encryptedPayload
:=
group
.
Encrypt
(
key
,
keyFp
,
payload
)
encryptedPayload
:=
group
.
Encrypt
(
key
,
cmixMsg
.
Fingerprint
,
payload
)
// Generate public message
public
Payload
:
=
setPublicPayload
(
pubMsg
,
salt
,
encryptedPayload
)
cmixMsg
.
Payload
=
setPublicPayload
(
pubMsg
,
salt
,
encryptedPayload
)
// Generate MAC
mac
:=
group
.
NewMAC
(
key
,
encryptedPayload
,
g
.
DhKeys
[
*
mem
.
ID
])
// Construct cMix message
cmixMsg
.
SetContents
(
publicPayload
)
cmixMsg
.
SetKeyFP
(
keyFp
)
cmixMsg
.
SetMac
(
mac
)
cmixMsg
.
Mac
=
group
.
NewMAC
(
key
,
encryptedPayload
,
g
.
DhKeys
[
*
mem
.
ID
])
return
cmixMsg
,
nil
}
// Build the group message ID
func
getGroupMessageId
(
grp
*
cyclic
.
Group
,
groupId
,
senderId
*
id
.
ID
,
timestamp
time
.
Time
,
msg
[]
byte
)
(
group
.
MessageID
,
error
)
{
cmixMsg
:=
format
.
NewMessage
(
grp
.
GetP
()
.
ByteLen
())
_
,
intlMsg
,
err
:=
newMessageParts
(
cmixMsg
.
ContentsSize
())
if
err
!=
nil
{
return
group
.
MessageID
{},
errors
.
WithMessage
(
err
,
"Failed to make message parts for message ID"
)
}
return
group
.
NewMessageID
(
groupId
,
setInternalPayload
(
intlMsg
,
timestamp
,
senderId
,
msg
)),
nil
}
// newMessageParts generates a public payload message and the internal payload
// message. An error is returned if the messages cannot fit in the payloadSize.
func
newMessageParts
(
payloadSize
int
)
(
publicMsg
,
internalMsg
,
error
)
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment