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" >
|
||||
<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}" />
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
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);
|
||||
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();
|
||||
|
@ -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"))
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user