public static void Save(Service service, DisaSettings settings)
        {
            lock (Lock)
            {
                var  path = GetPath(service);
                bool settingsFileExists = File.Exists(path);

                MemoryStream sw2;
                using (var sw = new MemoryStream())
                {
                    Save(sw, service.Information.Settings, settings);
                    sw2 = sw;
                }
                if (sw2 != null)
                {
                    File.WriteAllBytes(path, sw2.ToArray());
                    ServiceEvents.RaiseSettingsSaved(service);
                }

                if (!settingsFileExists)
                {
                    Analytics.RaiseServiceEvent(
                        Analytics.EventAction.ServiceSetup,
                        Analytics.EventCategory.Services,
                        service);
                }
            }
        }
        public static void Unregister(Service service)
        {
            if (!IsRegistered(service))
            {
                throw new ServiceSchedulerException("Service " + service.Information.ServiceName + "  is not registered!");
            }

            lock (ServicesBindings) ServicesBindings.Remove(ServicesBindings.FirstOrDefault(s => s.Service == service));
            ServiceEvents.RaiseServiceUnRegistered(service);
        }
        public static void Unregister(Service service)
        {
            if (!IsRegistered(service))
            {
                throw new ServiceSchedulerException("Service " + service.Information.ServiceName + "  is not registered!");
            }

            lock (ServicesBindings) ServicesBindings.Remove(ServicesBindings.FirstOrDefault(s => s.Service == service));
            ServiceEvents.RaiseServiceUnRegistered(service);
            SettingsChangedManager.SetNeedsContactSync(service, true);

            Analytics.RaiseServiceEvent(
                Analytics.EventAction.ServiceUnregistered,
                Analytics.EventCategory.Services,
                service);
        }
        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);
                        });
                    }
                }
            }));
        }
        private static void StartInternal(Service registeredService, WakeLock wakeLock)
        {
            if (IsManualSettingsNeeded(registeredService))
            {
                throw new ServiceSchedulerException("Service " + registeredService.Information.ServiceName + " needs manual input for settings.");
            }

            if (!IsRegistered(registeredService))
            {
                throw new ServiceSchedulerException("Could not locate service "
                                                    + registeredService.Information.ServiceName + ". Are you sure you registered it?");
            }

            if (IsRunning(registeredService))
            {
                throw new ServiceSchedulerException(registeredService.Information.ServiceName
                                                    + " service is already running.");
            }

            ClearFailures(registeredService);

            ServiceEvents.RaiseServiceSettingsLoaded(registeredService);

            Action connect = () =>
            {
                try
                {
                    registeredService.Connect(wakeLock);
                }
                catch (NotImplementedException)
                {
                }
                catch (ServiceSpecialRestartException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    GetFlags(registeredService).ConnectionFailed = true;
                    throw new Exception("Service " + registeredService.Information.ServiceName
                                        + " flat out failed to connect. Problem: " + ex);
                }
            };

            Action authenticate = () =>
            {
                try
                {
                    var authSuccess = registeredService.Authenticate(wakeLock);

                    if (!authSuccess)
                    {
                        throw new Exception("Failed authentication "
                                            + registeredService.Information.ServiceName + ".");
                    }
                }
                catch (NotImplementedException)
                {
                }
                catch (ServiceSpecialRestartException)
                {
                    throw;
                }
                catch (ServiceExpiredException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    GetFlags(registeredService).AuthenticationFailed = true;
                    throw new Exception("Service " + registeredService.Information.ServiceName
                                        + " flat out failed to authenticate. Problem: " + ex);
                }
            };

            if (registeredService.Information.Procedure
                == ServiceInfo.ProcedureType.AuthenticateConnect)
            {
                authenticate();
                connect();
            }
            else if (registeredService.Information.Procedure
                     == ServiceInfo.ProcedureType.ConnectAuthenticate)
            {
                connect();
                authenticate();
            }

            GetFlags(registeredService).Running = true;
            ServiceEvents.RaiseServiceStarted(registeredService);
        }
Exemple #6
0
        private static Task <bool> Send(Bubble b, BubbleGroup group, bool resend)
        {
            return(Task <bool> .Factory.StartNew(() =>
            {
                var vb = b as VisualBubble;
                if (vb != null)
                {
                    if (vb.Status == Bubble.BubbleStatus.Sent)
                    {
                        Utils.DebugPrint("Trying to send a bubble that is already sent! On " + vb.Service.Information.ServiceName);
                        return true;
                    }

                    Func <bool> restartServiceIfNeeded = () =>
                    {
                        if (!ServiceManager.IsRegistered(b.Service) ||
                            ServiceManager.IsRunning(b.Service) ||
                            ServiceManager.IsAborted(b.Service))
                        {
                            return false;
                        }

                        Utils.DebugPrint(
                            "For f***s sakes. The scheduler isn't doing it's job properly, or " +
                            "you're sending a message to it at a weird time. Starting it up bra (" +
                            b.Service.Information.ServiceName + ").");
                        ServiceManager.AbortAndRestart(b.Service);
                        return true;
                    };

                    var visualBubbleServiceId = vb.Service as IVisualBubbleServiceId;
                    if (vb.IdService == null && vb.IdService2 == null && visualBubbleServiceId != null)
                    {
                        visualBubbleServiceId.AddVisualBubbleIdServices(vb);
                    }

                    try
                    {
                        @group = Group(vb, resend, true);
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Problem in Send:GroupBubble from service " +
                                         vb.Service.Information.ServiceName + ": " + ex.Message);
                        return false;
                    }

                    if (@group == null)
                    {
                        Utils.DebugPrint("Could not find a suitable group for bubble " + vb.ID
                                         + " on " + vb.Service.Information.ServiceName);
                        return false;
                    }

                    var shouldQueue = vb.Service.QueuedBubblesParameters == null ||
                                      !vb.Service.QueuedBubblesParameters.BubblesNotToQueue.Contains(vb.GetType());

                    try
                    {
                        if (shouldQueue && !resend &&
                            BubbleQueueManager.HasQueuedBubbles(vb.Service.Information.ServiceName,
                                                                true, false))
                        {
                            BubbleQueueManager.JustQueue(group, vb);
                            restartServiceIfNeeded();
                            return false;
                        }

                        if (shouldQueue)
                        {
                            Monitor.Enter(vb.Service.SendBubbleLock);
                        }

                        using (var queued = new BubbleQueueManager.InsertBubble(group, vb, shouldQueue))
                        {
                            Action checkForQueued = () =>
                            {
                                if (!resend &&
                                    BubbleQueueManager.HasQueuedBubbles(vb.Service.Information.ServiceName, true, true))
                                {
                                    BubbleQueueManager.Send(new [] { vb.Service.Information.ServiceName });
                                }
                            };

                            try
                            {
                                FailBubbleIfPathDoesntExist(vb);
                                SendBubbleInternal(b);
                            }
                            catch (ServiceQueueBubbleException ex)
                            {
                                Utils.DebugPrint("Queuing visual bubble on service " +
                                                 vb.Service.Information.ServiceName + ": " + ex.Message);

                                UpdateStatus(vb, Bubble.BubbleStatus.Waiting, @group);

                                if (!restartServiceIfNeeded())
                                {
                                    checkForQueued();
                                }

                                return false;
                            }
                            catch (Exception ex)
                            {
                                queued.CancelQueue();

                                Utils.DebugPrint("Visual bubble on " +
                                                 vb.Service.Information.ServiceName + " failed to be sent: " +
                                                 ex);

                                UpdateStatus(vb, Bubble.BubbleStatus.Failed, @group);
                                BubbleGroupEvents.RaiseBubbleFailed(vb, @group);

                                if (!restartServiceIfNeeded())
                                {
                                    checkForQueued();
                                }

                                //FIXME: if the bubble fails to send, allow the queue manager to continue.
                                if (resend)
                                {
                                    return true;
                                }

                                return false;
                            }

                            queued.CancelQueue();

                            lock (BubbleGroupManager.LastBubbleSentTimestamps)
                            {
                                BubbleGroupManager.LastBubbleSentTimestamps[group.ID] = Time.GetNowUnixTimestamp();
                            }

                            if (vb.Status == Bubble.BubbleStatus.Delivered)
                            {
                                Utils.DebugPrint(
                                    "************ Race condition. The server set the status to delivered/read before we could send it to sent. :')");
                                checkForQueued();
                                return true;
                            }

                            UpdateStatus(vb, Bubble.BubbleStatus.Sent, @group);

                            checkForQueued();
                            return true;
                        }
                    }
                    finally
                    {
                        if (shouldQueue)
                        {
                            Monitor.Exit(vb.Service.SendBubbleLock);
                        }
                    }
                }
                else
                {
                    var composeBubble = b as ComposeBubble;

                    if (composeBubble != null)
                    {
                        var bubbleToSend = composeBubble.BubbleToSend;
                        var visualBubbleServiceId = bubbleToSend.Service as IVisualBubbleServiceId;
                        if (bubbleToSend.IdService == null && bubbleToSend.IdService2 == null &&
                            visualBubbleServiceId != null)
                        {
                            visualBubbleServiceId.AddVisualBubbleIdServices(bubbleToSend);
                        }
                        @group.InsertByTime(bubbleToSend);
                        try
                        {
                            BubbleGroupEvents.RaiseBubbleInserted(bubbleToSend, @group);
                        }
                        catch
                        {
                            // do nothing
                        }
                    }

                    try
                    {
                        SendBubbleInternal(b);
                    }
                    catch (ServiceBubbleGroupAddressException ex)
                    {
                        if (!String.IsNullOrWhiteSpace(ex.Address))
                        {
                            if (composeBubble != null)
                            {
                                composeBubble.BubbleToSend.Address = ex.Address;
                                composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Sent;

                                var actualGroup = Group(composeBubble.BubbleToSend, resend, true);

                                ServiceEvents.RaiseComposeFinished(
                                    @group as ComposeBubbleGroup, actualGroup);

                                return true;
                            }
                        }

                        composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        return false;
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Failed to send bubble on service " + b.Service.Information.ServiceName);

                        if (composeBubble != null)
                        {
                            composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        }

                        return false;
                    }

                    if (composeBubble != null)
                    {
                        composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        return false;
                    }

                    return true;
                }
            }));
        }
Exemple #7
0
        public static void OnPhoneContactsUpdated()
        {
            Task.Factory.StartNew(() =>
            {
                if (_isUpdating)
                {
                    Utils.DebugPrint("Contacts are already updating... Returning...");
                    return;
                }

                Action action = () =>
                {
                    lock (PhoneBookContactsLock)
                    {
                        using (new PhoneContactsUpdatingDisposable())
                        {
                            if (_phoneBookContacts == null)
                            {
                                Utils.DebugPrint("Phone contacts have not yet been used by the framework/services. Therefore, and update doesn't make sense. Skipping.");
                                return;
                            }

                            Utils.DebugPrint("Phone contacts have been updated! Querying phone contacts...");

                            var updatedPhoneContacts = Platform.GetPhoneBookContacts();

                            Utils.DebugPrint("Checking if any numbers/names have been updated...");

                            var updatedPhoneContactsNumbers =
                                (from phoneBookRelation in updatedPhoneContacts
                                 from phoneNumber in phoneBookRelation.PhoneNumbers
                                 select phoneNumber.Number).ToList();

                            var phoneBookContactsNumbers =
                                (from phoneBookRelation in _phoneBookContacts
                                 from phoneNumber in phoneBookRelation.PhoneNumbers
                                 select phoneNumber.Number).ToList();

                            var updatedPhoneContactsFullName =
                                (from phoneBookRelation in updatedPhoneContacts
                                 select phoneBookRelation.FullName).ToList();

                            var phoneContactsFullName =
                                (from phoneBookRelation in _phoneBookContacts
                                 select phoneBookRelation.FullName).ToList();

                            var phoneBooksEqual =
                                updatedPhoneContactsNumbers.Intersect(phoneBookContactsNumbers).Count() ==
                                updatedPhoneContactsNumbers.Union(phoneBookContactsNumbers).Count() &&
                                updatedPhoneContactsFullName.Intersect(phoneContactsFullName).Count() ==
                                updatedPhoneContactsFullName.Union(phoneContactsFullName).Count();

                            if (phoneBooksEqual)
                            {
                                Utils.DebugPrint(
                                    "Phone books are equal. No need to update contacts!");
                                return;
                            }

                            _phoneBookContacts = updatedPhoneContacts;

                            Utils.DebugPrint("Got phone contacts... updating running services...");

                            var notRunningServices = ServiceManager.AllNoUnified.ToList();

                            foreach (
                                var service in
                                ServiceManager.RunningNoUnified)
                            {
                                try
                                {
                                    service.RefreshPhoneBookContacts();
                                    BubbleGroupUpdater.Update(service);
                                    ServiceEvents.RaiseContactsUpdated(service);
                                    notRunningServices.Remove(service);
                                }
                                catch (Exception ex)
                                {
                                    Utils.DebugPrint("Service " + service.Information.ServiceName +
                                                     " failed to refresh it contacts. " + ex.Message);
                                }
                            }

                            if (notRunningServices.Any())
                            {
                                SettingsChangedManager.SetNeedsContactSync(notRunningServices.ToArray(), true);
                            }
                            SaveCachedPhoneBookContacts(updatedPhoneContacts);
                        }
                    }
                };

                using (Platform.AquireWakeLock("DisaContactsUpdate"))
                {
                    action();
                }
            });
        }