public DaemonRT(DaemonDto dto, string root, int delay) { this.delay = delay; this.dto = dto.Clone(); using (var disposer = new Disposer()) { process = new DaemonProcess(new DaemonProcess.Args { Executable = PathTools.Combine(root, dto.Path), //id matches [a-zA_Z][a-zA_Z0-9_]* Arguments = string.Format("Id={0} Daemon=True {1}", dto.Id, dto.Args), }); disposer.Push(process); status = "Starting..."; reader = new Runner(new Runner.Args { ThreadName = string.Format("DAEMON_{0}_{1}_O", dto.Id, process.Id) }); erroer = new Runner(new Runner.Args { ThreadName = string.Format("DAEMON_{0}_{1}_E", dto.Id, process.Id) }); disposer.Push(erroer); disposer.Push(Dispose); //ensure cleanup order erroer.Run(ErrorLoop); reader.Run(ReadLoop); reader.Run(UpdateRestart); disposer.Clear(); } }
public Listener(Args args) { var certfile = ExecutableTools.Relative("DaemonManager.pfx"); certificate = new X509Certificate2(certfile, "none"); factory = args.ShellFactory; clients = new Dictionary <string, ClientRt>(); server = new TcpListener(args.EndPoint); server.MakeNotInheritable(); using (var disposer = new Disposer()) { //push must match dispose order register = new Runner(new Runner.Args { ThreadName = "Register" }); disposer.Push(register); accepter = new Runner(new Runner.Args { ThreadName = "Accepter" }); disposer.Push(accepter); disposer.Push(Dispose); //ensure cleanup order server.Start(); endpoint = server.LocalEndpoint as IPEndPoint; disposer.Clear(); } }
public Instance(Args args) { using (var disposer = new Disposer()) { Logger.Trace("DbPath {0}", args.DbPath); Logger.Trace("Downloads {0}", args.Downloads); Logger.Trace("RestartDelay {0}ms", args.RestartDelay); Logger.Trace("EndPoint {0}", args.EndPoint); factory = new ShellFactory(); factory.Add(new SystemScriptable()); factory.Add(new RunnerScriptable(args.Downloads)); factory.Add(new DownloadScriptable(args.Downloads)); manager = new Manager(new Manager.Args { RestartDelay = args.RestartDelay, Root = args.Downloads, Database = args.DbPath, }); disposer.Push(manager); factory.Add(manager); listener = new Listener(new Listener.Args { ShellFactory = factory, EndPoint = args.EndPoint, }); disposer.Push(listener); factory.Add(listener); endpoint = listener.EndPoint; disposer.Push(Dispose); //ensure cleanup order listener.Start(); disposer.Clear(); } }
public static void Client(Config config, Action <ITestShell, string> action) { using (var disposer = new Disposer()) { var client = SocketTools.ConnectWithTimeout(config.ShellIP, config.ShellPort, 2000); var endpoint = client.Client.LocalEndPoint as IPEndPoint; var stream = SocketTools.SslWithTimeout(client, 2000); var read = new StreamReader(stream); var write = new StreamWriter(stream); //var passfile = ExecutableTools.Relative("Password.txt"); //var password = File.ReadAllText(passfile).Trim(); //write.WriteLine(password); var shell = new TestShell(); var reader = new Runner(new Runner.Args { ThreadName = "SOCKIN" }); var writer = new Runner(new Runner.Args { ThreadName = "SOCKOUT" }); reader.Run(() => { var line = read.ReadLine(); while (line != null) { Logger.Trace("<c {0}", line); shell.WriteLine("<c {0}", line); line = read.ReadLine(); } }); writer.Run(() => { var line = shell.ReadLine(); while (line != null) { Logger.Trace("c> {0}", line); write.WriteLine(line); write.Flush(); line = shell.ReadLine(); } }); disposer.Push(reader); disposer.Push(client); disposer.Push(writer); disposer.Push(shell); //netcore linux prints ipv6 in endpoint.tostring action(shell, $"{config.ShellIP}:{endpoint.Port}"); } }
private void AcceptLoop() { while (true) { var client = server.AcceptTcpClient(); register.Run(() => { using (var disposer = new Disposer()) { disposer.Push(client); var rt = new ClientRt(client, certificate, factory); disposer.Push(rt.Dispose); //ensure cleanup order clients.Add(rt.EndPoint.ToString(), rt); rt.Run(() => RemoveClient(rt)); Logger.Trace("Client {0} connected", rt.EndPoint); disposer.Clear(); } }); } }
public ClientRt(TcpClient client, X509Certificate2 certificate, ShellFactory factory) { //client disposed in caller on throw this.client = client; this.certificate = certificate; using (var disposer = new Disposer()) { start = DateTime.Now; last = DateTime.Now; shell = factory.Create(); endpoint = client.Client.RemoteEndPoint as IPEndPoint; reader = new Runner(new Runner.Args { ThreadName = string.Format("Client_{0}", endpoint) }); disposer.Push(reader); disposer.Push(Dispose); //ensure cleanup order reader.Run(ReadLoop); disposer.Clear(); } }
static void Main(string[] args) { ProgramTools.Setup(); var config = new Config(); //args will always log to stderr because trace flag not loaded yet ExecutableTools.LogArgs(new StderrWriteLine(), args, (arg) => { ConfigTools.SetProperty(config, arg); }); AssertTools.NotEmpty(config.EndPoint, "Missing EndPoint"); AssertTools.NotEmpty(config.Root, "Missing Root"); if (!config.Daemon) { Logger.TRACE = new StderrWriteLine(); } var uri = string.Format("http://{0}/", config.EndPoint); var http = new HttpListener(); http.Prefixes.Add(uri); http.Start(); var accepter = new Runner(new Runner.Args { ThreadName = "Accepter" }); var handler = new Runner(new Runner.Args { ThreadName = "Handler" }); accepter.Run(() => { while (http.IsListening) { var ctx = http.GetContext(); handler.Run(() => { var request = ctx.Request; var response = ctx.Response; var pass = true; var file = ctx.Request.RawUrl.Substring(1); //remove leading / if (!PathTools.IsChildPath(config.Root, file)) { pass = false; } var path = PathTools.Combine(config.Root, file); Logger.Trace("File {0} {1}", file, path); if (!File.Exists(path)) { pass = false; } if (ctx.Request.HttpMethod != "GET") { pass = false; } if (pass) { var fi = new FileInfo(path); var fs = new FileStream(path, FileMode.Open, FileAccess.Read); ctx.Response.StatusCode = (int)HttpStatusCode.OK; ctx.Response.ContentLength64 = fi.Length; ctx.Response.ContentType = "application/octet-stream"; var data = new byte[1024]; var count = fs.Read(data, 0, data.Length); while (count > 0) { ctx.Response.OutputStream.Write(data, 0, count); count = fs.Read(data, 0, data.Length); } } else { ctx.Response.StatusCode = (int)HttpStatusCode.NotFound; ctx.Response.ContentLength64 = 0; } ctx.Response.Close(); }); } }); Stdio.SetStatus("Listeninig on {0}", uri); using (var disposer = new Disposer()) { disposer.Push(handler); disposer.Push(accepter); disposer.Push(http.Stop); var line = Stdio.ReadLine(); while (line != null) { line = Stdio.ReadLine(); } } Logger.Trace("Stdin closed"); Environment.Exit(0); }
static void Main(string[] args) { ProgramTools.Setup(); var config = new Config(); config.IP = "0.0.0.0"; config.Port = 22333; config.Delay = 5000; config.Timeout = 5000; config.Root = ExecutableTools.Relative("Root"); //args will always log to stderr because daemon flag not loaded yet ExecutableTools.LogArgs(new StderrWriteLine(), args, (arg) => { ConfigTools.SetProperty(config, arg); }); AssertTools.NotEmpty(config.Root, "Missing Root path"); AssertTools.NotEmpty(config.IP, "Missing IP"); AssertTools.Ip(config.IP, "Invalid IP"); var pid = Process.GetCurrentProcess().Id; var writers = new WriteLineCollection(); if (!config.Daemon) { writers.Add(new StderrWriteLine()); Logger.TRACE = new TimedWriter(writers); } Logger.Trace("Root {0}", config.Root); var dbpath = Path.Combine(config.Root, "SharpDaemon.LiteDb"); var logpath = Path.Combine(config.Root, "SharpDaemon.Log.txt"); var eppath = Path.Combine(config.Root, "SharpDaemon.Endpoint.txt"); var downloads = Path.Combine(config.Root, "Downloads"); Directory.CreateDirectory(downloads); //creates root as well //acts like mutex for the workspace var log = new StreamWriter(logpath, true); writers.Add(new TextWriterWriteLine(log)); ExecutableTools.LogArgs(new TextWriterWriteLine(log), args); var instance = new Instance(new Instance.Args { DbPath = dbpath, RestartDelay = config.Delay, Downloads = downloads, EndPoint = new IPEndPoint(IPAddress.Parse(config.IP), config.Port), }); Stdio.SetStatus("Listening on {0}", instance.EndPoint); using (var disposer = new Disposer()) { //wrap to add to disposable count disposer.Push(new Disposable.Wrapper(log)); disposer.Push(instance); disposer.Push(() => Disposing(config.Timeout)); if (config.Daemon) { Logger.Trace("Stdin loop..."); var line = Stdio.ReadLine(); while (line != null) { Logger.Trace("> {0}", line); if ("exit!" == line) { break; } line = Stdio.ReadLine(); } Logger.Trace("Stdin closed"); } else { Logger.Trace("Stdin loop..."); var shell = instance.CreateShell(); var stream = new ShellStream(new StdoutWriteLine(), new ConsoleReadLine()); //disposer.Push(stream); //stdin.readline wont return even after close/dispose call var line = stream.ReadLine(); while (line != null) { if ("exit!" == line) { break; } Shell.ParseAndExecute(shell, stream, line); line = stream.ReadLine(); } Logger.Trace("Stdin closed"); } } Environment.Exit(0); }
/// <summary> /// Read the files from a package and import the package information into LearningStore. Only packages /// which may be executed can be imported into LearningStore. /// See the class overview information for details. /// </summary> /// <param name="packageReader">A reader to read the files in the package to be imported.</param> /// <param name="packageId">The identifier of the package whose files are being imported.</param> /// <returns>Returns the location of the package that was added.</returns> /// <remarks> /// <p/>This method copies all package files that are referenced in the manifest into a unique /// subdirectory in the basePath directory. /// /// <p/>This method will validate that the package does not have any errors when it is /// processed by the <c>PackageValidator</c> class. Warnings that occur during validaton /// will have no effect on adding the package. /// /// <p/>Only packages which can be excuted may be imported into LearningStore. A package may be /// executed if there is at least one <Organization> nodes within it. /// /// <p/>This method creates a transaction, regardless of whether or not it is called within /// a transaction. /// /// <p/>The identity passed to the constructor will be used to write the files to the file system. This /// account must have appropriate permissions to write to the basePath directory for the package store. /// /// <p/>The exceptions thrown by Directory.CreateDirectory() may also be thrown by this method. /// </remarks> /// <exception cref="PackageImportException">Thrown if the package to be added is not a /// <c>PackageType.ContentAggregation</c> or does not contain /// at least one <item> node.</exception> /// <exception cref="UnauthorizedAccessException">Thrown if the identity used to create this object /// does not have sufficient permissions in the file system directory.</exception> private string ImportFiles(PackageItemIdentifier packageId, PackageReader packageReader) { string relativePackageLocation; // package location unique to this pacakge // The outer try/catch block is there for security reasons. Search MSDN for // "WrapVulnerableFinallyClausesInOuterTry" to see details. try { string absPackageLocation = null; // Create directories using the identity account that was passed to the store. using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { // Create the directory, relative to m_basePath relativePackageLocation = CreatePackageDirectory(packageId.GetKey(), 100); // Get the absolution package location of the new package directory absPackageLocation = PackageReader.SafePathCombine(m_basePath, relativePackageLocation); } if (packageReader.GetType().Equals(typeof(ZipPackageReader))) { // Let the zip reader do its own copy, as it's more efficient. Do not impersonate, as the package reader // needs to use its own identity (not the the store's identity) to access the files // ZipPackageReader doesn't want the directory to exist. (We had to create it above to verify it was // possible). using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { Directory.Delete(absPackageLocation); } ZipPackageReader zipReader = packageReader as ZipPackageReader; zipReader.CopyTo(absPackageLocation); } else { foreach (string filePath in packageReader.GetFilePaths()) { using (Disposer disposer = new Disposer()) { string absFilePath; // absolute location of the file to write string absDirPath; // absolute location of the drectory to write to FileStream outputStream; // stream to write to // Get stream for file from package Stream pkgStream = packageReader.GetFileStream(filePath); disposer.Push(pkgStream); // Create subdirectory, if it's required using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { absFilePath = PackageReader.SafePathCombine(absPackageLocation, filePath); absDirPath = Path.GetDirectoryName(absFilePath); if (!File.Exists(absDirPath) && !Directory.Exists(absDirPath)) { // Create it Directory.CreateDirectory(absDirPath); } // Create file location to write outputStream = new FileStream(absFilePath, FileMode.Create); disposer.Push(outputStream); } // Copy from the pkgStream to the outputStream, using the correct identities Utilities.CopyStream(pkgStream, ImpersonationBehavior.UseImpersonatedIdentity, outputStream, m_impersonationBehavior); } } } using (ImpersonateIdentity id = new ImpersonateIdentity(m_impersonationBehavior)) { // Remove imsmanifest.xml from the target directory. It'll be stored in LearningStore and providing two // copies may cause confusion or sync issues. string manifestFilePath = PackageReader.SafePathCombine(absPackageLocation, "imsmanifest.xml"); File.Delete(manifestFilePath); } } catch { throw; } // Return the new package return(relativePackageLocation); }
public static void Shell(string path, string args, Action <ITestShell> action) { using (var disposer = new Disposer()) { var process = new DaemonProcess(new DaemonProcess.Args { Executable = path, Arguments = args, }); Logger.Trace("Shell process {0} {1}", process.Id, process.Name, process.Info.FileName); Logger.Trace("Shell path {0}", process.Info.FileName); Logger.Trace("Shell args {0}", process.Info.Arguments); var shell = new TestShell(); var reader = new Runner(new Runner.Args { ThreadName = "SDTOUT" }); var erroer = new Runner(new Runner.Args { ThreadName = "STDERR" }); var writer = new Runner(new Runner.Args { ThreadName = "STDIN" }); reader.Run(() => { var line = process.ReadLine(); while (line != null) { Logger.Trace("<o {0}", line); shell.WriteLine("<o {0}", line); line = process.ReadLine(); } shell.WriteLine(Environ.NewLines); }); erroer.Run(() => { var line = process.ReadError(); while (line != null) { Logger.Trace("<e {0}", line); shell.WriteLine("<e {0}", line); line = process.ReadError(); } }); writer.Run(() => { var line = shell.ReadLine(); while (line != null) { Logger.Trace("i> {0}", line); process.WriteLine(line); line = shell.ReadLine(); } }); disposer.Push(erroer); disposer.Push(reader); disposer.Push(process); disposer.Push(writer); disposer.Push(shell); action(shell); } }