public void Release() { //TODO invalidate view information Logger.LogTrace("Release()"); if (Running) { Logger.LogTrace("Release() locking"); SemaphoreSlim.Wait(CancelSource.Token); Logger.LogTrace("Release() locked"); Running = false; CancelSource.Cancel(); IncomingMessagesTask?.Wait(); OutgoingMessagesTask?.Wait(); Instance = null; Logger.LogTrace("Release() releasing global"); LibUtils.Unlock(); Logger.LogTrace("Release() releasing local"); SemaphoreSlim.Release(); Logger.LogTrace("Release() released"); } else { Logger.LogWarning("SignalLibHandle was already closed"); } }
public async Task Reacquire() { Logger.LogTrace("Reacquire() locking"); CancelSource = new CancellationTokenSource(); SemaphoreSlim.Wait(CancelSource.Token); try { GlobalResetEvent = LibUtils.OpenResetEventSet(); LibUtils.Lock(); GlobalResetEvent.Reset(); LibsignalDBContext.ClearSessionCache(); Instance = this; await Task.Run(async() => { List <Task> tasks = new List <Task>(); foreach (var f in Frames) { var conversations = GetConversations(); var taskCompletionSource = new TaskCompletionSource <bool>(); await f.Key.RunAsync(CoreDispatcherPriority.Normal, () => { try { f.Value.ReplaceConversationList(conversations); } catch (Exception e) { Logger.LogError("Reacquire() ReplaceConversationList() failed: {0}\n{1}", e.Message, e.StackTrace); } finally { taskCompletionSource.SetResult(false); } }); tasks.Add(taskCompletionSource.Task); } foreach (var t in tasks) { await t; } await RecoverDownloads(); Store = LibsignalDBContext.GetSignalStore(); if (Store != null) { LikelyHasValidStore = true; } }); if (LikelyHasValidStore) { InitNetwork(); } Running = true; } finally { SemaphoreSlim.Release(); Logger.LogTrace("Reacquire() released"); } }
public async Task Reacquire() { Logger.LogTrace("Reacquire() locking"); CancelSource = new CancellationTokenSource(); SemaphoreSlim.Wait(CancelSource.Token); GlobalResetEvent = LibUtils.OpenResetEventSet(); LibUtils.Lock(); GlobalResetEvent.Reset(); LibsignalDBContext.ClearSessionCache(); Instance = this; await Task.Run(() => { List <Task> tasks = new List <Task>(); foreach (var f in Frames) { var conversations = GetConversations(); tasks.Add(f.Key.RunTaskAsync(() => { f.Value.ReplaceConversationList(conversations); })); } Task.WaitAll(tasks.ToArray()); InitNetwork(); }); Running = true; Logger.LogTrace("Reacquire() releasing"); SemaphoreSlim.Release(); }
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"); } }
public void Release() { //TODO invalidate view information Logger.LogTrace("Release() locking"); SemaphoreSlim.Wait(CancelSource.Token); Running = false; CancelSource.Cancel(); IncomingMessagesTask?.Wait(); OutgoingMessagesTask?.Wait(); Instance = null; Logger.LogTrace("Release() releasing global)"); LibUtils.Unlock(); Logger.LogTrace("Release() releasing local)"); SemaphoreSlim.Release(); Logger.LogTrace("Release() released"); }
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 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"); } }