From ed9f9625aeb821bf893676e14c3f371289643253 Mon Sep 17 00:00:00 2001 From: jrandom Date: Sat, 31 Jul 2004 02:34:24 +0000 Subject: [PATCH] added actual form handling to the main config.jsp page dropped the old notice.jsp style result notification display destination info on the left nav --- .../net/i2p/router/web/ConfigNetHandler.java | 291 ++++++++++++++++++ .../net/i2p/router/web/ConfigNetHelper.java | 4 +- .../src/net/i2p/router/web/FormHandler.java | 109 +++++++ apps/routerconsole/jsp/config.jsp | 22 +- apps/routerconsole/jsp/configadvanced.jsp | 1 - apps/routerconsole/jsp/configclients.jsp | 1 - apps/routerconsole/jsp/configlogging.jsp | 1 - apps/routerconsole/jsp/help.jsp | 1 - apps/routerconsole/jsp/index.jsp | 1 - apps/routerconsole/jsp/logs.jsp | 1 - apps/routerconsole/jsp/netdb.jsp | 1 - apps/routerconsole/jsp/notice.jsp | 1 - apps/routerconsole/jsp/profiles.jsp | 1 - 13 files changed, 419 insertions(+), 16 deletions(-) create mode 100644 apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java create mode 100644 apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java delete mode 100644 apps/routerconsole/jsp/notice.jsp diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java new file mode 100644 index 000000000..83292bb14 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java @@ -0,0 +1,291 @@ +package net.i2p.router.web; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.File; +import java.io.FileOutputStream; + +import java.net.URL; +import java.net.URLConnection; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import net.i2p.util.Log; + +import net.i2p.router.RouterContext; +import net.i2p.router.ClientTunnelSettings; + +/** + * 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 _guessRequested; + private boolean _reseedRequested; + private boolean _saveRequested; + private boolean _timeSyncEnabled; + private String _port; + private String _inboundRate; + private String _inboundBurst; + private String _outboundRate; + private String _outboundBurst; + private String _reseedFrom; + + public void ConfigNetHandler() { + _guessRequested = false; + _reseedRequested = false; + _saveRequested = false; + _timeSyncEnabled = false; + } + + protected void processForm() { + if (_guessRequested) { + guessHostname(); + } else if (_reseedRequested) { + reseed(); + } else if (_saveRequested) { + saveChanges(); + } else { + // noop + } + } + + public void setGuesshost(String moo) { _guessRequested = true; } + public void setReseed(String moo) { _reseedRequested = true; } + public void setSave(String moo) { _saveRequested = true; } + public void setEnabletimesync(String moo) { _timeSyncEnabled = true; } + + public void setHostname(String hostname) { + _hostname = (hostname != null ? hostname.trim() : null); + } + public void setPort(String port) { + _port = (port != null ? port.trim() : null); + } + public void setInboundrate(String rate) { + _inboundRate = (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 setOutboundburstfactor(String factor) { + _outboundBurst = (factor != null ? factor.trim() : null); + } + public void setReseedfrom(String url) { + _reseedFrom = (url != null ? url.trim() : null); + } + + private static final String IP_PREFIX = "

Your IP is "; + private static final String IP_SUFFIX = "

"; + private void guessHostname() { + BufferedReader reader = null; + try { + URL url = new URL("http://www.whatismyip.com/"); + URLConnection con = url.openConnection(); + con.connect(); + reader = new BufferedReader(new InputStreamReader(con.getInputStream())); + String line = null; + while ( (line = reader.readLine()) != null) { + if (line.startsWith(IP_PREFIX)) { + int end = line.indexOf(IP_SUFFIX); + if (end == -1) { + addFormError("Unable to guess the host (BAD_SUFFIX)"); + return; + } + String ip = line.substring(IP_PREFIX.length(), end); + addFormNotice("Host guess: " + ip); + return; + } + } + addFormError("Unable to guess the host (NO_PREFIX)"); + } catch (IOException ioe) { + addFormError("Unable to guess the host (IO_ERROR)"); + } finally { + if (reader != null) try { reader.close(); } catch (IOException ioe) {} + } + } + + private static final String DEFAULT_SEED_URL = "http://dev.i2p.net/i2pdb/"; + /** + * Reseed has been requested, so lets go ahead and do it. Fetch all of + * the routerInfo-*.dat files from the specified URL (or the default) and + * save them into this router's netDb dir. + * + */ + private void reseed() { + String seedURL = DEFAULT_SEED_URL; + if (_reseedFrom != null) + seedURL = _reseedFrom; + try { + URL dir = new URL(seedURL); + String content = new String(readURL(dir)); + Set urls = new HashSet(); + int cur = 0; + while (true) { + int start = content.indexOf("href=\"routerInfo-", cur); + if (start < 0) + break; + + int end = content.indexOf(".dat\">", start); + String name = content.substring(start+"href=\"routerInfo-".length(), end); + urls.add(name); + cur = end + 1; + } + + int fetched = 0; + for (Iterator iter = urls.iterator(); iter.hasNext(); ) { + fetchSeed(seedURL, (String)iter.next()); + fetched++; + } + addFormNotice("Reseeded with " + fetched + " peers"); + } catch (Throwable t) { + _context.logManager().getLog(ConfigNetHandler.class).error("Error reseeding", t); + addFormError("Error reseeding (RESEED_EXCEPTION)"); + } + } + + private void fetchSeed(String seedURL, String peer) throws Exception { + URL url = new URL(seedURL + "/routerInfo-" + peer + ".dat"); + + byte data[] = readURL(url); + writeSeed(peer, data); + } + + private byte[] readURL(URL url) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + URLConnection con = url.openConnection(); + InputStream in = con.getInputStream(); + byte buf[] = new byte[1024]; + while (true) { + int read = in.read(buf); + if (read < 0) + break; + baos.write(buf, 0, read); + } + in.close(); + return baos.toByteArray(); + } + + private void writeSeed(String name, byte data[]) throws Exception { + // props taken from KademliaNetworkDatabaseFacade... + String dirName = _context.getProperty("router.networkDatabase.dbDir", "netDb"); + File netDbDir = new File(dirName); + if (!netDbDir.exists()) { + boolean ok = netDbDir.mkdirs(); + if (ok) + addFormNotice("Network database directory created: " + dirName); + else + addFormNotice("Error creating network database directory: " + dirName); + } + FileOutputStream fos = new FileOutputStream(new File(netDbDir, "routerInfo-" + name + ".dat")); + fos.write(data); + fos.close(); + } + + /** + * 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 ( (_hostname != null) && (_hostname.length() > 0) ) { + String oldHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_HOSTNAME); + if ( (oldHost == null) || (!oldHost.equalsIgnoreCase(_hostname)) ) { + _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_HOSTNAME, _hostname); + addFormNotice("Updating hostname from " + oldHost + " to " + _hostname); + restartRequired = true; + } + } + if ( (_port != null) && (_port.length() > 0) ) { + String oldPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT); + if ( (oldPort == null) || (!oldPort.equalsIgnoreCase(_port)) ) { + _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT, _port); + addFormNotice("Updating TCP port from " + oldPort + " to " + _port); + restartRequired = true; + } + } + + updateRates(); + + if (_timeSyncEnabled) { + System.setProperty("timestamper.enabled", "true"); + } else { + System.setProperty("timestamper.enabled", "false"); + } + + boolean saved = _context.router().saveConfig(); + if (saved) + addFormNotice("Configuration saved successfully"); + else + addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs"); + + if (restartRequired) { + addFormNotice("Performing a soft restart"); + _context.router().restart(); + addFormNotice("Soft restart complete"); + } + } + + private void updateRates() { + boolean updated = false; + if ( (_inboundRate != null) && (_inboundRate.length() > 0) ) { + _context.router().setConfigSetting(ConfigNetHelper.PROP_INBOUND_KBPS, _inboundRate); + updated = true; + } + if ( (_outboundRate != null) && (_outboundRate.length() > 0) ) { + _context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_KBPS, _outboundRate); + updated = true; + } + + String inRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_INBOUND_KBPS); + + if (_inboundBurst != null) { + int rateKBps = 0; + int burstSeconds = 0; + try { + rateKBps = Integer.parseInt(inRate); + burstSeconds = Integer.parseInt(_inboundBurst); + } catch (NumberFormatException nfe) { + // ignore + } + if ( (rateKBps > 0) && (burstSeconds > 0) ) { + int kb = rateKBps * burstSeconds; + _context.router().setConfigSetting(ConfigNetHelper.PROP_INBOUND_BURST, "" + kb); + updated = true; + } + } + + String outRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_OUTBOUND_KBPS); + + if (_outboundBurst != null) { + int rateKBps = 0; + int burstSeconds = 0; + try { + rateKBps = Integer.parseInt(outRate); + burstSeconds = Integer.parseInt(_outboundBurst); + } catch (NumberFormatException nfe) { + // ignore + } + if ( (rateKBps > 0) && (burstSeconds > 0) ) { + int kb = rateKBps * burstSeconds; + _context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_BURST, "" + kb); + updated = true; + } + } + + if (updated) + addFormNotice("Updated bandwidth limits"); + } +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java index 9054cbaa9..4af8fc832 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -30,8 +30,8 @@ public class ConfigNetHelper { public ConfigNetHelper() {} /** copied from various private TCP components */ - private final static String PROP_I2NP_TCP_HOSTNAME = "i2np.tcp.hostname"; - private final static String PROP_I2NP_TCP_PORT = "i2np.tcp.port"; + public final static String PROP_I2NP_TCP_HOSTNAME = "i2np.tcp.hostname"; + public final static String PROP_I2NP_TCP_PORT = "i2np.tcp.port"; public String getHostname() { return _context.getProperty(PROP_I2NP_TCP_HOSTNAME); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java new file mode 100644 index 000000000..73b12f4dd --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -0,0 +1,109 @@ +package net.i2p.router.web; + +import java.util.List; +import java.util.ArrayList; + +import net.i2p.util.Log; + +import net.i2p.router.RouterContext; +import net.i2p.router.ClientTunnelSettings; + +/** + * Simple form handler base class - does not depend on servlets or jsp, + * but instead the subclasses are populated with javabean properties. e.g. + * + * + * The form is "processed" after the properties are set and the first output + * property is retrieved - either getNotices() or getErrors(). + * + */ +public class FormHandler { + protected RouterContext _context; + private List _errors; + private List _notices; + private boolean _processed; + + public FormHandler() { + _errors = new ArrayList(); + _notices = new ArrayList(); + _processed = false; + } + + /** + * Configure this bean to query a particular router context + * + * @param contextId begging few characters of the routerHash, or null to pick + * the first one we come across. + */ + public void setContextId(String contextId) { + try { + _context = ContextHelper.getContext(contextId); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + /** + * Override this to perform the final processing (in turn, adding formNotice + * and formError messages, etc) + * + */ + protected void processForm() {} + + /** + * Add an error message to display + */ + protected void addFormError(String errorMsg) { + if (errorMsg == null) return; + _errors.add(errorMsg); + } + + /** + * Add a non-error message to display + */ + protected void addFormNotice(String msg) { + if (msg == null) return; + _notices.add(msg); + } + + /** + * Display any error messages (processing the form if it hasn't + * been yet) + * + */ + public String getErrors() { + return render(_errors); + } + + /** + * Display any non-error messages (processing the form if it hasn't + * been yet) + * + */ + public String getNotices() { + return render(_notices); + } + + private String render(List source) { + if (!_processed) { + processForm(); + _processed = true; + } + if (source.size() <= 0) { + return ""; + } else if (source.size() == 1) { + return (String)source.get(0); + } else { + StringBuffer buf = new StringBuffer(512); + buf.append("\n"); + return buf.toString(); + } + } + +} diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp index a66b99030..83716ebb9 100644 --- a/apps/routerconsole/jsp/config.jsp +++ b/apps/routerconsole/jsp/config.jsp @@ -1,5 +1,4 @@ -<%@page contentType="text/html"%> -<%@page pageEncoding="UTF-8"%> +<%@page contentType="text/html" %> @@ -9,13 +8,19 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %> " />
<%@include file="confignav.jsp" %> + + + + " /> + + +
External hostname/IP address: " /> @@ -29,7 +34,10 @@ to www.whatismyip.com.
Enable internal time synchronization? name="enabletimesync" />
- If disabled, your machine must be NTP synchronized + If disabled, your machine must be NTP synchronized. This option only + takes effect for the current run - if your machine is always synchronized within + (a few seconds), you can update your configuration so that it doesn't start the + "Timestamper" app (which would make this option irrelevent)
Bandwidth limiter
Inbound rate: @@ -44,8 +52,12 @@
Reseed (from ):
+ May take some time to download the peer references
- +
+ Changing the hostname or TCP port will force a 'soft restart' - dropping your connections + and clients as if the router was stopped and restarted. Please be patient - it may take + a few seconds to complete.
diff --git a/apps/routerconsole/jsp/configadvanced.jsp b/apps/routerconsole/jsp/configadvanced.jsp index 033d4f1c2..43743c32c 100644 --- a/apps/routerconsole/jsp/configadvanced.jsp +++ b/apps/routerconsole/jsp/configadvanced.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %> " /> diff --git a/apps/routerconsole/jsp/configclients.jsp b/apps/routerconsole/jsp/configclients.jsp index 34eca7a7e..e1f0db493 100644 --- a/apps/routerconsole/jsp/configclients.jsp +++ b/apps/routerconsole/jsp/configclients.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %> " /> diff --git a/apps/routerconsole/jsp/configlogging.jsp b/apps/routerconsole/jsp/configlogging.jsp index 23bef3e63..0c8fa2055 100644 --- a/apps/routerconsole/jsp/configlogging.jsp +++ b/apps/routerconsole/jsp/configlogging.jsp @@ -11,7 +11,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %>
<%@include file="confignav.jsp" %> diff --git a/apps/routerconsole/jsp/help.jsp b/apps/routerconsole/jsp/help.jsp index cca7e74f8..dc1708090 100644 --- a/apps/routerconsole/jsp/help.jsp +++ b/apps/routerconsole/jsp/help.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %>
hmm. we should probably have some help text here.
diff --git a/apps/routerconsole/jsp/index.jsp b/apps/routerconsole/jsp/index.jsp index ddb83d28e..bf8fbf426 100644 --- a/apps/routerconsole/jsp/index.jsp +++ b/apps/routerconsole/jsp/index.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %>

Welcome to your router console

diff --git a/apps/routerconsole/jsp/logs.jsp b/apps/routerconsole/jsp/logs.jsp index 19a999795..f46f2c7d6 100644 --- a/apps/routerconsole/jsp/logs.jsp +++ b/apps/routerconsole/jsp/logs.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %>
diff --git a/apps/routerconsole/jsp/netdb.jsp b/apps/routerconsole/jsp/netdb.jsp index 86c94fcdc..aac78a4d1 100644 --- a/apps/routerconsole/jsp/netdb.jsp +++ b/apps/routerconsole/jsp/netdb.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %>
diff --git a/apps/routerconsole/jsp/notice.jsp b/apps/routerconsole/jsp/notice.jsp deleted file mode 100644 index f623cde1f..000000000 --- a/apps/routerconsole/jsp/notice.jsp +++ /dev/null @@ -1 +0,0 @@ -<%=(null != request.getParameter("i2p.console.notice") ? request.getParameter("i2p.console.notice") : "")%> \ No newline at end of file diff --git a/apps/routerconsole/jsp/profiles.jsp b/apps/routerconsole/jsp/profiles.jsp index 710e376e2..dd0601454 100644 --- a/apps/routerconsole/jsp/profiles.jsp +++ b/apps/routerconsole/jsp/profiles.jsp @@ -9,7 +9,6 @@ <%@include file="nav.jsp" %> <%@include file="summary.jsp" %> -<%@include file="notice.jsp" %>