public void BackgroundAcquire()
 {
     CancelSource = new CancellationTokenSource();
     Instance     = this;
     SignalDBContext.FailAllPendingMessages();
     Store = LibsignalDBContext.GetSignalStore();
     InitNetwork();
     Running = true;
 }
 public void SaveAndDispatchSignalConversation(SignalConversation updatedConversation, SignalMessage updateMessage)
 {
     Logger.LogTrace("SaveAndDispatchSignalConversation() locking");
     SemaphoreSlim.Wait(CancelSource.Token);
     SignalDBContext.InsertOrUpdateConversationLocked(updatedConversation);
     DispatchAddOrUpdateConversation(updatedConversation, updateMessage);
     SemaphoreSlim.Release();
     Logger.LogTrace("SaveAndDispatchSignalConversation() released");
 }
        public async Task <bool> Acquire(CoreDispatcher d, ISignalFrontend w) //TODO wrap trycatch dispatch auth failure
        {
            Logger.LogTrace("Acquire() locking");
            CancelSource = new CancellationTokenSource();
            SemaphoreSlim.Wait(CancelSource.Token);
            try
            {
                GlobalResetEvent = LibUtils.OpenResetEventSet();
                LibUtils.Lock();
                GlobalResetEvent.Reset();
                MainWindowDispatcher = d;
                MainWindow           = w;
                Logger.LogDebug("Acquire() locked (global and local)");
                var getConversationsTask = Task.Run(() =>
                {
                    return(GetConversations()); // we want to display the conversations asap!
                });
                Instance = this;
                Frames.Add(d, w);
                w.ReplaceConversationList(await getConversationsTask);
                var failTask = Task.Run(() =>
                {
                    SignalDBContext.FailAllPendingMessages(); // TODO GetMessages needs to be protected by semaphoreslim as we fail defered
                });
                Store = await Task.Run(() =>
                {
                    return(LibsignalDBContext.GetSignalStore());
                });

                if (Store == null)
                {
                    return(false);
                }
                else
                {
                    LikelyHasValidStore = true;
                }
                var initNetwork = Task.Run(async() =>
                {
                    await InitNetwork();
                });
                var recoverDownloadsTask = Task.Run(() =>
                {
                    RecoverDownloads().Wait();
                });
                await failTask; // has to complete before messages are loaded
                await recoverDownloadsTask;
                Running = true;
                return(true);
            }
            finally
            {
                SemaphoreSlim.Release();
                Logger.LogTrace("Acquire() released");
            }
        }
        /// <summary>
        /// Deletes expired messages from the database.
        /// </summary>
        public static void DeleteExpiredMessages()
        {
            long currentTimeMillis = Util.CurrentTimeMillis();
            List <SignalMessage> expiredMessages = SignalDBContext.GetExpiredMessages(currentTimeMillis);

            foreach (var expiredMessage in expiredMessages)
            {
                DeleteFromDb(expiredMessage);
            }
        }
Exemple #5
0
 internal async void BlockButton_Click()
 {
     Contact.Blocked = !Contact.Blocked;
     Blocked         = Contact.Blocked;
     SignalDBContext.UpdateBlockStatus(Contact);
     await Task.Run(() =>
     {
         App.Handle.SendBlockedMessage();
     });
 }
        private async Task HandleSessionResetMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            SignalConversation     conversation;
            string prefix;
            string conversationId;
            Guid?  conversationGuid;
            long   composedTimestamp;

            if (isSync)
            {
                var sent = content.SynchronizeMessage.Sent;
                type              = SignalMessageDirection.Synced;
                status            = SignalMessageStatus.Confirmed;
                composedTimestamp = sent.Timestamp;
                author            = null;
                prefix            = "You have";
                conversationId    = sent.Destination.E164;
                conversationGuid  = sent.Destination.Uuid;
            }
            else
            {
                status = 0;
                type   = SignalMessageDirection.Incoming;
                author = await SignalDBContext.GetOrCreateContactLocked(content.Sender.E164, content.Sender.Uuid);

                prefix            = $"{author.ThreadDisplayName} has";
                composedTimestamp = envelope.GetTimestamp();
                conversationId    = content.Sender.E164;
                conversationGuid  = content.Sender.Uuid;
            }
            LibsignalDBContext.DeleteAllSessions(conversationId);
            conversation = await SignalDBContext.GetOrCreateContactLocked(conversationId, conversationGuid);

            SignalMessage sm = new SignalMessage()
            {
                Direction = type,
                Type      = SignalMessageType.SessionReset,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = $"{prefix} reset the session."
                },
                ThreadId          = conversationId,
                ThreadGuid        = conversationGuid,
                DeviceId          = (uint)envelope.GetSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
            };
            await SignalLibHandle.Instance.SaveAndDispatchSignalMessage(sm, null, conversation);
        }
        public async Task UIHandleIncomingMessage(SignalMessage message)
        {
            Debug.WriteLine("incoming lock await");
            using (await ActionInProgress.LockAsync())
            {
                Debug.WriteLine("incoming lock grabbed");
                var  thread      = ThreadsDictionary[message.ThreadId];
                uint unreadCount = thread.UnreadCount;
                if (SelectedThread == thread)
                {
                    message.Read = true;
                }
                await Task.Run(() =>
                {
                    SignalDBContext.SaveMessageLocked(message);
                });

                thread.MessagesCount += 1;
                if (SelectedThread == thread)
                {
                    var container = new SignalMessageContainer(message, (int)thread.MessagesCount - 1);
                    View.Thread.Append(container, false);
                    if (message.Direction == SignalMessageDirection.Synced)
                    {
                        View.Thread.AddToOutgoingMessagesCache(container);
                        unreadCount = 0;
                        thread.LastSeenMessageIndex = thread.MessagesCount;
                    }
                    else
                    {
                        //TODO don't increase unread if we did scroll automatically, and mark the message as seen
                        unreadCount++;
                    }
                }
                else
                {
                    if (message.Direction == SignalMessageDirection.Incoming)
                    {
                        unreadCount++;
                    }
                    else if (message.Direction == SignalMessageDirection.Synced)
                    {
                        unreadCount = 0;
                        thread.LastSeenMessageIndex = thread.MessagesCount;
                    }
                }
                thread.UnreadCount         = unreadCount;
                thread.LastActiveTimestamp = message.ReceivedTimestamp;
                thread.LastMessage         = message;
                thread.View.UpdateConversationDisplay(thread);
                MoveThreadToTop(thread);
            }
            Debug.WriteLine("incoming lock released");
        }
        internal void HandleMessageSentLocked(SignalMessage msg)
        {
            Logger.LogTrace("HandleMessageSentLocked() locking");
            SemaphoreSlim.Wait(CancelSource.Token);
            Logger.LogTrace("HandleMessageSentLocked() locked");
            var updated = SignalDBContext.UpdateMessageStatus(msg);

            DispatchMessageUpdate(updated);
            SemaphoreSlim.Release();
            Logger.LogTrace("HandleMessageSentLocked() released");
        }
Exemple #9
0
        private void HandleSessionResetMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            string prefix;
            string conversationId;
            long   composedTimestamp;

            if (isSync)
            {
                var sent = content.SynchronizeMessage.getSent().ForceGetValue();
                type              = SignalMessageDirection.Synced;
                status            = SignalMessageStatus.Confirmed;
                composedTimestamp = sent.getTimestamp();
                author            = null;
                prefix            = "You have";
                conversationId    = sent.getDestination().ForceGetValue();
            }
            else
            {
                status            = 0;
                type              = SignalMessageDirection.Incoming;
                author            = SignalDBContext.GetOrCreateContactLocked(envelope.getSource(), timestamp, this);
                prefix            = $"{author.ThreadDisplayName} has";
                composedTimestamp = envelope.getTimestamp();
                conversationId    = envelope.getSource();
            }
            LibsignalDBContext.DeleteAllSessions(conversationId);

            SignalMessage sm = new SignalMessage()
            {
                Direction = type,
                Type      = SignalMessageType.SessionReset,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = $"{prefix} reset the session."
                },
                ThreadId          = conversationId,
                DeviceId          = (uint)envelope.getSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
            };

            Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                await UIHandleIncomingMessage(sm);
            }).AsTask().Wait();
        }
 private async void UnblockButton_Click(object sender, RoutedEventArgs e)
 {
     if (SignalConversation is SignalContact contact)
     {
         contact.Blocked    = false;
         Blocked            = false;
         SendMessageVisible = !Blocked;
         SignalDBContext.UpdateBlockStatus(contact);
         await Task.Run(() =>
         {
             App.Handle.SendBlockedMessage();
         });
     }
 }
Exemple #11
0
 private async void UserInputBar_OnUnblockButtonClicked()
 {
     if (SignalConversation is SignalContact contact)
     {
         contact.Blocked    = false;
         Blocked            = false;
         SendMessageVisible = !Blocked;
         SignalDBContext.UpdateBlockStatus(contact);
         await Task.Run(() =>
         {
             App.Handle.SendBlockedMessage();
         });
     }
 }
        public async Task SendBlockedMessage()
        {
            List <SignalContact> blockedContacts = SignalDBContext.GetAllContactsLocked().Where(c => c.Blocked).ToList();
            List <string>        blockedNumbers  = new List <string>();

            foreach (var contact in blockedContacts)
            {
                blockedNumbers.Add(contact.ThreadId);
            }
            var blockMessage = SignalServiceSyncMessage.ForBlocked(new BlockedListMessage(blockedNumbers));

            OutgoingMessages.SendMessage(blockMessage);
            await DispatchHandleBlockedContacts(blockedContacts);
        }
        internal async Task DispatchHandleMessage(SignalMessage message, SignalConversation conversation)
        {
            List <Task <AppendResult> > operations = new List <Task <AppendResult> >();

            foreach (var dispatcher in Frames.Keys)
            {
                TaskCompletionSource <AppendResult> taskCompletionSource = new TaskCompletionSource <AppendResult>();
                await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    AppendResult ar = null;
                    try
                    {
                        ar = (Frames[dispatcher].HandleMessage(message, conversation));
                    }
                    catch (Exception e)
                    {
                        Logger.LogError("DispatchHandleMessage() dispatch failed: {0}\n{1}", e.Message, e.StackTrace);
                    }
                    finally
                    {
                        taskCompletionSource.SetResult(ar);
                    }
                });

                operations.Add(taskCompletionSource.Task);
            }
            SignalMessageEvent?.Invoke(this, new SignalMessageEventArgs(message, Events.SignalPipeMessageType.NormalMessage));
            if (message.Author != null)
            {
                bool wasInstantlyRead = false;
                foreach (var b in operations)
                {
                    AppendResult result = await b;
                    if (result != null && result.WasInstantlyRead)
                    {
                        UpdateMessageExpiration(message, conversation.ExpiresInSeconds);
                        var updatedConversation = SignalDBContext.UpdateMessageRead(message.ComposedTimestamp);
                        await DispatchMessageRead(updatedConversation);

                        wasInstantlyRead = true;
                        break;
                    }
                }
                if (!wasInstantlyRead)
                {
                    await DispatchHandleUnreadMessage(message);
                }
            }
        }
Exemple #14
0
        internal async Task HandleMessageSentLocked(ISendable msg)
        {
            if (msg is SignalMessageSendable smSendable)
            {
                Logger.LogTrace("HandleMessageSentLocked() locking");
                await SemaphoreSlim.WaitAsync(CancelSource.Token);

                Logger.LogTrace("HandleMessageSentLocked() locked");
                var updated = SignalDBContext.UpdateMessageStatus(smSendable.OutgoingSignalMessage);
                await DispatchMessageUpdate(updated);

                SemaphoreSlim.Release();
                Logger.LogTrace("HandleMessageSentLocked() released");
            }
        }
Exemple #15
0
        public async Task OnMessage(SignalServiceMessagePipeMessage message)
        {
            Logger.LogTrace("OnMessage() locking");
            await SignalLibHandle.Instance.SemaphoreSlim.WaitAsync(Token);

            Logger.LogTrace("OnMessage() locked");
            try
            {
                if (message is SignalServiceEnvelope envelope)
                {
                    List <SignalMessage> messages = new List <SignalMessage>();
                    if (envelope.IsReceipt())
                    {
                        SignalMessage update = SignalDBContext.IncreaseReceiptCountLocked(envelope);
                        if (update != null)
                        {
                            await SignalLibHandle.Instance.DispatchMessageUpdate(update);
                        }
                    }
                    else if (envelope.IsPreKeySignalMessage() || envelope.IsSignalMessage())
                    {
                        await HandleMessage(envelope);
                    }
                    else
                    {
                        Logger.LogWarning("OnMessage() could not handle unknown message type {0}", envelope.GetEnvelopeType());
                    }
                }
                else if (message is SignalServiceMessagePipeEmptyMessage)
                {
                    SignalLibHandle.Instance.DispatchPipeEmptyMessage();
                }
            }
            catch (Exception e)
            {
                Logger.LogError("OnMessage failed: {0}\n{1}", e.Message, e.StackTrace);
                if (e.InnerException != null)
                {
                    Logger.LogError("InnerException: {0}\n{1}", e.InnerException.Message, e.InnerException.StackTrace);
                }
            }
            finally
            {
                SignalLibHandle.Instance.SemaphoreSlim.Release();
                Logger.LogTrace("OnMessage() released");
            }
        }
 internal void SaveAndDispatchSignalMessage(SignalMessage message, SignalConversation conversation)
 {
     conversation.MessagesCount += 1;
     if (message.Direction == SignalMessageDirection.Incoming)
     {
         conversation.UnreadCount += 1;
     }
     else
     {
         conversation.UnreadCount          = 0;
         conversation.LastSeenMessageIndex = conversation.MessagesCount;
     }
     SignalDBContext.SaveMessageLocked(message);
     conversation.LastMessage         = message;
     conversation.LastActiveTimestamp = message.ComposedTimestamp;
     DispatchHandleMessage(message, conversation);
 }
 internal async Task SaveAndDispatchSignalMessage(SignalMessage message, SignalConversation conversation)
 {
     conversation.MessagesCount += 1;
     if (message.Direction == SignalMessageDirection.Incoming)
     {
         conversation.UnreadCount += 1;
     }
     else
     {
         conversation.UnreadCount          = 0;
         conversation.LastSeenMessageIndex = conversation.MessagesCount;
     }
     SignalDBContext.SaveMessageLocked(message);
     conversation.LastMessage         = message;
     conversation.LastActiveTimestamp = message.ComposedTimestamp;
     //StartAttachmentDownloads(message);
     await DispatchHandleMessage(message, conversation);
 }
        private List <SignalConversation> GetConversations()
        {
            List <SignalConversation> conversations = new List <SignalConversation>();
            List <SignalContact>      contacts      = SignalDBContext.GetAllContactsLocked();
            List <SignalGroup>        groups        = SignalDBContext.GetAllGroupsLocked();
            int amountContacts = contacts.Count;
            int amountGroups   = groups.Count;
            int contactsIdx    = 0;
            int groupsIdx      = 0;

            while (contactsIdx < amountContacts || groupsIdx < amountGroups)
            {
                if (contactsIdx < amountContacts)
                {
                    SignalConversation contact = contacts[contactsIdx];
                    if (groupsIdx < amountGroups)
                    {
                        SignalConversation group = groups[groupsIdx];
                        if (contact.LastActiveTimestamp > group.LastActiveTimestamp)
                        {
                            contactsIdx++;
                            conversations.Add(contact);
                        }
                        else
                        {
                            groupsIdx++;
                            conversations.Add(group);
                        }
                    }
                    else
                    {
                        contactsIdx++;
                        conversations.Add(contact);
                    }
                }
                else if (groupsIdx < amountGroups)
                {
                    SignalConversation group = groups[groupsIdx];
                    groupsIdx++;
                    conversations.Add(group);
                }
            }
            return(conversations);
        }
Exemple #19
0
 /// <summary>
 /// Initialisiert das Singletonanwendungsobjekt. Dies ist die erste Zeile von erstelltem Code
 /// und daher das logische Äquivalent von main() bzw. WinMain().
 /// </summary>
 public App()
 {
     this.InitializeComponent();
     this.Suspending += OnSuspending;
     try
     {
         Init = Task.Run(() =>
         {
             SignalDBContext.Migrate();
             LibsignalDBContext.Migrate();
             return(LibsignalDBContext.GetSignalStore());
         });
     }
     catch (Exception e)
     {
         Debug.WriteLine(e.Message);
         Debug.WriteLine(e.StackTrace);
     }
 }
        public async Task Acquire(CoreDispatcher d, ISignalFrontend w) //TODO wrap trycatch dispatch auth failure
        {
            Logger.LogTrace("Acquire() locking");
            CancelSource = new CancellationTokenSource();
            SemaphoreSlim.Wait(CancelSource.Token);
            GlobalResetEvent = LibUtils.OpenResetEventSet();
            LibUtils.Lock();
            GlobalResetEvent.Reset();
            var getConversationsTask = Task.Run(() =>
            {
                return(GetConversations()); // we want to display the conversations asap!
            });

            Logger.LogDebug("Acquire() locked (global and local)");
            Instance = this;
            Frames.Add(d, w);
            w.ReplaceConversationList(await getConversationsTask);
            var failTask = Task.Run(() =>
            {
                SignalDBContext.FailAllPendingMessages(); // TODO GetMessages needs to be protected by semaphoreslim as we fail defered
            });

            Store = await Task.Run(() =>
            {
                return(LibsignalDBContext.GetSignalStore());
            });

            if (Store == null)
            {
                SemaphoreSlim.Release();
                throw new Exception("Signal Store has not been setup yet.");
            }
            await Task.Run(() =>
            {
                InitNetwork();
            });

            await failTask; // has to complete before messages are loaded

            Running = true;
            Logger.LogTrace("Acquire() releasing");
            SemaphoreSlim.Release();
        }
 private async Task AddContact(string name, string number)
 {
     Debug.WriteLine("creating contact {0} ({1})", name, number);
     SignalContact contact = new SignalContact()
     {
         ThreadDisplayName   = name,
         ThreadId            = number,
         CanReceive          = true,
         AvatarFile          = null,
         LastActiveTimestamp = 0,
         Draft       = null,
         Color       = Utils.CalculateDefaultColor(name),
         UnreadCount = 0
     };
     await Task.Run(() =>
     {
         SignalDBContext.InsertOrUpdateContactLocked(contact, MainPageVM);
     });
 }
Exemple #22
0
 public void OnMessage(SignalServiceMessagePipeMessage message)
 {
     if (message is SignalServiceEnvelope)
     {
         SignalServiceEnvelope envelope = (SignalServiceEnvelope)message;
         List <SignalMessage>  messages = new List <SignalMessage>();
         if (envelope.isReceipt())
         {
             SignalDBContext.IncreaseReceiptCountLocked(envelope, this);
         }
         else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage())
         {
             HandleMessage(envelope);
         }
         else
         {
             Debug.WriteLine("received message of unknown type " + envelope.getType() + " from " + envelope.getSource());
         }
     }
 }
        public async Task SaveAndDispatchSignalConversation(SignalConversation updatedConversation, SignalMessage updateMessage)
        {
            Logger.LogTrace("SaveAndDispatchSignalConversation() locking");
            await SemaphoreSlim.WaitAsync(CancelSource.Token);

            try
            {
                SignalDBContext.InsertOrUpdateConversationLocked(updatedConversation);
                await DispatchAddOrUpdateConversation(updatedConversation, updateMessage);
            }
            catch (Exception e)
            {
                Logger.LogError("SaveAndDispatchSignalConversation() failed: {0}\n{1}", e.Message, e.StackTrace);
            }
            finally
            {
                SemaphoreSlim.Release();
                Logger.LogTrace("SaveAndDispatchSignalConversation() released");
            }
        }
 public async Task UIHandleIdentityKeyChange(string number)
 {
     Debug.WriteLine("IKChange lock await");
     using (await ActionInProgress.LockAsync())
     {
         Debug.WriteLine("IKChange lock grabbed");
         var messages = SignalDBContext.InsertIdentityChangedMessages(number);
         foreach (var message in messages)
         {
             var thread = ThreadsDictionary[message.ThreadId];
             thread.MessagesCount += 1;
             if (SelectedThread != null && SelectedThread.ThreadId == message.ThreadId)
             {
                 var container = new SignalMessageContainer(message, (int)thread.MessagesCount - 1);
                 View.Thread.Append(container, false);
             }
             thread.LastMessage = message;
             thread.View.UpdateConversationDisplay(thread);
         }
     }
     Debug.WriteLine("IKChange lock released");
 }
        internal void UpdateMessageExpiration(SignalMessage message, uint conversationExpireTimeSeconds)
        {
            if (message.Type == Signal_Windows.Models.SignalMessageType.Normal && message.ExpiresAt == 0)
            {
                long messageExpiration;
                if (conversationExpireTimeSeconds == 0)
                {
                    messageExpiration = 0;
                }
                else
                {
                    messageExpiration = Util.CurrentTimeMillis() + (long)TimeSpan.FromSeconds(conversationExpireTimeSeconds).TotalMilliseconds;
                }

                if (messageExpiration > 0)
                {
                    message.ExpiresAt = messageExpiration;
                    SignalDBContext.UpdateMessageExpiresAt(message);
                    DisappearingMessagesManager.QueueForDeletion(message);
                }
            }
        }
Exemple #26
0
 public void OnMessage(SignalServiceMessagePipeMessage message)
 {
     Logger.LogTrace("OnMessage() locking");
     Handle.SemaphoreSlim.Wait();
     Logger.LogTrace("OnMessage() locked");
     try
     {
         if (message is SignalServiceEnvelope envelope)
         {
             List <SignalMessage> messages = new List <SignalMessage>();
             if (envelope.isReceipt())
             {
                 SignalMessage update = SignalDBContext.IncreaseReceiptCountLocked(envelope);
                 if (update != null)
                 {
                     Handle.DispatchMessageUpdate(update);
                 }
             }
             else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage())
             {
                 HandleMessage(envelope);
             }
             else
             {
                 Logger.LogWarning("OnMessage() could not handle unknown message type {0}", envelope.getType());
             }
         }
         else if (message is SignalServiceMessagePipeEmptyMessage)
         {
             Handle.DispatchPipeEmptyMessage();
         }
     }
     finally
     {
         Handle.SemaphoreSlim.Release();
         Logger.LogTrace("OnMessage() released");
     }
 }
        private async Task RecoverDownloads()
        {
            var downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();

            foreach (DownloadOperation download in downloads)
            {
                try
                {
                    SignalAttachment attachment = SignalDBContext.GetAttachmentByGuidNameLocked(download.Guid.ToString());
                    if (attachment != null)
                    {
                        if (!Downloads.ContainsKey(attachment.Id))
                        {
                            Logger.LogInformation("Creating attach task for attachment {0} ({1})", attachment.Id, download.Guid);
                            Downloads.Add(attachment.Id, download);
                            var t = Task.Run(async() =>
                            {
                                await download.AttachAsync();
                                await HandleSuccessfullDownload(attachment, download.ResultFile, download);
                            });
                        }
                        else
                        {
                            Logger.LogInformation("Attachment {0} ({1}) already has a running task", attachment.Id, download.Guid);
                        }
                    }
                    else
                    {
                        Logger.LogInformation("Aborting unrecognized download {0}", download.Guid);
                        download.AttachAsync().Cancel();
                    }
                }
                catch (Exception e)
                {
                    Logger.LogError("TriageDownloads encountered an error: {0}\n{1}", e.Message, e.StackTrace);
                }
            }
        }
Exemple #28
0
        private void HandleSignalMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            string threadId;
            long   composedTimestamp;
            string body = dataMessage.Body != null ? dataMessage.Body : "";

            if (dataMessage.Group != null)
            {
                var rawId = dataMessage.Group.GroupId;
                threadId = Base64.encodeBytes(rawId);
                var g = SignalDBContext.GetOrCreateGroupLocked(threadId, timestamp, this);
                if (!g.CanReceive)
                {
                    SignalServiceGroup group = new SignalServiceGroup()
                    {
                        Type    = SignalServiceGroup.GroupType.REQUEST_INFO,
                        GroupId = rawId
                    };
                    SignalServiceDataMessage requestInfoMessage = new SignalServiceDataMessage()
                    {
                        Group     = group,
                        Timestamp = Util.CurrentTimeMillis()
                    };
                    MessageSender.sendMessage(envelope.getSourceAddress(), requestInfoMessage);
                }
                composedTimestamp = envelope.getTimestamp();
            }
            else
            {
                if (isSync)
                {
                    var sent = content.SynchronizeMessage.getSent().ForceGetValue();
                    threadId          = SignalDBContext.GetOrCreateContactLocked(sent.getDestination().ForceGetValue(), timestamp, this).ThreadId;
                    composedTimestamp = sent.getTimestamp();
                }
                else
                {
                    threadId          = SignalDBContext.GetOrCreateContactLocked(envelope.getSource(), timestamp, this).ThreadId;
                    composedTimestamp = envelope.getTimestamp();
                }
            }

            if (isSync)
            {
                type   = SignalMessageDirection.Synced;
                status = SignalMessageStatus.Confirmed;
                author = null;
            }
            else
            {
                status = 0;
                type   = SignalMessageDirection.Incoming;
                author = SignalDBContext.GetOrCreateContactLocked(envelope.getSource(), timestamp, this);
            }

            List <SignalAttachment> attachments = new List <SignalAttachment>();
            SignalMessage           message     = new SignalMessage()
            {
                Direction = type,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = body
                },
                ThreadId          = threadId,
                DeviceId          = (uint)envelope.getSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
                AttachmentsCount  = (uint)attachments.Count,
                Attachments       = attachments
            };

            if (dataMessage.Attachments != null)
            {
                var receivedAttachments = dataMessage.Attachments;
                foreach (var receivedAttachment in receivedAttachments)
                {
                    var pointer         = receivedAttachment.asPointer();
                    SignalAttachment sa = new SignalAttachment()
                    {
                        Message      = message,
                        Status       = (uint)SignalAttachmentStatus.Default,
                        SentFileName = pointer.FileName,
                        ContentType  = "",
                        Key          = pointer.Key,
                        Relay        = pointer.Relay,
                        StorageId    = pointer.Id
                    };
                    attachments.Add(sa);
                }
            }
            Debug.WriteLine("received message: " + message.Content);
            if (type == SignalMessageDirection.Incoming)
            {
                if (App.WindowActive)
                {
                    Utils.TryVibrate(true);
                }
                else
                {
                    SendTileNotification(message);
                    SendMessageNotification(message);
                }
            }
            Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                await UIHandleIncomingMessage(message);
            }).AsTask().Wait();
        }
Exemple #29
0
        private void HandleGroupUpdateMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            if (dataMessage.Group != null) //TODO check signal droid: group messages have different types!
            {
                SignalServiceGroup group       = dataMessage.Group;
                string             groupid     = Base64.encodeBytes(group.GroupId);
                SignalGroup        g           = new SignalGroup();
                string             displayname = "Unknown group";
                string             avatarfile  = null;
                if (group.Name != null)
                {
                    displayname = group.Name;
                }
                var dbgroup = SignalDBContext.InsertOrUpdateGroupLocked(groupid, displayname, avatarfile, true, timestamp, this);
                if (group.Members != null)
                {
                    foreach (var member in group.Members)
                    {
                        SignalDBContext.InsertOrUpdateGroupMembershipLocked(dbgroup.Id, SignalDBContext.GetOrCreateContactLocked(member, 0, this).Id);
                    }
                }

                /* insert message into conversation */
                SignalMessageDirection type;
                SignalContact          author;
                SignalMessageStatus    status;
                string prefix;
                long   composedTimestamp;

                if (isSync)
                {
                    var sent = content.SynchronizeMessage.getSent().ForceGetValue();
                    type              = SignalMessageDirection.Synced;
                    status            = SignalMessageStatus.Confirmed;
                    composedTimestamp = sent.getTimestamp();
                    author            = null;
                    prefix            = "You have";
                }
                else
                {
                    status            = 0;
                    type              = SignalMessageDirection.Incoming;
                    author            = SignalDBContext.GetOrCreateContactLocked(envelope.getSource(), timestamp, this);
                    prefix            = $"{author.ThreadDisplayName} has";
                    composedTimestamp = envelope.getTimestamp();
                }

                SignalMessage sm = new SignalMessage()
                {
                    Direction = type,
                    Type      = SignalMessageType.GroupUpdate,
                    Status    = status,
                    Author    = author,
                    Content   = new SignalMessageContent()
                    {
                        Content = $"{prefix} updated the group."
                    },
                    ThreadId          = groupid,
                    DeviceId          = (uint)envelope.getSourceDevice(),
                    Receipts          = 0,
                    ComposedTimestamp = composedTimestamp,
                    ReceivedTimestamp = timestamp,
                };
                Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
                {
                    await UIHandleIncomingMessage(sm);
                }).AsTask().Wait();
            }
            else
            {
                Debug.WriteLine("received group update without group info!");
            }
        }
Exemple #30
0
        private async Task HandleSignalMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            SignalConversation     conversation;
            long   composedTimestamp;
            string body = dataMessage.Body ?? "";

            if (dataMessage.Group != null)
            {
                var rawId    = dataMessage.Group.GroupId;
                var threadId = Base64.EncodeBytes(rawId);
                conversation = await SignalDBContext.GetOrCreateGroupLocked(threadId, timestamp);

                if (!conversation.CanReceive)
                {
                    SignalServiceGroup group = new SignalServiceGroup()
                    {
                        Type    = SignalServiceGroup.GroupType.REQUEST_INFO,
                        GroupId = rawId
                    };
                    SignalServiceDataMessage requestInfoMessage = new SignalServiceDataMessage()
                    {
                        Group     = group,
                        Timestamp = Util.CurrentTimeMillis()
                    };
                    SignalLibHandle.Instance.OutgoingQueue.Add(new SignalServiceDataMessageSendable(requestInfoMessage, envelope.GetSourceAddress()));
                }
                composedTimestamp = envelope.GetTimestamp();
            }
            else
            {
                if (isSync)
                {
                    var sent = content.SynchronizeMessage.Sent;
                    conversation = await SignalDBContext.GetOrCreateContactLocked(sent.Destination.ForceGetValue(), timestamp);

                    composedTimestamp = sent.Timestamp;
                }
                else
                {
                    conversation = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp);

                    composedTimestamp = envelope.GetTimestamp();
                }
            }

            if (isSync)
            {
                type   = SignalMessageDirection.Synced;
                status = SignalMessageStatus.Confirmed;
                author = null;
            }
            else
            {
                status = 0;
                type   = SignalMessageDirection.Incoming;
                author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp);
            }

            if (author != null && author.Blocked)
            {
                // Don't save blocked messages
                return;
            }

            List <SignalAttachment> attachments = new List <SignalAttachment>();
            SignalMessage           message     = new SignalMessage()
            {
                Direction = type,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = body.Truncate(2000)
                },
                ThreadId          = conversation.ThreadId,
                DeviceId          = (uint)envelope.GetSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
                AttachmentsCount  = (uint)attachments.Count,
                Attachments       = attachments
            };

            if (dataMessage.Attachments != null)
            {
                var receivedAttachments = dataMessage.Attachments;
                foreach (var receivedAttachment in receivedAttachments)
                {
                    var pointer         = receivedAttachment.AsPointer();
                    SignalAttachment sa = new SignalAttachment()
                    {
                        Message      = message,
                        Status       = (uint)SignalAttachmentStatus.Default,
                        SentFileName = pointer.FileName,
                        ContentType  = receivedAttachment.ContentType,
                        Key          = pointer.Key,
                        Relay        = pointer.Relay,
                        StorageId    = pointer.Id,
                        Size         = (long)pointer.Size,
                        Digest       = pointer.Digest
                    };
                    attachments.Add(sa);
                }

                // Make sure to update attachments count
                message.AttachmentsCount = (uint)attachments.Count;
            }
            await SignalLibHandle.Instance.SaveAndDispatchSignalMessage(message, null, conversation);
        }