Esempio n. 1
0
            public NodeConfig(string relativeTo)
            {
                RelativeTo = relativeTo;

                /*
                 * Read wrapper config: wrapper log location, PID file location, anchor location.
                 * The PID file location is specified on the command line, so if none is read
                 * it will use a default. It's not in the default wrapper.conf and is defined on
                 * the command line in run.sh.
                 */
                PidFilename = "freenet.pid";
                // wrapper.conf is relative to the wrapper's location.
                var wrapperDir = Directory.GetParent(Path.Combine(relativeTo, WrapperFilename()));

                foreach (var line in File.ReadAllLines(wrapperDir.FullName + '\\' + WrapperConfFilename))
                {
                    // TODO: Map between constants and variables to reduce repetition?
                    if (Defines(line, "wrapper.logfile"))
                    {
                        WrapperLogFilename = Path.Combine(relativeTo, Value(line));
                    }
                    else if (Defines(line, "wrapper.pidfile"))
                    {
                        PidFilename = Path.Combine(relativeTo, Value(line));
                    }
                    else if (Defines(line, "wrapper.anchorfile"))
                    {
                        AnchorFilename = Path.Combine(relativeTo, Value(line));
                    }
                }

                // TODO: A mapping between config location and variable would reduce verbosity here too.
                if (WrapperLogFilename == null)
                {
                    throw new MissingConfigValueException(WrapperConfFilename, "wrapper.logfile");
                }

                if (AnchorFilename == null)
                {
                    throw new MissingConfigValueException(WrapperConfFilename, "wrapper.anchorfile");
                }

                // Read Freenet config: FProxy port TODO: Use ini-parser instead
                // TODO: Does this need to wait until the node is running for the first run?
                var freenetIniLines = File.ReadAllLines(Path.Combine(relativeTo, FreenetIniFilename));

                var port    = RequireValue(freenetIniLines, "fproxy.port");
                var isValid = int.TryParse(port, out FProxyPort);

                if (!isValid)
                {
                    FNLog.Error("fproxy.port is not an integer.");
                    throw new MissingConfigValueException(FreenetIniFilename, "fproxy.port");
                }

                DownloadsDir = Path.Combine(RelativeTo,
                                            RequireValue(freenetIniLines, "node.downloadsDir"));
            }
Esempio n. 2
0
        static void Main()
        {
            // migrate settings from older config files for previous assembly versions
            FreenetTray.Properties.Settings.Default.Upgrade();

            FNLog.Initialize();

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new CommandsMenu());
        }
Esempio n. 3
0
 private void Wrapper_Exited(object sender, EventArgs e)
 {
     // TODO: Is exit code enough to distinguish between stopping and crashing?
     if (_wrapper.ExitCode == 0)
     {
         FNLog.Debug("Wrapper exited.");
         OnStopped(sender, e);
     }
     else
     {
         FNLog.Error("Wrapper crashed. Exit code: {0}", _wrapper.ExitCode);
         OnCrashed(CrashType.WrapperCrashed);
     }
 }
Esempio n. 4
0
        /*
         * TODO: What are the function documentation comments supposed to be formatted like?
         * Start the node if it is not already started.
         *
         * Throws FileNotFoundException
         */
        public void Start()
        {
            if (IsRunning())
            {
                return;
            }

            try
            {
                // TODO: Under what circumstances will Process.Start() return null?
                _wrapper = Process.Start(_wrapperInfo);
                _wrapper.EnableRaisingEvents = true;
                _wrapper.Exited += Wrapper_Exited;
            }
            catch (Win32Exception ex)
            {
                // http://msdn.microsoft.com/en-us/library/0w4h05yb%28v=vs.110%29.aspx
                switch (ex.NativeErrorCode)
                {
                case ERROR_FILE_NOT_FOUND:
                    FNLog.Error("Cannot start Freenet: wrapper executable not found.");
                    OnCrashed(CrashType.WrapperFileNotFound);
                    return;

                case ERROR_INSUFFICIENT_BUFFER:
                case ERROR_ACCESS_DENIED:
                    FNLog.Error("Cannot start Freenet: the file path is too long.");
                    OnCrashed(CrashType.PathTooLong);
                    return;

                default:
                    FNLog.ErrorException(ex, "Cannot start Freenet: Process.Start() gave an error code it is not documented as giving.");
                    throw;
                }
            }

            OnStarted(this, null);
        }
Esempio n. 5
0
        // TODO: Where to document? Throws FileNotFound, DirectoryNotFound, MissingJRE
        public NodeController()
        {
            if (Properties.Settings.Default.CustomLocation.Length != 0)
            {
                _config = new NodeConfig(Properties.Settings.Default.CustomLocation);
            }
            else
            {
                Exception configException = null;
                foreach (var path in new[]
                {
                    Directory.GetCurrentDirectory(),
                    Environment.ExpandEnvironmentVariables(@"%LocalAppData%\Freenet"),
                })
                {
                    // TODO: If the wrapper has problems with arguments with non-ASCII characters should
                    // this the wrapper invocation change the working directory? Won't work in the general
                    // case because the pidfile location could contain non-ASCII characters, but it
                    // works for the default configuration.
                    // http://sourceforge.net/p/wrapper/bugs/290/
                    try
                    {
                        _config         = new NodeConfig(path);
                        configException = null;
                        break;
                    }
                    catch (Exception e)
                    {
                        configException = e;
                    }
                }

                if (configException != null)
                {
                    FNLog.Error("Failed to detect Freenet installation.", configException);
                    throw configException;
                }
            }

            // Search for an existing wrapper process.
            try
            {
                using (var reader = new StreamReader(_config.PidFilename))
                {
                    var line = reader.ReadLine();

                    if (line != null)
                    {
                        var pid = int.Parse(line);
                        _wrapper = Process.GetProcessById(pid);
                        _wrapper.EnableRaisingEvents = true;
                        _wrapper.Exited += Wrapper_Exited;
                    }
                }
            }
            catch (ArgumentException)
            {
                FNLog.Debug("No process has the PID in the PID file.");
                // The wrapper can refuse to start if there is a stale PID file - "strict".
                try
                {
                    File.Delete(_config.PidFilename);
                }
                catch (IOException)
                {
                    // TODO: Be louder about this? Or will the wrapper fail to start and exit nonzero?
                    FNLog.Debug("Stale PID file is still held.");
                }
            }
            catch (FormatException)
            {
                FNLog.Debug("PID file does not contain an integer.");
            }
            catch (OverflowException)
            {
                FNLog.Debug("PID file does not contain an integer.");
            }
            catch (FileNotFoundException)
            {
                FNLog.Debug("PID file not found.");
            }

            /*
             * Hide the wrapper window when launching it. This prevents (or at least heavily complicates)
             * stopping it with Process.CloseMainWindow() or by sending ctrl + C.
             */
            _wrapperInfo.FileName = Path.Combine(_config.RelativeTo, WrapperFilename());
            // TODO: Is it worthwhile to omit the pidfile here when it's in the config file?
            _wrapperInfo.Arguments       = "-c " + WrapperConfFilename + " wrapper.pidfile=" + _config.PidFilename;
            _wrapperInfo.UseShellExecute = false;
            _wrapperInfo.CreateNoWindow  = true;
        }
Esempio n. 6
0
        private void FindNode()
        {
            while (true)
            {
                try
                {
                    _node = new NodeController();
                    break;
                }
                catch (FileNotFoundException e)
                {
                    FNLog.ErrorException(e, "Failed to find file");
                }
                catch (DirectoryNotFoundException e)
                {
                    FNLog.ErrorException(e, "Failed to find directory");
                }
                catch (NodeController.MissingConfigValueException e)
                {
                    // If the configuration files exist but are missing required
                    // values it is sufficiently surprising to warrant an error
                    // dialog.
                    FNLog.Error(strings.MalformedConfig, e.Filename, e.Value);
                    MessageBox.Show(String.Format(strings.MalformedConfig, e.Filename, e.Value), "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                catch (MissingJRE)
                {
                    // No JRE was found
                    FNLog.Error(strings.JRENotFound);
                    MessageBox.Show(strings.JRENotFound, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    /* Cannot continue for now */
                    Application.Exit();
                    return;
                }
                // TODO: Explain what happened to prompt a custom location?
                try
                {
                    PreferencesWindow.PromptCustomLocation(this);
                }
                catch (OperationCanceledException)
                {
                    /* User exited the file browser. */
                    Application.Exit();
                    return;
                }
            }

            _node.OnStarted += NodeStarted;
            _node.OnStopped += NodeStopped;
            _node.OnCrashed += NodeCrashed;

            foreach (var menuItem in new[]
            {
                openFreenetMenuItem,
                startFreenetMenuItem,
                stopFreenetMenuItem,
                downloadsMenuItem,
                viewLogsMenuItem,
                preferencesMenuItem,
                hideIconMenuItem,
            })
            {
                menuItem.Enabled = true;
            }

            // Set menu up for whether there is an existing node.
            RefreshMenu(_node.IsRunning());

            ReadCommandLine();
        }
Esempio n. 7
0
        private void openFreenetMenuItem_Click(object sender = null, EventArgs e = null)
        {
            Start();

            var pollFproxy = new Thread(() =>
            {
                var fproxyListening = false;
                var showSlowOpen    = Settings.Default.ShowSlowOpenTip;
                var openArgs        = e as OpenArgs;
                if (openArgs != null)
                {
                    showSlowOpen = openArgs.ShowSlow;
                }

                /*
                 * TODO: Programatic way to get loopback address? This would not support IPv6.
                 * Use FProxy bind interface?
                 */
                var loopback = new IPAddress(new byte[] { 127, 0, 0, 1 });

                var timer = new Stopwatch();

                using (var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    timer.Start();
                    while (_node.IsRunning())
                    {
                        try
                        {
                            sock.Connect(loopback, _node.FProxyPort);
                            fproxyListening = true;
                            break;
                        }
                        catch (SocketException ex)
                        {
                            FNLog.Debug("Connecting got error: {0}",
                                        Enum.GetName(typeof(SocketError), ex.SocketErrorCode));
                            Thread.Sleep(SocketPollInterval);
                        }

                        // Show a startup notification if it's taking a while.
                        if (showSlowOpen && timer.ElapsedMilliseconds > SlowOpenThreshold)
                        {
                            BeginInvoke(new Action(() =>
                            {
                                trayIcon.BalloonTipText = strings.FreenetStarting;
                                trayIcon.ShowBalloonTip(SlowOpenTimeout);
                            }));
                            showSlowOpen = false;
                        }
                    }
                    timer.Stop();
                }

                if (fproxyListening)
                {
                    FNLog.Debug("FProxy listening after {0}", timer.Elapsed);
                    BrowserUtil.Open(new Uri(String.Format("http://localhost:{0:d}", _node.FProxyPort)), true);
                }
            });

            pollFproxy.Start();
        }