Skip to content

Commit

Permalink
backup: Update Backup.proto
Browse files Browse the repository at this point in the history
Major changes to SendStatus, minor changes elsewhere.
  • Loading branch information
jrose-signal committed Aug 12, 2024
1 parent d44fdc9 commit d2919ea
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 61 deletions.
128 changes: 93 additions & 35 deletions rust/message-backup/src/backup/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,25 @@ pub struct OutgoingSend {
pub recipient: RecipientId,
pub status: DeliveryStatus,
pub last_status_update: Timestamp,
pub network_failure: bool,
pub identity_key_mismatch: bool,
pub sealed_sender: bool,
}

#[derive(Debug, serde::Serialize)]
#[cfg_attr(test, derive(PartialEq))]
pub enum DeliveryFailureReason {
Unknown,
Network,
IdentityKeyMismatch,
}

#[derive(Debug, serde::Serialize)]
#[cfg_attr(test, derive(PartialEq))]
pub enum DeliveryStatus {
Failed,
Failed(DeliveryFailureReason),
Pending,
Sent,
Delivered,
Read,
Viewed,
Sent { sealed_sender: bool },
Delivered { sealed_sender: bool },
Read { sealed_sender: bool },
Viewed { sealed_sender: bool },
Skipped,
}

Expand All @@ -282,8 +287,8 @@ pub enum DeliveryStatus {
pub enum OutgoingSendError {
/// send status has unknown recipient {0:?}
UnknownRecipient(RecipientId),
/// send status is unknown
SendStatusUnknown,
/// send status is missing
SendStatusMissing,
}

impl std::fmt::Display for InvalidExpiration {
Expand Down Expand Up @@ -526,11 +531,8 @@ impl<R: Contains<RecipientId>> TryFromWith<proto::SendStatus, R> for OutgoingSen
fn try_from_with(item: proto::SendStatus, context: &R) -> Result<Self, Self::Error> {
let proto::SendStatus {
recipientId,
timestamp,
deliveryStatus,
lastStatusUpdateTimestamp,
networkFailure,
identityKeyMismatch,
sealedSender,
special_fields: _,
} = item;

Expand All @@ -540,30 +542,64 @@ impl<R: Contains<RecipientId>> TryFromWith<proto::SendStatus, R> for OutgoingSen
return Err(OutgoingSendError::UnknownRecipient(recipient));
}

use proto::send_status::Status;
let status = match deliveryStatus.enum_value_or_default() {
Status::UNKNOWN => return Err(OutgoingSendError::SendStatusUnknown),
Status::FAILED => DeliveryStatus::Failed,
Status::PENDING => DeliveryStatus::Pending,
Status::SENT => DeliveryStatus::Sent,
Status::DELIVERED => DeliveryStatus::Delivered,
Status::READ => DeliveryStatus::Read,
Status::VIEWED => DeliveryStatus::Viewed,
Status::SKIPPED => DeliveryStatus::Skipped,
let Some(status) = deliveryStatus else {
return Err(OutgoingSendError::SendStatusMissing);
};

let last_status_update = Timestamp::from_millis(
lastStatusUpdateTimestamp,
"SendStatus.lastStatusUpdateTimestamp",
);
use proto::send_status;
let status = match status {
send_status::DeliveryStatus::Pending(send_status::Pending { special_fields: _ }) => {
DeliveryStatus::Pending
}
send_status::DeliveryStatus::Sent(send_status::Sent {
sealedSender,
special_fields: _,
}) => DeliveryStatus::Sent {
sealed_sender: sealedSender,
},
send_status::DeliveryStatus::Delivered(send_status::Delivered {
sealedSender,
special_fields: _,
}) => DeliveryStatus::Delivered {
sealed_sender: sealedSender,
},
send_status::DeliveryStatus::Read(send_status::Read {
sealedSender,
special_fields: _,
}) => DeliveryStatus::Read {
sealed_sender: sealedSender,
},
send_status::DeliveryStatus::Viewed(send_status::Viewed {
sealedSender,
special_fields: _,
}) => DeliveryStatus::Viewed {
sealed_sender: sealedSender,
},
send_status::DeliveryStatus::Skipped(send_status::Skipped { special_fields: _ }) => {
DeliveryStatus::Skipped
}
send_status::DeliveryStatus::Failed(send_status::Failed {
reason,
special_fields: _,
}) => {
// Note that we treat truly unknown enum values here as the default; that's already
// checked separately.
DeliveryStatus::Failed(match reason.enum_value_or_default() {
send_status::failed::FailureReason::UNKNOWN => DeliveryFailureReason::Unknown,
send_status::failed::FailureReason::NETWORK => DeliveryFailureReason::Network,
send_status::failed::FailureReason::IDENTITY_KEY_MISMATCH => {
DeliveryFailureReason::IdentityKeyMismatch
}
})
}
};

let last_status_update = Timestamp::from_millis(timestamp, "SendStatus.timestamp");

Ok(Self {
recipient,
status,
last_status_update,
network_failure: networkFailure,
identity_key_mismatch: identityKeyMismatch,
sealed_sender: sealedSender,
})
}
}
Expand Down Expand Up @@ -655,7 +691,7 @@ mod test {

use assert_matches::assert_matches;

use protobuf::{EnumOrUnknown, SpecialFields};
use protobuf::SpecialFields;
use test_case::test_case;

use crate::backup::chat::testutil::TestContext;
Expand Down Expand Up @@ -727,7 +763,9 @@ mod test {
fn test_data() -> Self {
Self {
recipientId: proto::Recipient::TEST_ID,
deliveryStatus: proto::send_status::Status::PENDING.into(),
deliveryStatus: Some(proto::send_status::DeliveryStatus::Pending(
proto::send_status::Pending::default(),
)),
..Default::default()
}
}
Expand Down Expand Up @@ -816,7 +854,26 @@ mod test {
message.directionalDetails = Some(
proto::chat_item::OutgoingMessageDetails {
sendStatus: vec![proto::SendStatus {
deliveryStatus: EnumOrUnknown::default(),
deliveryStatus: None,
..proto::SendStatus::test_data()
}],
..proto::chat_item::OutgoingMessageDetails::test_data()
}
.into(),
);
}
fn outgoing_send_status_failed(message: &mut proto::ChatItem) {
message.directionalDetails = Some(
proto::chat_item::OutgoingMessageDetails {
sendStatus: vec![proto::SendStatus {
deliveryStatus: Some(proto::send_status::DeliveryStatus::Failed(
proto::send_status::Failed {
// Unlike many other UNKNOWN cases in Backup.proto, this one is
// considered valid; the other cases are just being more specific.
reason: proto::send_status::failed::FailureReason::UNKNOWN.into(),
..Default::default()
},
)),
..proto::SendStatus::test_data()
}],
..proto::chat_item::OutgoingMessageDetails::test_data()
Expand Down Expand Up @@ -845,8 +902,9 @@ mod test {
#[test_case(outgoing_valid, Ok(()))]
#[test_case(
outgoing_send_status_unknown,
Err(ChatItemError::Outgoing(OutgoingSendError::SendStatusUnknown))
Err(ChatItemError::Outgoing(OutgoingSendError::SendStatusMissing))
)]
#[test_case(outgoing_send_status_failed, Ok(()))]
#[test_case(
outgoing_unknown_recipient,
Err(ChatItemError::Outgoing(OutgoingSendError::UnknownRecipient(RecipientId(0xffff))))
Expand Down
6 changes: 3 additions & 3 deletions rust/message-backup/src/backup/chat/chat_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub struct BubbleColorPreset {
}

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, serde::Serialize)]
pub struct CustomColorId(pub(crate) u32);
pub struct CustomColorId(pub(crate) u64);

#[derive(Debug, serde::Serialize)]
#[cfg_attr(test, derive(PartialEq))]
Expand Down Expand Up @@ -115,9 +115,9 @@ pub enum ChatStyleError {
/// bubble gradient position is invalid: {0}
InvalidBubbleGradientPosition(f32),
/// referenced unknown custom color ID {0:?}
UnknownCustomColorId(u32),
UnknownCustomColorId(u64),
/// duplicate custom color ID {0}
DuplicateCustomChatColorId(u32),
DuplicateCustomChatColorId(u64),
}

impl<M: ReferencedTypes> TryFrom<Vec<proto::chat_style::CustomChatColor>> for CustomColorMap<M> {
Expand Down
6 changes: 6 additions & 0 deletions rust/message-backup/src/backup/chat/update_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub enum SimpleChatUpdate {
UnsupportedProtocolMessage,
ReleaseChannelDonationRequest,
ReportedSpam,
Blocked,
Unblocked,
MessageRequestAccepted,
}

impl<C: Lookup<RecipientId, R>, R: Clone> TryFromWith<proto::ChatUpdateMessage, C>
Expand Down Expand Up @@ -85,6 +88,9 @@ impl<C: Lookup<RecipientId, R>, R: Clone> TryFromWith<proto::ChatUpdateMessage,
SimpleChatUpdate::ReleaseChannelDonationRequest
}
Type::REPORTED_SPAM => SimpleChatUpdate::ReportedSpam,
Type::BLOCKED => SimpleChatUpdate::Blocked,
Type::UNBLOCKED => SimpleChatUpdate::Unblocked,
Type::MESSAGE_REQUEST_ACCEPTED => SimpleChatUpdate::MessageRequestAccepted,
}
}),
Update::GroupChange(proto::GroupChangeChatUpdate {
Expand Down
6 changes: 3 additions & 3 deletions rust/message-backup/src/backup/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub enum AttachmentLocator {
key: Vec<u8>,
digest: Vec<u8>,
is_thumbnail: bool,
size: u64,
size: u32,
transit_cdn_key: Option<String>,
transit_cdn_number: Option<u32>,
},
Expand All @@ -33,7 +33,7 @@ pub enum AttachmentLocator {
upload_timestamp: Timestamp,
key: Vec<u8>,
digest: Vec<u8>,
size: u64,
size: u32,
},
#[cfg_attr(test, default)]
Invalid,
Expand Down Expand Up @@ -137,7 +137,7 @@ impl TryFrom<proto::file_pointer::Locator> for AttachmentLocator {
upload_timestamp,
key,
digest,
size: size.into(),
size,
})
}
proto::file_pointer::Locator::InvalidAttachmentLocator(
Expand Down
70 changes: 51 additions & 19 deletions rust/message-backup/src/proto/backup.proto
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ message Group {
// We would use Groups.proto if we could, but we want a plaintext version to improve export readability.
// For documentation, defer to Groups.proto. The only name change is Group -> GroupSnapshot to avoid the naming conflict.
message GroupSnapshot {
bytes publicKey = 1;
reserved /*publicKey*/ 1; // The field is deprecated in the context of static group state
GroupAttributeBlob title = 2;
GroupAttributeBlob description = 11;
string avatarUrl = 3;
Expand Down Expand Up @@ -343,23 +343,49 @@ message ChatItem {
}

message SendStatus {
enum Status {
UNKNOWN = 0;
FAILED = 1;
PENDING = 2;
SENT = 3;
DELIVERED = 4;
READ = 5;
VIEWED = 6;
SKIPPED = 7; // e.g. user in group was blocked, so we skipped sending to them
message Pending {}

message Sent {
bool sealedSender = 1;
}

message Delivered {
bool sealedSender = 1;
}

message Read {
bool sealedSender = 1;
}

message Viewed {
bool sealedSender = 1;
}

// e.g. user in group was blocked, so we skipped sending to them
message Skipped {}

message Failed {
enum FailureReason {
UNKNOWN = 0; // A valid value -- could indicate a crash or lack of information
NETWORK = 1;
IDENTITY_KEY_MISMATCH = 2;
}

FailureReason reason = 1;
}

uint64 recipientId = 1;
Status deliveryStatus = 2;
bool networkFailure = 3;
bool identityKeyMismatch = 4;
bool sealedSender = 5;
uint64 lastStatusUpdateTimestamp = 6; // the time the status was last updated -- if from a receipt, it should be the sentTime of the receipt
uint64 timestamp = 2; // the time the status was last updated -- if from a receipt, it should be the sentTime of the receipt

oneof deliveryStatus {
Pending pending = 3;
Sent sent = 4;
Delivered delivered = 5;
Read read = 6;
Viewed viewed = 7;
Skipped skipped = 8;
Failed failed = 9;
}
}

message Text {
Expand Down Expand Up @@ -565,7 +591,7 @@ message FilePointer {
optional uint32 cdnNumber = 2;
bytes key = 3;
bytes digest = 4;
uint64 size = 5;
uint32 size = 5;
// Fallback in case backup tier upload failed.
optional string transitCdnKey = 6;
optional uint32 transitCdnNumber = 7;
Expand Down Expand Up @@ -652,8 +678,11 @@ message Reaction {
string emoji = 1;
uint64 authorId = 2;
uint64 sentTimestamp = 3;
// Optional because some clients may not track this data
optional uint64 receivedTimestamp = 4;
uint64 sortOrder = 5; // A higher sort order means that a reaction is more recent
// A higher sort order means that a reaction is more recent. Some clients may export this as
// incrementing numbers (e.g. 1, 2, 3), others as timestamps.
uint64 sortOrder = 5;
}

message ChatUpdateMessage {
Expand Down Expand Up @@ -749,6 +778,9 @@ message SimpleChatUpdate {
PAYMENT_ACTIVATION_REQUEST = 11;
UNSUPPORTED_PROTOCOL_MESSAGE = 12;
REPORTED_SPAM = 13;
BLOCKED = 14;
UNBLOCKED = 15;
MESSAGE_REQUEST_ACCEPTED = 16;
}

Type type = 1;
Expand Down Expand Up @@ -1040,7 +1072,7 @@ message ChatStyle {
}

message CustomChatColor {
uint32 id = 1;
uint64 id = 1;

oneof color {
fixed32 solid = 2;
Expand Down Expand Up @@ -1114,7 +1146,7 @@ message ChatStyle {
BubbleColorPreset bubbleColorPreset = 4;

// See AccountSettings.customChatColors
uint32 customColorId = 5;
uint64 customColorId = 5;
}

bool dimWallpaperInDarkMode = 7;
Expand Down

0 comments on commit d2919ea

Please sign in to comment.