Пример #1
0
            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();
                }
            }
Пример #2
0
        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();
            }
        }
Пример #3
0
        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();
            }
        }
Пример #4
0
        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}");
            }
        }
Пример #5
0
 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();
             }
         });
     }
 }
Пример #6
0
            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();
                }
            }
Пример #7
0
        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);
        }
Пример #8
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);
        }
Пример #9
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 &lt;Organization&gt; 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 &lt;item&gt; 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);
        }
Пример #10
0
        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);
            }
        }