Skip to content
Snippets Groups Projects
Commit bdb09399 authored by Jono Wenger's avatar Jono Wenger
Browse files

Make group chat send return timestamp of send

parent c63bff68
No related branches found
No related tags found
1 merge request!67Release
......@@ -104,14 +104,14 @@ func (g *GroupChat) LeaveGroup(groupIdBytes []byte) error {
// Send sends the message to the specified group. Returns the round the messages
// were sent on.
func (g *GroupChat) Send(groupIdBytes, message []byte) (int64, error) {
func (g *GroupChat) Send(groupIdBytes, message []byte) (*GroupSendReport, error) {
groupID, err := id.Unmarshal(groupIdBytes)
if err != nil {
return 0, errors.Errorf("Failed to unmarshal group ID: %+v", err)
return nil, errors.Errorf("Failed to unmarshal group ID: %+v", err)
}
round, err := g.m.Send(groupID, message)
return int64(round), err
round, timestamp, err := g.m.Send(groupID, message)
return &GroupSendReport{round, timestamp}, err
}
// GetGroups returns an IdList containing a list of group IDs that the user is a
......@@ -141,6 +141,10 @@ func (g *GroupChat) NumGroups() int {
return g.m.NumGroups()
}
////
// NewGroupReport Structure
////
// NewGroupReport is returned when creating a new group and contains the ID of
// the group, a list of rounds that the group requests were sent on, and the
// status of the send.
......@@ -170,6 +174,28 @@ func (ngr *NewGroupReport) GetStatus() int {
return int(ngr.status)
}
////
// NewGroupReport Structure
////
// GroupSendReport is returned when sending a group message. It contains the
// round ID sent on and the timestamp of the send.
type GroupSendReport struct {
roundID id.Round
timestamp time.Time
}
// GetRoundID returns the ID of the round that the send occurred on.
func (gsr *GroupSendReport) GetRoundID() int64 {
return int64(gsr.roundID)
}
// GetTimestampMS returns the timestamp of the send in milliseconds.
func (gsr *GroupSendReport) GetTimestampMS() int64 {
ts := uint64(gsr.timestamp.UnixNano()) / uint64(time.Millisecond)
return int64(ts)
}
////
// Group Structure
////
......
......@@ -218,12 +218,13 @@ func sendGroup(groupIdString string, msg []byte, gm *groupChat.Manager) {
jww.INFO.Printf("Sending to group %s message %q", groupID, msg)
rid, err := gm.Send(groupID, msg)
rid, timestamp, err := gm.Send(groupID, msg)
if err != nil {
jww.FATAL.Panicf("Sending message to group %s: %+v", groupID, err)
}
jww.INFO.Printf("Sent to group %s on round %d", groupID, rid)
jww.INFO.Printf("Sent to group %s on round %d at %s",
groupID, rid, timestamp)
fmt.Printf("Sent message %q to group.\n", msg)
}
......
......@@ -22,6 +22,7 @@ package groupChat
import (
gs "gitlab.com/elixxir/client/groupChat/groupStore"
"gitlab.com/xx_network/primitives/id"
"time"
)
// GroupChat is used to send and receive cMix messages to/from multiple users.
......@@ -49,8 +50,9 @@ type GroupChat interface {
LeaveGroup(groupID *id.ID) error
// Send sends a message to all GroupChat members using Client.SendManyCMIX.
// The send fails if the message is too long.
Send(groupID *id.ID, message []byte) (id.Round, error)
// The send fails if the message is too long. Returns the ID of the round
// sent on and the timestamp of the message send.
Send(groupID *id.ID, message []byte) (id.Round, time.Time, error)
// GetGroups returns a list of all registered GroupChat IDs.
GetGroups() []*id.ID
......
......@@ -36,36 +36,38 @@ 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, error) {
func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time,
error) {
timeNow := netTime.Now()
// Create a cMix message for each group member
messages, err := m.createMessages(groupID, message)
messages, err := m.createMessages(groupID, message, timeNow)
if err != nil {
return 0, errors.Errorf(newCmixMsgErr, err)
return 0, time.Time{}, errors.Errorf(newCmixMsgErr, err)
}
rid, _, err := m.net.SendManyCMIX(messages, params.GetDefaultCMIX())
if err != nil {
return 0, errors.Errorf(sendManyCmixErr, m.gs.GetUser().ID, groupID, err)
return 0, time.Time{},
errors.Errorf(sendManyCmixErr, m.gs.GetUser().ID, groupID, err)
}
jww.DEBUG.Printf("Sent message to group %s.", groupID)
return rid, nil
return rid, timeNow, nil
}
// createMessages generates a list of cMix messages and a list of corresponding
// recipient IDs.
func (m *Manager) createMessages(groupID *id.ID, msg []byte) (
map[id.ID]format.Message, error) {
timeNow := netTime.Now()
func (m *Manager) createMessages(groupID *id.ID, msg []byte,
timestamp time.Time) (map[id.ID]format.Message, error) {
g, exists := m.gs.Get(groupID)
if !exists {
return map[id.ID]format.Message{}, errors.Errorf(newNoGroupErr, groupID)
}
return m.newMessages(g, msg, timeNow)
return m.newMessages(g, msg, timestamp)
}
// newMessages is a private function that allows the passing in of a timestamp
......
......@@ -29,7 +29,7 @@ func TestManager_Send(t *testing.T) {
message := []byte("Group chat message.")
sender := m.gs.GetUser().DeepCopy()
_, err := m.Send(g.ID, message)
_, _, err := m.Send(g.ID, message)
if err != nil {
t.Errorf("Send() returned an error: %+v", err)
}
......@@ -109,7 +109,7 @@ func TestManager_Send_CmixMessageError(t *testing.T) {
expectedErr := strings.SplitN(newCmixMsgErr, "%", 2)[0]
// Send message
_, err := m.Send(g.ID, make([]byte, 400))
_, _, err := m.Send(g.ID, make([]byte, 400))
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("Send() failed to return the expected error."+
"\nexpected: %s\nreceived: %+v", expectedErr, err)
......@@ -124,7 +124,7 @@ func TestManager_Send_SendManyCMIXError(t *testing.T) {
expectedErr := strings.SplitN(sendManyCmixErr, "%", 2)[0]
// Send message
_, err := m.Send(g.ID, []byte("message"))
_, _, err := m.Send(g.ID, []byte("message"))
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("Send() failed to return the expected error."+
"\nexpected: %s\nreceived: %+v", expectedErr, err)
......@@ -144,7 +144,7 @@ func TestManager_createMessages(t *testing.T) {
message := []byte("Test group message.")
sender := m.gs.GetUser()
messages, err := m.createMessages(g.ID, message)
messages, err := m.createMessages(g.ID, message, netTime.Now())
if err != nil {
t.Errorf("createMessages() returned an error: %+v", err)
}
......@@ -204,7 +204,8 @@ func TestManager_createMessages_InvalidGroupIdError(t *testing.T) {
m, _ := newTestManagerWithStore(prng, 10, 0, nil, nil, t)
// Read message and make sure the error is expected
_, err := m.createMessages(id.NewIdFromString("invalidID", id.Group, t), nil)
_, err := m.createMessages(
id.NewIdFromString("invalidID", id.Group, t), nil, time.Time{})
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("createMessages() did not return the expected error."+
"\nexpected: %s\nreceived: %+v", expectedErr, err)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment