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); } }
// 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; }
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(); }