Return ID and use chat topic when sending community message

This commit is contained in:
Andrea Maria Piana 2022-09-05 13:08:44 +01:00
parent 0170d50702
commit d689b337c9
4 changed files with 71 additions and 21 deletions

View File

@ -232,13 +232,20 @@ func (s *MessageSender) getMessageID(rawMessage *RawMessage) (types.HexBytes, er
return messageID, nil
}
// sendCommunity sends data to the recipient identifying with a given public key.
// sendCommunity sends a message that's to be sent in a community
// If it's a chat message, it will go to the respective topic derived by the
// chat id, if it's not a chat message, it will go to the community topic.
func (s *MessageSender) sendCommunity(
ctx context.Context,
rawMessage *RawMessage,
) ([]byte, error) {
s.logger.Debug("sending community message", zap.String("recipient", types.EncodeHex(crypto.FromECDSAPub(&rawMessage.Sender.PublicKey))))
// Set sender
if rawMessage.Sender == nil {
rawMessage.Sender = s.identity
}
messageID, err := s.getMessageID(rawMessage)
if err != nil {
return nil, err
@ -250,6 +257,11 @@ func (s *MessageSender) sendCommunity(
// earlier than the scheduled
s.notifyOnScheduledMessage(nil, rawMessage)
var hash []byte
var newMessage *types.NewMessage
// Check if it's a key exchange message. In this case we send it
// to all the recipients
if rawMessage.CommunityKeyExMsgType != KeyExMsgNone {
keyExMessageSpecs, err := s.protocol.GetKeyExMessageSpecs(rawMessage.CommunityID, s.identity, rawMessage.Recipients, rawMessage.CommunityKeyExMsgType == KeyExMsgRekey)
if err != nil {
@ -269,35 +281,48 @@ func (s *MessageSender) sendCommunity(
return nil, err
}
var payload []byte
// If it's a chat message, we send it on the community chat topic
if rawMessage.MessageType == protobuf.ApplicationMetadataMessage_CHAT_MESSAGE {
messageSpec, err := s.protocol.BuildHashRatchetMessage(rawMessage.CommunityID, wrappedMessage)
if err != nil {
return nil, err
}
payload, err = proto.Marshal(messageSpec.Message)
payload, err := proto.Marshal(messageSpec.Message)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal")
}
hash, newMessage, err = s.sendCommunityChatMessage(ctx, rawMessage, payload)
if err != nil {
return nil, err
}
sentMessage := &SentMessage{
Spec: messageSpec,
MessageIDs: messageIDs,
}
s.notifyOnSentMessage(sentMessage)
} else {
payload = wrappedMessage
payload := wrappedMessage
pubkey, err := crypto.DecompressPubkey(rawMessage.CommunityID)
if err != nil {
return nil, errors.Wrap(err, "failed to decompress pubkey")
}
hash, newMessage, err = s.sendCommunityMessage(ctx, pubkey, payload, messageIDs)
if err != nil {
s.logger.Error("failed to send a community message", zap.Error(err))
return nil, errors.Wrap(err, "failed to send a message spec")
}
s.logger.Debug("sent community message ", zap.String("messageID", messageID.String()), zap.String("hash", types.EncodeHex(hash)))
}
pubkey, err := crypto.DecompressPubkey(rawMessage.CommunityID)
if err != nil {
return nil, errors.Wrap(err, "failed to decompress pubkey")
}
hash, newMessage, err := s.sendCommunityRawMessage(ctx, pubkey, payload, messageIDs)
if err != nil {
s.logger.Error("failed to send a community message", zap.Error(err))
return nil, errors.Wrap(err, "failed to send a message spec")
}
s.logger.Debug("sent community message ", zap.String("messageID", messageID.String()), zap.String("hash", types.EncodeHex(hash)))
s.transport.Track(messageIDs, hash, newMessage)
}
s.transport.Track(messageIDs, hash, newMessage)
return messageID, nil
}
@ -467,6 +492,26 @@ func (s *MessageSender) EncodeAbridgedMembershipUpdate(
return s.encodeMembershipUpdate(message, chatEntity)
}
func (s *MessageSender) sendCommunityChatMessage(ctx context.Context, rawMessage *RawMessage, wrappedMessage []byte) ([]byte, *types.NewMessage, error) {
newMessage := &types.NewMessage{
TTL: whisperTTL,
Payload: wrappedMessage,
PowTarget: calculatePoW(wrappedMessage),
PowTime: whisperPoWTime,
}
// notify before dispatching
s.notifyOnScheduledMessage(nil, rawMessage)
hash, err := s.transport.SendPublic(ctx, newMessage, rawMessage.LocalChatID)
if err != nil {
return nil, nil, err
}
return hash, newMessage, nil
}
// SendPublic takes encoded data, encrypts it and sends through the wire.
func (s *MessageSender) SendPublic(
ctx context.Context,
@ -757,9 +802,9 @@ func (s *MessageSender) sendPrivateRawMessage(ctx context.Context, rawMessage *R
return hash, newMessage, nil
}
// sendCommunityRawMessage sends a message not wrapped in an encryption layer
// sendCommunityMessage sends a message not wrapped in an encryption layer
// to a community
func (s *MessageSender) sendCommunityRawMessage(ctx context.Context, publicKey *ecdsa.PublicKey, payload []byte, messageIDs [][]byte) ([]byte, *types.NewMessage, error) {
func (s *MessageSender) sendCommunityMessage(ctx context.Context, publicKey *ecdsa.PublicKey, payload []byte, messageIDs [][]byte) ([]byte, *types.NewMessage, error) {
newMessage := &types.NewMessage{
TTL: whisperTTL,
Payload: payload,

View File

@ -729,6 +729,7 @@ func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() {
s.Require().NoError(err)
s.Require().Len(response.Messages(), 1)
s.Require().Equal(inputMessage.Text, response.Messages()[0].Text)
// check if response contains the chat we're interested in
// we use this instead of checking just the length of the chat because

View File

@ -728,5 +728,9 @@ func (s *encryptor) decryptWithHR(groupID []byte, keyID uint32, seqNo uint32, pa
decryptedPayload, err := crypto.DecryptSymmetric(hash, payload)
return decryptedPayload, err
if err != nil {
s.logger.Error("failed to decrypt hash", zap.Error(err))
return nil, err
}
return decryptedPayload, nil
}

View File

@ -1806,7 +1806,7 @@ func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage common.RawMe
rawMessage.CommunityID, err = types.DecodeHex(chat.CommunityID)
if err == nil {
_, err = m.sender.SendCommunityMessage(ctx, rawMessage)
id, err = m.sender.SendCommunityMessage(ctx, rawMessage)
}
}
if err != nil {