* Move StatsGenerator from router to routerconsole

* Move the unused AdminManager from router to the apps directory
This commit is contained in:
zzz
2009-08-09 19:33:15 +00:00
parent a431137f45
commit 1282434684
6 changed files with 1 additions and 10 deletions

View File

@ -0,0 +1,126 @@
package net.i2p.router.admin;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Listen for connections on the specified port, and toss them onto the client manager's
* set of connections once they are established.
*
* @author jrandom
*/
public class AdminListener implements Runnable {
private Log _log;
private RouterContext _context;
private ServerSocket _socket;
private int _port;
private boolean _running;
private long _nextFailDelay = 1000;
public AdminListener(RouterContext context, int port) {
_context = context;
_log = context.logManager().getLog(AdminListener.class);
_port = port;
_running = false;
}
public void restart() {
// this works by taking advantage of the auto-retry mechanism in the
// startup() loop (which we reset to wait 1s). by failing the socket
// (through close()) and nulling it, we will have to try to build a new
// serverSocket (using the *new* _port)
_nextFailDelay = 1000;
ServerSocket s = _socket;
try {
_socket = null;
s.close();
} catch (IOException ioe) {}
}
public void setPort(int port) { _port = port; }
public int getPort() { return _port; }
/** max time to bind */
private final static int MAX_FAIL_DELAY = 5*60*1000;
/**
* Start up the socket listener, listens for connections, and
* fires those connections off via {@link #runConnection runConnection}.
* This only returns if the socket cannot be opened or there is a catastrophic
* failure.
*
*/
public void startup() {
_running = true;
int curDelay = 0;
while ( (_running) && (curDelay < MAX_FAIL_DELAY) ) {
try {
_log.info("Starting up listening for connections on port " + _port);
_socket = new ServerSocket(_port);
curDelay = 0;
while (_running && (_socket != null) ) {
try {
Socket socket = _socket.accept();
_log.debug("Connection received");
runConnection(socket);
} catch (IOException ioe) {
_log.error("Server error accepting", ioe);
} catch (Throwable t) {
_log.error("Fatal error running client listener - killing the thread!", t);
return;
}
}
} catch (IOException ioe) {
_log.error("Error listening on port " + _port, ioe);
}
if (_socket != null) {
try { _socket.close(); } catch (IOException ioe) {}
_socket = null;
}
_log.error("Error listening, waiting " + _nextFailDelay + "ms before we try again");
try { Thread.sleep(_nextFailDelay); } catch (InterruptedException ie) {}
curDelay += _nextFailDelay;
_nextFailDelay *= 5;
}
_log.error("CANCELING ADMIN LISTENER. delay = " + curDelay, new Exception("ADMIN LISTENER cancelled!!!"));
_running = false;
}
/**
* Handle the connection by passing it off to an AdminRunner
*
*/
protected void runConnection(Socket socket) throws IOException {
AdminRunner runner = new AdminRunner(_context, socket);
I2PThread t = new I2PThread(runner);
t.setName("Admin Runner");
//t.setPriority(Thread.MIN_PRIORITY);
t.setDaemon(true);
t.start();
}
public void shutdown() {
_running = false;
if (_socket != null) try {
_socket.close();
_socket = null;
} catch (IOException ioe) {}
}
public void run() { startup(); }
}

View File

@ -0,0 +1,67 @@
package net.i2p.router.admin;
import java.io.Writer;
import net.i2p.router.RouterContext;
import net.i2p.router.Service;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
public class AdminManager implements Service {
private Log _log;
private RouterContext _context;
public final static String PARAM_ADMIN_PORT = "router.adminPort";
public final static int DEFAULT_ADMIN_PORT = 7655;
private AdminListener _listener;
public AdminManager(RouterContext context) {
_context = context;
_log = context.logManager().getLog(AdminManager.class);
}
public void renderStatusHTML(Writer out) { }
public void shutdown() {
if (_listener != null) {
_log.info("Shutting down admin listener");
_listener.shutdown();
_listener = null;
}
}
public void restart() {
startup();
}
public void startup() {
int port = DEFAULT_ADMIN_PORT;
String str = _context.router().getConfigSetting(PARAM_ADMIN_PORT);
if (str != null) {
try {
int val = Integer.parseInt(str);
port = val;
_log.info("Starting up admin listener on port " + port);
} catch (NumberFormatException nfe) {
_log.warn("Invalid admin port specified [" + str + "], using the default " + DEFAULT_ADMIN_PORT, nfe);
}
} else {
_log.warn("Router admin port not specified, using the default " + DEFAULT_ADMIN_PORT);
}
startup(port);
}
private void startup(int port) {
if (_listener == null) {
_listener = new AdminListener(_context, port);
I2PThread t = new I2PThread(_listener);
t.setName("Admin Listener:" + port);
t.setDaemon(true);
//t.setPriority(Thread.MIN_PRIORITY);
t.start();
} else {
_listener.setPort(port);
_listener.restart();
}
}
}

View File

@ -0,0 +1,150 @@
package net.i2p.router.admin;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Iterator;
import java.util.Set;
import net.i2p.data.Hash;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
class AdminRunner implements Runnable {
private Log _log;
private RouterContext _context;
private Socket _socket;
private StatsGenerator _generator;
public AdminRunner(RouterContext context, Socket socket) {
_context = context;
_log = context.logManager().getLog(AdminRunner.class);
_socket = socket;
_generator = new StatsGenerator(context);
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
OutputStream out = _socket.getOutputStream();
String command = in.readLine();
runCommand(command, out);
} catch (IOException ioe) {
_log.error("Error running admin command", ioe);
}
}
private void runCommand(String command, OutputStream out) throws IOException {
_log.debug("Command [" + command + "]");
if (command.indexOf("favicon") >= 0) {
reply(out, "this is not a website");
} else if ( (command.indexOf("routerStats.html") >= 0) || (command.indexOf("oldstats.jsp") >= 0) ) {
try {
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
_generator.generateStatsPage(new OutputStreamWriter(out));
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error writing out the admin reply");
throw ioe;
}
} else if (command.indexOf("/profile/") >= 0) {
replyText(out, getProfile(command));
} else if (command.indexOf("/shutdown") >= 0) {
reply(out, shutdown(command));
} else if (true || command.indexOf("routerConsole.html") > 0) {
try {
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
_context.router().renderStatusHTML(new OutputStreamWriter(out));
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error writing out the admin reply");
throw ioe;
}
}
}
private void reply(OutputStream out, String content) throws IOException {
StringBuilder reply = new StringBuilder(10240);
reply.append("HTTP/1.1 200 OK\n");
reply.append("Connection: close\n");
reply.append("Cache-control: no-cache\n");
reply.append("Content-type: text/html\n\n");
reply.append(content);
try {
out.write(reply.toString().getBytes());
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error writing out the admin reply:\n" + content);
throw ioe;
}
}
private void replyText(OutputStream out, String content) throws IOException {
StringBuilder reply = new StringBuilder(10240);
reply.append("HTTP/1.1 200 OK\n");
reply.append("Connection: close\n");
reply.append("Cache-control: no-cache\n");
reply.append("Content-type: text/plain\n\n");
reply.append(content);
try {
out.write(reply.toString().getBytes());
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error writing out the admin reply:\n" + content);
throw ioe;
}
}
private String getProfile(String cmd) {
Set peers = _context.profileOrganizer().selectAllPeers();
for (Iterator iter = peers.iterator(); iter.hasNext(); ) {
Hash peer = (Hash)iter.next();
if (cmd.indexOf(peer.toBase64().substring(0,10)) >= 0) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(64*1024);
_context.profileOrganizer().exportProfile(peer, baos);
return new String(baos.toByteArray());
} catch (IOException ioe) {
_log.error("Error exporting the profile", ioe);
return "Error exporting the peer profile\n";
}
}
}
return "No such peer is being profiled\n";
}
private static final String SHUTDOWN_PASSWORD_PROP = "router.shutdownPassword";
private String shutdown(String cmd) {
String password = _context.router().getConfigSetting(SHUTDOWN_PASSWORD_PROP);
if (password == null)
password = _context.getProperty(SHUTDOWN_PASSWORD_PROP);
if (password == null)
return "No shutdown password specified in the config or context - <b>REFUSING SHUTDOWN</b>." +
"<a href=\"/routerConsole.html\">back</a>";
if (cmd.indexOf(password) > 0) {
I2PThread t = new I2PThread(new Runnable() {
public void run() {
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
_context.router().shutdown(Router.EXIT_HARD);
}
});
t.start();
return "Shutdown request accepted. Killing the router in 30 seconds";
} else {
return "Incorrect shutdown password specified. Please edit your router.config appropriately." +
"<a href=\"/routerConsole.html\">back</a>";
}
}
}