/// <summary> /// Handle requests to sync updates. A client presents the list of installed updates and detectoids and the server /// replies with a list of more applicable updates, if any. /// </summary> /// <param name="cookie">Access cookie</param> /// <param name="parameters">Request parameters: list of installed updates, list of known updates, etc.</param> /// <returns>SyncInfo containing updates applicable to the caller.</returns> public Task <SyncInfo> SyncUpdatesAsync(Cookie cookie, SyncUpdateParameters parameters) { if (parameters.SkipSoftwareSync) { return(DoDriversSync(parameters)); } else { return(DoSoftwareUpdateSync(parameters)); } }
/// <summary> /// Handle software sync request from a client /// </summary> /// <param name="parameters">Sync parameters</param> /// <returns></returns> private Task <SyncInfo> DoSoftwareUpdateSync(SyncUpdateParameters parameters) { MetadataSourceLock.EnterReadLock(); if (MetadataSource == null) { throw new FaultException(); } // Get list of installed non leaf updates; these are prerequisites that the client has installed. // This list is used to check what updates are applicable to the client // We will not send updates that already appear on this list var installedNonLeafUpdatesGuids = GetInstalledNotLeafGuidsFromSyncParameters(parameters); // Other known updates to the client; we will not send any updates that are on this list var otherCachedUpdatesGuids = GetOtherCachedUpdateGuidsFromSyncParameters(parameters); // Initialize the response var response = new SyncInfo() { NewCookie = new Cookie() { Expiration = DateTime.Now.AddDays(5), EncryptedData = new byte[12] }, DriverSyncNotNeeded = "false" }; // Add root updates first; if any new root updates were added, return the response to the client immediatelly AddMissingRootUpdatesToSyncUpdatesResponse(installedNonLeafUpdatesGuids, otherCachedUpdatesGuids, response, out bool rootUpdatesAdded); if (!rootUpdatesAdded) { // No root updates were added; add non-leaf updates now AddMissingNonLeafUpdatesToSyncUpdatesResponse(installedNonLeafUpdatesGuids, otherCachedUpdatesGuids, response, out bool nonLeafUpdatesAdded); if (!nonLeafUpdatesAdded) { // No leaf updates were added; add leaf bundle updates now AddMissingBundleUpdatesToSyncUpdatesResponse(installedNonLeafUpdatesGuids, otherCachedUpdatesGuids, response, out bool bundleUpdatesAdded); if (!bundleUpdatesAdded) { // No bundles were added; finally add leaf software updates AddMissingSoftwareUpdatesToSyncUpdatesResponse(installedNonLeafUpdatesGuids, otherCachedUpdatesGuids, response, out bool softwareUpdatesAdded); } } } MetadataSourceLock.ExitReadLock(); return(Task.FromResult(response)); }
/// <summary> /// Handle driver sync requests /// </summary> /// <param name="parameters"></param> /// <returns></returns> private Task <SyncInfo> DoDriversSync(SyncUpdateParameters parameters) { // Get list of driver updates known to the client var cachedDrivers = GetUpdateIdentitiesFromClientIndexes(parameters.CachedDriverIDs); // Get list of installed non-leaf updates. Used to match pre-requisites for driver updates var installedNonLeafUpdatesGuids = GetInstalledNotLeafGuidsFromSyncParameters(parameters); // Initialize the response var syncResult = new SyncInfo() { NewCookie = new Cookie() { Expiration = DateTime.Now.AddDays(5), EncryptedData = new byte[12] }, DriverSyncNotNeeded = "false", Truncated = false }; List <Guid> computerHardwareIds = parameters.ComputerSpec.HardwareIDs != null?parameters.ComputerSpec.HardwareIDs.ToList() : new List <Guid>(); List <UpdateInfo> driverUpdates = new List <UpdateInfo>(); List <Update> unapprovedDriversMatched = new List <Update>(); // Go through all client reported devices foreach (var device in parameters.SystemSpec) { // Combine the list hardware ids and compatible hwids; we will // match them in this order, from specific to less specific var hardwareIdsToMatch = new List <string>(device.HardwareIDs); if (device.CompatibleIDs != null) { hardwareIdsToMatch.AddRange(device.CompatibleIDs); } // Get best match driver var driverMatchResult = MetadataSource.MatchDriver(hardwareIdsToMatch, computerHardwareIds, installedNonLeafUpdatesGuids); // If we have a match and the client does not have it, add it to the list if (driverMatchResult != null && !cachedDrivers.Contains(driverMatchResult.Driver.Identity) && !IsInstalledDriverBetterMatch(device.installedDriver, driverMatchResult, hardwareIdsToMatch, computerHardwareIds)) { if (ApprovedSoftwareUpdates.Contains(driverMatchResult.Driver.Identity)) { // Get core XML fragment for driver update var coreXml = GetCoreFragment(driverMatchResult.Driver.Identity); driverUpdates.Add(new UpdateInfo() { Deployment = new Deployment() { Action = DeploymentAction.Install, ID = 25000, AutoDownload = "0", AutoSelect = "0", SupersedenceBehavior = "0", IsAssigned = true, LastChangeTime = "2019-08-06" }, ID = IdToRevisionMap[driverMatchResult.Driver.Identity.ID], IsLeaf = true, Xml = coreXml, IsShared = false, Verification = null }); } else { unapprovedDriversMatched.Add(driverMatchResult.Driver); } } // Stop matching if we have max updates already if (driverUpdates.Count == MaxUpdatesInResponse) { syncResult.Truncated = true; break; } } if (unapprovedDriversMatched.Count > 0) { OnUnApprovedDriverUpdatesRequested?.Invoke(unapprovedDriversMatched); } syncResult.NewUpdates = driverUpdates.ToArray(); return(Task.FromResult(syncResult)); }
/// <summary> /// Extract list of other known updates from the client and maps them to a GUID /// </summary> /// <param name="parameters">Sync parameters</param> /// <returns>List of update GUIDs</returns> private List <Guid> GetOtherCachedUpdateGuidsFromSyncParameters(SyncUpdateParameters parameters) { return(GetUpdateIdentitiesFromClientIndexes(parameters.OtherCachedUpdateIDs) .Select(u => u.ID) .ToList()); }
/// <summary> /// Extract installed non-leaf updates from the response and maps them to a GUID /// </summary> /// <param name="parameters">Sync parameters</param> /// <returns>List of update GUIDs</returns> private List <Guid> GetInstalledNotLeafGuidsFromSyncParameters(SyncUpdateParameters parameters) { return(GetUpdateIdentitiesFromClientIndexes(parameters.InstalledNonLeafUpdateIDs) .Select(u => u.ID) .ToList()); }