package net.i2p.router.web; import net.i2p.data.RouterInfo; import net.i2p.router.Router; import net.i2p.router.transport.FIFOBandwidthRefiller; import net.i2p.router.transport.TransportManager; import net.i2p.router.transport.udp.UDPTransport; import net.i2p.router.web.ConfigServiceHandler.UpdateWrapperManagerAndRekeyTask; import net.i2p.time.Timestamper; /** * Handler to deal with form submissions from the main config form and act * upon the values. * */ public class ConfigNetHandler extends FormHandler { private String _hostname; private boolean _reseedRequested; private boolean _saveRequested; private boolean _recheckReachabilityRequested; private boolean _timeSyncEnabled; private boolean _requireIntroductions; private boolean _hiddenMode; private boolean _dynamicKeys; private String _ntcpHostname; private String _ntcpPort; private String _tcpPort; private String _udpHost1; private String _udpHost2; private String _udpPort; private String _udpAutoIP; private String _ntcpAutoIP; private boolean _ntcpAutoPort; private boolean _upnp; private String _inboundRate; private String _inboundBurstRate; private String _inboundBurst; private String _outboundRate; private String _outboundBurstRate; private String _outboundBurst; private String _reseedFrom; private boolean _enableLoadTesting; private String _sharePct; private static final boolean _ratesOnly = false; // always false - delete me private static final String PROP_HIDDEN = Router.PROP_HIDDEN_HIDDEN; // see Router for other choice protected void processForm() { if (_saveRequested || ( (_action != null) && ("Save changes".equals(_action)) )) { saveChanges(); } else if (_recheckReachabilityRequested) { recheckReachability(); } else { // noop } } public void setSave(String moo) { _saveRequested = true; } public void setEnabletimesync(String moo) { _timeSyncEnabled = true; } public void setRecheckReachability(String moo) { _recheckReachabilityRequested = true; } public void setRequireIntroductions(String moo) { _requireIntroductions = true; } public void setDynamicKeys(String moo) { _dynamicKeys = true; } public void setEnableloadtesting(String moo) { _enableLoadTesting = true; } public void setUdpAutoIP(String mode) { _udpAutoIP = mode; _hiddenMode = "hidden".equals(mode); } public void setNtcpAutoIP(String mode) { _ntcpAutoIP = mode; } public void setNtcpAutoPort(String mode) { _ntcpAutoPort = mode.equals("2"); } public void setUpnp(String moo) { _upnp = true; } public void setHostname(String hostname) { _hostname = (hostname != null ? hostname.trim() : null); } public void setTcpPort(String port) { _tcpPort = (port != null ? port.trim() : null); } public void setNtcphost(String host) { _ntcpHostname = (host != null ? host.trim() : null); } public void setNtcpport(String port) { _ntcpPort = (port != null ? port.trim() : null); } public void setUdpHost1(String host) { _udpHost1 = (host != null ? host.trim() : null); } public void setUdpHost2(String host) { _udpHost2 = (host != null ? host.trim() : null); } public void setUdpPort(String port) { _udpPort = (port != null ? port.trim() : null); } public void setInboundrate(String rate) { _inboundRate = (rate != null ? rate.trim() : null); } public void setInboundburstrate(String rate) { _inboundBurstRate = (rate != null ? rate.trim() : null); } public void setInboundburstfactor(String factor) { _inboundBurst = (factor != null ? factor.trim() : null); } public void setOutboundrate(String rate) { _outboundRate = (rate != null ? rate.trim() : null); } public void setOutboundburstrate(String rate) { _outboundBurstRate = (rate != null ? rate.trim() : null); } public void setOutboundburstfactor(String factor) { _outboundBurst = (factor != null ? factor.trim() : null); } public void setSharePercentage(String pct) { _sharePct = (pct != null ? pct.trim() : null); } private void recheckReachability() { _context.commSystem().recheckReachability(); addFormNotice("Rechecking router reachability..."); } /** * The user made changes to the network config and wants to save them, so * lets go ahead and do so. * */ private void saveChanges() { boolean restartRequired = false; if (!_ratesOnly) { // IP Settings String oldUdp = _context.getProperty(UDPTransport.PROP_SOURCES, UDPTransport.DEFAULT_SOURCES); String oldUHost = _context.getProperty(UDPTransport.PROP_EXTERNAL_HOST, ""); if (_udpAutoIP != null) { String uhost = ""; if (_udpAutoIP.equals("fixed")) { if (_udpHost1 != null && _udpHost1.length() > 0) uhost = _udpHost1; else if (_udpHost2 != null && _udpHost2.length() > 0) uhost = _udpHost2; else _udpAutoIP = UDPTransport.DEFAULT_SOURCES; } _context.router().setConfigSetting(UDPTransport.PROP_SOURCES, _udpAutoIP); // Todo: Catch local IPs right here rather than complaining later _context.router().setConfigSetting(UDPTransport.PROP_EXTERNAL_HOST, uhost); if ((!oldUdp.equals(_udpAutoIP)) || (!oldUHost.equals(uhost))) { addFormNotice("Updating IP address"); restartRequired = true; } } // NTCP Settings // Normalize some things to make the following code a little easier... String oldNHost = _context.getProperty(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME, ""); String oldNPort = _context.getProperty(ConfigNetHelper.PROP_I2NP_NTCP_PORT, ""); String oldAutoHost = _context.getProperty(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP, "true"); String sAutoPort = _context.getProperty(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT, "true"); boolean oldAutoPort = "true".equalsIgnoreCase(sAutoPort); if (_ntcpHostname == null) _ntcpHostname = ""; if (_ntcpPort == null) _ntcpPort = ""; if (_ntcpAutoIP == null) _ntcpAutoIP = "true"; if ((!oldAutoHost.equals(_ntcpAutoIP)) || ! oldNHost.equalsIgnoreCase(_ntcpHostname)) { if ("disabled".equals(_ntcpAutoIP)) { addFormNotice("Disabling TCP completely"); } else if ("false".equals(_ntcpAutoIP) && _ntcpHostname.length() > 0) { // Todo: Catch local IPs right here rather than complaining later _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME, _ntcpHostname); addFormNotice("Updating inbound TCP address to " + _ntcpHostname); } else { _context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME); if ("false".equals(_ntcpAutoIP)) addFormNotice("Disabling inbound TCP"); else addFormNotice("Updating inbound TCP address to auto"); // true or always } _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP, _ntcpAutoIP); _context.router().setConfigSetting(TransportManager.PROP_ENABLE_NTCP, "" + !"disabled".equals(_ntcpAutoIP)); restartRequired = true; } if (oldAutoPort != _ntcpAutoPort || ! oldNPort.equals(_ntcpPort)) { if (_ntcpPort.length() > 0 && !_ntcpAutoPort) { _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT, _ntcpPort); addFormNotice("Updating inbound TCP port to " + _ntcpPort); } else { _context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT); addFormNotice("Updating inbound TCP port to auto"); } _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT, "" + _ntcpAutoPort); restartRequired = true; } // UDP Settings if ( (_udpPort != null) && (_udpPort.length() > 0) ) { String oldPort = "" + _context.getProperty(UDPTransport.PROP_INTERNAL_PORT, UDPTransport.DEFAULT_INTERNAL_PORT); if (!oldPort.equals(_udpPort)) { _context.router().setConfigSetting(UDPTransport.PROP_INTERNAL_PORT, _udpPort); _context.router().setConfigSetting(UDPTransport.PROP_EXTERNAL_PORT, _udpPort); addFormNotice("Updating UDP port from " + oldPort + " to " + _udpPort); restartRequired = true; } } } updateRates(); boolean switchRequired = false; if (!_ratesOnly) { // If hidden mode value changes, restart is required switchRequired = _hiddenMode != _context.router().isHidden(); if (switchRequired) { _context.router().setConfigSetting(PROP_HIDDEN, "" + _hiddenMode); if (_hiddenMode) addFormError("Gracefully restarting into Hidden Router Mode"); else addFormError("Gracefully restarting to exit Hidden Router Mode"); } _context.router().setConfigSetting(Router.PROP_DYNAMIC_KEYS, "" + _dynamicKeys); if (Boolean.valueOf(_context.getProperty(TransportManager.PROP_ENABLE_UPNP)).booleanValue() != _upnp) { // This is minor, don't set restartRequired if (_upnp) addFormNotice("Enabling UPnP, restart required to take effect"); else addFormNotice("Disabling UPnP, restart required to take effect"); } _context.router().setConfigSetting(TransportManager.PROP_ENABLE_UPNP, "" + _upnp); if (_requireIntroductions) { _context.router().setConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS, "true"); addFormNotice("Requiring SSU introduers"); } else { _context.router().removeConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS); } // Time sync enable, means NOT disabled // Hmm router sets this at startup, not required here //_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false"); // Hidden in the GUI //LoadTestManager.setEnableLoadTesting(_context, _enableLoadTesting); } boolean saved = _context.router().saveConfig(); if ( (_action != null) && ("Save changes".equals(_action)) ) { if (saved) addFormNotice("Configuration saved successfully"); else addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs"); } if (switchRequired) { hiddenSwitch(); } else if (restartRequired) { // Wow this dumps all conns immediately and really isn't nice //addFormNotice("Performing a soft restart"); //_context.router().restart(); //addFormNotice("Soft restart complete"); // Most of the time we aren't changing addresses, just enabling or disabling // things, so let's try just a new routerInfo and see how that works. // Maybe we should restart if we change addresses though? // No, this doesn't work well, really need to call SSU Transport externalAddressReceived(), // but that's hard to get to, and doesn't handle port changes, etc. // So don't do this... //_context.router().rebuildRouterInfo(); //addFormNotice("Router Info rebuilt"); // There's a few changes that don't really require restart (e.g. enabling inbound TCP) // But it would be hard to get right, so just do a restart. addFormError("Gracefully restarting I2P to change published router address"); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } } private void hiddenSwitch() { // Full restart required to generate new keys _context.addShutdownTask(new UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL_RESTART)); _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); } private void updateRates() { boolean updated = false; if (_sharePct != null) { String old = _context.router().getConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE); if ( (old == null) || (!old.equalsIgnoreCase(_sharePct)) ) { _context.router().setConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE, _sharePct); addFormNotice("Updating bandwidth share percentage"); updated = true; } } if ( (_inboundRate != null) && (_inboundRate.length() > 0) && !_inboundRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_INBOUND_BANDWIDTH))) { _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, _inboundRate); updated = true; } if ( (_outboundRate != null) && (_outboundRate.length() > 0) && !_outboundRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_OUTBOUND_BANDWIDTH))) { _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, _outboundRate); updated = true; } /******* These aren't in the GUI for now if ( (_inboundBurstRate != null) && (_inboundBurstRate.length() > 0) && !_inboundBurstRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_INBOUND_BURST_BANDWIDTH))) { _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, _inboundBurstRate); updated = true; } if ( (_outboundBurstRate != null) && (_outboundBurstRate.length() > 0) && !_outboundBurstRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_OUTBOUND_BURST_BANDWIDTH))) { _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, _outboundBurstRate); updated = true; } String inBurstRate = _context.router().getConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH); if (_inboundBurst != null) { int rateKBps = 0; int burstSeconds = 0; try { rateKBps = Integer.parseInt(inBurstRate); burstSeconds = Integer.parseInt(_inboundBurst); } catch (NumberFormatException nfe) { // ignore } if ( (rateKBps > 0) && (burstSeconds > 0) ) { int kb = rateKBps * burstSeconds; _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH_PEAK, "" + kb); updated = true; } } String outBurstRate = _context.router().getConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH); if (_outboundBurst != null) { int rateKBps = 0; int burstSeconds = 0; try { rateKBps = Integer.parseInt(outBurstRate); burstSeconds = Integer.parseInt(_outboundBurst); } catch (NumberFormatException nfe) { // ignore } if ( (rateKBps > 0) && (burstSeconds > 0) ) { int kb = rateKBps * burstSeconds; _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH_PEAK, "" + kb); updated = true; } } ***********/ if (updated && !_ratesOnly) { _context.bandwidthLimiter().reinitialize(); addFormNotice("Updated bandwidth limits"); } } }