public static void SendLastPresence(Service service) { if (!service.Information.DoesSupport(typeof(PresenceBubble))) { return; } lock (LastPresenceBubbles) { var presenceBubble = LastPresenceBubbles.FirstOrDefault(pb => pb.Service == service); if (presenceBubble == null) { return; } Utils.DebugPrint("Sending last presence for service " + service.Information.ServiceName + ". " + (presenceBubble.Available ? "Available." : "Unavailable.")); Send(presenceBubble); if (presenceBubble.Available) { return; } foreach (var group in BubbleGroupManager.FindAll(presenceBubble.Service)) { @group.PresenceType = PresenceBubble.PresenceType.Unavailable; } } }
public static void UpdatePartyParticipants(Service service, string bubbleGroupAddress, Action <bool> finished = null) { var bubbleGroup = BubbleGroupManager.FindWithAddress(service, bubbleGroupAddress); if (bubbleGroup == null) { finished(false); } UpdatePartyParticipants(bubbleGroup, () => { try { BubbleGroupEvents.RaiseBubblesUpdated(bubbleGroup); } catch { // do nothing } if (finished != null) { finished(true); } }); }
public static void Delete(BubbleGroup group) { lock (BubbleGroupDatabase.OperationLock) { var unifiedGroup = @group as UnifiedBubbleGroup; if (unifiedGroup != null) { DeleteUnified(unifiedGroup); return; } var file = BubbleGroupDatabase.GetLocation(@group); if (File.Exists(file)) { File.Delete(file); } BubbleGroupSync.RemoveFromSync(@group); BubbleGroupSync.DeleteBubbleGroupIfHasAgent(@group); BubbleGroupManager.BubbleGroupsRemove(@group); } }
public static void UpdateParties(Service service, string participantAddress) { Utils.DebugPrint("Updating bubble group parties that contain participant address: " + participantAddress); foreach (var @group in BubbleGroupManager.FindAll(@group => @group.IsParty && @group.Service == service && @group.Participants.Any())) { foreach (var participant in @group.Participants) { //TODO: this needs to be made into a comparer eventually //TODO: as it stands... a participant with address 16041234567 != 6041234567 if (participant.Address != participantAddress) { continue; } Utils.DebugPrint("Updating " + @group.ID + " (party) with name " + (@group.Title != null ? @group.Title : "[unknown]")); Update(@group); break; //don't update the same group again } } }
public static UnifiedBubbleGroup CreateUnified(List <BubbleGroup> groups, BubbleGroup primaryGroup) { lock (BubbleGroupDatabase.OperationLock) { var unifiedGroupsToKill = new HashSet <UnifiedBubbleGroup>(); foreach (var group in groups) { if (group.IsUnified) { unifiedGroupsToKill.Add(group.Unified); @group.DeregisterUnified(); } } foreach (var unifiedGroup in unifiedGroupsToKill) { BubbleGroupManager.BubbleGroupsRemove(unifiedGroup); } UnifiedBubbleGroupsDatabase.Remove(unifiedGroupsToKill); var unified = CreateUnifiedInternal(groups, primaryGroup); UnifiedBubbleGroupsDatabase.Add(unified, new DisaUnifiedBubbleGroupEntry(unified.ID, unified.Groups.Select(innerGroup => innerGroup.ID) .ToArray(), primaryGroup.ID, primaryGroup.ID)); BubbleGroupManager.BubbleGroupsAdd(unified); return(unified); } }
public static void Load() { lock (_lock) { using (var db = new SqlDatabase <BubbleGroupSettings>(GetPath())) { var toRemoves = new List <BubbleGroupSettings>(); foreach (var settings in db.Store.ToList()) { var bubbleGroup = BubbleGroupManager.Find(settings.Guid); if (bubbleGroup == null) { toRemoves.Add(settings); } else { bubbleGroup.Settings = settings; } } if (toRemoves.Any()) { foreach (var toRemove in toRemoves) { db.Remove(toRemove); } } } } }
public static UnifiedBubbleGroup CreateUnified(List <BubbleGroup> groups, BubbleGroup primaryGroup) { lock (BubbleGroupDatabase.OperationLock) { var unifiedGroupsToKill = new HashSet <UnifiedBubbleGroup>(); foreach (var group in groups) { if (group.IsUnified) { unifiedGroupsToKill.Add(group.Unified); @group.DeregisterUnified(); } } foreach (var unifiedGroup in unifiedGroupsToKill) { BubbleGroupManager.BubbleGroupsRemove(unifiedGroup); } BubbleGroupIndex.RemoveUnified(unifiedGroupsToKill.Select(x => x.ID).ToArray()); var unified = CreateUnifiedInternal(groups, primaryGroup); BubbleGroupIndex.AddUnified(unified); BubbleGroupManager.BubbleGroupsAdd(unified); BubbleGroupSettingsManager.SetUnreadIndicatorGuid(unified, unified.LastBubbleSafe().ID, false); return(unified); } }
public static void SendPresence(Service service, bool available, bool justAddIfNoLastPresence = false) { if (!service.Information.DoesSupport(typeof(PresenceBubble))) { return; } var presenceBubble = new PresenceBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing, null, false, service, available); Utils.DebugPrint("Sending " + (presenceBubble.Available ? "available" : "unavailble") + " to " + presenceBubble.Service.Information.ServiceName); lock (LastPresenceBubbles) { Action a = () => { LastPresenceBubbles.RemoveAll(pb => pb.Service == presenceBubble.Service); LastPresenceBubbles.Add(presenceBubble); }; if (!justAddIfNoLastPresence) { a(); } else { var hasPresence = LastPresenceBubbles.Any(x => x.Service == presenceBubble.Service); if (hasPresence) { // do-nothing } else { a(); } } } if (!justAddIfNoLastPresence && ServiceManager.IsRunning(service)) { Send(presenceBubble); } if (justAddIfNoLastPresence) { return; } if (available) { return; } foreach (var group in BubbleGroupManager.FindAll(service)) { @group.PresenceType = PresenceBubble.PresenceType.Unavailable; } }
public static void SetNotQueuedToFailures(BubbleGroup group) { var groups = BubbleGroupManager.GetInner(@group).Where(x => !x.PartiallyLoaded && (x.Service.QueuedBubblesParameters != null && x.Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart != null && x.Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart.Any())); var failed = new List <Tuple <BubbleGroup, VisualBubble> >(); foreach (var innerGroup in groups) { foreach (var bubble in innerGroup) { if (bubble.Direction == Bubble.BubbleDirection.Outgoing && bubble.Status == Bubble.BubbleStatus.Waiting) { if (innerGroup .Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart .FirstOrDefault(x => x == bubble.GetType()) != null) { failed.Add(new Tuple <BubbleGroup, VisualBubble>(innerGroup, bubble)); } } } } if (!failed.Any()) { return; } var somethingUpdated = false; var failuresGroupedByBubbleGroup = failed.GroupBy(x => x.Item1); foreach (var failureGroup in failuresGroupedByBubbleGroup) { var groupOfBubbles = failureGroup.First().Item1; var bubbles = failureGroup.Select(x => x.Item2).ToArray(); foreach (var bubble in bubbles) { bubble.Status = Bubble.BubbleStatus.Failed; } BubbleGroupDatabase.UpdateBubble(groupOfBubbles, bubbles, groupOfBubbles.Bubbles.Count + 100); // 100 is really a tolerance here (just in case) foreach (var bubble in bubbles) { BubbleGroupEvents.RaiseBubbleFailed(bubble, groupOfBubbles); } somethingUpdated = true; } if (somethingUpdated) { BubbleGroupEvents.RaiseBubblesUpdated(@group); BubbleGroupEvents.RaiseRefreshed(@group); } }
public Task <List <VisualBubble> > FetchNext() { return(Task.Factory.StartNew <List <VisualBubble> >(() => { if (_endReached) { return null; } lock (BubbleGroupDatabase.OperationLock) { var groups = BubbleGroupManager.GetInner(_group); var groupCursors = groups.Select(@group => new Tuple <BubbleGroup, long>(@group, -1)).ToList(); var allBubbles = new List <VisualBubble>(); var handles = OpenDatabaseStreams(groups).ToList(); GetMoreBubbles: var result = LoadDatabaseBubblesOnUnitInto(groups, _day, handles, groupCursors, _selection.BubbleTypes, _selection.Comparer); var bubbles = result.Item1; if (bubbles != null) { allBubbles.AddRange(bubbles); } groupCursors = result.Item2; _day++; var endReached = result.Item2.Count(cursor => cursor.Item2 == -2); if (endReached == result.Item2.Count) { _endReached = true; goto ReturnResult; } if (bubbles == null) { goto GetMoreBubbles; } if (allBubbles.Count < 100) { goto GetMoreBubbles; } ReturnResult: CloseDatabaseStreams(handles); allBubbles.TimSort((x, y) => - x.Time.CompareTo(y.Time)); return allBubbles; } })); }
public static List <VisualBubble> FindAll(Service service, string address) { var bubbleGroup = BubbleGroupManager.FindWithAddress(service, address); if (bubbleGroup == null) { return(new List <VisualBubble>()); } BubbleGroupFactory.LoadFullyIfNeeded(bubbleGroup); return(bubbleGroup.Bubbles.ToList()); }
public static BubbleGroup AddNewIfNotExist(VisualBubble bubble, bool updateUi = false) { var group = BubbleGroupManager.FindWithAddress(bubble.Service, bubble.Address); if (@group != null) { return(null); } return(AddNewInternal(bubble, updateUi)); }
public static void ResetSyncsIfHasAgent(Service service) { if (!SupportsSync(service)) { return; } foreach (var group in BubbleGroupManager.FindAll(service)) { group.NeedsSync = true; } }
internal static void LoadAll() { lock (Lock) { var sw = new Stopwatch(); sw.Start(); var location = GetLocation(); try { if (File.Exists(location)) { using (var fs = File.OpenRead(location)) { var items = Serializer.Deserialize<List<BubbleGroupCache>>(fs); foreach (var item in items) { var associatedGroup = BubbleGroupManager.Find(item.Guid); if (associatedGroup == null) { continue; } var unifiedGroup = associatedGroup as UnifiedBubbleGroup; if (unifiedGroup != null) { associatedGroup = unifiedGroup.PrimaryGroup; } Bind(associatedGroup, item); } } } } catch (Exception ex) { Utils.DebugPrint("Failed to load bubble group cache: " + ex); if (File.Exists(location)) { File.Delete(location); } } sw.Stop(); Utils.DebugPrint("Loading bubble group cache took " + sw.ElapsedMilliseconds + "ms."); } }
internal static void UnloadFullLoad(BubbleGroup group) { var innerGroups = BubbleGroupManager.GetInner(@group); foreach (var innerGroup in innerGroups) { innerGroup.UnloadFullLoad(); } var unifiedGroup = @group as UnifiedBubbleGroup; if (unifiedGroup != null) { unifiedGroup.UnloadFullUnifiedLoad(); } }
public static bool UpdateQuotedMessageTitle(VisualBubble bubble, Action <string> onTitleUpdated) { var service = bubble.Service; if (!ServiceManager.IsRunning(service)) { return(false); } if (string.IsNullOrWhiteSpace(bubble.QuotedAddress)) { return(false); } try { service.GetQuotedMessageTitle(bubble, result => { var bubbleGroup = BubbleGroupManager.FindWithAddress(bubble.Service, bubble.Address); if (bubbleGroup != null) { var quotedTitles = bubbleGroup.QuotedTitles == null ? new List <DisaQuotedTitle>() : bubbleGroup.QuotedTitles.ToList(); var quotedTitle = quotedTitles.FirstOrDefault(x => bubbleGroup.Service.BubbleGroupComparer(x.Address, bubble.QuotedAddress)); if (quotedTitle == null) { quotedTitles.Add(new DisaQuotedTitle { Address = bubble.QuotedAddress, Title = result, }); } else { quotedTitle.Title = result; } bubbleGroup.QuotedTitles = quotedTitles.ToArray(); } onTitleUpdated(result); }); return(true); } catch (Exception e) { Utils.DebugPrint("Error getting quoted message title " + e); return(false); } }
public static void UpdateStatus(Service service, string bubbleId, Bubble.BubbleStatus status) { var serviceGroups = BubbleGroupManager.FindAll(service); foreach (var group in serviceGroups) { foreach (var bubble in @group) { if (bubble.ID == bubbleId) { UpdateStatus(bubble, status, @group); return; } } } }
public static IEnumerable <VisualBubble> FindAllUnread(Service service, string address) { var bubbleGroup = BubbleGroupManager.FindWithAddress(service, address); if (bubbleGroup != null) { foreach (var bubble in bubbleGroup) { if (bubble.Direction == Bubble.BubbleDirection.Incoming && bubble.Time >= BubbleGroupSettingsManager.GetLastUnreadSetTime(bubbleGroup)) { yield return(bubble); } } } }
public static void Update(Service service, string bubbleGroupAddress) { Utils.DebugPrint("Service: " + service.Information.ServiceName + " has called UpdateBubbleGroup with id: " + bubbleGroupAddress); var selectedGroup = BubbleGroupManager.FindWithAddress(service, bubbleGroupAddress); if (selectedGroup == null) { return; } Utils.DebugPrint("Updating " + selectedGroup.ID + " with name " + (selectedGroup.Title != null ? selectedGroup.Title : "[unknown]")); Update(selectedGroup); }
public static void SendSubscribe(Service service, bool subscribe) { if (!service.Information.DoesSupport(typeof(SubscribeBubble))) { return; } Utils.DebugPrint((subscribe ? "Subscribing" : "Unsubscribing") + " to " + service.Information.ServiceName + " solo bubble groups."); foreach (var bubbleGroup in BubbleGroupManager.FindAll(g => !g.IsParty && g.Service == service)) { SendSubscribe(bubbleGroup, subscribe); } }
public static bool ResetSyncsIfHasAgent(Service service, string bubbleGroupAddress) { if (!SupportsSync(service)) { return(false); } foreach (var group in BubbleGroupManager.FindAll(service)) { if (service.BubbleGroupComparer(group.Address, bubbleGroupAddress)) { group.NeedsSync = true; return(true); } } return(false); }
public static List <BubbleGroup> DeleteUnified(UnifiedBubbleGroup unifiedGroup, bool deleteInnerGroups = true) { lock (BubbleGroupDatabase.OperationLock) { foreach (var group in unifiedGroup.Groups) { @group.DeregisterUnified(); if (deleteInnerGroups) { Delete(@group); } } BubbleGroupManager.BubbleGroupsRemove(unifiedGroup); BubbleGroupIndex.RemoveUnified(unifiedGroup.ID); return(deleteInnerGroups ? null : unifiedGroup.Groups); } }
public static void SetNotQueuedToFailures(Service service) { if (service is UnifiedService) { return; } if (service.QueuedBubblesParameters == null || service.QueuedBubblesParameters.BubblesNotToQueue == null || !service.QueuedBubblesParameters.BubblesNotToQueue.Any()) { return; } foreach (var group in BubbleGroupManager.FindAll(service)) { SetNotQueuedToFailures(@group); } }
public static bool UpdateStatus(Service service, string bubbleGroupAddress, string bubbleId, Bubble.BubbleStatus status) { var group = BubbleGroupManager.FindWithAddress(service, bubbleGroupAddress); if (group == null) { return(false); } BubbleGroupFactory.LoadFullyIfNeeded(group); foreach (var bubble in @group.Bubbles) { if (bubble.ID == bubbleId) { UpdateStatus(bubble, status, @group); return(true); } } return(false); }
public static void Update(Service service, bool optimized = true) { const int Interval = 5; var updateCounter = 0; var groupsDoneCounter = 0; var groups = BubbleGroupManager.FindAll(service); var updateCounterThreshold = groups.Count / Interval; foreach (var group in groups) { Action chainFinished = null; if (groups.Count >= Interval) { chainFinished = () => { Action <bool> doUpdate = singleton => { BubbleGroupEvents.RaiseRefreshed(groups); BubbleGroupEvents.RaiseBubblesUpdated(groups); BubbleGroupEvents.RaiseInformationUpdated(groups); }; groupsDoneCounter++; if (groupsDoneCounter % Interval == 0) { updateCounter++; doUpdate(false); } // do the remainder one by one ... else if (updateCounter >= updateCounterThreshold) { doUpdate(true); } }; } Update(@group, optimized, chainFinished); } }
private static BubbleGroup AddNewInternal(VisualBubble newBubble, bool raiseBubbleInserted) { var group = new BubbleGroup(newBubble, null, false); BubbleGroupSettingsManager.SetUnreadIndicatorGuid(group, group.LastBubbleSafe().ID, true); if (ServiceManager.IsRunning(@group.Service)) { newBubble.Service.NewBubbleGroupCreated(@group).ContinueWith(x => { // force the UI to refetch the photo @group.IsPhotoSetFromService = false; BubbleManager.SendSubscribe(@group, true); BubbleGroupUpdater.Update(@group); }); } BubbleGroupManager.BubbleGroupsAdd(@group); BubbleGroupDatabase.AddBubble(@group, newBubble); if (raiseBubbleInserted) { try { BubbleGroupEvents.RaiseBubbleInserted(newBubble, @group); } catch (Exception ex) { Utils.DebugPrint( "Error in notifying the interface that the bubble group has been updated (" + newBubble.Service.Information.ServiceName + "): " + ex.Message); } } BubbleGroupUpdater.Update(@group); return(@group); }
public static void SetNotQueuedToFailures(BubbleGroup group) { var nowUnixTimeStamp = Time.GetNowUnixTimestamp(); var groups = BubbleGroupManager.GetInner(@group).Where(x => (x.Service.QueuedBubblesParameters != null && x.Service.QueuedBubblesParameters.BubblesNotToQueue != null && x.Service.QueuedBubblesParameters.BubblesNotToQueue.Any())); if (!groups.Any()) { return; } foreach (var innerGroup in groups) { if (HasNotQueued(innerGroup)) { if (innerGroup.PartiallyLoaded) { BubbleGroupFactory.LoadFullyIfNeeded(innerGroup); } var bubblesSetToFailed = new List <VisualBubble>(); foreach (var bubble in innerGroup.Bubbles) { if (bubble.Direction == Bubble.BubbleDirection.Outgoing && bubble.Status == Bubble.BubbleStatus.Waiting) { if (innerGroup .Service.QueuedBubblesParameters.BubblesNotToQueue .FirstOrDefault(x => x == bubble.GetType()) != null) { var failBubble = innerGroup .Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart .FirstOrDefault(x => x == bubble.GetType()) != null; // Older than 10 minutes, fail it regardless. if (!failBubble && bubble.Time < (nowUnixTimeStamp - 600)) { failBubble = true; } if (failBubble) { RemoveNotQueued(bubble); bubble.Status = Bubble.BubbleStatus.Failed; bubblesSetToFailed.Add(bubble); } } } } if (bubblesSetToFailed.Any()) { BubbleGroupDatabase.UpdateBubble(innerGroup, bubblesSetToFailed.ToArray(), 100); foreach (var bubble in bubblesSetToFailed) { BubbleGroupEvents.RaiseBubbleFailed(bubble, innerGroup); } BubbleGroupEvents.RaiseBubblesUpdated(innerGroup); BubbleGroupEvents.RaiseRefreshed(innerGroup); } } } NotQueuedSanityCheckup(); }
private static void StopInternal(Service registeredService, bool clearFailures = true) { if (!IsRegistered(registeredService)) { throw new ServiceSchedulerException("Could not locate service " + registeredService.Information.ServiceName + ". Are you sure you registered it?"); } if (clearFailures) { ClearFailures(registeredService); } Action deAuthenticate = () => { try { registeredService.Deauthenticate(); } catch (NotImplementedException) { } catch (Exception ex) { GetFlags(registeredService).DeauthenticationFailed = true; Utils.DebugPrint(registeredService.Information.ServiceName + "service failed to deauthenticate. " + "This may lead to a memory leak. Problem: " + ex.Message); } }; Action disconnect = () => { try { registeredService.Disconnect(); } catch (NotImplementedException) { } catch (Exception ex) { GetFlags(registeredService).DisconnectionFailed = true; Utils.DebugPrint(registeredService.Information.ServiceName + "service failed to disconnect. " + "This may lead to a memory leak. Problem: " + ex.Message); } }; if (registeredService.Information.Procedure == ServiceInfo.ProcedureType.AuthenticateConnect) { deAuthenticate(); disconnect(); } else if (registeredService.Information.Procedure == ServiceInfo.ProcedureType.ConnectAuthenticate) { disconnect(); deAuthenticate(); } //there may be exceptions, but we have to remove the service. GetFlags(registeredService).Running = false; foreach ( var group in BubbleGroupManager.FindAll( x => x.Service == registeredService && !(x is UnifiedBubbleGroup))) { @group.Typing = false; @group.PresenceType = PresenceBubble.PresenceType.Unavailable; } }
internal static void OnBubbleReceived(Bubble b) { var visualBubble = b as VisualBubble; if (visualBubble != null) { try { BubbleManager.Group(visualBubble); } catch (Exception ex) { Utils.DebugPrint("Problem in OnBubbleReceived (VisualBubble) from service " + visualBubble.Service.Information.ServiceName + ": " + ex.Message); } if (visualBubble.Direction == Bubble.BubbleDirection.Incoming && IsRunning(visualBubble.Service) && BubbleQueueManager.HasQueuedBubbles(b.Service.Information.ServiceName, true, true)) { Utils.DebugPrint("Sending queued bubbles as we're getting some received."); BubbleQueueManager.Send(new [] { b.Service.Information.ServiceName }); } } else if (b is AbstractBubble) { Utils.DebugPrint("We got an abstract bubble: " + b.GetType().Name + " Address: " + b.Address); BubbleGroup group = null; var deliveredBubble = b as DeliveredBubble; if (deliveredBubble != null) { @group = BubbleGroupManager.FindWithAddress(deliveredBubble.Service, deliveredBubble.Address); if (@group != null) { BubbleGroupFactory.LoadFullyIfNeeded(@group); var bubbles = @group.Bubbles; for (var i = bubbles.Count - 1; i >= 0; i--) { var bubble = bubbles[i]; if (bubble.ID != deliveredBubble.VisualBubbleID) { continue; } BubbleManager.UpdateStatus(bubble, Bubble.BubbleStatus.Delivered, @group); if (@group.Service.Information.DoesSupport(typeof(DeliveredBubbleReceipt))) { BubbleManager.Send(new DeliveredBubbleReceipt(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing, @group.Service, bubble)); } break; } } } var readBubble = b as ReadBubble; if (readBubble != null) { @group = BubbleGroupManager.FindWithAddress(readBubble.Service, readBubble.Address); if (@group != null) { BubbleGroupFactory.LoadFullyIfNeeded(@group); if (@group.ReadTimes == null || [email protected]) { @group.ReadTimes = new [] { new DisaReadTime { ParticipantAddress = readBubble.ParticipantAddress, Time = readBubble.ReadTime } }; } else { var readTimes = @group.ReadTimes.ToList(); var duplicateReadTime = readTimes.FirstOrDefault(x => @group.Service.BubbleGroupComparer(x.ParticipantAddress, readBubble.ParticipantAddress)); if (duplicateReadTime != null) { readTimes.Remove(duplicateReadTime); } readTimes.Add(new DisaReadTime { ParticipantAddress = readBubble.ParticipantAddress, Time = readBubble.ReadTime }); @group.ReadTimes = readTimes.ToArray(); } } } var prescenceBubble = b as PresenceBubble; if (prescenceBubble != null) { @group = BubbleGroupManager.Find(bubbleGroup => !bubbleGroup.IsParty && bubbleGroup.Service == prescenceBubble.Service && prescenceBubble.Service.BubbleGroupComparer( bubbleGroup.Address, prescenceBubble.Address)); if (@group != null) { if ([email protected] && !prescenceBubble.Available) { var oldPresence = @group.PresenceType; @group.PresenceType = PresenceBubble.PresenceType.Unavailable; if (oldPresence != prescenceBubble.Presence) { BubbleGroupManager.UpdateLastOnline(@group); } } else { @group.PresenceType = prescenceBubble.Presence; @group.PresencePlatformType = prescenceBubble.Platform; } if (!prescenceBubble.Available) { @group.Typing = false; } } } var typingBubble = b as TypingBubble; if (typingBubble != null) { @group = BubbleGroupManager.Find(bubbleGroup => !bubbleGroup.IsParty && bubbleGroup.Service == typingBubble.Service && typingBubble.Service.BubbleGroupComparer( bubbleGroup.Address, typingBubble.Address)); if (@group != null) { if (@group.Presence) { @group.Typing = typingBubble.Typing; @group.TypingIsAudio = typingBubble.IsAudio; } else { @group.Typing = false; } } } try { if (@group != null) { BubbleGroupEvents.RaiseNewAbstractBubble(b as AbstractBubble, @group); } } catch (Exception ex) { Utils.DebugPrint("Problem in OnBubbleReceived (AbstractBubble) from service " + b.Service.Information.ServiceName + ": " + ex.Message); } } }
public static Task Start(Service service, bool smartStart = false, int smartStartSeconds = 10) { return(Task.Factory.StartNew(() => { using (var wakeLock = Platform.AquireWakeLock("DisaStart")) { if (IsRunning(service)) { Utils.DebugPrint( "The service is already running. Preventing possible deadlock. SmartStart? " + smartStart); return; } if (IsStarting(service)) { Utils.DebugPrint( "The service is being started. Preventing possible deadlock. SmartStart? " + smartStart); return; } Action epilogue = () => { GetFlags(service).Starting = false; }; lock (service) { GetFlags(service).Aborted = false; GetFlags(service).AbortedSpecial = false; GetFlags(service).Starting = true; GetFlags(service).ManualSettingsNeeded = false; Utils.DebugPrint("Loading settings for service " + service.Information.ServiceName); try { var settings = SettingsManager.Load(service); if (settings == null) { Utils.DebugPrint("Failed to load saved settings for " + service.Information.ServiceName + ". Will try to initialize with no settings..."); if (!service.InitializeDefault()) { Utils.DebugPrint( "Service doesn't allow initializing without settings. Needs manual input."); GetFlags(service).ManualSettingsNeeded = true; ServiceEvents.RaiseServiceManualSettingsNeeded(service); } else { Utils.DebugPrint("Service initialized under no settings."); } } else { Utils.DebugPrint("Loading saved settings! Initializing..."); if (service.Initialize(settings)) { Utils.DebugPrint("Successfully initialized service!"); } else { Utils.DebugPrint("Failed to initialize service. Needs manual input."); GetFlags(service).ManualSettingsNeeded = true; ServiceEvents.RaiseServiceManualSettingsNeeded(service); } } } catch (Exception ex) { Utils.DebugPrint("Failed: " + ex); epilogue(); return; } Utils.DebugPrint("Starting service " + service.Information.ServiceName); try { if (service.Information.UsesInternet && !Platform.HasInternetConnection()) { throw new Exception("No internet connection. Cannot connect service: " + service.Information.ServiceName); } StartInternal(service, wakeLock); } catch (ServiceSchedulerException ex) { Utils.DebugPrint("Problem in scheduler: " + ex.Message); epilogue(); return; } catch (ServiceSpecialRestartException) { Utils.DebugPrint("Service " + service.Information.ServiceName + " is asking to be restarted on connect/authenticate. This should be called sparingly, Disa can easily " + "break under these circumstances. Restarting..."); StopInternal(service); epilogue(); Start(service, smartStart, smartStartSeconds); return; } catch (ServiceExpiredException) { Utils.DebugPrint("The service " + service.Information.ServiceName + " has expired. :("); GetFlags(service).Aborted = true; GetFlags(service).Expired = true; ServiceEvents.RaiseServiceExpired(service); StopInternal(service); epilogue(); return; } catch (Exception ex) { if (smartStart) { StopInternal(service, false); if (smartStartSeconds > 600) { Utils.DebugPrint("Service " + service.Information.ServiceName + " needs to wait over 10minutes to be restarted." + " Killing SmartStart. The service will not be restarted. Reason: " + ex); epilogue(); return; } Utils.DebugPrint("Service " + service.Information.ServiceName + " failed to be started. SmartStart enabled. " + "Service being scheduled to be re-started in T-" + smartStartSeconds + " seconds! Reason: " + ex); var hasSmartStart = new object(); service.HasSmartStart = hasSmartStart; Platform.ScheduleAction(smartStartSeconds, new WakeLockBalancer.ActionObject(() => { if (IsAborted(service)) { Utils.DebugPrint( "Service " + service.Information .ServiceName + " tried to be started, but it deemed killed."); return; } if (service.HasSmartStart != hasSmartStart) { Utils.DebugPrint( "This smart start has been invalidated. There " + "seems to be another one on the block."); return; } Utils.DebugPrint( "Smart start is firing the service " + service.Information .ServiceName + " up again!"); StopInternal(service); Start(service, true, smartStartSeconds * 2); }, WakeLockBalancer.ActionObject.ExecuteType.TaskWithWakeLock)); epilogue(); return; } Utils.DebugPrint("Failed to start service " + service.Information.ServiceName + " (No SmartStart) : " + ex); StopInternal(service, false); epilogue(); return; } BubbleManager.SendSubscribe(service, true); BubbleManager.SendLastPresence(service); service.ReceivingBubblesThread = new Thread(() => { try { StartReceiveBubbles(service); } catch (ThreadAbortException) { Utils.DebugPrint( "Abort thread excepton in receiving bubbles on service (outer thread) " + service.Information.ServiceName); } catch (Exception ex) { Utils.DebugPrint(">>>>>>>>> " + ex.Message + " " + ex.StackTrace); } Utils.DebugPrint("Receiving bubbles for service " + service.Information.ServiceName + " has come to an end."); }); service.ReceivingBubblesThread.Start(); GetFlags(service).Starting = false; BubbleManager.SetNotQueuedToFailures(service); Utils.Delay(1000).ContinueWith(x => { BubbleGroupSync.ResetSyncsIfHasAgent(service); BubbleGroupUpdater.Update(service); BubbleQueueManager.Send(new[] { service.Information.ServiceName }); BubbleGroupManager.ProcessUpdateLastOnlineQueue(service); }); } } })); }