/// <summary>
        /// Gets a new web proxy orchestrator
        /// </summary>
        public WebRemoteOrchestrator(string serviceUri,
                                     IConverter customConverter           = null,
                                     HttpClient client                    = null,
                                     SyncPolicy syncPolicy                = null,
                                     int maxDownladingDegreeOfParallelism = 4)
            : base(null, new SyncOptions())
        {
            this.httpRequestHandler = new HttpRequestHandler(this);

            // if no HttpClient provisionned, create a new one
            if (client == null)
            {
                var handler = new HttpClientHandler();

                // Activated by default
                if (handler.SupportsAutomaticDecompression)
                {
                    handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
                }

                this.HttpClient = new HttpClient(handler);
            }
            else
            {
                this.HttpClient = client;
            }

            this.SyncPolicy = this.EnsurePolicy(syncPolicy);
            this.Converter  = customConverter;
            this.MaxDownladingDegreeOfParallelism = maxDownladingDegreeOfParallelism <= 0 ? -1 : maxDownladingDegreeOfParallelism;
            this.ServiceUri        = serviceUri;
            this.SerializerFactory = SerializersCollection.JsonSerializerFactory;
        }
Пример #2
0
        /// <summary>
        /// Create a new MySql Server database
        /// </summary>
        private static async Task CreateMariaDBDatabaseAsync(string dbName, bool recreateDb = true)
        {
            var onRetry = new Func <Exception, int, TimeSpan, object, Task>((ex, cpt, ts, arg) =>
            {
                Console.WriteLine($"Creating MariaDB database failed when connecting to information_schema ({ex.Message}). Wating {ts.Milliseconds}. Try number {cpt}");
                return(Task.CompletedTask);
            });

            SyncPolicy policy = SyncPolicy.WaitAndRetry(3, TimeSpan.FromMilliseconds(500), null, onRetry);

            await policy.ExecuteAsync(async() =>
            {
                using var sysConnection = new MySqlConnection(Setup.GetMariaDBDatabaseConnectionString("information_schema"));
                sysConnection.Open();

                if (recreateDb)
                {
                    using var cmdDrop = new MySqlCommand($"Drop schema if exists  {dbName};", sysConnection);
                    await cmdDrop.ExecuteNonQueryAsync();
                }

                using (var cmdDb = new MySqlCommand($"create schema {dbName};", sysConnection))
                    cmdDb.ExecuteNonQuery();

                sysConnection.Close();
            });
        }
        /// <summary>
        /// Ensure we have policy. Create a new one, if not provided
        /// </summary>
        private SyncPolicy EnsurePolicy(SyncPolicy policy)
        {
            if (policy != default)
            {
                return(policy);
            }

            // Defining my retry policy
            policy = SyncPolicy.WaitAndRetry(2,
                                             (retryNumber) =>
            {
                return(TimeSpan.FromMilliseconds(500 * retryNumber));
            },
                                             (ex, arg) =>
            {
                var webEx = ex as SyncException;

                // handle session lost
                return(webEx == null || webEx.TypeName != nameof(HttpSessionLostException));
            }, async(ex, cpt, ts, arg) =>
            {
                await this.InterceptAsync(new HttpSyncPolicyArgs(10, cpt, ts), default).ConfigureAwait(false);
            });


            return(policy);
        }
Пример #4
0
        /// <summary>
        /// Gets a new web proxy orchestrator
        /// </summary>
        public WebClientOrchestrator(string serviceUri,
                                     ISerializerFactory serializerFactory = null,
                                     IConverter customConverter           = null,
                                     HttpClient client     = null,
                                     SyncPolicy syncPolicy = null)
            : base(new FancyCoreProvider(), new SyncOptions(), new SyncSetup())
        {
            this.httpRequestHandler = new HttpRequestHandler(this);

            // if no HttpClient provisionned, create a new one
            if (client == null)
            {
                var handler = new HttpClientHandler();

                // Activated by default
                if (handler.SupportsAutomaticDecompression)
                {
                    handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
                }

                this.HttpClient = new HttpClient(handler);
            }
            else
            {
                this.HttpClient = client;
            }

            this.SyncPolicy        = this.EnsurePolicy(syncPolicy);
            this.Converter         = customConverter;
            this.SerializerFactory = serializerFactory ?? SerializersCollection.JsonSerializer;
            this.ServiceUri        = serviceUri;
        }
Пример #5
0
        /// <summary>
        /// Create a new Sql Server database
        /// </summary>
        public static async Task CreateSqlServerDatabaseAsync(string dbName, bool recreateDb = true)
        {
            var onRetry = new Func <Exception, int, TimeSpan, object, Task>((ex, cpt, ts, arg) =>
            {
                Console.WriteLine($"Creating SQL Server database failed when connecting to master ({ex.Message}). Wating {ts.Milliseconds}. Try number {cpt}");
                return(Task.CompletedTask);
            });

            SyncPolicy policy = SyncPolicy.WaitAndRetry(3, TimeSpan.FromMilliseconds(500), null, onRetry);

            await policy.ExecuteAsync(async() =>
            {
                using var masterConnection = new SqlConnection(Setup.GetSqlDatabaseConnectionString("master"));
                masterConnection.Open();

                using (var cmdDb = new SqlCommand(GetSqlCreationScript(dbName, recreateDb), masterConnection))
                    await cmdDb.ExecuteNonQueryAsync();

                masterConnection.Close();
            });
        }
Пример #6
0
        /// <summary>
        /// Gets whether the manager can and should sync.
        /// May return false because sync process is already running or because the last
        /// synchronization attempt was too soon.
        /// </summary>
        public bool CheckSyncConditions(SyncPolicy policy)
        {
#if DEBUG
            if (policy != SyncPolicy.Forced)
            {
                Log.Debug("Unforced sync aborted in debug configuration");
                return(false);
            }
#endif

            if (Settings.OfflineMode)
            {
                Log.Debug("Can't sync: synchronization disabled in offline mode");
                return(false);
            }

            if (IsSyncing)
            {
                Log.Debug("Can't sync: SyncManager already syncing");
                return(false);
            }

            return(CheckPlatformSyncConditions());
        }
Пример #7
0
        /// <summary>
        /// Inner worker synchronizer.
        /// Will never throw for normal sync operations, even in case of failure.
        /// </summary>
        /// <exception cref="TaskCanceledException">Thrown when sync canceled.</exception>
        private async Task <SyncResult> SynchronizeInner(CancellationToken token, SyncPolicy policy)
        {
            token.ThrowIfCancellationRequested();

            IList <DatabaseQueries.TrackAndCount> tracks = await Task.Run(() => {
                using (var db = DatabaseUtility.OpenConnection()) {
                    return((from t in db.GetAllPendingTracks()
                            let trackFilepath = FileNaming.GetDataTrackFilepath(t.TrackId)
                                                where File.Exists(trackFilepath)
                                                select t).ToList());
                }
            });

            if (tracks.Count == 0)
            {
                Log.Debug("No files to synchronize");
                return(new SyncResult(0, 0));
            }

            token.ThrowIfCancellationRequested();

            Log.Debug("{0} tracks queued to synchronize", tracks.Count);
            Log.Event("Sync.start", new Dictionary <string, string>()
            {
                { "policy", policy.ToString() }
            });

            if (policy == SyncPolicy.ForceLast && tracks.Count > 1)
            {
                Log.Debug("Constraining upload to most recent file as per policy");
                tracks = new DatabaseQueries.TrackAndCount[] { tracks.First() };
            }

            int countUploadedPoints = 0;
            int countUploadedChunks = 0;

            foreach (var track in tracks)
            {
                token.ThrowIfCancellationRequested();

                int pendingPoints = track.DataCount - track.UploadedCount;
                Log.Debug("Uploading {0}/{1} points from track {2}", pendingPoints, track.DataCount, track.TrackId);

                try {
                    var reader = new DataReader(track.TrackId);
                    if (!await reader.Skip(track.UploadedCount))
                    {
                        Log.Error(null, "Cannot advance {0} rows in file for track {1}", track.UploadedCount, track.TrackId);
                        continue;
                    }

                    int currentChunk = 0;
                    while (pendingPoints > 0)
                    {
                        int chunkPoints = Math.Min(ChunkSize, pendingPoints);
                        Log.Debug("Processing chunk {0} with {1} points", currentChunk + 1, chunkPoints);

                        var package = new List <DataPiece>(chunkPoints);
                        for (int p = 0; p < chunkPoints; ++p)
                        {
                            if (!await reader.Advance())
                            {
                                throw new Exception(string.Format("Cannot read line for {0}th point", p + 1));
                            }
                            package.Add(new DataPiece {
                                TrackId        = track.TrackId,
                                StartTimestamp = new DateTime(reader.Current.StartTicks),
                                EndTimestamp   = new DateTime(reader.Current.EndTicks),
                                Ppe            = reader.Current.Ppe,
                                PpeX           = reader.Current.PpeX,
                                PpeY           = reader.Current.PpeY,
                                PpeZ           = reader.Current.PpeZ,
                                Latitude       = reader.Current.Latitude,
                                Longitude      = reader.Current.Longitude,
                                Bearing        = reader.Current.Bearing,
                                Accuracy       = reader.Current.Accuracy,
                                Vehicle        = track.VehicleType,
                                Anchorage      = track.AnchorageType,
                                NumberOfPeople = track.NumberOfPeople
                            });
                        }

                        var secret     = Crypto.GenerateSecret();
                        var secretHash = secret.ToSha512Hash();

                        var uploadQuery = new UploadDataQuery {
                            Package    = package,
                            SecretHash = secretHash
                        };
                        var response = await uploadQuery.Execute(token);

                        Log.Debug("Points uploaded successfully, chunk {0} for track ID {1}", currentChunk + 1, track.TrackId);

                        //Store record of uploaded chunk
                        using (var db = DatabaseUtility.OpenConnection()) {
                            var record = new TrackUploadRecord {
                                TrackId    = track.TrackId,
                                UploadedId = response.UploadedTrackId,
                                Secret     = secret,
                                UploadedOn = DateTime.UtcNow,
                                Count      = chunkPoints
                            };

                            db.Insert(record);
                        }

                        pendingPoints -= chunkPoints;
                        currentChunk++;

                        countUploadedPoints += chunkPoints;
                        countUploadedChunks++;
                    }
                }
                catch (IOException exIo) {
                    Log.Error(exIo, "File for track {0} not found", track.TrackId);
                }
                catch (Exception ex) {
                    Log.Error(ex, "Failed while processing track {0}", track.TrackId);
                }
            }

            return(new SyncResult(countUploadedPoints, countUploadedChunks));
        }
Пример #8
0
        /// <summary>
        /// Runs the synchronization attempt.
        /// Does not raise exceptions.
        /// </summary>
        public async Task <SyncResult> Synchronize(CancellationToken token, SyncPolicy policy = SyncPolicy.Default)
        {
            if (DateTime.UtcNow < NextUploadOpportunity && policy == SyncPolicy.Default)
            {
                Log.Debug("Can't sync: sync attempt too early, next upload scheduled after {0}", NextUploadOpportunity);

                return(new SyncResult(new InvalidOperationException("Sync attempt too early")));
            }

            Settings.LastUploadAttempt = DateTime.UtcNow;

            if (!CheckSyncConditions(policy))
            {
                return(new SyncResult(error: new InvalidOperationException("Sync conditions not met")));
            }

            Log.Debug("Sync attempt started (policy {0})", policy);

            IsSyncing = true;
            StatusChanged.Raise(this);

            try {
                var ret = await SynchronizeInner(token, policy);

                Log.Debug("Sync process terminated normally");
                Log.Event("Sync.terminate", new Dictionary <string, string>()
                {
                    { "policy", policy.ToString() }
                });

                if (ret.HasFailed)
                {
                    UserLog.Add(UserLog.Icon.Error, LogStrings.FileUploadFailure, ret.Error.Message);

                    SyncError.Raise(this, new SyncErrorEventArgs(ret.Error));
                }
                else
                {
                    if (ret.ChunksUploaded == 1)
                    {
                        UserLog.Add(LogStrings.FileUploadSummarySingular);
                    }
                    else
                    {
                        UserLog.Add(LogStrings.FileUploadSummaryPlural, ret.ChunksUploaded);
                    }
                }

                return(ret);
            }
            catch (TaskCanceledException) {
                Log.Debug("Sync process was canceled");
                return(new SyncResult(0, 0));
            }
            catch (Exception ex) {
                Log.Error(ex, "Sync process failed with unforeseen error");

                UserLog.Add(UserLog.Icon.Error, LogStrings.FileUploadFailure, ex.Message);

                return(new SyncResult(error: ex));
            }
            finally {
                IsSyncing = false;
                StatusChanged.Raise(this);
            }
        }
Пример #9
0
        static int Main()
        {
            FoxEventLog.Shutup = true;
            string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            if (dir.EndsWith("\\") == false)
            {
                dir += "\\";
            }

            ProgramAgent.Init();

            if (ProgramAgent.LoadDLL() == false)
            {
                return(1);
            }

            if (SystemInfos.CollectSystemInfo() != 0)
            {
                return(1);
            }

            if (ApplicationCertificate.LoadCertificate() == false)
            {
                FoxEventLog.WriteEventLog("Cannot load certificate", System.Diagnostics.EventLogEntryType.Error);
                return(1);
            }

            if (FilesystemData.LoadCertificates() == false)
            {
                return(1);
            }
            if (FilesystemData.LoadPolicies() == false)
            {
                return(1);
            }
            FilesystemData.LoadLocalPackageData();
            FilesystemData.LoadLocalPackages();
            FilesystemData.LoadUserPackageData();
            FilesystemData.LoadEventLogList();

            FoxEventLog.Shutup = false;

            if (SyncPolicy.ApplyPolicy(SyncPolicy.ApplyPolicyFunction.Uninstall) == false)
            {
                return(5);
            }

            ServiceController svc = new ServiceController("FoxSDCA");

            try
            {
                svc.Stop();
            }
            catch
            {
            }

            int i = 0;

            do
            {
                i++;
                if (i > 120 * 4)
                {
                    break;
                }
                svc.Refresh();
                Thread.Sleep(1000);
            } while (svc.Status != ServiceControllerStatus.Stopped);

            #region Kill Processes

            foreach (Process proc in Process.GetProcesses())
            {
                try
                {
                    if (proc.MainModule.FileName.ToLower() == dir.ToLower() + "foxsdc_agent_ui.exe")
                    {
                        proc.Kill();
                    }
                }
                catch
                {
                }
            }

            foreach (Process proc in Process.GetProcesses())
            {
                try
                {
                    if (proc.MainModule.FileName.ToLower() == dir.ToLower() + "foxsdc_applyusersettings.exe")
                    {
                        proc.Kill();
                    }
                }
                catch
                {
                }
            }

            foreach (Process proc in Process.GetProcesses())
            {
                try
                {
                    if (proc.MainModule.FileName.ToLower() == dir.ToLower() + "foxsdc_agent.exe")
                    {
                        proc.Kill();
                    }
                }
                catch
                {
                }
            }

            #endregion

            try
            {
                RegistryKey reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                reg.DeleteValue("FoxSDCAgent", false);
                reg.DeleteValue("FoxSDCAgentApply", false);
                reg.Close();
            }
            catch
            {
            }

            try
            {
                Process.Start(Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\msiexec.exe"), "/x {A6F066EE-E795-4C65-8FE4-2D93AB52BC36} /passive");
            }
            catch
            {
            }
            return(0);
        }
Пример #10
0
        static int Main(string[] args)
        {
            foreach (string arg in args)
            {
                if (arg.ToLower() == "-nopackages")
                {
                    NoPackages = true;
                }
            }

            FoxEventLog.Shutup = true;

            ProgramAgent.Init();

            if (ProgramAgent.LoadDLL() == false)
            {
                return(1);
            }

            FoxEventLog.Shutup = false;
#if !DEBUG
            List <string> Additionals = new List <string>();
            Additionals.Add(Assembly.GetExecutingAssembly().Location);
            if (ProgramAgent.TestIntegrity(Additionals) == false)
            {
                FoxEventLog.WriteEventLog("Apply User settings: Integrity failed!", EventLogEntryType.Error, true);
                return(1);
            }
#endif

            FoxEventLog.Shutup = true;

            if (SystemInfos.CollectSystemInfo() != 0)
            {
                return(1);
            }

            if (ApplicationCertificate.LoadCertificate() == false)
            {
                FoxEventLog.Shutup = false;
                FoxEventLog.WriteEventLog("Apply User settings: Cannot load certificate", System.Diagnostics.EventLogEntryType.Error);
                return(1);
            }

            FoxEventLog.Shutup = false;

            if (FilesystemData.LoadCertificates(true) == false)
            {
                return(1);
            }
            if (FilesystemData.LoadPolicies() == false)
            {
                return(1);
            }
            FilesystemData.LoadLocalPackageData();
            FilesystemData.LoadLocalPackages();
            FilesystemData.LoadUserPackageData();
            FilesystemData.LoadEventLogList();

            SyncPolicy.ApplyPolicy(SyncPolicy.ApplyPolicyFunction.ApplyUser);

            if (NoPackages == true)
            {
                return(0);
            }

            string PackagesFolder = SystemInfos.ProgramData + "Packages\\";
            if (Directory.Exists(PackagesFolder) == false)
            {
                return(2);
            }

            foreach (PackagesToInstall pkg in FilesystemData.LocalPackages)
            {
                LocalPackageData lpkg = FilesystemData.FindLocalPackageFromListLatest(pkg.PackageID);
                if (lpkg == null)
                {
                    continue;
                }
                if (pkg.Version != lpkg.Version)
                {
                    continue;
                }

                PackageInstaller inst     = new PackageInstaller();
                string           metafile = PackagesFolder + pkg.MetaFilename;
                if (File.Exists(metafile) == false)
                {
                    continue;
                }
                string         Error;
                PKGRecieptData Reciept;
                PKGStatus      res;
                if (inst.InstallPackage(metafile, PackageCertificate.ActivePackageCerts, PackageInstaller.InstallMode.ApplyUserSettingsTest, true, out Error, out res, out Reciept) == false)
                {
                    FoxEventLog.WriteEventLog("Apply User settings: The Metapackage " + pkg.MetaFilename + " cannot be tested: " + Error, System.Diagnostics.EventLogEntryType.Error);
                    continue;
                }
                FoxEventLog.VerboseWriteEventLog("Apply User settings: Applying user settings for " + pkg.MetaFilename, EventLogEntryType.Information);
                if (inst.ApplyUserSettings(metafile, PackageCertificate.ActivePackageCerts, out Error, out res) == false)
                {
                    FoxEventLog.WriteEventLog("Apply User settings: The Metapackage " + pkg.MetaFilename + " cannot be used to apply user settings: " + Error, System.Diagnostics.EventLogEntryType.Error);
                    continue;
                }
            }

            if (RegistryData.Verbose == 1)
            {
                FoxEventLog.VerboseWriteEventLog("Apply User settings: ApplyUserSettings success for " + Environment.UserDomainName + "\\" + Environment.UserName, EventLogEntryType.Information);
            }

            return(0);
        }