forked from I2P_Developers/i2p.i2p
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:
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
<target name="war" depends="compile" >
|
<target name="war" depends="compile" >
|
||||||
<war destfile="build/jsonrpc.war" webxml="web.xml" >
|
<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>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
<attribute name="Built-By" value="${build.built-by}" />
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||||||
* all the webapps (not just routerconsole).
|
* all the webapps (not just routerconsole).
|
||||||
* Therefore, this protects all the webapps.
|
* 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
|
* @since 0.12 copied from routerconsole
|
||||||
*/
|
*/
|
||||||
public class HostCheckHandler extends HandlerWrapper
|
public class HostCheckHandler extends HandlerWrapper
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ import java.util.StringTokenizer;
|
|||||||
*
|
*
|
||||||
* Usage: I2PControlController -d $PLUGIN [start|stop]
|
* Usage: I2PControlController -d $PLUGIN [start|stop]
|
||||||
*
|
*
|
||||||
|
* This class is NOT used for the webapp or the bare ServerSocket implementation.
|
||||||
|
*
|
||||||
* @author hottuna
|
* @author hottuna
|
||||||
*/
|
*/
|
||||||
public class I2PControlController implements RouterApp {
|
public class I2PControlController implements RouterApp {
|
||||||
@@ -78,6 +80,7 @@ public class I2PControlController implements RouterApp {
|
|||||||
private static I2PControlController _instance;
|
private static I2PControlController _instance;
|
||||||
static final String PROP_ALLOWED_HOSTS = "i2pcontrol.allowedhosts";
|
static final String PROP_ALLOWED_HOSTS = "i2pcontrol.allowedhosts";
|
||||||
private static final String SVC_HTTPS_I2PCONTROL = "https_i2pcontrol";
|
private static final String SVC_HTTPS_I2PCONTROL = "https_i2pcontrol";
|
||||||
|
private static final int DEFAULT_PORT = 7650;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RouterApp (new way)
|
* RouterApp (new way)
|
||||||
@@ -207,7 +210,7 @@ public class I2PControlController implements RouterApp {
|
|||||||
_server.start();
|
_server.start();
|
||||||
_context.portMapper().register(SVC_HTTPS_I2PCONTROL,
|
_context.portMapper().register(SVC_HTTPS_I2PCONTROL,
|
||||||
_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
|
_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) {
|
private Connector buildDefaultListener(Server server) {
|
||||||
Connector ssl = buildSslListener(server, _conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
|
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;
|
return ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
246
apps/i2pcontrol/java/net/i2p/i2pcontrol/SocketController.java
Normal file
246
apps/i2pcontrol/java/net/i2p/i2pcontrol/SocketController.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -802,6 +802,10 @@ public class RouterConsoleRunner implements RouterApp {
|
|||||||
props.remove(PREFIX + "addressbook" + ENABLED);
|
props.remove(PREFIX + "addressbook" + ENABLED);
|
||||||
rewrite = true;
|
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)) {
|
} else if (! "false".equals(enabled)) {
|
||||||
try {
|
try {
|
||||||
String path = files[i].getCanonicalPath();
|
String path = files[i].getCanonicalPath();
|
||||||
|
|||||||
@@ -228,6 +228,14 @@ class SummaryBarRenderer {
|
|||||||
.append("</a>\n");
|
.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)) {
|
if (pm.isRegistered(PortMapper.SVC_I2PSNARK)) {
|
||||||
buf.append("<a href=\"/torrents\" target=\"_top\" title=\"")
|
buf.append("<a href=\"/torrents\" target=\"_top\" title=\"")
|
||||||
.append(_t("Built-in anonymous BitTorrent Client"))
|
.append(_t("Built-in anonymous BitTorrent Client"))
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ public class PortMapper {
|
|||||||
* @since 0.9.34
|
* @since 0.9.34
|
||||||
*/
|
*/
|
||||||
public static final String SVC_SUSIMAIL = "susimail";
|
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 */
|
/** @since 0.9.34 */
|
||||||
public static final int DEFAULT_CONSOLE_PORT = 7657;
|
public static final int DEFAULT_CONSOLE_PORT = 7657;
|
||||||
|
|||||||
Reference in New Issue
Block a user