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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
 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;
 }
Esempio n. 4
0
        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;
 }
Esempio n. 6
0
        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));
        }
Esempio n. 8
0
        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));
        }
Esempio n. 10
0
        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());
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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());
        }
Esempio n. 14
0
        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());
        }
Esempio n. 15
0
        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));
        }
Esempio n. 16
0
        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));
        }