public void OnMsg(ReliableTransferMsg msg) { if (netFail) { return; } StreamTransferSession session; ArgCollection args; AppRef appRef; AppPackageInfo packageInfo; string path; args = ArgCollection.Parse(msg.Args); appRef = AppRef.Parse(args["appref"]); if (msg.Direction == TransferDirection.Upload) { path = packageFolder.BeginTransit(appRef); session = StreamTransferSession.ServerUpload(router, msg, path); session.BeginTransfer(onTransfer, new TransferInfo(session, path, msg.Direction)); } else { packageInfo = packageFolder.GetPackageInfo(appRef); if (packageInfo == null) { throw SessionException.Create(null, "Package [{0}] cannot be found.", appRef); } path = packageInfo.FullPath; session = StreamTransferSession.ServerDownload(router, msg, path); session.BeginTransfer(onTransfer, new TransferInfo(session, path, msg.Direction)); } }
public void AppStoreMsgs_Ack() { EnhancedStream es = new EnhancedMemoryStream(); AppPackageInfo[] packages = new AppPackageInfo[] { new AppPackageInfo(AppRef.Parse("appref://myapps/app01.zip?version=1.2.3.4"), "app01.zip", "", new byte[] { 0, 1, 2 }, 55, DateTime.MinValue), new AppPackageInfo(AppRef.Parse("appref://myapps/app02.zip?version=5.6.7.8"), "app02.zip", "", new byte[] { 3, 4, 5 }, 66, DateTime.MinValue) }; AppStoreAck msgIn, msgOut; msgOut = new AppStoreAck(); msgOut.StoreEP = "logical://foo/bar"; msgOut.Packages = packages; Msg.Save(es, msgOut); es.Position = 0; msgIn = (AppStoreAck)Msg.Load(es); Assert.IsNotNull(msgIn); Assert.AreEqual("logical://foo/bar", msgIn.StoreEP); Assert.AreEqual(2, msgIn.Packages.Length); Assert.AreEqual(AppRef.Parse("appref://myapps/app01.zip?version=1.2.3.4"), msgIn.Packages[0].AppRef); CollectionAssert.AreEqual(new byte[] { 0, 1, 2 }, msgIn.Packages[0].MD5); Assert.AreEqual(55, msgIn.Packages[0].Size); Assert.AreEqual(AppRef.Parse("appref://myapps/app02.zip?version=5.6.7.8"), msgIn.Packages[1].AppRef); CollectionAssert.AreEqual(new byte[] { 3, 4, 5 }, msgIn.Packages[1].MD5); Assert.AreEqual(66, msgIn.Packages[1].Size); }
public void AppPackage_MultiRead() { // Verify that a package can be opened for reading by multiple streams. string tempPath = GetTempFileName(); string tempDir = Helper.AddTrailingSlash(Path.GetTempPath()); AppRef appRef = AppRef.Parse("appref://myapps/mypackage.zip?version=1.2.3.4"); AppPackage pack1 = null; AppPackage pack2 = null; FileStream fs = null; MemoryStream ms; try { pack1 = AppPackage.Create(tempPath, appRef, @" LaunchType = Test.MyType:MyAssembly.dll; LaunchMethod = Foo; LaunchArgs = Bar; "); using (ms = new MemoryStream(4096)) { for (int i = 0; i < 4096; i++) { ms.WriteByte((byte)i); } ms.Position = 0; pack1.AddFile("Test.dat", ms); } pack1.Close(); pack1 = null; pack1 = AppPackage.Open(tempPath); pack2 = AppPackage.Open(tempPath); fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read); } finally { if (pack1 != null) { pack1.Close(); } if (pack2 != null) { pack2.Close(); } if (fs != null) { fs.Close(); } Delete(tempPath); } }
public void AppPackage_MD5() { string tempPath = GetTempFileName(); string tempDir = Helper.AddTrailingSlash(Path.GetTempPath()); AppPackage package = null; MemoryStream ms; byte[] md5; try { package = AppPackage.Create(tempPath, AppRef.Parse("appref://myapps/mypackage.zip?version=1.2.3.4"), @" LaunchType = Test.MyType:MyAssembly.dll; LaunchMethod = Foo; LaunchArgs = Bar; "); using (ms = new MemoryStream(4096)) { for (int i = 0; i < 4096; i++) { ms.WriteByte((byte)i); } ms.Position = 0; package.AddFile("Test.dat", ms); } package.Close(); package = null; // Verify that a MD5 hash computed manually on the package file jibes // with what AppPackage computes. using (var fs = new EnhancedFileStream(tempPath, FileMode.Open, FileAccess.Read)) { md5 = MD5Hasher.Compute(fs, fs.Length); } package = AppPackage.Open(tempPath); CollectionAssert.AreEqual(md5, package.MD5); package.Close(); package = null; } finally { if (package != null) { package.Close(); } Delete(tempPath); } }
public void AppStoreMsgs_Query() { EnhancedStream es = new EnhancedMemoryStream(); AppStoreQuery msgIn, msgOut; msgOut = new AppStoreQuery(AppStoreQuery.GetPrimaryCmd, AppRef.Parse("appref://myapps/theapp.zip?version=1.2.3.4")); Msg.Save(es, msgOut); es.Position = 0; msgIn = (AppStoreQuery)Msg.Load(es); Assert.IsNotNull(msgIn); Assert.AreEqual(AppStoreQuery.GetPrimaryCmd, msgIn.Command); Assert.AreEqual(AppRef.Parse("appref://myapps/theapp.zip?version=1.2.3.4"), msgIn.AppRef); }
public void AppPackage_ExtractTo() { string tempPath = GetTempFileName(); string tempDir = Helper.AddTrailingSlash(Path.GetTempPath()); AppPackage package = null; try { package = AppPackage.Create(tempPath, AppRef.Parse("appref://myapps/mypackage.zip?version=1.2.3.4"), @" LaunchType = Test.MyType:MyAssembly.dll; LaunchMethod = Foo; LaunchArgs = Bar; "); package.AddFile("File1.txt", Helper.ToUTF8("Hello World! #1\r\n")); package.AddFile("File2.txt", Helper.ToUTF8("Hello World! #2\r\n")); package.Close(); package = null; package = AppPackage.Open(tempPath); package.ExtractTo(tempDir); package.Close(); package = null; Assert.IsTrue(File.Exists(tempDir + "Package.ini")); Assert.IsTrue(File.Exists(tempDir + "File1.txt")); Assert.IsTrue(File.Exists(tempDir + "File2.txt")); using (var reader = new StreamReader(tempDir + "File1.txt")) { Assert.AreEqual("Hello World! #1", reader.ReadLine()); } using (var reader = new StreamReader(tempDir + "File2.txt")) { Assert.AreEqual("Hello World! #2", reader.ReadLine()); } } finally { if (package != null) { package.Close(); } Delete(tempPath); } }
public void AppRef_Basic() { AppRef appRef; appRef = AppRef.Parse("appref://jeff/code/mycode.zip?version=1.2.3.4"); Assert.AreEqual("appref://jeff/code/mycode.zip?version=1.2.3.4", appRef.ToString()); Assert.AreEqual(new Uri("appref://jeff/code/mycode.zip?version=1.2.3.4"), appRef.Uri); Assert.AreEqual("jeff.code.mycode-0001.0002.0003.0004.zip", appRef.FileName); Assert.AreEqual(new Version(1, 2, 3, 4), appRef.Version); Assert.AreEqual("appref://jeff/code/mycode.zip?version=1.2.3.4", appRef.ToString()); appRef = AppRef.Parse("APPREF://JEFF/CODE/MYCODE.ZIP?VERSION=1.2&extra=param"); Assert.AreEqual("appref://jeff/code/mycode.zip?version=1.2", appRef.ToString()); Assert.AreEqual(new Uri("appref://jeff/code/mycode.zip?version=1.2"), appRef.Uri); Assert.AreEqual("jeff.code.mycode-0001.0002.-1.-1.zip", appRef.FileName); Assert.AreEqual(new Version(1, 2), appRef.Version); Assert.AreEqual("appref://jeff/code/mycode.zip?version=1.2", appRef.ToString()); }
public void AppStore_EndToEnd() { // This test peforms a simple end-to-end test of the AppStore // service by starting the service, uploading, downloading // and then deleting a package file. Process svcProcess = null; LeafRouter router = null; AppStoreClient client = null; Assembly assembly; string packageFolder; string tempFolder; AppRef appRef; Helper.InitializeApp(Assembly.GetExecutingAssembly()); assembly = typeof(LillTek.Datacenter.AppStore.Program).Assembly; tempFolder = Helper.AddTrailingSlash(Path.GetTempPath()); packageFolder = Helper.GetAssemblyFolder(assembly) + "packages\\"; appRef = AppRef.Parse("appref://MyApps/App00.zip?version=1.2.0.0"); try { // Start a local router and open a client. Config.SetConfig(@" //----------------------------------------------------------------------------- // LeafRouter Settings §ion MsgRouter AppName = LillTek.Test Router AppDescription = Unit Test RouterEP = physical://DETACHED/$(LillTek.DC.DefHubName)/$(Guid) CloudEP = $(LillTek.DC.CloudEP) CloudAdapter = ANY UdpEP = ANY:0 TcpEP = ANY:0 TcpBacklog = 100 TcpDelay = off BkInterval = 1s MaxIdle = 5m EnableP2P = yes AdvertiseTime = 1m DefMsgTTL = 5 Encryption = PLAINTEXT Key = 00 SessionCacheTime = 2m SessionRetries = 3 SessionTimeout = 10s MaxLogicalAdvertiseEPs = 256 DeadRouterTTL = 2s // This maps the abstract AppStore endpoints to their default logical endpoints. AbstractMap[abstract://LillTek/DataCenter/AppStore] = logical://LillTek/DataCenter/AppStore AbstractMap[abstract://LillTek/DataCenter/AppStore/*] = logical://LillTek/DataCenter/AppStore/* &endsection ".Replace('&', '#')); router = new LeafRouter(); router.Start(); client = new AppStoreClient(); client.Open(router, AppStoreClientSettings.LoadConfig("AppStore.Client")); // Start the application store service svcProcess = Helper.StartProcess(assembly, "-mode:form -start"); Thread.Sleep(10000); // Give the process a chance to spin up // Upload a package to the server CreatePackage(tempFolder, appRef); client.UploadPackage(null, appRef, tempFolder + appRef.FileName); Thread.Sleep(1000); CompareFiles(tempFolder + appRef.FileName, packageFolder + appRef.FileName); // Download the package File.Delete(tempFolder + appRef.FileName); client.DownloadPackage(null, appRef, tempFolder + appRef.FileName); Thread.Sleep(1000); CompareFiles(tempFolder + appRef.FileName, packageFolder + appRef.FileName); // Delete the package client.RemoveRemotePackage(null, appRef); Thread.Sleep(1000); Assert.IsFalse(File.Exists(packageFolder + appRef.FileName)); } finally { if (svcProcess != null) { svcProcess.Kill(); svcProcess.Close(); } if (client != null) { client.Close(); } if (router != null) { router.Stop(); } if (File.Exists(tempFolder + appRef.FileName)) { File.Delete(tempFolder + appRef.FileName); } Config.SetConfig(null); } }
/// <summary> /// Executes the specified PACK command. /// </summary> /// <param name="args">The command arguments.</param> /// <returns>0 on success, a non-zero error code otherwise.</returns> public static int Execute(string[] args) { const string usage = @" Usage: ------------------------------------------------------------------------------- vegomatic pack [-r] [-out:<path>] <appref> <path-0> <path-1>... <path-N> Creates an application package from a set of assembly and data files. -r Indicates that subfolders are to be searched recursively for files to be added to the archive. -out:path Specifies where the generated packaged file is to be written. If this specifies a folder then the package will be named using the standard package file naming convention in that folder. If this option is not present, then the package will be saved in the current folder using the standard name. <appref> The application reference to be used for this package. See the note below describing how the version number can be loaded from an assembly. <path-#> Path of the files or directories to be added to the archive. File specifications may include wildcards. AppRef Format ------------- Application references are URIs formatted as: appref://Root/Segment0/Segment1/../SegmentN.zip?version=1.2.3.4 where the Root and Segment#s uniquely identify the application and the version query parameter specifies the version number. Note that vegomatic supports a specialized notation for apprefs that indicate that the version should be loaded from an assembly's version number rather than being specified directly on the command line. This can make it easy to automate the creation of application packages during the build process. To accomplish this, set the version to an ""@"" followed by the path to the assembly file. Here's an example: vegomatic pack appref://myapps/[email protected] In this case, vegomatic will load myassembly.dll from the current folder and use the assembly's version number when creating the package. Package.ini File ---------------- One of the files that must be included in all applications is the PACKAGE.INI file. This is a text file formatted using the standard LillTek Platform config conventions that describes the metadata to be associated with the package. One required setting is the APPREF setting which should be set to the same appref value specified on the command line. This can be accomplished via the $(appref) macro as in: AppRef = $(appref) Vegomatic will replace this macro with the appref specified on the command line before adding the PACKAGE.INI file to the package. "; AppPackage package = null; bool recursive = false; string outPath = null; string sAppRef; AppRef appRef; int argPos; int cAdded; bool packageIni; if (args.Length < 2) { Program.Error(usage); return(1); } for (argPos = 0; argPos < args.Length; argPos++) { string arg = args[argPos]; if (!arg.StartsWith("-")) { break; } else if (arg == "-r") { recursive = true; } else if (arg.StartsWith("-out:")) { outPath = arg.Substring(5); } else { Program.Error(usage); return(1); } } // Parse the application reference, reading the version number // from the referenced assembly file if requested. // $todo(jeff.lill): // // The version parsing code is really simplistic. // It assumes that "version" is the only possible // query parameter or than it appears first in // the appref URI. string assemblyPath; string appName; int pos; sAppRef = args[argPos++]; pos = sAppRef.ToLowerInvariant().IndexOf("?version=@"); if (pos == -1) { appRef = AppRef.Parse(sAppRef); } else { appName = sAppRef.Substring(0, pos); assemblyPath = sAppRef.Substring(pos + 10); appRef = AppRef.Parse(appName + "?version=" + Helper.GetVersion(Assembly.ReflectionOnlyLoadFrom(assemblyPath)).ToString()); } if (outPath == null) { outPath = appRef.FileName; } else if (Directory.Exists(outPath)) { outPath = Helper.AddTrailingSlash(outPath) + appRef.FileName; } if (argPos == args.Length) { Program.Error(usage); return(1); } Helper.CreateFileTree(outPath); if (File.Exists(outPath)) { File.Delete(outPath); } package = AppPackage.Create(outPath, appRef, null); cAdded = 0; packageIni = false; try { for (; argPos < args.Length; argPos++) { string path = args[argPos]; bool hasWildcards; bool isFolder; string basePath; hasWildcards = path.IndexOfAny(Helper.FileWildcards) != -1; if (!hasWildcards) { isFolder = (File.GetAttributes(path) & FileAttributes.Directory) != 0; } else { isFolder = false; } basePath = Path.GetFullPath(path.Replace('?', 'x').Replace('*', 'x')); pos = basePath.LastIndexOf(Helper.PathSepChar); if (pos == -1) { throw new Exception(string.Format("Invalid file path [{0}].", path)); } basePath = basePath.Substring(0, pos); if (isFolder) { Program.Output("Adding: {0}", path); foreach (string file in Helper.GetFilesByPattern(path + Helper.PathSepString + "*.*", SearchOption.AllDirectories)) { if (String.Compare(outPath, file, true) == 0) { continue; // Ignore the zip archive being created } Program.Output("Adding: {0}", file); packageIni = AddFile(package, file, basePath) || packageIni; cAdded++; } } else { foreach (string file in Helper.GetFilesByPattern(path, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { if (String.Compare(outPath, file, true) == 0) { continue; // Ignore the zip archive being created } Program.Output("Adding: {0}", file); packageIni = AddFile(package, file, basePath) || packageIni; cAdded++; } } } package.Close(); if (!packageIni) { throw new Exception("PACKAGE.INI file with the package metadata is missing."); } } catch (Exception e) { Program.Error("{0}: {1}", e.GetType().Name, e.Message); } finally { if (package != null) { package.Close(); } } Program.Output(""); Program.Output("[{0}] files added.", cAdded); return(0); }
public void AppPackage_Basic() { string tempPath = GetTempFileName(); string tempDir = Helper.AddTrailingSlash(Path.GetTempPath()); string testPath = tempDir + "Test.txt"; AppPackage package = null; MemoryStream ms; StreamReader reader; try { // Generate the package package = AppPackage.Create(tempPath, AppRef.Parse("appref://myapps/mypackage.zip?version=1.2.3.4"), @" LaunchType = Test.MyType:MyAssembly.dll; LaunchMethod = Foo; LaunchArgs = Bar; "); using (StreamWriter writer = new StreamWriter(testPath)) { for (int i = 0; i < 4000; i++) { writer.WriteLine("Hello World!"); } } package.AddFile(testPath, tempDir); using (ms = new MemoryStream(4096)) { for (int i = 0; i < 4096; i++) { ms.WriteByte((byte)i); } ms.Position = 0; package.AddFile("Test.dat", ms); } package.Close(); package = null; // Verify that the package can be opened and the contents look good. package = AppPackage.Open(tempPath); Assert.AreEqual(new AppRef("appref://myapps/mypackage.zip?version=1.2.3.4"), package.AppRef); Assert.AreEqual(new Version(1, 2, 3, 4), package.Version); Assert.AreEqual("Test.MyType:MyAssembly.dll", package.Settings.Get("LaunchType")); Assert.AreEqual("Foo", package.Settings.Get("LaunchMethod")); Assert.AreEqual("Bar", package.Settings.Get("LaunchArgs")); Assert.IsTrue(package.ContainsFile("Test.txt")); Assert.IsTrue(package.ContainsFile("Test.dat")); ms = new MemoryStream(); package.CopyFile("Test.txt", ms); ms.Position = 0; reader = new StreamReader(ms); for (int i = 0; i < 4000; i++) { Assert.AreEqual("Hello World!", reader.ReadLine()); } string tempPath2 = Path.GetTempFileName(); try { using (var fs = new FileStream(tempPath2, FileMode.Create, FileAccess.ReadWrite)) { package.CopyFile("test.dat", fs); Assert.AreEqual(4096, fs.Length); fs.Position = 0; for (int i = 0; i < 4096; i++) { Assert.AreEqual((byte)i, fs.ReadByte()); } } } finally { File.Delete(tempPath2); } package.Close(); package = null; } finally { if (package != null) { package.Close(); } Delete(tempPath); Delete(testPath); } }