I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
ConfigNetHandler.java 19.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • package net.i2p.router.web;
    
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    
    import net.i2p.router.Router;
    
    zzz's avatar
    zzz committed
    import net.i2p.router.transport.FIFOBandwidthRefiller;
    
    import net.i2p.router.transport.TransportImpl;
    
    zzz's avatar
    zzz committed
    import net.i2p.router.transport.TransportManager;
    
    import net.i2p.router.transport.udp.UDPTransport;
    
    zzz's avatar
    zzz committed
    import net.i2p.router.web.ConfigServiceHandler;
    
    
    /**
     * 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;
    
    jrandom's avatar
    jrandom committed
        private boolean _recheckReachabilityRequested;
    
        private boolean _timeSyncEnabled;
    
    jrandom's avatar
    jrandom committed
        private boolean _requireIntroductions;
    
    jrandom's avatar
    jrandom committed
        private boolean _hiddenMode;
        private boolean _dynamicKeys;
    
    jrandom's avatar
    jrandom committed
        private String _ntcpHostname;
        private String _ntcpPort;
    
    jrandom's avatar
    jrandom committed
        private String _tcpPort;
    
        private String _udpHost1;
        private String _udpHost2;
    
    jrandom's avatar
    jrandom committed
        private String _udpPort;
    
        private String _udpAutoIP;
    
        private String _ntcpAutoIP;
    
    zzz's avatar
    zzz committed
        private boolean _ntcpAutoPort;
    
    zzz's avatar
    zzz committed
        private boolean _upnp;
    
    zzz's avatar
    zzz committed
        private boolean _laptop;
    
        private String _inboundRate;
    
    jrandom's avatar
    jrandom committed
        private String _inboundBurstRate;
    
        private String _inboundBurst;
        private String _outboundRate;
    
    jrandom's avatar
    jrandom committed
        private String _outboundBurstRate;
    
        private String _outboundBurst;
        private String _reseedFrom;
    
    jrandom's avatar
    jrandom committed
        private boolean _enableLoadTesting;
    
    jrandom's avatar
    jrandom committed
        private String _sharePct;
    
    zzz's avatar
    zzz committed
        private boolean _ratesOnly;
    
        private static final String PROP_HIDDEN = Router.PROP_HIDDEN_HIDDEN; // see Router for other choice
    
        @Override
    
        protected void processForm() {
    
            if (_saveRequested || ( (_action != null) && (_("Save changes").equals(_action)) )) {
    
    jrandom's avatar
    jrandom committed
            } else if (_recheckReachabilityRequested) {
                recheckReachability();
    
            } else {
                // noop
            }
        }
        
        public void setSave(String moo) { _saveRequested = true; }
        public void setEnabletimesync(String moo) { _timeSyncEnabled = true; }
    
    jrandom's avatar
    jrandom committed
        public void setRecheckReachability(String moo) { _recheckReachabilityRequested = true; }
    
    jrandom's avatar
    jrandom committed
        public void setRequireIntroductions(String moo) { _requireIntroductions = true; }
    
    jrandom's avatar
    jrandom committed
        public void setDynamicKeys(String moo) { _dynamicKeys = true; }
    
    jrandom's avatar
    jrandom committed
        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");
        }
    
    zzz's avatar
    zzz committed
        public void setUpnp(String moo) { _upnp = true; }
    
    zzz's avatar
    zzz committed
        public void setLaptop(String moo) { _laptop = true; }
    
        
        public void setHostname(String hostname) { 
            _hostname = (hostname != null ? hostname.trim() : null); 
        }
    
    jrandom's avatar
    jrandom committed
        public void setTcpPort(String port) { 
            _tcpPort = (port != null ? port.trim() : null); 
        }
    
    jrandom's avatar
    jrandom committed
        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); 
        }
    
    jrandom's avatar
    jrandom committed
        public void setUdpPort(String port) { 
            _udpPort = (port != null ? port.trim() : null); 
    
        }
        public void setInboundrate(String rate) { 
            _inboundRate = (rate != null ? rate.trim() : null); 
        }
    
    jrandom's avatar
    jrandom committed
        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); 
        }
    
    jrandom's avatar
    jrandom committed
        public void setOutboundburstrate(String rate) { 
            _outboundBurstRate = (rate != null ? rate.trim() : null); 
        }
    
        public void setOutboundburstfactor(String factor) { 
            _outboundBurst = (factor != null ? factor.trim() : null); 
        }
    
    jrandom's avatar
    jrandom committed
        public void setSharePercentage(String pct) {
            _sharePct = (pct != null ? pct.trim() : null);
        }
    
    zzz's avatar
    zzz committed
        /** @since 0.8.12 */
        public void setRatesOnly(String foo) {
            _ratesOnly = true;
        }
        
    
    jrandom's avatar
    jrandom committed
        private void recheckReachability() {
            _context.commSystem().recheckReachability();
    
            addFormNotice(_("Rechecking router reachability..."));
    
    jrandom's avatar
    jrandom committed
        }
        
    
        /**
         * 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;
            
    
    jrandom's avatar
    jrandom committed
            if (!_ratesOnly) {
    
                // IP Settings
    
    zzz's avatar
    zzz committed
                String oldUdp = _context.getProperty(UDPTransport.PROP_SOURCES,
                                                     _context.router().isHidden() ? "hidden" : 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);
    
                    boolean valid = true;
                    if (uhost.length() > 0) {
                        valid = verifyAddress(uhost);
                        if (valid) {
                            _context.router().setConfigSetting(UDPTransport.PROP_EXTERNAL_HOST, uhost);
                        }
                    } else {
    
                        _context.router().removeConfigSetting(UDPTransport.PROP_EXTERNAL_HOST);
    
                    }
                    if (valid && ((!oldUdp.equals(_udpAutoIP)) || (!oldUHost.equals(uhost)))) {
    
                       addFormNotice(_("Updating IP address"));
    
                       restartRequired = true;
                    }
                }
    
                // NTCP Settings
    
    zzz's avatar
    zzz committed
                // 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 = Boolean.valueOf(sAutoPort).booleanValue();
    
                if (_ntcpHostname == null) _ntcpHostname = "";
                if (_ntcpPort == null) _ntcpPort = "";
    
                if (_ntcpAutoIP == null) _ntcpAutoIP = "true";
    
    zzz's avatar
    zzz committed
    
    
                if ((!oldAutoHost.equals(_ntcpAutoIP)) || ! oldNHost.equalsIgnoreCase(_ntcpHostname)) {
    
    zzz's avatar
    zzz committed
                    if ("disabled".equals(_ntcpAutoIP)) {
    
                        addFormNotice(_("Disabling TCP completely"));
    
    zzz's avatar
    zzz committed
                    } else if ("false".equals(_ntcpAutoIP) && _ntcpHostname.length() > 0) {
    
                        valid = verifyAddress(_ntcpHostname);
                        if (valid) {
                            _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME, _ntcpHostname);
                            addFormNotice(_("Updating inbound TCP address to") + " " + _ntcpHostname);
                        }
    
    zzz's avatar
    zzz committed
                    } else {
    
    jrandom's avatar
    jrandom committed
                        _context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
    
                        if ("false".equals(_ntcpAutoIP))
    
                            addFormNotice(_("Disabling inbound TCP"));
    
                            addFormNotice(_("Updating inbound TCP address to auto")); // true or always
    
    zzz's avatar
    zzz committed
                    }
    
                    if (valid) {
                        _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP, _ntcpAutoIP);
                        _context.router().setConfigSetting(TransportManager.PROP_ENABLE_NTCP, "" + !"disabled".equals(_ntcpAutoIP));
                        restartRequired = true;
                    }
    
    zzz's avatar
    zzz committed
                }
                if (oldAutoPort != _ntcpAutoPort || ! oldNPort.equals(_ntcpPort)) {
    
                    if (_ntcpPort.length() > 0 && !_ntcpAutoPort) {
    
    zzz's avatar
    zzz committed
                        _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT, _ntcpPort);
    
                        addFormNotice(_("Updating inbound TCP port to") + " " + _ntcpPort);
    
    zzz's avatar
    zzz committed
                    } else {
                        _context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
    
                        addFormNotice(_("Updating inbound TCP port to auto"));
    
    jrandom's avatar
    jrandom committed
                    }
    
                    _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT, "" + _ntcpAutoPort);
    
    zzz's avatar
    zzz committed
                    restartRequired = true;
    
    jrandom's avatar
    jrandom committed
                }
    
    
                // UDP Settings
    
    jrandom's avatar
    jrandom committed
                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);
    
    jrandom's avatar
    jrandom committed
                        restartRequired = true;
                    }
    
    jrandom's avatar
    jrandom committed
    
    
            boolean switchRequired = false;
    
    jrandom's avatar
    jrandom committed
            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"));
    
                        addFormError(_("Gracefully restarting to exit Hidden Router Mode"));
    
    jrandom's avatar
    jrandom committed
                }
    
    jrandom's avatar
    jrandom committed
    
    
    zzz's avatar
    zzz committed
                _context.router().setConfigSetting(Router.PROP_DYNAMIC_KEYS, "" + _dynamicKeys);
    
                if (Boolean.valueOf(_context.getProperty(TransportManager.PROP_ENABLE_UPNP)).booleanValue() !=
                    _upnp) {
    
    zzz's avatar
    zzz committed
                    // This is minor, don't set restartRequired
    
    zzz's avatar
    zzz committed
                    if (_upnp)
    
                        addFormNotice(_("Enabling UPnP, restart required to take effect"));
    
    zzz's avatar
    zzz committed
                    else
    
                        addFormNotice(_("Disabling UPnP, restart required to take effect"));
    
    jrandom's avatar
    jrandom committed
                }
    
    zzz's avatar
    zzz committed
                _context.router().setConfigSetting(TransportManager.PROP_ENABLE_UPNP, "" + _upnp);
    
    jrandom's avatar
    jrandom committed
    
    
    zzz's avatar
    zzz committed
                if (Boolean.valueOf(_context.getProperty(UDPTransport.PROP_LAPTOP_MODE)).booleanValue() !=
                    _laptop) {
                    // This is minor, don't set restartRequired
                    if (_laptop)
                        addFormNotice(_("Enabling laptop mode"));
                    else
                        addFormNotice(_("Disabling laptop mode"));
                }
                _context.router().setConfigSetting(UDPTransport.PROP_LAPTOP_MODE, "" + _laptop);
    
    
    jrandom's avatar
    jrandom committed
                if (_requireIntroductions) {
                    _context.router().setConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS, "true");
    
    echelon's avatar
    echelon committed
                    addFormNotice(_("Requiring SSU introducers"));
    
    jrandom's avatar
    jrandom committed
                } else {
                    _context.router().removeConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS);
                }
    
    
    zzz's avatar
    zzz committed
                // Time sync enable, means NOT disabled 
    
    zzz's avatar
    zzz committed
                // Hmm router sets this at startup, not required here
                //_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false");
    
    jrandom's avatar
    jrandom committed
                
    
    zzz's avatar
    zzz committed
                // Hidden in the GUI
                //LoadTestManager.setEnableLoadTesting(_context, _enableLoadTesting);
    
            }
            
            boolean saved = _context.router().saveConfig();
    
    zzz's avatar
    zzz committed
            if (saved) 
                addFormNotice(_("Configuration saved successfully"));
            else
                addFormError(_("Error saving the configuration (applied but not saved) - please see the error logs"));
    
            if (switchRequired) {
                hiddenSwitch();
            } else if (restartRequired) {
    
                //if (_context.hasWrapper()) {
    
    zzz's avatar
    zzz committed
                    // Wow this dumps all conns immediately and really isn't nice
                    addFormNotice("Performing a soft restart");
                    _context.router().restart();
    
                    // restart() returns immediately now
                    //addFormNotice("Soft restart complete");
    
    zzz's avatar
    zzz committed
    
    
    zzz's avatar
    zzz committed
                    // 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");
    
    zzz's avatar
    zzz committed
                    // 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);
                //}
    
    jrandom's avatar
    jrandom committed
    
    
        /**
         *  Do basic verification of address here to prevent problems later
         *  @return valid
         *  @since 0.8.9
         */
        private boolean verifyAddress(String addr) {
            if (addr == null || addr.length() <= 0)
                return false;
            try {
                InetAddress ia = InetAddress.getByName(addr);
                byte[] iab = ia.getAddress();
                boolean rv = TransportImpl.isPubliclyRoutable(iab);
                if (!rv)
                    addFormError(_("The hostname or IP {0} is not publicly routable", addr));
                return rv;
            } catch (UnknownHostException uhe) {
                addFormError(_("The hostname or IP {0} is invalid", addr) + ": " + uhe);
                return false;
            }
        }
    
    
    jrandom's avatar
    jrandom committed
        private void hiddenSwitch() {
            // Full restart required to generate new keys
    
            // FIXME don't call wrapper if not present, only rekey
    
    zzz's avatar
    zzz committed
            ConfigServiceHandler.registerWrapperNotifier(_context, Router.EXIT_GRACEFUL_RESTART, false);
    
    jrandom's avatar
    jrandom committed
            _context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
        }
    
        private static final int DEF_BURST_PCT = 10;
        private static final int DEF_BURST_TIME = 20;
    
    
        private void updateRates() {
            boolean updated = false;
    
    zzz's avatar
    zzz committed
            boolean bwUpdated = false;
    
    
            if (_sharePct != null) {
                String old = _context.router().getConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE);
    
                if ( (old == null) || (!old.equals(_sharePct)) ) {
    
                    _context.router().setConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE, _sharePct);
    
                    addFormNotice(_("Updating bandwidth share percentage"));
    
            // Since burst is now hidden in the gui, set burst to +10% for 20 seconds
    
            if ( (_inboundRate != null) && (_inboundRate.length() > 0) &&
                !_inboundRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_INBOUND_BANDWIDTH))) {
    
    zzz's avatar
    zzz committed
                _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, _inboundRate);
    
                try {
                    int rate = Integer.parseInt(_inboundRate) * (100 + DEF_BURST_PCT) / 100;
                    int kb = DEF_BURST_TIME * rate;
                    _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, "" + rate);
                    _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH_PEAK, "" + kb);
                } catch (NumberFormatException nfe) {}
    
    zzz's avatar
    zzz committed
                bwUpdated = true;
    
            if ( (_outboundRate != null) && (_outboundRate.length() > 0) &&
                !_outboundRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_OUTBOUND_BANDWIDTH))) {
    
    zzz's avatar
    zzz committed
                _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, _outboundRate);
    
                try {
                    int rate = Integer.parseInt(_outboundRate) * (100 + DEF_BURST_PCT) / 100;
                    int kb = DEF_BURST_TIME * rate;
                    _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, "" + rate);
                    _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH_PEAK, "" + kb);
                } catch (NumberFormatException nfe) {}
    
    zzz's avatar
    zzz committed
                bwUpdated = true;
            }
    
            if (bwUpdated) {
                addFormNotice(_("Updated bandwidth limits"));
    
    zzz's avatar
    zzz committed
    
    /******* 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))) {
    
    zzz's avatar
    zzz committed
                _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, _inboundBurstRate);
    
    jrandom's avatar
    jrandom committed
                updated = true;
            }
    
            if ( (_outboundBurstRate != null) && (_outboundBurstRate.length() > 0) &&
                !_outboundBurstRate.equals(_context.getProperty(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, "" + FIFOBandwidthRefiller.DEFAULT_OUTBOUND_BURST_BANDWIDTH))) {
    
    zzz's avatar
    zzz committed
                _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, _outboundBurstRate);
    
    jrandom's avatar
    jrandom committed
                updated = true;
            }
    
    zzz's avatar
    zzz committed
            String inBurstRate = _context.router().getConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH);
    
            
            if (_inboundBurst != null) {
                int rateKBps = 0;
                int burstSeconds = 0;
                try {
    
    jrandom's avatar
    jrandom committed
                    rateKBps = Integer.parseInt(inBurstRate);
    
                    burstSeconds = Integer.parseInt(_inboundBurst);
                } catch (NumberFormatException nfe) {
                    // ignore
                }
                if ( (rateKBps > 0) && (burstSeconds > 0) ) {
                    int kb = rateKBps * burstSeconds;
    
    zzz's avatar
    zzz committed
                    _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH_PEAK, "" + kb);
    
    zzz's avatar
    zzz committed
            String outBurstRate = _context.router().getConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH);
    
            
            if (_outboundBurst != null) {
                int rateKBps = 0;
                int burstSeconds = 0;
                try {
    
    jrandom's avatar
    jrandom committed
                    rateKBps = Integer.parseInt(outBurstRate);
    
                    burstSeconds = Integer.parseInt(_outboundBurst);
                } catch (NumberFormatException nfe) {
                    // ignore
                }
                if ( (rateKBps > 0) && (burstSeconds > 0) ) {
                    int kb = rateKBps * burstSeconds;
    
    zzz's avatar
    zzz committed
                    _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH_PEAK, "" + kb);
    
    zzz's avatar
    zzz committed
    
    ***********/
    
    
    zzz's avatar
    zzz committed
            if (updated)
    
    zzz's avatar
    zzz committed
                _context.bandwidthLimiter().reinitialize();