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); }
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 async Task HandleGroupLeaveMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp) { SignalServiceGroup sentGroup = dataMessage.Group; if (sentGroup != null) { string groupid = Base64.EncodeBytes(sentGroup.GroupId); SignalGroup group = await SignalDBContext.GetOrCreateGroupLocked(groupid, 0); if (isSync) { SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0); SignalMessage sm = new SignalMessage() { Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.GroupLeave, Status = SignalMessageStatus.Received, Author = author, Content = new SignalMessageContent() { Content = $"You have left the group." }, ThreadId = groupid, DeviceId = (uint)envelope.GetSourceDevice(), Receipts = 0, ComposedTimestamp = envelope.GetTimestamp(), ReceivedTimestamp = timestamp, }; SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm); await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm); } else { SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0); SignalMessage sm = new SignalMessage() { Direction = SignalMessageDirection.Incoming, Type = SignalMessageType.GroupLeave, Status = SignalMessageStatus.Received, Author = author, Content = new SignalMessageContent() { Content = $"{author.ThreadDisplayName} has left the group." }, ThreadId = groupid, DeviceId = (uint)envelope.GetSourceDevice(), Receipts = 0, ComposedTimestamp = envelope.GetTimestamp(), ReceivedTimestamp = timestamp, }; SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm); await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm); } } else { Logger.LogError("HandleGroupLeaveMessage() received group update without group info"); } }
private async Task HandleExpirationUpdateMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage message, bool isSync, long timestamp) { SignalMessageDirection type; SignalContact author; SignalMessageStatus status; string prefix; SignalConversation conversation; long composedTimestamp; if (isSync) { var sent = content.SynchronizeMessage.Sent; type = SignalMessageDirection.Synced; status = SignalMessageStatus.Confirmed; composedTimestamp = sent.Timestamp; author = null; prefix = "You have"; if (message.Group != null) { conversation = await SignalDBContext.GetOrCreateGroupLocked(Base64.EncodeBytes(message.Group.GroupId), 0); } else { conversation = await SignalDBContext.GetOrCreateContactLocked(sent.Destination.ForceGetValue(), 0); } } else { status = 0; type = SignalMessageDirection.Incoming; author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp); prefix = $"{author.ThreadDisplayName} has"; composedTimestamp = envelope.GetTimestamp(); if (message.Group != null) { conversation = await SignalDBContext.GetOrCreateGroupLocked(Base64.EncodeBytes(message.Group.GroupId), 0); } else { conversation = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0); } } conversation.ExpiresInSeconds = (uint)message.ExpiresInSeconds; SignalDBContext.UpdateExpiresInLocked(conversation); SignalMessage sm = new SignalMessage() { Direction = type, Type = SignalMessageType.ExpireUpdate, Status = status, Author = author, Content = new SignalMessageContent() { Content = $"{prefix} set the expiration timer to {message.ExpiresInSeconds} seconds." }, ThreadId = conversation.ThreadId, DeviceId = (uint)envelope.GetSourceDevice(), Receipts = 0, ComposedTimestamp = composedTimestamp, ReceivedTimestamp = timestamp, }; await SignalLibHandle.Instance.SaveAndDispatchSignalMessage(sm, null, conversation); }
public async Task HandleOutgoingMessages() { Logger.LogDebug("HandleOutgoingMessages()"); while (!Token.IsCancellationRequested) { SignalMessage outgoingSignalMessage = null; try { outgoingSignalMessage = Handle.OutgoingQueue.Take(Token); SignalServiceDataMessage message = new SignalServiceDataMessage() { Body = outgoingSignalMessage.Content.Content, Timestamp = outgoingSignalMessage.ComposedTimestamp, ExpiresInSeconds = (int)outgoingSignalMessage.ExpiresAt }; if (!outgoingSignalMessage.ThreadId.EndsWith("=")) { if (!Token.IsCancellationRequested) { await MessageSender.SendMessage(Token, new SignalServiceAddress(outgoingSignalMessage.ThreadId), message); outgoingSignalMessage.Status = SignalMessageStatus.Confirmed; } } else { List <SignalServiceAddress> recipients = new List <SignalServiceAddress>(); SignalGroup g = await SignalDBContext.GetOrCreateGroupLocked(outgoingSignalMessage.ThreadId, 0); foreach (GroupMembership sc in g.GroupMemberships) { if (sc.Contact.ThreadId != SignalLibHandle.Instance.Store.Username) { recipients.Add(new SignalServiceAddress(sc.Contact.ThreadId)); } } message.Group = new SignalServiceGroup() { GroupId = Base64.Decode(g.ThreadId), Type = SignalServiceGroup.GroupType.DELIVER }; if (!Token.IsCancellationRequested) { await SendMessage(recipients, message); outgoingSignalMessage.Status = SignalMessageStatus.Confirmed; } } } catch (OperationCanceledException) { Logger.LogInformation("HandleOutgoingMessages() finished"); return; } catch (EncapsulatedExceptions exceptions) { outgoingSignalMessage.Status = SignalMessageStatus.Confirmed; Logger.LogError("HandleOutgoingMessages() encountered libsignal exceptions"); IList <UntrustedIdentityException> identityExceptions = exceptions.UntrustedIdentityExceptions; if (exceptions.NetworkExceptions.Count > 0) { outgoingSignalMessage.Status = SignalMessageStatus.Failed_Network; } if (identityExceptions.Count > 0) { outgoingSignalMessage.Status = SignalMessageStatus.Failed_Identity; } foreach (UntrustedIdentityException e in identityExceptions) { await Handle.HandleOutgoingKeyChangeLocked(e.E164number, Base64.EncodeBytes(e.IdentityKey.serialize())); } } catch (RateLimitException) { Logger.LogError("HandleOutgoingMessages() could not send due to rate limits"); outgoingSignalMessage.Status = SignalMessageStatus.Failed_Ratelimit; } catch (UntrustedIdentityException e) { Logger.LogError("HandleOutgoingMessages() could not send due to untrusted identities"); outgoingSignalMessage.Status = SignalMessageStatus.Failed_Identity; await Handle.HandleOutgoingKeyChangeLocked(e.E164number, Base64.EncodeBytes(e.IdentityKey.serialize())); } catch (Exception e) { var line = new StackTrace(e, true).GetFrames()[0].GetFileLineNumber(); Logger.LogError("HandleOutgoingMessages() failed in line {0}: {1}\n{2}", line, e.Message, e.StackTrace); outgoingSignalMessage.Status = SignalMessageStatus.Failed_Unknown; } await Handle.HandleMessageSentLocked(outgoingSignalMessage); } Logger.LogInformation("HandleOutgoingMessages() finished"); }
/// <summary> /// Reads pending messages from the <see cref="OutgoingQueue"/> and attempts to send them /// </summary> public void HandleOutgoingMessages() { Debug.WriteLine("HandleOutgoingMessages starting..."); CancellationToken token = CancelSource.Token; while (!token.IsCancellationRequested) { SignalMessage outgoingSignalMessage = null; try { outgoingSignalMessage = OutgoingQueue.Take(token); SignalServiceDataMessage message = new SignalServiceDataMessage() { Body = outgoingSignalMessage.Content.Content, Timestamp = outgoingSignalMessage.ComposedTimestamp, ExpiresInSeconds = (int)outgoingSignalMessage.ExpiresAt }; if (!outgoingSignalMessage.ThreadId.EndsWith("=")) { if (!token.IsCancellationRequested) { MessageSender.sendMessage(new SignalServiceAddress(outgoingSignalMessage.ThreadId), message); outgoingSignalMessage.Status = SignalMessageStatus.Confirmed; } } else { List <SignalServiceAddress> recipients = new List <SignalServiceAddress>(); SignalGroup g = SignalDBContext.GetOrCreateGroupLocked(outgoingSignalMessage.ThreadId, 0, this); foreach (GroupMembership sc in g.GroupMemberships) { if (sc.Contact.ThreadId != App.Store.Username) { recipients.Add(new SignalServiceAddress(sc.Contact.ThreadId)); } } message.Group = new SignalServiceGroup() { GroupId = Base64.decode(g.ThreadId), Type = SignalServiceGroup.GroupType.DELIVER }; if (!token.IsCancellationRequested) { MessageSender.sendMessage(recipients, message); outgoingSignalMessage.Status = SignalMessageStatus.Confirmed; } } } catch (OperationCanceledException e) { Debug.WriteLine(e.Message); Debug.WriteLine(e.StackTrace); Debug.WriteLine("HandleOutgoingMessages finished"); return; } catch (EncapsulatedExceptions exceptions) { outgoingSignalMessage.Status = SignalMessageStatus.Confirmed; Debug.WriteLine(exceptions.Message); Debug.WriteLine(exceptions.StackTrace); IList <UntrustedIdentityException> identityExceptions = exceptions.getUntrustedIdentityExceptions(); if (exceptions.getNetworkExceptions().Count > 0) { outgoingSignalMessage.Status = SignalMessageStatus.Failed_Network; } if (identityExceptions.Count > 0) { outgoingSignalMessage.Status = SignalMessageStatus.Failed_Identity; } foreach (UntrustedIdentityException e in identityExceptions) { Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() => { await MainPage.NotifyNewIdentity(e.getE164Number()); }).AsTask().Wait(); LibsignalDBContext.SaveIdentityLocked(new SignalProtocolAddress(e.getE164Number(), 1), Base64.encodeBytes(e.getIdentityKey().serialize())); } } catch (RateLimitException e) { Debug.WriteLine(e.Message); Debug.WriteLine(e.StackTrace); outgoingSignalMessage.Status = SignalMessageStatus.Failed_Ratelimit; } catch (UntrustedIdentityException e) { Debug.WriteLine(e.Message); Debug.WriteLine(e.StackTrace); outgoingSignalMessage.Status = SignalMessageStatus.Failed_Identity; Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() => { await MainPage.NotifyNewIdentity(e.getE164Number()); }).AsTask().Wait(); LibsignalDBContext.SaveIdentityLocked(new SignalProtocolAddress(e.getE164Number(), 1), Base64.encodeBytes(e.getIdentityKey().serialize())); } catch (Exception e) { Debug.WriteLine(e.Message); Debug.WriteLine(e.StackTrace); outgoingSignalMessage.Status = SignalMessageStatus.Failed_Unknown; } SignalDBContext.UpdateMessageStatus(outgoingSignalMessage, this); } Debug.WriteLine("HandleOutgoingMessages finished"); }
private void 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 = 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() }; //MessageSender.sendMessage(envelope.getSourceAddress(), requestInfoMessage); TODO } composedTimestamp = envelope.getTimestamp(); } else { if (isSync) { var sent = content.SynchronizeMessage.getSent().ForceGetValue(); conversation = SignalDBContext.GetOrCreateContactLocked(sent.getDestination().ForceGetValue(), timestamp); composedTimestamp = sent.getTimestamp(); } else { conversation = 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 = SignalDBContext.GetOrCreateContactLocked(envelope.getSource(), timestamp); } List <SignalAttachment> attachments = new List <SignalAttachment>(); SignalMessage message = new SignalMessage() { Direction = type, Status = status, Author = author, Content = new SignalMessageContent() { Content = body }, 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 = "", Key = pointer.Key, Relay = pointer.Relay, StorageId = pointer.Id }; attachments.Add(sa); } } SignalLibHandle.Instance.SaveAndDispatchSignalMessage(message, conversation); }