Console: Use registered host/port for eepsite link (ticket #1604)

Jetty starter: Register host/port when started
PortMapper: Add hostname support
This commit is contained in:
zzz
2015-06-25 17:00:52 +00:00
parent 25268e7cb2
commit dd47389ad1
6 changed files with 89 additions and 16 deletions

View File

@ -16,6 +16,7 @@ package net.i2p.jetty;
// limitations under the License.
// ========================================================================
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -25,8 +26,10 @@ import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.app.*;
import static net.i2p.app.ClientAppState.*;
import net.i2p.util.PortMapper;
import java.io.InputStream;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
@ -45,13 +48,15 @@ public class JettyStart implements ClientApp {
private final ClientAppManager _mgr;
private final String[] _args;
private final List<LifeCycle> _jettys;
private final I2PAppContext _context;
private volatile ClientAppState _state;
private volatile int _port;
/**
* All args must be XML file names.
* Does not support any of the other argument types from org.mortbay.start.Main.
*
* @param context unused, may be null
* @param context may be null
* @param mgr may be null e.g. for use in plugins
*/
public JettyStart(I2PAppContext context, ClientAppManager mgr, String[] args) throws Exception {
@ -59,6 +64,7 @@ public class JettyStart implements ClientApp {
_mgr = mgr;
_args = args;
_jettys = new ArrayList<LifeCycle>(args.length);
_context = context;
parseArgs(args);
_state = INITIALIZED;
}
@ -116,6 +122,22 @@ public class JettyStart implements ClientApp {
if (!lc.isRunning()) {
try {
lc.start();
if (_context != null && _context.portMapper().getPort(PortMapper.SVC_EEPSITE) <= 0) {
if (lc instanceof Server) {
Server server = (Server) lc;
Connector[] connectors = server.getConnectors();
if (connectors.length > 0) {
int port = connectors[0].getPort();
if (port > 0) {
_port = port;
String host = connectors[0].getHost();
if (host.equals("0.0.0.0") || host.equals("::"))
host = "127.0.0.1";
_context.portMapper().register(PortMapper.SVC_EEPSITE, host, port);
}
}
}
}
} catch (Exception e) {
changeState(START_FAILED, e);
return;
@ -154,6 +176,10 @@ public class JettyStart implements ClientApp {
}
}
}
if (_context != null && _port > 0 && _context.portMapper().getPort(PortMapper.SVC_EEPSITE) == _port) {
_port = 0;
_context.portMapper().unregister(PortMapper.SVC_EEPSITE);
}
changeState(STOPPED);
}
}

View File

@ -167,13 +167,22 @@ public class HomeHelper extends HelperBase {
ctx.router().saveConfig(prop, buf.toString());
}
private static String renderApps(Collection<App> apps) {
private String renderApps(Collection<App> apps) {
String website = _("Website");
StringBuilder buf = new StringBuilder(1024);
buf.append("<div class=\"appgroup\">");
for (App app : apps) {
String url;
if (app.name.equals(website) && app.url.equals("http://127.0.0.1:7658/")) {
// fixup eepsite link
url = "http://" + _context.portMapper().getHost(PortMapper.SVC_EEPSITE, "127.0.0.1") +
':' + _context.portMapper().getPort(PortMapper.SVC_EEPSITE, 7658) + '/';
} else {
url = app.url;
}
buf.append("<div class=\"app\">" +
"<div class=\"appimg\">" +
"<a href=\"").append(app.url).append("\">" +
"<a href=\"").append(url).append("\">" +
"<img class=\"");
// toopie is 54x68, not 16x16, needs special alignment and sizing
if (app.icon.endsWith("/itoopie_sm.png"))
@ -184,7 +193,7 @@ public class HomeHelper extends HelperBase {
"</div>" +
"<table class=\"app\"><tr class=\"app\"><td class=\"app\">" +
"<div class=\"applabel\">" +
"<a href=\"").append(app.url).append("\" title=\"").append(app.desc).append("\">").append(app.name).append("</a>" +
"<a href=\"").append(url).append("\" title=\"").append(app.desc).append("\">").append(app.name).append("</a>" +
"</div>" +
"</td></tr></table>" +
"</div>\n");

View File

@ -11,6 +11,7 @@ import java.util.Map;
import net.i2p.crypto.SigType;
import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.util.PortMapper;
/**
* Refactored from summarynoframe.jsp to save ~100KB
@ -146,7 +147,11 @@ public class SummaryBarRenderer {
.append(nbsp(_("Torrents")))
.append("</a>\n" +
"<a href=\"http://127.0.0.1:7658/\" target=\"_blank\" title=\"")
"<a href=\"http://")
.append(_context.portMapper().getHost(PortMapper.SVC_EEPSITE, "127.0.0.1"))
.append(':')
.append(_context.portMapper().getPort(PortMapper.SVC_EEPSITE, 7658))
.append("/\" target=\"_blank\" title=\"")
.append(_("Local web server"))
.append("\">")
.append(nbsp(_("Website")))

View File

@ -2,6 +2,7 @@ package net.i2p.util;
import java.io.IOException;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -16,7 +17,7 @@ import net.i2p.I2PAppContext;
* @since 0.8.12
*/
public class PortMapper {
private final ConcurrentHashMap<String, Integer> _dir;
private final ConcurrentHashMap<String, InetSocketAddress> _dir;
public static final String SVC_CONSOLE = "console";
public static final String SVC_HTTPS_CONSOLE = "https_console";
@ -37,7 +38,7 @@ public class PortMapper {
* @param context unused for now
*/
public PortMapper(I2PAppContext context) {
_dir = new ConcurrentHashMap<String, Integer>(8);
_dir = new ConcurrentHashMap<String, InetSocketAddress>(8);
}
/**
@ -46,9 +47,19 @@ public class PortMapper {
* @return success, false if already registered
*/
public boolean register(String service, int port) {
if (port <= 0)
return register(service, "127.0.0.1", port);
}
/**
* Add the service
* @param port > 0
* @return success, false if already registered
* @since 0.9.21
*/
public boolean register(String service, String host, int port) {
if (port <= 0 || port > 65535)
return false;
return _dir.putIfAbsent(service, Integer.valueOf(port)) == null;
return _dir.putIfAbsent(service, InetSocketAddress.createUnresolved(host, port)) == null;
}
/**
@ -73,10 +84,24 @@ public class PortMapper {
* @return def if not registered
*/
public int getPort(String service, int def) {
Integer port = _dir.get(service);
if (port == null)
InetSocketAddress ia = _dir.get(service);
if (ia == null)
return def;
return port.intValue();
return ia.getPort();
}
/**
* Get the registered host for a service.
* Will return "127.0.0.1" if the service was registered without a host.
* @param def default
* @return def if not registered
* @since 0.9.21
*/
public String getHost(String service, String def) {
InetSocketAddress ia = _dir.get(service);
if (ia == null)
return def;
return ia.getHostName();
}
/**
@ -85,10 +110,13 @@ public class PortMapper {
*/
public void renderStatusHTML(Writer out) throws IOException {
List<String> services = new ArrayList(_dir.keySet());
out.write("<h2>Port Mapper</h2><table><tr><th>Service<th>Port\n");
out.write("<h2>Port Mapper</h2><table><tr><th>Service<th>Host<th>Port\n");
Collections.sort(services);
for (String s : services) {
out.write("<tr><td>" + s + "<td>" + _dir.get(s) + '\n');
InetSocketAddress ia = _dir.get(s);
if (ia == null)
continue;
out.write("<tr><td>" + s + "<td>" + ia.getHostName() + "<td>" + ia.getPort() + '\n');
}
out.write("</table>\n");
}

View File

@ -1,3 +1,8 @@
2015-06-25 zzz
* Console: Use registered host/port for eepsite link (ticket #1604)
* Jetty starter: Register host/port when started
* PortMapper: Add hostname support
2015-06-24 zzz
* Transport: Add failsafe to prevent complete SSU stall waiting
for bandwidth limiter

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 11;
public final static long BUILD = 12;
/** for example "-test" */
public final static String EXTRA = "";