diff --git a/build.xml b/build.xml
index 28debc3..78c61f3 100644
--- a/build.xml
+++ b/build.xml
@@ -4,12 +4,12 @@
-
-
-
-
+
+
+
+
-
+
@@ -24,10 +24,7 @@
-
-
-
-
+
@@ -46,14 +43,17 @@
+
+
+
+
-
@@ -84,7 +84,7 @@
-
+
diff --git a/scripts/i2pcontrol.py b/scripts/i2pcontrol.py
new file mode 100755
index 0000000..e279301
--- /dev/null
+++ b/scripts/i2pcontrol.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+
+#
+# If it fails "No module named yaml"
+# then sudo apt install python-yaml
+#
+
+import argparse
+import json
+import urllib2
+import httplib
+import socket
+import ssl
+import sys
+import yaml
+from urllib2 import HTTPError, URLError
+from string import whitespace
+
+# Info about requestable data can be found at https://geti2p.net/i2pcontrol.html & https://geti2p.net/ratestats.html
+
+address = "127.0.0.1" # Default I2PControl Address
+port = 7650 # Default I2PControl Port
+apiPassword = "itoopie" # Default I2PControl password
+
+
+## Do not edit below
+apiVersion = 1 # Default API Version
+msgId = 1
+token = None
+
+def checkToken():
+ global token
+ if (token == None):
+ token = getToken()
+ if (token == None):
+ print("Unable to login. Quitting..")
+ sys.exit()
+
+def getToken():
+ loginStr = "{\"id\":" + str(msgId) + ", \"method\":\"Authenticate\",\"params\":{\"API\":" + str(apiVersion) + ", \"Password\":\"" + apiPassword + "\"}, \"jsonrpc\":\"2.0\"}"
+
+ try:
+ jsonResp = sendMsg(loginStr)
+ return jsonResp.get("result").get("Token")
+
+ except HTTPError, e:
+ print("HTTPError: %s" % e.reason)
+ except URLError, e:
+ print("URLError: %s" % e.reason)
+
+def getRate(rateName, ratePeriod):
+ checkToken()
+ msgStr = "{\"id\":" + str(msgId) + ", \"method\":\"GetRate\",\"params\":{\"Stat\":\"" + rateName + "\", \"Period\":" + str(ratePeriod) + ", \"Token\":\"" + token +"\" }, \"jsonrpc\":\"2.0\"}"
+ jsonResp = sendMsg(msgStr)
+ return jsonResp.get("result").get("Result")
+
+def getRouterInfo(infoName):
+ checkToken()
+ ## The parameter names in 'params' defines which answers are requested
+ msgStr = "{\"id\":" + str(msgId) + ", \"method\":\"RouterInfo\",\"params\":{\""+infoName+"\":\"\", \"Token\":\"" + token +"\" }, \"jsonrpc\":\"2.0\"}"
+ jsonResp = sendMsg(msgStr)
+ return jsonResp.get("result").get(infoName)
+
+def sendMsg(jsonStr):
+ global msgId
+ https_handler = UnauthenticatedHTTPSHandler()
+ url_opener = urllib2.build_opener(https_handler)
+ handle = url_opener.open("https://"+address+":"+ str(port) + "/jsonrpc", jsonStr)
+ response = handle.read()
+ handle.close()
+ msgId = msgId + 1;
+
+ jsonResp = json.loads(response)
+ if (jsonResp.has_key("error")):
+ print ("Remote server: I2PControl Error: " + str(jsonResp.get("error").get("code")) + ", " + jsonResp.get("error").get("message"))
+ sys.exit()
+ return jsonResp
+
+###
+# Overrides the version in httplib so that we can ignore server certificate authenticity
+###
+class UnauthenticatedHTTPSConnection(httplib.HTTPSConnection):
+ def connect(self):
+ #
+ sock = socket.create_connection((self.host, self.port), self.timeout)
+ if self._tunnel_host:
+ self.sock = sock
+ self._tunnel()
+ self.sock = ssl.wrap_socket(sock,
+ cert_reqs=ssl.CERT_NONE)
+
+###
+# HTTPS handler which uses SSLv3 and ignores server cert authenticity
+###
+class UnauthenticatedHTTPSHandler(urllib2.HTTPSHandler):
+ def __init__(self, connection_class = UnauthenticatedHTTPSConnection):
+ self.specialized_conn_class = connection_class
+ urllib2.HTTPSHandler.__init__(self)
+ def https_open(self, req):
+ return self.do_open(self.specialized_conn_class, req)
+
+def zabbix_config(fileName, outfile):
+ yamlDict = dict()
+ for line in open(fileName):
+ li=line.strip()
+ if li.startswith("UserParameter"):
+ i2pCtrlOpt = li.strip("UserParameter=").split(",")
+ i2pCtrlOpt[1] = i2pCtrlOpt[1].split()
+ i2pCtrlOpt[1].pop(0) # Remove path of this script (i2pcontrol)
+ i2pCtrlParams = i2pCtrlOpt[1]
+ #print i2pCtrlOpt #Delete me!
+ result = ""
+ if (i2pCtrlParams[0] == "-i" or i2pCtrlParams[0] == "--router-info"):
+ result = getRouterInfo(i2pCtrlParams[1])
+ elif (i2pCtrlParams[0] == "-s" or i2pCtrlParams[0] == "--rate-stat"):
+ result = getRate(i2pCtrlParams[1], i2pCtrlParams[2])
+ else:
+ result = "Bad query syntax."
+ yamlDict[i2pCtrlParams[1]] = result
+ #print yaml.dump(yamlDict)
+ yaml.dump(yamlDict, open(outfile,'w'))
+
+def from_file(infile, parameter):
+ try:
+ yamlDict = yaml.load(open(infile,'r'))
+ print yamlDict[parameter]
+ except IOError, e:
+ print "File \""+ infile +"\" couldn't be read."
+def main():
+ parser = argparse.ArgumentParser(description='Fetch I2P info via the I2PControl API.')
+ parser.add_argument("-i",
+ "--router-info",
+ nargs=1,
+ metavar="router-info-id",
+ dest="router_info",
+ action="store",
+ help="Request info such as I2P version and uptime. Returned info can be of any type. Full list of options at https://geti2p.net/i2pcontrol.html. Usage: \"-i i2p.router.version\"")
+
+ parser.add_argument("-s",
+ "--rate-stat",
+ nargs=2,
+ metavar=("rateStatName", "period"),
+ dest="rate_stat",
+ action="store",
+ help="Request info such as bandwidth, number active peers, clock skew, etc.. The period is measured in ms and must be longer than 60s. Full list at https://geti2p.net/ratestats.html. Usage: \"-s bw.receiveBps 3600000\"")
+
+ parser.add_argument("-z",
+ "--zabbix",
+ nargs=2,
+ metavar=("\"path to zabbix_agent.conf\"", "\"path to output file\""),
+ dest="zabbix",
+ action="store",
+ help="Parse options to request, by reading a zabbix config file for \"UserParameter\"s relating to I2P. Usage: \"-z /etc/zabbix/zabbix_agent.conf\"")
+
+ parser.add_argument("-f",
+ "--from-file",
+ nargs=1,
+ metavar=("\"path to input file\""),
+ dest="from_file",
+ action="store",
+ help="Parse options to request, by reading a zabbix config file for \"UserParameter\"s relating to I2P. Usage: \"-z /etc/zabbix/zabbix_agent.conf\"")
+
+ if (len(sys.argv) == 1):
+ parser.parse_args(["-h"])
+ options = parser.parse_args()
+
+ if ((options.rate_stat != None) and (options.router_info != None)):
+ print("Error: Choose _one_ option. \n\n")
+ parser.parse_args(["-h"])
+
+ if ((options.zabbix != None) and ((options.rate_stat != None) or (options.router_info != None) or (options.from_file != None))):
+ print("Error: Don't combine option --zabbix with other options.\n")
+ parser.parse_args(["-h"])
+
+ # From-file can only be used when either router-info or rate-stat is enabled.
+ if ((options.from_file != None) and (options.rate_stat == None) and (options.router_info == None)):
+ print("Error: --from-file must be used with either --router-info or --rate-stat.\n")
+ parser.parse_args(["-h"])
+
+ if (options.from_file != None):
+ if (options.router_info != None):
+ from_file(options.from_file[0], options.router_info[0])
+ if (options.rate_stat != None):
+ from_file(options.from_file[0], options.rate_stat[0])
+ sys.exit()
+
+ if (options.rate_stat != None):
+ try:
+ period = int(options.rate_stat[1])
+ if (period < 60000):
+ raise ValueError
+ print getRate(options.rate_stat[0], period)
+ except ValueError, e:
+ print("Error: \""+options.rate_stat[1]+"\" is not an integer > 60000 \n\n")
+ parser.parse_args(["-h"])
+ sys.exit()
+
+ if (options.router_info != None):
+ print getRouterInfo(options.router_info[0])
+ sys.exit()
+
+ if (options.zabbix != None):
+ zabbix_config(options.zabbix[0], options.zabbix[1])
+ sys.exit()
+
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/makeplugin.sh b/scripts/makeplugin.sh
index 97686fd..8611e2c 100755
--- a/scripts/makeplugin.sh
+++ b/scripts/makeplugin.sh
@@ -7,6 +7,18 @@
# zzz 2010-02
# zzz 2014-08 added support for su3 files
#
+
+if [ -z "$I2P" -a -d "$PWD/../i2p/pkg-temp" ]; then
+ export I2P=$PWD/../i2p/pkg-temp
+fi
+
+if [ ! -d "$I2P" ]; then
+ echo "Can't locate your I2P installation. Please add a environment variable named I2P with the path to the folder as value"
+ echo "On OSX this solved with running: export I2P=/Applications/i2p if default install directory is used."
+ exit 1
+fi
+
+CPATH=$I2P/lib/i2p.jar:/usr/share/java/gnu-getopt.jar
PUBKEYDIR=$HOME/.i2p-plugin-keys
PUBKEYFILE=$PUBKEYDIR/plugin-public-signing.key
PRIVKEYFILE=$PUBKEYDIR/plugin-private-signing.key
@@ -15,60 +27,59 @@ PUBKEYSTORE=$PUBKEYDIR/plugin-su3-public-signing.crt
PRIVKEYSTORE=$PUBKEYDIR/plugin-su3-keystore.ks
KEYTYPE=RSA_SHA512_4096
-export I2P=../i2p.i2p/pkg-temp
-
+# put your files in here
PLUGINDIR=${1:-plugin}
PC=plugin.config
PCT=${PC}.tmp
-if [ ! -d $PLUGINDIR ]
+if [ ! -d "$PLUGINDIR" ]
then
echo "You must have a $PLUGINDIR directory"
exit 1
fi
-if [ ! -f $PLUGINDIR/$PC ]
+if [ ! -f "$PLUGINDIR/$PC" ]
then
echo "You must have a $PLUGINDIR/$PC file"
exit 1
fi
-SIGNER=`grep '^signer=' $PLUGINDIR/$PC`
+SIGNER=`grep '^signer=' "$PLUGINDIR/$PC"`
if [ "$?" -ne "0" ]
then
- echo "You must have a plugin name in $PC"
+ echo "You must have a signer name in $PC"
echo 'For example name=foo'
exit 1
fi
SIGNER=`echo $SIGNER | cut -f 2 -d '='`
-if [ ! -f $PRIVKEYFILE ]
+if [ ! -f "$PRIVKEYFILE" ]
then
echo "Creating new XPI2P DSA keys"
- mkdir -p $PUBKEYDIR || exit 1
- java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate keygen $PUBKEYFILE $PRIVKEYFILE || exit 1
- java -cp $I2P/lib/i2p.jar net.i2p.data.Base64 encode $PUBKEYFILE $B64KEYFILE || exit 1
+ mkdir -p "$PUBKEYDIR" || exit 1
+ java -cp "$CPATH" net.i2p.crypto.TrustedUpdate keygen "$PUBKEYFILE" "$PRIVKEYFILE" || exit 1
+ java -cp "$CPATH" net.i2p.data.Base64 encode "$PUBKEYFILE" "$B64KEYFILE" || exit 1
rm -rf logs/
- chmod 444 $PUBKEYFILE $B64KEYFILE
- chmod 400 $PRIVKEYFILE
+ chmod 444 "$PUBKEYFILE" "$B64KEYFILE"
+ chmod 400 "$PRIVKEYFILE"
echo "Created new XPI2P keys: $PUBKEYFILE $PRIVKEYFILE"
fi
-if [ ! -f $PRIVKEYSTORE ]
+if [ ! -f "$PRIVKEYSTORE" ]
then
echo "Creating new SU3 $KEYTYPE keys for $SIGNER"
- java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File keygen -t $KEYTYPE $PUBKEYSTORE $PRIVKEYSTORE $SIGNER || exit 1
+ java -cp "$CPATH" net.i2p.crypto.SU3File keygen -t $KEYTYPE "$PUBKEYSTORE" "$PRIVKEYSTORE" $SIGNER || exit 1
echo '*** Save your password in a safe place!!! ***'
rm -rf logs/
# copy to the router dir so verify will work
CDIR=$I2P/certificates/plugin
- mkdir -p $CDIR || exit 1
+ mkdir -p "$CDIR" || exit 1
CFILE=$CDIR/`echo $SIGNER | sed s/@/_at_/`.crt
- cp $PUBKEYSTORE $CFILE
- chmod 444 $PUBKEYSTORE
- chmod 400 $PRIVKEYSTORE
- chmod 644 $CFILE
+ cp "$PUBKEYSTORE" "$CFILE"
+ chmod 444 "$PUBKEYSTORE"
+ chmod 400 "$PRIVKEYSTORE"
+ chmod 644 "$CFILE"
echo "Created new SU3 keys: $PUBKEYSTORE $PRIVKEYSTORE"
echo "Copied public key to $CFILE for testing"
fi
@@ -76,7 +87,7 @@ fi
rm -f plugin.zip
OPWD=$PWD
-cd $PLUGINDIR
+cd "$PLUGINDIR"
grep -q '^name=' $PC
if [ "$?" -ne "0" ]
@@ -97,17 +108,17 @@ fi
# update the date
grep -v '^date=' $PC > $PCT
DATE=`date '+%s000'`
-echo "date=$DATE" >> $PCT
+echo "date=$DATE" >> $PCT || exit 1
mv $PCT $PC || exit 1
# add our Base64 key
grep -v '^key=' $PC > $PCT
-B64KEY=`cat $B64KEYFILE`
+B64KEY=`cat "$B64KEYFILE"`
echo "key=$B64KEY" >> $PCT || exit 1
mv $PCT $PC || exit 1
# zip it
-zip -r $OPWD/plugin.zip * || exit 1
+zip -r "$OPWD/plugin.zip" * || exit 1
# get the version and use it for the sud header
VERSION=`grep '^version=' $PC | cut -f 2 -d '='`
@@ -115,24 +126,24 @@ VERSION=`grep '^version=' $PC | cut -f 2 -d '='`
NAME=`grep '^name=' $PC | cut -f 2 -d '='`
XPI2P=${NAME}.xpi2p
SU3=${NAME}.su3
-cd $OPWD
+cd "$OPWD"
# sign it
echo 'Signing. ...'
-java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate sign plugin.zip $XPI2P $PRIVKEYFILE $VERSION || exit 1
-java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip $SU3 $PRIVKEYSTORE $VERSION $SIGNER || exit 1
+java -cp "$CPATH" net.i2p.crypto.TrustedUpdate sign plugin.zip "$XPI2P" "$PRIVKEYFILE" "$VERSION" || exit 1
+java -cp "$CPATH" net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip "$SU3" "$PRIVKEYSTORE" "$VERSION" "$SIGNER" || exit 1
rm -f plugin.zip
# verify
echo 'Verifying. ...'
-java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate showversion $XPI2P || exit 1
-java -cp $I2P/lib/i2p.jar -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig $XPI2P || exit 1
-java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File showversion $SU3 || exit 1
-java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File verifysig -k $PUBKEYSTORE $SU3 || exit 1
+java -cp "$CPATH" net.i2p.crypto.TrustedUpdate showversion "$XPI2P" || exit 1
+java -cp "$CPATH" -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig "$XPI2P" || exit 1
+java -cp "$CPATH" net.i2p.crypto.SU3File showversion "$SU3" || exit 1
+java -cp "$CPATH" net.i2p.crypto.SU3File verifysig -k "$PUBKEYSTORE" "$SU3" || exit 1
rm -rf logs/
echo 'Plugin files created: '
-wc -c $XPI2P
-wc -c $SU3
+wc -c "$XPI2P"
+wc -c "$SU3"
exit 0
diff --git a/scripts/plugin.config b/scripts/plugin.config
index 4372afb..f3d369e 100644
--- a/scripts/plugin.config
+++ b/scripts/plugin.config
@@ -1,11 +1,11 @@
name=I2PControl
-signer=dev@robertfoss.se
+signer=zzz-plugin@mail.i2p
consoleLinkName=I2PControl
description=Remote Control Service
author=hottuna
-websiteURL=http://itoopie.i2p/
-updateURL=http://itoopie.i2p/files/I2PControl-update.xpi2p
+websiteURL=http://zzz.i2p/forums/16
+updateURL=http://zzz.i2p/i2p/plugins/I2PControl-update.xpi2p
+updateURL.su3=http://zzz.i2p/i2p/plugins/I2PControl-update.su3
license=Apache 2.0
-min-jetty-version=7
-max-jetty-version=8.9999
-min-i2p-version=0.9.20
+min-jetty-version=9
+min-i2p-version=0.9.30
diff --git a/src/build.xml b/src/build.xml
index 93e4591..bfee176 100644
--- a/src/build.xml
+++ b/src/build.xml
@@ -3,24 +3,15 @@
-
+
-
-
-
-
-
-
-
-
-
@@ -41,7 +32,7 @@
destdir="./build/obj"
classpath="${cp}">
-
+
diff --git a/src/java/com/thetransactioncompany/jsonrpc2/JSONRPC2ParseException.java b/src/java/com/thetransactioncompany/jsonrpc2/JSONRPC2ParseException.java
index 434ee20..ba07e44 100644
--- a/src/java/com/thetransactioncompany/jsonrpc2/JSONRPC2ParseException.java
+++ b/src/java/com/thetransactioncompany/jsonrpc2/JSONRPC2ParseException.java
@@ -18,13 +18,13 @@ public class JSONRPC2ParseException extends Exception {
* Indicates a parse exception caused by a JSON message not conforming
* to the JSON-RPC 2.0 protocol.
*/
- public static int PROTOCOL = 0;
+ public static final int PROTOCOL = 0;
/**
* Indicates a parse exception caused by invalid JSON.
*/
- public static int JSON = 1;
+ public static final int JSON = 1;
/**
diff --git a/src/java/net/i2p/i2pcontrol/I2PControlController.java b/src/java/net/i2p/i2pcontrol/I2PControlController.java
index 0eb2cae..a3395e3 100644
--- a/src/java/net/i2p/i2pcontrol/I2PControlController.java
+++ b/src/java/net/i2p/i2pcontrol/I2PControlController.java
@@ -17,16 +17,29 @@ package net.i2p.i2pcontrol;
*/
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.i2pcontrol.security.KeyStoreProvider;
import net.i2p.i2pcontrol.security.SecurityManager;
import net.i2p.i2pcontrol.servlets.JSONRPC2Servlet;
import net.i2p.i2pcontrol.servlets.configuration.ConfigurationManager;
-import net.i2p.util.Log;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ssl.SslSocketConnector;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
import java.io.File;
import java.io.IOException;
@@ -45,14 +58,109 @@ import java.security.KeyStore;
*
* @author hottuna
*/
-public class I2PControlController {
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlController.class);
- private static String _pluginDir = "";
- private static ConfigurationManager _conf;
- private static SecurityManager _secMan;
- private static Server _server;
+public class I2PControlController implements RouterApp {
+ // non-null
+ private final I2PAppContext _appContext;
+ // warning, null in app context
+ 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 final Server _server;
+ private ClientAppState _state = UNINITIALIZED;
+ // only for main()
+ private static I2PControlController _instance;
+
+ public I2PControlController(RouterContext ctx, ClientAppManager mgr, String args[]) {
+ _appContext = _context = ctx;
+ _mgr = mgr;
+ _log = _appContext.logManager().getLog(I2PControlController.class);
+ File pluginDir = new File(_context.getAppDir(), "plugins/I2PControl");
+ _pluginDir = pluginDir.getAbsolutePath();
+ _conf = new ConfigurationManager(_pluginDir);
+ _ksp = new KeyStoreProvider(_pluginDir);
+ _secMan = new SecurityManager(_ksp, _conf);
+ _server = buildServer();
+ _state = INITIALIZED;
+ }
+
+ /**
+ * From main()
+ */
+ public I2PControlController(File pluginDir) {
+ _appContext = I2PAppContext.getGlobalContext();
+ if (_appContext instanceof RouterContext)
+ _context = (RouterContext) _appContext;
+ else
+ _context = null;
+ _mgr = null;
+ _log = _appContext.logManager().getLog(I2PControlController.class);
+ _pluginDir = pluginDir.getAbsolutePath();
+ _conf = new ConfigurationManager(_pluginDir);
+ _ksp = new KeyStoreProvider(_pluginDir);
+ _secMan = new SecurityManager(_ksp, _conf);
+ _server = buildServer();
+ _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 jetty server", e);
+ }
+ }
+
+ 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";
+ }
+
+ public String getDisplayName() {
+ return "I2PControl";
+ }
+
+ /////// 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();
+ }
+ }
+ /**
+ * Deprecated, use constructor
+ */
public static void main(String args[]) {
if (args.length != 3 || (!"-d".equals(args[0])))
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
@@ -61,37 +169,33 @@ public class I2PControlController {
File pluginDir = new File(args[1]);
if (!pluginDir.exists())
throw new IllegalArgumentException("Plugin directory " + pluginDir.getAbsolutePath() + " does not exist");
- _pluginDir = pluginDir.getAbsolutePath();
- ConfigurationManager.setConfDir(pluginDir.getAbsolutePath());
- _conf = ConfigurationManager.getInstance();
- _secMan = SecurityManager.getInstance();
- start(args);
- //stop(); // Delete Me
-
- } else if ("stop".equals(args[2]))
- stop();
- else
+ synchronized(I2PControlController.class) {
+ if (_instance != null)
+ throw new IllegalStateException();
+ I2PControlController i2pcc = new I2PControlController(pluginDir);
+ try {
+ i2pcc.startup();
+ _instance = i2pcc;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ } else if ("stop".equals(args[2])) {
+ synchronized(I2PControlController.class) {
+ if (_instance != null) {
+ _instance.shutdown(null);
+ _instance = null;
+ }
+ }
+ } else {
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
+ }
}
- private static void start(String args[]) {
- I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class).setMinimumPriority(Log.DEBUG);
-
- try {
- Connector ssl = buildDefaultListenter();
- _server = buildServer(ssl);
- } catch (IOException e) {
- _log.error("Unable to add listener " + _conf.getConf("i2pcontrol.listen.address", "127.0.0.1") + ":" + _conf.getConf("i2pcontrol.listen.port", 7560) + " - " + e.getMessage());
- } catch (ClassNotFoundException e) {
- _log.error("Unable to find class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
- } catch (InstantiationException e) {
- _log.error("Unable to instantiate class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
- } catch (IllegalAccessException e) {
- _log.error("Illegal access: " + e.getMessage());
- } catch (Exception e) {
- _log.error("Unable to start jetty server: " + e.getMessage());
- }
+ private synchronized void start(String args[]) throws Exception {
+ _appContext.logManager().getLog(JSONRPC2Servlet.class).setMinimumPriority(Log.DEBUG);
+ _server.start();
}
@@ -99,10 +203,9 @@ public class I2PControlController {
/**
* Builds a new server. Used for changing ports during operation and such.
* @return Server - A new server built from current configuration.
- * @throws UnknownHostException
*/
- public static Connector buildDefaultListenter() throws UnknownHostException {
- SslSocketConnector ssl = buildSslListener(_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
+ private Connector buildDefaultListener(Server server) {
+ Connector ssl = buildSslListener(server, _conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
_conf.getConf("i2pcontrol.listen.port", 7650));
return ssl;
}
@@ -110,20 +213,19 @@ public class I2PControlController {
/**
* 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.
- * @throws UnknownHostException
- * @throws Exception
- * @throws InstantiationException
- * @throws IllegalAccessException
*/
- public static Server buildServer(Connector ssl) throws UnknownHostException, Exception, InstantiationException, IllegalAccessException {
+ public Server buildServer() {
Server server = new Server();
+ Connector ssl = buildDefaultListener(server);
server.addConnector(ssl);
ServletHandler sh = new ServletHandler();
- sh.addServletWithMapping(net.i2p.i2pcontrol.servlets.JSONRPC2Servlet.class, "/");
+ sh.addServletWithMapping(new ServletHolder(new JSONRPC2Servlet(_context, _secMan)), "/");
server.getServer().setHandler(sh);
- server.start();
return server;
}
@@ -134,24 +236,38 @@ public class I2PControlController {
* @param address - The address the listener will listen to.
* @param port - The port the listener will listen to.
* @return - Newly created listener
- * @throws UnknownHostException
*/
- public static SslSocketConnector buildSslListener(String address, int port) throws UnknownHostException {
+ private Connector buildSslListener(Server server, String address, int port) {
int listeners = 0;
- if (_server != null) {
- listeners = _server.getConnectors().length;
+ if (server != null) {
+ listeners = server.getConnectors().length;
}
- SslSocketConnector ssl = new SslSocketConnector();
- ssl.setProvider(_secMan.getSecurityProvider());
- //ssl.setCipherSuites(_secMan.getSupprtedSSLCipherSuites()); Removed in Jetty 5->6 port.
+ // the keystore path and password
+ SslContextFactory sslFactory = new SslContextFactory(_ksp.getKeyStoreLocation());
+ sslFactory.setKeyStorePassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
+ // the X.509 cert password (if not present, verifyKeyStore() returned false)
+ sslFactory.setKeyManagerPassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
+ sslFactory.addExcludeProtocols(I2PSSLSocketFactory.EXCLUDE_PROTOCOLS.toArray(
+ new String[I2PSSLSocketFactory.EXCLUDE_PROTOCOLS.size()]));
+ sslFactory.addExcludeCipherSuites(I2PSSLSocketFactory.EXCLUDE_CIPHERS.toArray(
+ new String[I2PSSLSocketFactory.EXCLUDE_CIPHERS.size()]));
+
+ HttpConfiguration httpConfig = new HttpConfiguration();
+ httpConfig.setSecureScheme("https");
+ httpConfig.setSecurePort(port);
+ httpConfig.addCustomizer(new SecureRequestCustomizer());
+ // number of acceptors, (default) number of selectors
+ ServerConnector ssl = new ServerConnector(server, 1, 0,
+ new SslConnectionFactory(sslFactory, "http/1.1"),
+ new HttpConnectionFactory(httpConfig));
ssl.setHost(address);
ssl.setPort(port);
- ssl.setWantClientAuth(false); // Don't care about client authentication.
- ssl.setPassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
- ssl.setKeyPassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
- ssl.setKeystoreType(KeyStore.getDefaultType());
- ssl.setKeystore(KeyStoreProvider.getKeyStoreLocation());
+ ssl.setIdleTimeout(90*1000); // default 10 sec
+ // all with same name will use the same thread pool
+ //ssll.setName("ConsoleSocket");
+ ssl.setName("I2PControl");
+
ssl.setName("SSL Listener-" + ++listeners);
return ssl;
@@ -166,36 +282,45 @@ public class I2PControlController {
* @param listener
* @throws Exception
*/
- public static void replaceListener(Connector listener) throws Exception {
+/****
+ public synchronized void replaceListener(Connector listener) throws Exception {
if (_server != null) {
stopServer();
}
_server = buildServer(listener);
}
+****/
/**
* Get all listeners of the server.
* @return
*/
- public static Connector[] getListeners() {
+/****
+ public synchronized Connector[] getListeners() {
if (_server != null) {
return _server.getConnectors();
}
return new Connector[0];
}
+****/
/**
* Removes all listeners
*/
- public static void clearListeners() {
+/****
+ public synchronized void clearListeners() {
if (_server != null) {
for (Connector listen : getListeners()) {
_server.removeConnector(listen);
}
}
}
+****/
- private static void stopServer()
+ /**
+ * Stop it
+ */
+ private synchronized void stopServer()
{
try {
if (_server != null) {
@@ -204,21 +329,18 @@ public class I2PControlController {
listener.stop();
}
_server.destroy();
- _server = null;
}
} catch (Exception e) {
- _log.error("Stopping server" + e);
+ _log.error("Stopping server", e);
}
}
- private static void stop() {
- ConfigurationManager.writeConfFile();
- if (_secMan != null) {
- _secMan.stopTimedEvents();
- }
-
+ private synchronized void stop() {
+ _conf.writeConfFile();
+ _secMan.stopTimedEvents();
stopServer();
+/****
// Get and stop all running threads
ThreadGroup threadgroup = Thread.currentThread().getThreadGroup();
Thread[] threads = new Thread[threadgroup.activeCount() + 3];
@@ -237,9 +359,10 @@ public class I2PControlController {
threadgroup.interrupt();
//Thread.currentThread().getThreadGroup().destroy();
+****/
}
- public static String getPluginDir() {
+ public String getPluginDir() {
return _pluginDir;
}
}
diff --git a/src/java/net/i2p/i2pcontrol/router/RouterManager.java b/src/java/net/i2p/i2pcontrol/router/RouterManager.java
deleted file mode 100644
index 8219306..0000000
--- a/src/java/net/i2p/i2pcontrol/router/RouterManager.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package net.i2p.i2pcontrol.router;
-
-
-import net.i2p.I2PAppContext;
-import net.i2p.router.RouterContext;
-import net.i2p.util.Log;
-
-/**
- * Handle communications with the router instance.
- * @author mathias
- *
- */
-public class RouterManager {
- private final static Log _log = new Log(RouterManager.class);
- private static I2PAppContext context = I2PAppContext.getCurrentContext();
- private static boolean startedTestRouter = false;
- private final static String I2P_DIR = "/home/hottuna/Apps/i2p/";
- private final static String I2P_CONFIG_FILE = "/home/hottuna/.i2p/router.config";
-
-
- public static I2PAppContext getAppContext() {
- return context;
- }
-
- public static RouterContext getRouterContext() throws Exception {
- // If not running as a plugin from within I2P.
- if (context.isRouterContext()) {
- return (RouterContext) context;
- } else {
- throw new Exception("No RouterContext available!");
- }
- }
-}
diff --git a/src/java/net/i2p/i2pcontrol/security/AuthToken.java b/src/java/net/i2p/i2pcontrol/security/AuthToken.java
index 5eb5680..e17468a 100644
--- a/src/java/net/i2p/i2pcontrol/security/AuthToken.java
+++ b/src/java/net/i2p/i2pcontrol/security/AuthToken.java
@@ -11,8 +11,8 @@ public class AuthToken {
private String id;
private Date expiry;
- public AuthToken(String password) {
- _secMan = SecurityManager.getInstance();
+ public AuthToken(SecurityManager secMan, String password) {
+ _secMan = secMan;
String hash = _secMan.getPasswdHash(password);
this.id = _secMan.getHash(hash + Calendar.getInstance().getTimeInMillis());
Calendar expiry = Calendar.getInstance();
diff --git a/src/java/net/i2p/i2pcontrol/security/KeyStoreProvider.java b/src/java/net/i2p/i2pcontrol/security/KeyStoreProvider.java
index eaa037e..c77aac7 100644
--- a/src/java/net/i2p/i2pcontrol/security/KeyStoreProvider.java
+++ b/src/java/net/i2p/i2pcontrol/security/KeyStoreProvider.java
@@ -1,9 +1,13 @@
package net.i2p.i2pcontrol.security;
import net.i2p.crypto.KeyStoreUtil;
-import net.i2p.i2pcontrol.I2PControlController;
-import java.io.*;
-import java.security.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@@ -15,10 +19,14 @@ public class KeyStoreProvider {
public final static String DEFAULT_CERTIFICATE_ALIAS = "I2PControl CA";
public static final String DEFAULT_KEYSTORE_NAME = "key.store";
public static final String DEFAULT_KEYSTORE_PASSWORD = "nut'nfancy";
- private static KeyStore _keystore = null;
+ private final String _pluginDir;
+ private KeyStore _keystore;
+ public KeyStoreProvider(String pluginDir) {
+ _pluginDir = pluginDir;
+ }
- public static void initialize() {
+ public void initialize() {
KeyStoreUtil.createKeys(new File(getKeyStoreLocation()),
DEFAULT_KEYSTORE_PASSWORD,
DEFAULT_CERTIFICATE_ALIAS,
@@ -30,6 +38,10 @@ public class KeyStoreProvider {
DEFAULT_KEYSTORE_PASSWORD);
}
+ /**
+ * @param password unused
+ * @return null on failure
+ */
public static X509Certificate readCert(KeyStore ks, String certAlias, String password) {
try {
X509Certificate cert = (X509Certificate) ks.getCertificate(certAlias);
@@ -51,6 +63,11 @@ public class KeyStoreProvider {
return null;
}
+ /**
+ * @param password for the keystore
+ * @return null on failure
+ */
+/****
public static X509Certificate readCert(File keyStoreFile, String certAlias, String password) {
try {
KeyStore ks = getDefaultKeyStore();
@@ -81,7 +98,13 @@ public class KeyStoreProvider {
}
return null;
}
+****/
+ /**
+ * @param password for the key
+ * @return null on failure, or throws RuntimeException...
+ */
+/****
public static PrivateKey readPrivateKey(KeyStore ks, String alias, String password) {
try {
// load the key entry from the keystore
@@ -102,7 +125,12 @@ public class KeyStoreProvider {
}
return null;
}
+****/
+ /**
+ * @return null on failure
+ */
+/****
public static PrivateKey readPrivateKey(String alias, File keyStoreFile, String keyStorePassword, String keyPassword) {
try {
KeyStore ks = getDefaultKeyStore();
@@ -120,7 +148,12 @@ public class KeyStoreProvider {
}
return null;
}
+****/
+ /**
+ * @return null on failure
+ */
+/****
public static KeyStore writeCACertToKeyStore(KeyStore keyStore, String keyPassword, String alias, PrivateKey caPrivKey, X509Certificate caCert) {
try {
X509Certificate[] chain = new X509Certificate[1];
@@ -143,8 +176,12 @@ public class KeyStoreProvider {
}
return null;
}
+****/
- public static synchronized KeyStore getDefaultKeyStore() {
+ /**
+ * @return null on failure
+ */
+ public synchronized KeyStore getDefaultKeyStore() {
if (_keystore == null) {
File keyStoreFile = new File(getKeyStoreLocation());
@@ -157,7 +194,6 @@ public class KeyStoreProvider {
}
initialize();
- _keystore = KeyStore.getInstance(KeyStore.getDefaultType());
if (keyStoreFile.exists()) {
InputStream is = new FileInputStream(keyStoreFile);
_keystore.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
@@ -174,8 +210,8 @@ public class KeyStoreProvider {
}
}
- public static String getKeyStoreLocation() {
- File keyStoreFile = new File(I2PControlController.getPluginDir() + File.separator + DEFAULT_KEYSTORE_NAME);
+ public String getKeyStoreLocation() {
+ File keyStoreFile = new File(_pluginDir, DEFAULT_KEYSTORE_NAME);
return keyStoreFile.getAbsolutePath();
}
}
diff --git a/src/java/net/i2p/i2pcontrol/security/SecurityManager.java b/src/java/net/i2p/i2pcontrol/security/SecurityManager.java
index d73a579..02aa489 100644
--- a/src/java/net/i2p/i2pcontrol/security/SecurityManager.java
+++ b/src/java/net/i2p/i2pcontrol/security/SecurityManager.java
@@ -35,24 +35,16 @@ import java.util.*;
* Manage the password storing for I2PControl.
*/
public class SecurityManager {
- private final static String SSL_PROVIDER = "SunJSSE";
private final static String DEFAULT_AUTH_BCRYPT_SALT = "$2a$11$5aOLx2x/8i4fNaitoCSSWu";
private final static String DEFAULT_AUTH_PASSWORD = "$2a$11$5aOLx2x/8i4fNaitoCSSWuut2wEl3Hupuca8DCT.NXzvH9fq1pBU.";
- private HashMap authTokens;
- private Timer timer;
- private String[] SSL_CIPHER_SUITES;
- private KeyStore _ks;
- private Log _log;
- private static SecurityManager _securityManager;
+ private final HashMap authTokens;
+ private final Timer timer;
+ private final KeyStore _ks;
+ private final Log _log;
+ private final ConfigurationManager _conf;
- public static SecurityManager getInstance() {
- if (_securityManager == null) {
- _securityManager = new SecurityManager();
- }
- return _securityManager;
- }
-
- private SecurityManager() {
+ public SecurityManager(KeyStoreProvider ksp, ConfigurationManager conf) {
+ _conf = conf;
_log = I2PAppContext.getGlobalContext().logManager().getLog(SecurityManager.class);
authTokens = new HashMap();
@@ -60,23 +52,7 @@ public class SecurityManager {
// Start running periodic task after 20 minutes, run periodically every 10th minute.
timer.scheduleAtFixedRate(new Sweeper(), 1000 * 60 * 20, 1000 * 60 * 10);
- // Get supported SSL cipher suites.
- SocketFactory SSLF = SSLSocketFactory.getDefault();
- try {
- SSL_CIPHER_SUITES = ((SSLSocket)SSLF.createSocket()).getSupportedCipherSuites();
- } catch (Exception e) {
- _log.log(Log.CRIT, "Unable to create SSLSocket used for fetching supported ssl cipher suites.", e);
- }
-
- _ks = KeyStoreProvider.getDefaultKeyStore();
- }
-
- public String[] getSupprtedSSLCipherSuites() {
- return SSL_CIPHER_SUITES;
- }
-
- public String getSecurityProvider() {
- return SSL_PROVIDER;
+ _ks = ksp.getDefaultKeyStore();
}
public void stopTimedEvents() {
@@ -116,7 +92,7 @@ public class SecurityManager {
* @return BCrypt hash of salt and input string
*/
public String getPasswdHash(String pwd) {
- return BCrypt.hashpw(pwd, ConfigurationManager.getInstance().getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
+ return BCrypt.hashpw(pwd, _conf.getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
}
/**
@@ -138,9 +114,9 @@ public class SecurityManager {
* @return Returns AuthToken if password is valid. If password is invalid null will be returned.
*/
public AuthToken validatePasswd(String pwd) {
- String storedPass = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
+ String storedPass = _conf.getConf("auth.password", DEFAULT_AUTH_PASSWORD);
if (getPasswdHash(pwd).equals(storedPass)) {
- AuthToken token = new AuthToken(pwd);
+ AuthToken token = new AuthToken(this, pwd);
synchronized (authTokens) {
authTokens.put(token.getId(), token);
}
@@ -157,10 +133,10 @@ public class SecurityManager {
*/
public boolean setPasswd(String newPasswd) {
String newHash = getPasswdHash(newPasswd);
- String oldHash = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
+ String oldHash = _conf.getConf("auth.password", DEFAULT_AUTH_PASSWORD);
if (!newHash.equals(oldHash)) {
- ConfigurationManager.getInstance().setConf("auth.password", newHash);
+ _conf.setConf("auth.password", newHash);
synchronized (authTokens) {
authTokens.clear();
}
diff --git a/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java b/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java
index 229d49f..b9cc570 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/JSONRPC2Servlet.java
@@ -18,17 +18,27 @@ package net.i2p.i2pcontrol.servlets;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.Dispatcher;
+
import net.i2p.I2PAppContext;
+import net.i2p.router.RouterContext;
+import net.i2p.util.Log;
+
import net.i2p.i2pcontrol.I2PControlVersion;
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.*;
-import net.i2p.util.Log;
+import net.i2p.i2pcontrol.security.SecurityManager;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.io.*;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
/**
@@ -38,25 +48,33 @@ public class JSONRPC2Servlet extends HttpServlet {
private static final long serialVersionUID = -45075606818515212L;
private static final int BUFFER_LENGTH = 2048;
- private static Dispatcher disp;
- private static char[] readBuffer;
- private static Log _log;
+ private Dispatcher disp;
+ private Log _log;
+ private final SecurityManager _secMan;
+ private final JSONRPC2Helper _helper;
+ private final RouterContext _context;
+ public JSONRPC2Servlet(RouterContext ctx, SecurityManager secMan) {
+ _context = ctx;
+ _secMan = secMan;
+ _helper = new JSONRPC2Helper(_secMan);
+ if (ctx != null)
+ _log = ctx.logManager().getLog(JSONRPC2Servlet.class);
+ else
+ _log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class);
+ }
@Override
public void init() {
- _log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class);
- readBuffer = new char[BUFFER_LENGTH];
-
disp = new Dispatcher();
- disp.register(new EchoHandler());
- disp.register(new GetRateHandler());
- disp.register(new AuthenticateHandler());
- disp.register(new NetworkSettingHandler());
- disp.register(new RouterInfoHandler());
- disp.register(new RouterManagerHandler());
- disp.register(new I2PControlHandler());
- disp.register(new AdvancedSettingsHandler());
+ disp.register(new EchoHandler(_helper));
+ disp.register(new GetRateHandler(_helper));
+ disp.register(new AuthenticateHandler(_helper, _secMan));
+ disp.register(new NetworkSettingHandler(_context, _helper));
+ disp.register(new RouterInfoHandler(_context, _helper));
+ disp.register(new RouterManagerHandler(_context, _helper));
+ disp.register(new I2PControlHandler(_context, _helper));
+ disp.register(new AdvancedSettingsHandler(_context, _helper));
}
@Override
@@ -80,12 +98,15 @@ public class JSONRPC2Servlet extends HttpServlet {
if (msg instanceof JSONRPC2Request) {
jsonResp = disp.dispatch((JSONRPC2Request)msg, null);
jsonResp.toJSON().put("API", I2PControlVersion.API_VERSION);
- _log.debug("Request: " + msg);
- _log.debug("Response: " + jsonResp);
+ if (_log.shouldDebug()) {
+ _log.debug("Request: " + msg);
+ _log.debug("Response: " + jsonResp);
+ }
}
else if (msg instanceof JSONRPC2Notification) {
disp.dispatch((JSONRPC2Notification)msg, null);
- _log.debug("Notification: " + msg);
+ if (_log.shouldDebug())
+ _log.debug("Notification: " + msg);
}
out.println(jsonResp);
@@ -99,6 +120,7 @@ public class JSONRPC2Servlet extends HttpServlet {
Writer writer = new StringWriter();
BufferedReader reader = new BufferedReader(new InputStreamReader(sis, "UTF-8"));
+ char[] readBuffer = new char[BUFFER_LENGTH];
int n;
while ((n = reader.read(readBuffer)) != -1) {
writer.write(readBuffer, 0, n);
diff --git a/src/java/net/i2p/i2pcontrol/servlets/configuration/ConfigurationManager.java b/src/java/net/i2p/i2pcontrol/servlets/configuration/ConfigurationManager.java
index 0002401..2a62533 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/configuration/ConfigurationManager.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/configuration/ConfigurationManager.java
@@ -2,8 +2,15 @@ package net.i2p.i2pcontrol.servlets.configuration;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
+import net.i2p.util.SecureFileOutputStream;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -16,44 +23,30 @@ import java.util.TreeMap;
*
*/
public class ConfigurationManager {
- private static String configLocation = "I2PControl.conf";
- private static boolean configLocationModified = false;
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ConfigurationManager.class);
+ private final String CONFIG_FILE = "I2PControl.conf";
+ private final String configLocation;
+ private final Log _log;
- private static ConfigurationManager instance;
+ private ConfigurationManager instance;
//Configurations with a String as value
- private static Map stringConfigurations = new HashMap();
+ private final Map stringConfigurations = new HashMap();
//Configurations with a Boolean as value
- private static Map booleanConfigurations = new HashMap();
+ private final Map booleanConfigurations = new HashMap();
//Configurations with an Integer as value
- private static Map integerConfigurations = new HashMap();
+ private final Map integerConfigurations = new HashMap();
- /**
- * Should only be set before getInstance is first called.
- * @param dir
- */
- public static void setConfDir(String dir) {
- if (!configLocationModified) {
- if (dir.endsWith("/")) {
- configLocation = dir + configLocation;
- } else {
- configLocation = dir + "/" + configLocation;
- }
+
+ public ConfigurationManager(String dir) {
+ _log = I2PAppContext.getGlobalContext().logManager().getLog(ConfigurationManager.class);
+ if (dir.endsWith("/")) {
+ configLocation = dir + CONFIG_FILE;
+ } else {
+ configLocation = dir + "/" + CONFIG_FILE;
}
- }
-
- private ConfigurationManager() {
readConfFile();
}
- public synchronized static ConfigurationManager getInstance() {
- if (instance == null) {
- instance = new ConfigurationManager();
- }
- return instance;
- }
-
/**
* Collects settingNameuments of the form --word, --word=otherword and -blah
* to determine user parameters.
@@ -71,7 +64,7 @@ public class ConfigurationManager {
/**
* Reads configuration from file itoopie.conf, every line is parsed as key=value.
*/
- public static void readConfFile() {
+ public void readConfFile() {
try {
BufferedReader br = new BufferedReader(new FileReader(configLocation));
String input;
@@ -89,7 +82,7 @@ public class ConfigurationManager {
/**
* Write configuration into default config file.
*/
- public static void writeConfFile() {
+ public void writeConfFile() {
TreeMap tree = new TreeMap();
for (Entry e : stringConfigurations.entrySet()) {
tree.put(e.getKey(), e.getValue());
@@ -101,7 +94,7 @@ public class ConfigurationManager {
tree.put(e.getKey(), e.getValue().toString());
}
try {
- BufferedWriter bw = new BufferedWriter(new FileWriter(configLocation));
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(configLocation)));
for (Entry e : tree.entrySet()) {
bw.write(e.getKey() + "=" + e.getValue() + "\r\n");
}
@@ -116,7 +109,7 @@ public class ConfigurationManager {
* where value will (in order) be parsed as integer/boolean/string.
* @param str
*/
- public static void parseConfigStr(String str) {
+ public void parseConfigStr(String str) {
int eqIndex = str.indexOf('=');
if (eqIndex != -1) {
String key = str.substring(0, eqIndex).trim().toLowerCase();
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AdvancedSettingsHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AdvancedSettingsHandler.java
index 9f26ae7..f6607e3 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AdvancedSettingsHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AdvancedSettingsHandler.java
@@ -7,7 +7,6 @@ import com.thetransactioncompany.jsonrpc2.server.MessageContext;
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
import net.i2p.I2PAppContext;
-import net.i2p.i2pcontrol.router.RouterManager;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
@@ -18,18 +17,20 @@ import java.util.Set;
public class AdvancedSettingsHandler implements RequestHandler {
- private static RouterContext _context;
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(AdvancedSettingsHandler.class);
+ private final RouterContext _context;
+ private final Log _log;
+ private final JSONRPC2Helper _helper;
+ private static final String[] requiredArgs = {};
- static {
- try {
- _context = RouterManager.getRouterContext();
- } catch (Exception e) {
- _log.error("Unable to initialize RouterContext.", e);
- }
+ public AdvancedSettingsHandler(RouterContext ctx, JSONRPC2Helper helper) {
+ _helper = helper;
+ _context = ctx;
+ if (ctx != null)
+ _log = ctx.logManager().getLog(AdvancedSettingsHandler.class);
+ else
+ _log = I2PAppContext.getGlobalContext().logManager().getLog(AdvancedSettingsHandler.class);
}
- private String[] requiredArgs = {};
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[] {"AdvancedSettings"};
@@ -39,11 +40,18 @@ public class AdvancedSettingsHandler implements RequestHandler {
@SuppressWarnings("unchecked")
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("AdvancedSettings")) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
+ JSONRPC2Error err = _helper.validateParams(requiredArgs, req);
if (err != null) {
return new JSONRPC2Response(err, req.getID());
}
+ if (_context == null) {
+ return new JSONRPC2Response(new JSONRPC2Error(
+ JSONRPC2Error.INTERNAL_ERROR.getCode(),
+ "RouterContext was not initialized. Query failed"),
+ req.getID());
+ }
+
@SuppressWarnings("rawtypes")
HashMap inParams = (HashMap) req.getParams();
Map outParams = new HashMap();
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AuthenticateHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AuthenticateHandler.java
index 0e41907..cbc2e6b 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AuthenticateHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/AuthenticateHandler.java
@@ -31,7 +31,15 @@ import java.util.Map;
public class AuthenticateHandler implements RequestHandler {
- private String[] requiredArgs = {"Password", "API"};
+ private static final String[] requiredArgs = {"Password", "API"};
+ private final JSONRPC2Helper _helper;
+ private final SecurityManager _secMan;
+
+ public AuthenticateHandler(JSONRPC2Helper helper, SecurityManager secMan) {
+ _helper = helper;
+ _secMan = secMan;
+ }
+
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[] {"Authenticate"};
@@ -40,7 +48,7 @@ public class AuthenticateHandler implements RequestHandler {
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("Authenticate")) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req, JSONRPC2Helper.USE_NO_AUTH);
+ JSONRPC2Error err = _helper.validateParams(requiredArgs, req, JSONRPC2Helper.USE_NO_AUTH);
if (err != null)
return new JSONRPC2Response(err, req.getID());
@@ -50,7 +58,7 @@ public class AuthenticateHandler implements RequestHandler {
// Try get an AuthToken
- AuthToken token = SecurityManager.getInstance().validatePasswd(pwd);
+ AuthToken token = _secMan.validatePasswd(pwd);
if (token == null) {
return new JSONRPC2Response(JSONRPC2ExtendedError.INVALID_PASSWORD, req.getID());
}
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/EchoHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/EchoHandler.java
index e37dbac..f816ab4 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/EchoHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/EchoHandler.java
@@ -11,7 +11,13 @@ import java.util.Map;
public class EchoHandler implements RequestHandler {
- private String[] requiredArgs = {"Echo"};
+ private static final String[] requiredArgs = {"Echo"};
+ private final JSONRPC2Helper _helper;
+
+ public EchoHandler(JSONRPC2Helper helper) {
+ _helper = helper;
+ }
+
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[] {"Echo"};
@@ -20,7 +26,7 @@ public class EchoHandler implements RequestHandler {
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("Echo")) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
+ JSONRPC2Error err = _helper.validateParams(requiredArgs, req);
if (err != null)
return new JSONRPC2Response(err, req.getID());
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/GetRateHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/GetRateHandler.java
index fc83705..fdf8bdf 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/GetRateHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/GetRateHandler.java
@@ -31,7 +31,13 @@ import java.util.Map;
public class GetRateHandler implements RequestHandler {
- private String[] requiredArgs = {"Stat", "Period"};
+ private static final String[] requiredArgs = {"Stat", "Period"};
+ private final JSONRPC2Helper _helper;
+
+ public GetRateHandler(JSONRPC2Helper helper) {
+ _helper = helper;
+ }
+
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[] {"GetRate"};
@@ -40,7 +46,7 @@ public class GetRateHandler implements RequestHandler {
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("GetRate")) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
+ JSONRPC2Error err = _helper.validateParams(requiredArgs, req);
if (err != null)
return new JSONRPC2Response(err, req.getID());
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java
index be2ee7f..6eddf1a 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/I2PControlHandler.java
@@ -5,14 +5,13 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
import com.thetransactioncompany.jsonrpc2.server.MessageContext;
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
+
import net.i2p.I2PAppContext;
import net.i2p.i2pcontrol.I2PControlController;
-import net.i2p.i2pcontrol.router.RouterManager;
import net.i2p.i2pcontrol.security.SecurityManager;
import net.i2p.i2pcontrol.servlets.configuration.ConfigurationManager;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
-import org.eclipse.jetty.server.ssl.SslSocketConnector;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -37,20 +36,24 @@ import java.util.Map;
*/
public class I2PControlHandler implements RequestHandler {
+
private static final int BW_BURST_PCT = 110;
private static final int BW_BURST_TIME = 20;
- private static RouterContext _context;
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlHandler.class);
- private static final ConfigurationManager _conf = ConfigurationManager.getInstance();
+ private final RouterContext _context;
+ private final Log _log;
+ //private final ConfigurationManager _conf;
+ private final JSONRPC2Helper _helper;
- static {
- try {
- _context = RouterManager.getRouterContext();
- } catch (Exception e) {
- _log.error("Unable to initialize RouterContext.", e);
- }
+ public I2PControlHandler(RouterContext ctx, JSONRPC2Helper helper) {
+ _helper = helper;
+ _context = ctx;
+ if (ctx != null)
+ _log = ctx.logManager().getLog(I2PControlHandler.class);
+ else
+ _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlHandler.class);
}
+
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[] {"I2PControl"};
@@ -59,7 +62,8 @@ public class I2PControlHandler implements RequestHandler {
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("I2PControl")) {
- return process(req);
+ //return process(req);
+ return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
} else {
// Method name not supported
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
@@ -67,8 +71,9 @@ public class I2PControlHandler implements RequestHandler {
}
+/****
private JSONRPC2Response process(JSONRPC2Request req) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
+ JSONRPC2Error err = _helper.validateParams(null, req);
if (err != null)
return new JSONRPC2Response(err, req.getID());
@@ -191,4 +196,5 @@ public class I2PControlHandler implements RequestHandler {
outParams.put("RestartNeeded", restartNeeded);
return new JSONRPC2Response(outParams, req.getID());
}
+****/
}
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/JSONRPC2Helper.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/JSONRPC2Helper.java
index 044c777..ade177e 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/JSONRPC2Helper.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/JSONRPC2Helper.java
@@ -30,6 +30,12 @@ public class JSONRPC2Helper {
public final static Boolean USE_NO_AUTH = false;
public final static Boolean USE_AUTH = true;
+ private final SecurityManager _secMan;
+
+ public JSONRPC2Helper(SecurityManager secMan) {
+ _secMan = secMan;
+ }
+
/**
* Check incoming request for required arguments, to make sure they are valid.
* @param requiredArgs - Array of names of required arguments. If null don't check for any parameters.
@@ -37,7 +43,7 @@ public class JSONRPC2Helper {
* @param useAuth - If true, will validate authentication token.
* @return - null if no errors were found. Corresponding JSONRPC2Error if error is found.
*/
- public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req, Boolean useAuth) {
+ public JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req, Boolean useAuth) {
// Error on unnamed parameters
if (req.getParamsType() != JSONRPC2ParamsType.OBJECT) {
@@ -75,7 +81,7 @@ public class JSONRPC2Helper {
* @param req - Incoming JSONRPC2 request
* @return - null if no errors were found. Corresponding JSONRPC2Error if error is found.
*/
- public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req) {
+ public JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req) {
return validateParams(requiredArgs, req, JSONRPC2Helper.USE_AUTH);
}
@@ -86,13 +92,13 @@ public class JSONRPC2Helper {
* @param req - Parameters of incoming request
* @return null if everything is fine, JSONRPC2Error for any corresponding error.
*/
- private static JSONRPC2Error validateToken(HashMap params) {
+ private JSONRPC2Error validateToken(HashMap params) {
String tokenID = (String) params.get("Token");
if (tokenID == null) {
return JSONRPC2ExtendedError.NO_TOKEN;
}
try {
- SecurityManager.getInstance().verifyToken(tokenID);
+ _secMan.verifyToken(tokenID);
} catch (InvalidAuthTokenException e) {
return JSONRPC2ExtendedError.INVALID_TOKEN;
} catch (ExpiredAuthTokenException e) {
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/NetworkSettingHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/NetworkSettingHandler.java
index 389d12c..80cd6e9 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/NetworkSettingHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/NetworkSettingHandler.java
@@ -7,7 +7,6 @@ import com.thetransactioncompany.jsonrpc2.server.MessageContext;
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
import net.i2p.I2PAppContext;
-import net.i2p.i2pcontrol.router.RouterManager;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.transport.FIFOBandwidthRefiller;
@@ -41,15 +40,12 @@ import java.util.Map;
public class NetworkSettingHandler implements RequestHandler {
private static final int BW_BURST_PCT = 110;
private static final int BW_BURST_TIME = 20;
- private static RouterContext _context;
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(NetworkSettingHandler.class);
+ private final JSONRPC2Helper _helper;
+ private final RouterContext _context;
- static {
- try {
- _context = RouterManager.getRouterContext();
- } catch (Exception e) {
- _log.error("Unable to initialize RouterContext.", e);
- }
+ public NetworkSettingHandler(RouterContext ctx, JSONRPC2Helper helper) {
+ _helper = helper;
+ _context = ctx;
}
// Reports the method names of the handled requests
@@ -69,7 +65,7 @@ public class NetworkSettingHandler implements RequestHandler {
private JSONRPC2Response process(JSONRPC2Request req) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
+ JSONRPC2Error err = _helper.validateParams(null, req);
if (err != null)
return new JSONRPC2Response(err, req.getID());
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterInfoHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterInfoHandler.java
index 5b5d1d6..94251cf 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterInfoHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterInfoHandler.java
@@ -5,9 +5,9 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
import com.thetransactioncompany.jsonrpc2.server.MessageContext;
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
+
import net.i2p.I2PAppContext;
import net.i2p.data.router.RouterAddress;
-import net.i2p.i2pcontrol.router.RouterManager;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
@@ -15,7 +15,6 @@ import net.i2p.router.RouterVersion;
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.router.transport.TransportUtil;
import net.i2p.router.transport.ntcp.NTCPTransport;
-import net.i2p.util.Log;
import java.util.HashMap;
import java.util.Map;
@@ -38,17 +37,15 @@ import java.util.Map;
*/
public class RouterInfoHandler implements RequestHandler {
- private static RouterContext _context;
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(RouterInfoHandler.class);
+ private final JSONRPC2Helper _helper;
+ private final RouterContext _context;
- static {
- try {
- _context = RouterManager.getRouterContext();
- } catch (Exception e) {
- _log.error("Unable to initialize RouterContext.", e);
- }
+ public RouterInfoHandler(RouterContext ctx, JSONRPC2Helper helper) {
+ _helper = helper;
+ _context = ctx;
}
+
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[] { "RouterInfo" };
@@ -67,7 +64,7 @@ public class RouterInfoHandler implements RequestHandler {
@SuppressWarnings("unchecked")
private JSONRPC2Response process(JSONRPC2Request req) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
+ JSONRPC2Error err = _helper.validateParams(null, req);
if (err != null)
return new JSONRPC2Response(err, req.getID());
diff --git a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterManagerHandler.java b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterManagerHandler.java
index 384fc1c..2a2dd89 100644
--- a/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterManagerHandler.java
+++ b/src/java/net/i2p/i2pcontrol/servlets/jsonrpc2handlers/RouterManagerHandler.java
@@ -5,6 +5,7 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
import com.thetransactioncompany.jsonrpc2.server.MessageContext;
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
+
import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.i2pcontrol.router.RouterManager;
@@ -14,6 +15,7 @@ import net.i2p.router.networkdb.reseed.ReseedChecker;
import net.i2p.update.UpdateManager;
import net.i2p.update.UpdateType;
import net.i2p.util.Log;
+
import org.tanukisoftware.wrapper.WrapperManager;
import java.util.HashMap;
@@ -37,17 +39,15 @@ import java.util.Map;
*/
public class RouterManagerHandler implements RequestHandler {
- private static RouterContext _context;
- private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(RouterManagerHandler.class);
+ private final JSONRPC2Helper _helper;
+ private final RouterContext _context;
private final static int SHUTDOWN_WAIT = 1500;
- static {
- try {
- _context = RouterManager.getRouterContext();
- } catch (Exception e) {
- _log.error("Unable to initialize RouterContext.", e);
- }
+
+ public RouterManagerHandler(RouterContext ctx, JSONRPC2Helper helper) {
+ _helper = helper;
+ _context = ctx;
}
// Reports the method names of the handled requests
@@ -67,7 +67,7 @@ public class RouterManagerHandler implements RequestHandler {
}
private JSONRPC2Response process(JSONRPC2Request req) {
- JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
+ JSONRPC2Error err = _helper.validateParams(null, req);
if (err != null)
return new JSONRPC2Response(err, req.getID());