private void writeGroupDetails(DeviceGroup group)// throws IOException { GroupDetails groupDetails = new GroupDetails { }; groupDetails.Id = ByteString.CopyFrom(group.getId()); if (group.getName().HasValue) { groupDetails.Name = group.getName().Match(e => e, () => { throw new Exception(); }); } if (group.getAvatar().HasValue) { GroupDetails.Types.Avatar avatarBuilder = new GroupDetails.Types.Avatar { }; SignalServiceAttachmentStream avatar = group.getAvatar().Match(e => e, () => { throw new Exception(); }); avatarBuilder.ContentType = avatar.getContentType(); avatarBuilder.Length = (uint)avatar.getLength(); groupDetails.Avatar = avatarBuilder; } groupDetails.Members.AddRange(group.getMembers()); groupDetails.Active = group.isActive(); byte[] serializedContactDetails = groupDetails.ToByteArray(); writeVarint32(serializedContactDetails.Length); output.Write(serializedContactDetails, 0, serializedContactDetails.Length); }
private void writeGroupDetails(DeviceGroup group)// throws IOException { SignalServiceProtos.GroupDetails.Builder groupDetails = SignalServiceProtos.GroupDetails.CreateBuilder(); groupDetails.SetId(ByteString.CopyFrom(group.getId())); if (group.getName().HasValue) { groupDetails.SetName(group.getName().Match(e => e, () => { throw new Exception(); })); } if (group.getAvatar().HasValue) { SignalServiceProtos.GroupDetails.Types.Avatar.Builder avatarBuilder = SignalServiceProtos.GroupDetails.Types.Avatar.CreateBuilder(); SignalServiceAttachmentStream avatar = group.getAvatar().Match(e => e, () => { throw new Exception(); }); avatarBuilder.SetContentType(avatar.getContentType()); avatarBuilder.SetLength((uint)avatar.getLength()); groupDetails.SetAvatar(avatarBuilder); } groupDetails.AddRangeMembers(group.getMembers()); groupDetails.SetActive(group.isActive()); byte[] serializedContactDetails = groupDetails.Build().ToByteArray(); writeVarint32(serializedContactDetails.Length); output.Write(serializedContactDetails, 0, serializedContactDetails.Length); }
public DeviceGroup(byte[] id, string name, IList <string> members, SignalServiceAttachmentStream avatar, bool active, uint?expirationTimer) { Id = id; Name = name; Members = members; Avatar = avatar; Active = active; ExpirationTimer = expirationTimer; }
private async Task <byte[]> createMultiDeviceGroupsContent(SignalServiceAttachmentStream groups) { Content.Builder container = Content.CreateBuilder(); SyncMessage.Builder builder = SyncMessage.CreateBuilder(); builder.SetGroups(SyncMessage.Types.Groups.CreateBuilder() .SetBlob(await createAttachmentPointer(groups))); return(container.SetSyncMessage(builder).Build().ToByteArray()); }
public DeviceContact(string number, string name, SignalServiceAttachmentStream avatar, string?color, VerifiedMessage verified, byte[] profileKey, bool blocked, uint?expirationTimer) { Number = number; Name = name; Avatar = avatar; Color = color; Verified = verified; ProfileKey = profileKey; Blocked = blocked; ExpirationTimer = expirationTimer; }
private byte[] createMultiDeviceGroupsContent(SignalServiceAttachmentStream groups) { Content content = new Content { }; SyncMessage syncMessage = new SyncMessage { }; syncMessage.Groups = new SyncMessage.Types.Groups { Blob = createAttachmentPointer(groups) }; content.SyncMessage = syncMessage; return(content.ToByteArray()); }
/// <summary> /// /// </summary> /// <returns></returns> /// <exception cref="IOException"></exception> public DeviceGroup?Read() { int detailsLength = ReadRawVarint32(); if (detailsLength == -1) { return(null); } byte[] detailsSerialized = new byte[detailsLength]; Util.ReadFully(inputStream, detailsSerialized); GroupDetails details = GroupDetails.Parser.ParseFrom(detailsSerialized); if (!details.HasId) { throw new IOException("ID missing on group record!"); } byte[] id = details.Id.ToByteArray(); string?name = details.HasName ? details.Name : null; List <GroupDetails.Types.Member> members = details.Members.ToList(); SignalServiceAttachmentStream? avatar = null; bool active = details.Active; uint? expirationTimer = null; string?color = details.HasColor ? details.Color : null; bool blocked = details.Blocked; if (details.Avatar != null) { long avatarLength = details.Avatar.Length; Stream avatarStream = new LimitedInputStream(inputStream, avatarLength); string avatarContentType = details.Avatar.ContentType; avatar = new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, null, false, null); } if (details.HasExpireTimer && details.ExpireTimer > 0) { expirationTimer = details.ExpireTimer; } List <SignalServiceAddress> addressMembers = new List <SignalServiceAddress>(members.Count); foreach (GroupDetails.Types.Member member in members) { addressMembers.Add(new SignalServiceAddress(UuidUtil.ParseOrNull(member.Uuid), member.E164)); } return(new DeviceGroup(id, name, addressMembers, avatar, active, expirationTimer, color, blocked)); }
private byte[] createMultiDeviceContactsContent(SignalServiceAttachmentStream contacts, bool complete) { Content content = new Content { }; SyncMessage syncMessage = new SyncMessage { }; syncMessage.Contacts = new SyncMessage.Types.Contacts { Blob = createAttachmentPointer(contacts), Complete = complete }; content.SyncMessage = syncMessage; return(content.ToByteArray()); }
public DeviceGroup Read() { int detailsLength = ReadRawVarint32(); if (detailsLength == -1) { return(null); } byte[] detailsSerialized = new byte[detailsLength]; Util.ReadFully(InputStream, detailsSerialized); GroupDetails details = GroupDetails.Parser.ParseFrom(detailsSerialized); byte[] id = details.Id.ToByteArray(); string name = details.Name; List <string> members = new List <string>(); members.AddRange(details.Members); SignalServiceAttachmentStream avatar = null; bool active = details.Active; uint? expirationTimer = null; string?color = details.ColorOneofCase == GroupDetails.ColorOneofOneofCase.Color ? details.Color : null; var blocked = details.Blocked; if (details.AvatarOneofCase == GroupDetails.AvatarOneofOneofCase.Avatar) { long avatarLength = details.Avatar.Length; Stream avatarStream = new LimitedInputStream(InputStream, avatarLength); string avatarContentType = details.Avatar.ContentType; avatar = new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, null, false, null); } if (details.ExpireTimerOneofCase == GroupDetails.ExpireTimerOneofOneofCase.ExpireTimer) { expirationTimer = details.ExpireTimer; } return(new DeviceGroup(id, name, members, avatar, active, expirationTimer, color, blocked)); }
private async Task <AttachmentPointer> createAttachmentPointer(SignalServiceAttachmentStream attachment) { byte[] attachmentKey = Util.getSecretBytes(64); PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(), attachment.getInputStream().AsInputStream(), (ulong)attachment.getLength(), attachmentKey); ulong attachmentId = await socket.sendAttachment(attachmentData); var builder = AttachmentPointer.CreateBuilder() .SetContentType(attachment.getContentType()) .SetId(attachmentId) .SetKey(ByteString.CopyFrom(attachmentKey)) .SetSize((uint)attachment.getLength()); if (attachment.getPreview().HasValue) { builder.SetThumbnail(ByteString.CopyFrom(attachment.getPreview().ForceGetValue())); } return(builder.Build()); }
private AttachmentPointer createAttachmentPointer(SignalServiceAttachmentStream attachment) { byte[] attachmentKey = Util.getSecretBytes(64); PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(), attachment.getInputStream(), (ulong)attachment.getLength(), attachmentKey); Tuple <ulong, byte[]> attachmentIdAndDigest = socket.SendAttachment(attachmentData); var attachmentPointer = new AttachmentPointer { ContentType = attachment.getContentType(), Id = attachmentIdAndDigest.Item1, Key = ByteString.CopyFrom(attachmentKey), Digest = ByteString.CopyFrom(attachmentIdAndDigest.Item2), Size = (uint)attachment.getLength() }; if (attachment.FileName != null) { attachmentPointer.FileName = attachment.FileName; } if (attachment.getPreview().HasValue) { attachmentPointer.Thumbnail = ByteString.CopyFrom(attachment.getPreview().ForceGetValue()); } if (attachment.VoiceNote) { attachmentPointer.Flags = (uint)AttachmentPointer.Types.Flags.VoiceMessage; } return(attachmentPointer); }
private async Task <AttachmentPointer> CreateAttachmentPointer(CancellationToken token, SignalServiceAttachmentStream attachment) { byte[] attachmentKey = Util.GetSecretBytes(64); long paddedLength = PaddingInputStream.GetPaddedSize(attachment.Length); long ciphertextLength = AttachmentCipherInputStream.GetCiphertextLength(paddedLength); PushAttachmentData attachmentData = new PushAttachmentData(attachment.ContentType, new PaddingInputStream(attachment.InputStream, attachment.Length), ciphertextLength, new AttachmentCipherOutputStreamFactory(attachmentKey), attachment.Listener); (ulong id, byte[] digest) = await socket.SendAttachment(token, attachmentData); var attachmentPointer = new AttachmentPointer { ContentType = attachment.ContentType, Id = id, Key = ByteString.CopyFrom(attachmentKey), Digest = ByteString.CopyFrom(digest), Size = (uint)attachment.Length }; if (attachment.FileName != null) { attachmentPointer.FileName = attachment.FileName; } if (attachment.Preview != null) { attachmentPointer.Thumbnail = ByteString.CopyFrom(attachment.Preview); } if (attachment.Width > 0) { attachmentPointer.Width = (uint)attachment.Width; } if (attachment.Height > 0) { attachmentPointer.Height = (uint)attachment.Height; } if (attachment.VoiceNote) { attachmentPointer.Flags = (uint)AttachmentPointer.Types.Flags.VoiceMessage; } return(attachmentPointer); }
private async Task <byte[]> CreateMultiDeviceGroupsContent(CancellationToken token, SignalServiceAttachmentStream groups) { Content content = new Content { }; SyncMessage syncMessage = CreateSyncMessage(); syncMessage.Groups = new SyncMessage.Types.Groups { Blob = await CreateAttachmentPointer(token, groups) }; content.SyncMessage = syncMessage; return(content.ToByteArray()); }
private async Task <byte[]> CreateMultiDeviceContactsContent(CancellationToken token, SignalServiceAttachmentStream contacts, bool complete) { Content content = new Content { }; SyncMessage syncMessage = CreateSyncMessage(); syncMessage.Contacts = new SyncMessage.Types.Contacts { Blob = await CreateAttachmentPointer(token, contacts), Complete = complete }; content.SyncMessage = syncMessage; return(content.ToByteArray()); }
public DeviceContact Read()// throws IOException { int detailsLength = ReadRawVarint32(); if (detailsLength == -1) { return(null); } byte[] detailsSerialized = new byte[(int)detailsLength]; Util.ReadFully(InputStream, detailsSerialized); var details = ContactDetails.Parser.ParseFrom(detailsSerialized); string number = details.Number; string name = details.Name; SignalServiceAttachmentStream avatar = null; string color = details.ColorOneofCase == ContactDetails.ColorOneofOneofCase.Color ? details.Color : null; VerifiedMessage verified = null; byte[] profileKey = null; bool blocked = false; uint? expireTimer = null; if (details.AvatarOneofCase == ContactDetails.AvatarOneofOneofCase.Avatar) { long avatarLength = details.Avatar.Length; Stream avatarStream = new LimitedInputStream(InputStream, avatarLength); String avatarContentType = details.Avatar.ContentType; avatar = new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, null, false, null); } if (details.VerifiedOneofCase == ContactDetails.VerifiedOneofOneofCase.Verified) { string destination = details.Verified.Destination; IdentityKey identityKey = new IdentityKey(details.Verified.IdentityKey.ToByteArray(), 0); VerifiedState state; switch (details.Verified.State) { case Verified.Types.State.Verified: state = VerifiedState.Verified; break; case Verified.Types.State.Unverified: state = VerifiedState.Unverified; break; case Verified.Types.State.Default: state = VerifiedState.Default; break; default: throw new InvalidMessageException("Unknown state: " + details.Verified.State); } verified = new VerifiedMessage(destination, identityKey, state, Util.CurrentTimeMillis()); } if (details.ProfileKeyOneofCase == ContactDetails.ProfileKeyOneofOneofCase.ProfileKey) { profileKey = details.ProfileKey.ToByteArray(); } if (details.ExpireTimerOneofCase == ContactDetails.ExpireTimerOneofOneofCase.ExpireTimer && details.ExpireTimer > 0) { expireTimer = details.ExpireTimer; } return(new DeviceContact(number, name, avatar, color, verified, profileKey, blocked, expireTimer)); }
private async Task HandleMessage(SignalServiceEnvelope envelope) { var cipher = new SignalServiceCipher(new SignalServiceAddress(SignalLibHandle.Instance.Store.Username), new Store()); var content = cipher.Decrypt(envelope); long timestamp = Util.CurrentTimeMillis(); if (content.Message != null) { SignalServiceDataMessage message = content.Message; if (message.EndSession) { await HandleSessionResetMessage(envelope, content, message, false, timestamp); } else if (message.IsGroupUpdate()) { if (message.Group.Type == SignalServiceGroup.GroupType.UPDATE) { await HandleGroupUpdateMessage(envelope, content, message, false, timestamp); } else if (message.Group.Type == SignalServiceGroup.GroupType.QUIT) { await HandleGroupLeaveMessage(envelope, content, message, false, timestamp); } else if (message.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO) { Logger.LogWarning("Received REQUEST_INFO request"); } } else if (message.ExpirationUpdate) { await HandleExpirationUpdateMessage(envelope, content, message, false, timestamp); } else { await HandleSignalMessage(envelope, content, message, false, timestamp); } } else if (content.SynchronizeMessage != null) { if (content.SynchronizeMessage.Sent != null) { var syncMessage = content.SynchronizeMessage.Sent; var dataMessage = syncMessage.Message; if (dataMessage.EndSession) { await HandleSessionResetMessage(envelope, content, dataMessage, true, timestamp); } else if (dataMessage.IsGroupUpdate()) { if (dataMessage.Group.Type == SignalServiceGroup.GroupType.UPDATE) { await HandleGroupUpdateMessage(envelope, content, dataMessage, true, timestamp); } else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.QUIT) { await HandleGroupLeaveMessage(envelope, content, dataMessage, true, timestamp); } else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO) { Logger.LogWarning("Received synced REQUEST_INFO request"); } } else if (dataMessage.ExpirationUpdate) { await HandleExpirationUpdateMessage(envelope, content, dataMessage, true, timestamp); } else { await HandleSignalMessage(envelope, content, dataMessage, true, timestamp); } } else if (content.SynchronizeMessage.Reads != null) { var readMessages = content.SynchronizeMessage.Reads; foreach (var readMessage in readMessages) { try { await HandleSyncedReadMessage(readMessage); } catch (Exception e) { Logger.LogError("HandleReadMessage failed: {0}\n{1}", e.Message, e.StackTrace); } } } else if (content.SynchronizeMessage.BlockedList != null) { List <string> blockedNumbers = content.SynchronizeMessage.BlockedList.Numbers; await HandleBlockedNumbers(blockedNumbers); } else if (content.SynchronizeMessage.Groups != null) { Logger.LogInformation("HandleMessage() handling groups sync message from device {0}", envelope.GetSourceDevice()); int read; var avatarBuffer = new byte[4096]; var groups = content.SynchronizeMessage.Groups; using (var tmpFile = LibUtils.CreateTmpFile("groups_sync")) { var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, groups.AsPointer(), tmpFile, 10000, null); var deviceGroupsStream = new DeviceGroupsInputStream(plaintextStream); var groupsList = new List <(SignalGroup, IList <string>)>(); DeviceGroup g; while ((g = deviceGroupsStream.Read()) != null) { if (g.Avatar != null) { SignalServiceAttachmentStream ssas = g.Avatar.AsStream(); while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0) { } } var group = new SignalGroup() { ThreadDisplayName = g.Name, ThreadId = Base64.EncodeBytes(g.Id), GroupMemberships = new List <GroupMembership>(), CanReceive = true, ExpiresInSeconds = g.ExpirationTimer != null ? g.ExpirationTimer.Value : 0 }; groupsList.Add((group, g.Members)); } List <SignalConversation> dbGroups = await SignalDBContext.InsertOrUpdateGroups(groupsList); await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbGroups); } } else if (content.SynchronizeMessage.Contacts != null && content.SynchronizeMessage.Contacts.Complete) //TODO incomplete updates { Logger.LogInformation("HandleMessage() handling contacts sync message from device {0}", envelope.GetSourceDevice()); int read; var avatarBuffer = new byte[4096]; ContactsMessage contacts = content.SynchronizeMessage.Contacts; using (var tmpFile = LibUtils.CreateTmpFile("contacts_sync")) { var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, contacts.Contacts.AsPointer(), tmpFile, 10000, null); var deviceContactsStream = new DeviceContactsInputStream(plaintextStream); List <SignalContact> contactsList = new List <SignalContact>(); DeviceContact c; while ((c = deviceContactsStream.Read()) != null) { if (c.Avatar != null) { SignalServiceAttachmentStream ssas = c.Avatar.AsStream(); while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0) { } } SignalContact contact = new SignalContact() { ThreadDisplayName = c.Name, ThreadId = c.Number, Color = c.Color, CanReceive = true, ExpiresInSeconds = c.ExpirationTimer != null ? c.ExpirationTimer.Value : 0 }; contactsList.Add(contact); } var dbContacts = SignalDBContext.InsertOrUpdateContacts(contactsList); await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbContacts); } } } else if (content.ReadMessage != null) { SignalServiceReceiptMessage receiptMessage = content.ReadMessage; Logger.LogTrace("HandleMessage() received ReceiptMessage (type={0}, when={1})", receiptMessage.ReceiptType, receiptMessage.When); } else { //TODO callmessages Logger.LogWarning("HandleMessage() received unrecognized message"); } }
public DeviceContact?Read() { int detailsLength = ReadRawVarint32(); if (detailsLength == -1) { return(null); } byte[] detailsSerialized = new byte[(int)detailsLength]; Util.ReadFully(inputStream, detailsSerialized); var details = ContactDetails.Parser.ParseFrom(detailsSerialized); SignalServiceAddress address = new SignalServiceAddress(UuidUtil.ParseOrNull(details.Uuid), details.Number); string?name = details.Name; SignalServiceAttachmentStream?avatar = null; string? color = details.HasColor ? details.Color : null; VerifiedMessage?verified = null; byte[]? profileKey = null; bool blocked = false; uint?expireTimer = null; if (details.Avatar != null) { long avatarLength = details.Avatar.Length; Stream avatarStream = new LimitedInputStream(inputStream, avatarLength); string avatarContentType = details.Avatar.ContentType; avatar = new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, null, false, null); } if (details.Verified != null) { try { IdentityKey identityKey = new IdentityKey(details.Verified.IdentityKey.ToByteArray(), 0); SignalServiceAddress destination = new SignalServiceAddress(UuidUtil.ParseOrNull(details.Verified.DestinationUuid), details.Verified.Destination); VerifiedState state; switch (details.Verified.State) { case Verified.Types.State.Verified: state = VerifiedState.Verified; break; case Verified.Types.State.Unverified: state = VerifiedState.Unverified; break; case Verified.Types.State.Default: state = VerifiedState.Default; break; default: throw new InvalidMessageException("Unknown state: " + details.Verified.State); } verified = new VerifiedMessage(destination, identityKey, state, Util.CurrentTimeMillis()); } catch (Exception ex) when(ex is InvalidKeyException || ex is InvalidMessageException) { logger.LogWarning(new EventId(), ex, ""); verified = null; } } if (details.HasProfileKey) { profileKey = details.ProfileKey.ToByteArray(); } if (details.HasExpireTimer && details.ExpireTimer > 0) { expireTimer = details.ExpireTimer; } return(new DeviceContact(address, name, avatar, color, verified, profileKey, blocked, expireTimer)); }