I2PControl:

Disable webapp by default
Add link in Services section of sidebar
Add definition in PortMapper
Add stub controller for socket implementation, WIP
Javadocs
This commit is contained in:
zzz
2019-01-28 13:31:54 +00:00
parent 47beb8250e
commit 24fd48815a
7 changed files with 272 additions and 3 deletions

View File

@ -51,7 +51,7 @@
<target name="war" depends="compile" >
<war destfile="build/jsonrpc.war" webxml="web.xml" >
<classes dir="./build/obj" excludes="net/i2p/i2pcontrol/I2PControlController.class net/i2p/i2pcontrol/HostCheckHandler.class" />
<classes dir="./build/obj" excludes="net/i2p/i2pcontrol/I2PControlController.class net/i2p/i2pcontrol/HostCheckHandler.class net/i2p/i2pcontrol/SocketController*.class" />
<manifest>
<attribute name="Implementation-Version" value="${full.version}" />
<attribute name="Built-By" value="${build.built-by}" />

View File

@ -24,6 +24,8 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* all the webapps (not just routerconsole).
* Therefore, this protects all the webapps.
*
* This class is NOT used for the webapp or the bare ServerSocket implementation.
*
* @since 0.12 copied from routerconsole
*/
public class HostCheckHandler extends HandlerWrapper

View File

@ -59,6 +59,8 @@ import java.util.StringTokenizer;
*
* Usage: I2PControlController -d $PLUGIN [start|stop]
*
* This class is NOT used for the webapp or the bare ServerSocket implementation.
*
* @author hottuna
*/
public class I2PControlController implements RouterApp {
@ -78,6 +80,7 @@ public class I2PControlController implements RouterApp {
private static I2PControlController _instance;
static final String PROP_ALLOWED_HOSTS = "i2pcontrol.allowedhosts";
private static final String SVC_HTTPS_I2PCONTROL = "https_i2pcontrol";
private static final int DEFAULT_PORT = 7650;
/**
* RouterApp (new way)
@ -207,7 +210,7 @@ public class I2PControlController implements RouterApp {
_server.start();
_context.portMapper().register(SVC_HTTPS_I2PCONTROL,
_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
_conf.getConf("i2pcontrol.listen.port", 7650));
_conf.getConf("i2pcontrol.listen.port", DEFAULT_PORT));
}
@ -218,7 +221,7 @@ public class I2PControlController implements RouterApp {
*/
private Connector buildDefaultListener(Server server) {
Connector ssl = buildSslListener(server, _conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
_conf.getConf("i2pcontrol.listen.port", 7650));
_conf.getConf("i2pcontrol.listen.port", DEFAULT_PORT));
return ssl;
}

View File

@ -0,0 +1,246 @@
package net.i2p.i2pcontrol;
/*
* Copyright 2010 hottuna (dev@robertfoss.se)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*;
import net.i2p.router.RouterContext;
import net.i2p.router.app.RouterApp;
import net.i2p.util.I2PSSLSocketFactory;
import net.i2p.util.Log;
import net.i2p.util.PortMapper;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import net.i2p.i2pcontrol.security.KeyStoreProvider;
import net.i2p.i2pcontrol.security.SecurityManager;
import net.i2p.i2pcontrol.servlets.JSONRPC2Servlet;
import net.i2p.i2pcontrol.servlets.configuration.ConfigurationManager;
/**
* This handles the starting and stopping of a ServerSocket
* from a single static class so it can be called via clients.config.
*
* This class is NOT used for the webapp or the HTTP/HTTPS implementation.
*
* @author hottuna
*/
public class SocketController implements RouterApp {
// non-null
private final RouterContext _context;
private final ClientAppManager _mgr;
private final Log _log;
private final String _pluginDir;
private final ConfigurationManager _conf;
private final KeyStoreProvider _ksp;
private final SecurityManager _secMan;
private ServerSocket _server;
private final List<Socket> _listeners;
private ClientAppState _state = UNINITIALIZED;
// only for main()
private static SocketController _instance;
static final String PROP_ALLOWED_HOSTS = "i2pcontrol.allowedhosts";
private static final String SVC_SKT_I2PCONTROL = "skt_i2pcontrol";
private static final String SVC_SSL_I2PCONTROL = "skt_ssl_i2pcontrol";
private static final int DEFAULT_PORT = 7640;
/**
* RouterApp (new way)
*/
public SocketController(RouterContext ctx, ClientAppManager mgr, String args[]) throws IOException {
_context = ctx;
_mgr = mgr;
_log = _context.logManager().getLog(SocketController.class);
File pluginDir = new File(_context.getConfigDir(), "keystore/I2PControl");
_pluginDir = pluginDir.getAbsolutePath();
_conf = new ConfigurationManager(_context, pluginDir, true);
_ksp = new KeyStoreProvider(_pluginDir);
_secMan = new SecurityManager(_context, _ksp, _conf);
_listeners = new ArrayList<Socket>(4);
_state = INITIALIZED;
}
/////// ClientApp methods
public synchronized void startup() {
changeState(STARTING);
try {
start(null);
changeState(RUNNING);
} catch (Exception e) {
changeState(START_FAILED, "Failed to start", e);
_log.error("Unable to start socket server", e);
stop();
}
}
public synchronized void shutdown(String[] args) {
if (_state == STOPPED)
return;
changeState(STOPPING);
stop();
changeState(STOPPED);
}
public synchronized ClientAppState getState() {
return _state;
}
public String getName() {
return "I2PControl-Socket";
}
public String getDisplayName() {
return "I2PControl-Socket";
}
/////// end ClientApp methods
private void changeState(ClientAppState state) {
changeState(state, null, null);
}
private synchronized void changeState(ClientAppState state, String msg, Exception e) {
_state = state;
if (_mgr != null)
_mgr.notify(this, state, msg, e);
if (_context == null) {
if (msg != null)
System.out.println(state + ": " + msg);
if (e != null)
e.printStackTrace();
}
}
private synchronized void start(String args[]) throws Exception {
_context.logManager().getLog(JSONRPC2Servlet.class).setMinimumPriority(Log.DEBUG);
_server = buildServer();
_context.portMapper().register(SVC_SKT_I2PCONTROL,
_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
_conf.getConf("i2pcontrol.listen.port", DEFAULT_PORT));
}
/**
* Builds a new server. Used for changing ports during operation and such.
*
* Does NOT start the server. Must call start() on the returned server.
*
* @return Server - A new server built from current configuration.
*/
public ServerSocket buildServer() throws IOException {
String address = _conf.getConf("i2pcontrol.listen.address", "127.0.0.1");
int port = _conf.getConf("i2pcontrol.listen.port", DEFAULT_PORT);
ServerSocket server = new ServerSocket(port, 0, InetAddress.getByName(address));
_conf.writeConfFile();
return server;
}
private class Server implements Runnable {
public void run() {
try {
while (true) {
Socket s = _server.accept();
synchronized (SocketController.this) {
_listeners.add(s);
}
new Handler(s);
}
} catch (IOException ioe) {
_log.error("i2pcontrol server", ioe);
} finally {
synchronized (SocketController.this) {
if (_server != null) {
try { _server.close(); } catch (IOException ioe) {}
}
}
}
}
}
private class Handler implements Runnable {
private final Socket s;
public Handler(Socket skt) { s = skt; }
public void run() {
try {
final BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
final JSONParser parser = new JSONParser();
while (true) {
Object o = parser.parse(reader);
// TODO
System.out.println("i2pcontrol got: " + o);
}
} catch (ParseException pe) {
_log.error("i2pcontrol handler", pe);
return;
} catch (IOException ioe) {
_log.error("i2pcontrol handler", ioe);
return;
} finally {
synchronized (SocketController.this) {
_listeners.remove(s);
}
try { s.close(); } catch (IOException ioe) {}
}
}
}
/**
* Stop it
*/
private synchronized void stopServer()
{
try {
if (_server != null) {
_context.portMapper().unregister(SVC_SKT_I2PCONTROL);
try {
_server.close();
} catch (IOException ioe) {}
for (Socket listener : _listeners) {
try {
listener.close();
} catch (IOException ioe) {}
}
_listeners.clear();
}
} catch (Exception e) {
_log.error("Stopping server", e);
}
}
private synchronized void stop() {
_conf.writeConfFile();
_secMan.stopTimedEvents();
stopServer();
}
}

View File

@ -802,6 +802,10 @@ public class RouterConsoleRunner implements RouterApp {
props.remove(PREFIX + "addressbook" + ENABLED);
rewrite = true;
}
} else if (appName.equals("jsonrpc") && enabled == null) {
// jsonrpc (i2pcontrol) webapp default is false
props.setProperty(PREFIX + "jsonrpc" + ENABLED, "false");
rewrite = true;
} else if (! "false".equals(enabled)) {
try {
String path = files[i].getCanonicalPath();

View File

@ -228,6 +228,14 @@ class SummaryBarRenderer {
.append("</a>\n");
}
if (pm.isRegistered(PortMapper.SVC_JSONRPC)) {
buf.append("<a href=\"/jsonrpc/\" target=\"_top\" title=\"")
.append(_t("RPC Service"))
.append("\">")
.append(nbsp(_t("I2PControl")))
.append("</a>\n");
}
if (pm.isRegistered(PortMapper.SVC_I2PSNARK)) {
buf.append("<a href=\"/torrents\" target=\"_top\" title=\"")
.append(_t("Built-in anonymous BitTorrent Client"))

View File

@ -78,6 +78,12 @@ public class PortMapper {
* @since 0.9.34
*/
public static final String SVC_SUSIMAIL = "susimail";
/**
* To indicate presence, alternative to WebAppStarter.isWebappRunning().
* For actual base URL, use getConsoleURL()
* @since 0.9.39
*/
public static final String SVC_JSONRPC = "jsonrpc";
/** @since 0.9.34 */
public static final int DEFAULT_CONSOLE_PORT = 7657;