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); } }
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"); }
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(); }); } }
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); } } }
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"); } }
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); }
/// <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); }); }
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); } } }
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); } } }
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(); }
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!"); } }
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); }