Пример #1
0
        internal static RemoteAssemblyState ParseFromManifestRow(RemoteAssemblyManifest manifest, string line)
        {
            string[] columns = line.Split(',');
            if (columns.Length < 11)
            {
                return(null);
            }
            string id                        = columns[0].Trim();
            string url                       = columns[1].Trim();
            string directoryName             = columns[2].Trim();
            string isStable                  = columns[3].Trim();
            string wasExplicitVersionRequest = columns[4].Trim();
            string lastUsedTimestampRaw      = columns[5].Trim();
            string lastLatestCheckRaw        = columns[6].Trim();
            string hasCni                    = columns[7].Trim();
            string isDllDownloaded           = columns[8].Trim();

            string[] platformsRaw         = columns[9].Split('|').Select(s => s.Trim()).Where(s => s.Length > 0).ToArray();
            string[] platforms            = platformsRaw.Select(s => s[0] == '*' ? s.Substring(1) : s).ToArray();
            bool[]   platformIsDownloaded = platformsRaw.Select(s => s[0] == '*').ToArray();

            string version = columns[10];

            for (int i = 11; i < columns.Length; ++i)
            {
                version += "," + columns[i];
            }
            version = version.Trim();

            int lastUsedTimestamp;
            int lastLatestCheck;

            if (!int.TryParse(lastUsedTimestampRaw, out lastUsedTimestamp) ||
                !int.TryParse(lastLatestCheckRaw, out lastLatestCheck))
            {
                return(null);
            }

            RemoteAssemblyState ras = new RemoteAssemblyState(manifest)
            {
                Id                  = id,
                LastUsed            = lastUsedTimestamp,
                LastLatestCheck     = lastLatestCheck,
                LocalDirectory      = directoryName,
                Url                 = url,
                Version             = version,
                IsLatestStable      = wasExplicitVersionRequest == "1",
                IsStable            = isStable == "1",
                HasCni              = hasCni == "1",
                RuntimeIsDownloaded = isDllDownloaded == "1",
            };

            for (int i = 0; i < platforms.Length; ++i)
            {
                ras.platformsSupportedAndCurrentSyncState[platforms[i]] = platformIsDownloaded[i];
            }

            return(ras);
        }
Пример #2
0
        private RemoteAssemblyState PerformSyncImpl(RemoteAssemblyManifest manifest, string libraryUrl, string libraryVersionOrNullForLatest, bool isRequired)
        {
            string fullStructuredUrl = libraryVersionOrNullForLatest == null
                ? libraryUrl
                : (libraryUrl + ":" + libraryVersionOrNullForLatest);
            Pair<FetchAssemblyStatus, RemoteAssemblyState> t = new RemoteAssemblyFetcher().FetchNewAssembly(manifest, fullStructuredUrl);

            switch (t.First)
            {
                case FetchAssemblyStatus.NO_CONNECTION:
                case FetchAssemblyStatus.SERVER_NOT_RESPONDING:
                case FetchAssemblyStatus.UNKNOWN_RESPONSE:
                    if (isRequired)
                    {
                        throw new System.InvalidOperationException("Could not sync required dependency: " + libraryUrl);
                    }
                    return null;

                case FetchAssemblyStatus.INVALID_URL:
                    throw new System.InvalidOperationException("Invalid remote library URL: " + libraryUrl);

                case FetchAssemblyStatus.LIBRARY_NOT_FOUND:
                    throw new System.InvalidOperationException("Remote Library not found: " + libraryUrl);

                case FetchAssemblyStatus.VERSION_NOT_FOUND:
                    if (isRequired)
                    {
                        throw new System.InvalidOperationException("Remote Library version not found: " + libraryUrl);
                    }
                    else
                    {
                        // This could happen if the library was taken down by the provider
                    }
                    return null;

                case FetchAssemblyStatus.SUCCESS:
                    manifest.AddOrReplaceAssemblyState(t.Second);
                    return t.Second;

                default:
                    throw new System.NotImplementedException(); // this should not happen.
            }
        }
Пример #3
0
        public Pair <FetchAssemblyStatus, RemoteAssemblyState> FetchNewAssembly(RemoteAssemblyManifest manifest, string urlAndVersion)
        {
            RemoteAssemblyUrl structuredUrl = RemoteAssemblyUrl.FromUrl(urlAndVersion);

            if (!structuredUrl.IsValid)
            {
                return(new Pair <FetchAssemblyStatus, RemoteAssemblyState>(FetchAssemblyStatus.INVALID_URL, null));
            }

            HttpRequest requestSender = new HttpRequest("GET", structuredUrl.Url)
                                        .SetHeader("CrayonLib-Component-Type", "source")
                                        .SetHeader("User-Agent", Common.VersionInfo.UserAgent);

            if (!structuredUrl.IsLatestStableVersionRequested)
            {
                requestSender.SetHeader("CrayonLib-Version-Info", structuredUrl.VersionInfo);
            }

            HttpResponse response = requestSender.Send();
            Pair <FetchAssemblyStatus, RemoteAssemblyState> error = CheckForBasicErrors(response, structuredUrl.LibraryName);

            if (error != null)
            {
                return(error);
            }

            string versionInfo = response.GetHeader("CrayonLib-Version-Info");
            // Not used. Not sure why this is returned.
            // string componentType = response.GetHeader("CrayonLib-Component-Type");
            bool hasNativeInterface = response.GetHeaderAsBoolean("CrayonLib-Has-Native-Interface");

            string[] platformsSupported = response.GetHeaderAsList("CrayonLib-Platforms-Supported");
            string   libraryName        = response.GetHeader("CrayonLib-Library-Name");
            bool     isStable           = response.GetHeaderAsBoolean(("CrayonLib-Is-Stable"));
            string   directoryName      = this.CreateNewDirectoryForLibrary(manifest.Directory, libraryName, versionInfo);

            byte[]        crypkg        = response.Content;
            CryPkgDecoder crypkgDecoder = new CryPkgDecoder(response.Content);

            // TODO: crypkgDecoder.IsValid

            this.ExpandCryPkgToDirectory(crypkgDecoder, Path.Join(manifest.Directory, directoryName, libraryName));
            int now = CommonUtil.DateTime.Time.UnixTimeNow;
            RemoteAssemblyState ras = new RemoteAssemblyState(manifest)
            {
                HasCni              = hasNativeInterface,
                Id                  = libraryName,
                IsStable            = isStable,
                IsLatestStable      = structuredUrl.IsLatestStableVersionRequested,
                LastUsed            = now,
                LastLatestCheck     = now,
                LocalDirectory      = directoryName,
                RuntimeIsDownloaded = false,
                Url                 = structuredUrl.Url,
                Version             = versionInfo,
            };

            foreach (string platformSupported in platformsSupported)
            {
                ras.IndicatePlatformSupport(platformSupported);
            }

            return(new Pair <FetchAssemblyStatus, RemoteAssemblyState>(FetchAssemblyStatus.SUCCESS, ras));
        }
Пример #4
0
 private RemoteAssemblyState PerformSyncForOptionalRefresh(RemoteAssemblyManifest manifest, string libraryUrl)
 {
     return PerformSyncImpl(manifest, libraryUrl, null, false);
 }
Пример #5
0
 private RemoteAssemblyState PerformSyncForMissingAssembly(RemoteAssemblyManifest manifest, string libraryUrl, string libraryVersionOrNullForLatest)
 {
     return PerformSyncImpl(manifest, libraryUrl, libraryVersionOrNullForLatest, true);
 }
Пример #6
0
        public IList<AssemblyMetadata> GetRemoteAssemblies(string[] urlsAndVersionInfo)
        {
            Dictionary<string, AssemblyMetadata> assemblies = new Dictionary<string, AssemblyMetadata>();
            if (urlsAndVersionInfo == null || urlsAndVersionInfo.Length == 0) return new AssemblyMetadata[0];

            RemoteAssemblyManifest manifest = new RemoteAssemblyManifest();
            List<string[]> librariesMissing = new List<string[]>();
            List<RemoteAssemblyState> librariesThatMightNeedRefresh = new List<RemoteAssemblyState>();
            bool anyLibrariesWereMissing = false;
            List<RemoteAssemblyState> usedAssemblies = new List<RemoteAssemblyState>();
            foreach (string info in urlsAndVersionInfo)
            {
                string[] parts = StringUtil.SplitOnce(info, ",");
                string url = parts[0];
                string version = null;
                if (parts.Length == 2)
                {
                    version = parts[1] == "LATEST" ? null : parts[1];
                }
                bool isLatestStableRequested = version == null;

                RemoteAssemblyState currentState = manifest.GetAssemblyState(url, version);
                if (currentState == null)
                {
                    currentState = PerformSyncForMissingAssembly(manifest, url, version);
                    if (currentState == null) throw new System.Exception(); // all code paths that return null from the above function should have thrown a proper error message exception.
                    anyLibrariesWereMissing = true;
                    usedAssemblies.Add(currentState);
                }
                else if (isLatestStableRequested)
                {
                    librariesThatMightNeedRefresh.Add(currentState);
                }
                else
                {
                    usedAssemblies.Add(currentState);
                }
            }

            int now = CommonUtil.DateTime.Time.UnixTimeNow;
            int ageToDefinitelySync = 7 * 24 * 3600;
            int expiration = now - ageToDefinitelySync;
            bool refreshNeeded = anyLibrariesWereMissing || librariesThatMightNeedRefresh.Where(lib => lib.LastLatestCheck < expiration).FirstOrDefault() != null;
            if (refreshNeeded)
            {
                foreach (RemoteAssemblyState lib in librariesThatMightNeedRefresh)
                {
                    RemoteAssemblyState nullableNewLib = PerformSyncForOptionalRefresh(manifest, lib.Url);
                    usedAssemblies.Add(nullableNewLib ?? lib);
                }
            }
            else
            {
                usedAssemblies.AddRange(librariesThatMightNeedRefresh);
            }

            foreach (RemoteAssemblyState ras in usedAssemblies)
            {
                ras.LastUsed = now;
            }

            manifest.ReserializeFile();

            foreach (RemoteAssemblyState ras in usedAssemblies)
            {
                assemblies.Add(ras.Id, new AssemblyMetadata(ras.AbsolutePathToLibrary, ras.Id));
            }

            return assemblies.Values.ToArray();
        }
Пример #7
0
 internal RemoteAssemblyState(RemoteAssemblyManifest remoteAssemblyManifest)
 {
     this.remoteAssemblyManifest = remoteAssemblyManifest;
 }