Rewrote JSONInterface to reflect new features provided by the I2PControl API.
Added new API test to Main, maybe time to extract them to testclass. Refactored JSONInterface to (more) gracefully handle connection issues.
This commit is contained in:
@ -2,12 +2,19 @@ package net.i2p.itoopie.i2pcontrol;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.itoopie.configuration.ConfigurationManager;
|
||||
|
||||
import org.GNOME.Accessibility.CollectionHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@ -25,13 +32,47 @@ public class JSONInterface {
|
||||
private static final int MAX_NBR_RETRIES = 2;
|
||||
private static JSONRPC2Session session;
|
||||
private static String token;
|
||||
|
||||
/*
|
||||
* i2p.router.net.ntcp.port
|
||||
* i2p.router.net.ntcp.hostname
|
||||
* i2p.router.net.ntcp.autoip // true|always|false //disables autodetect|disabled //disables ntcp
|
||||
* i2p.router.net.ssu.port
|
||||
* i2p.router.net.ssu.hostname
|
||||
* i2p.router.net.ssu.detectedip
|
||||
* i2p.router.net.ssu.autoip //[local,upnp,ssu] any of prev., in order |fixed // fixed = no detection
|
||||
* i2p.router.net.upnp //
|
||||
* i2p.router.net.bw.share
|
||||
* i2p.router.net.bw.in
|
||||
* i2p.router.net.bw.out
|
||||
* i2p.router.net.laptopmode
|
||||
*/
|
||||
public interface RemoteSetable{ public boolean isSetable(); }
|
||||
public static enum NETWORK_INFO implements RemoteSetable{
|
||||
DETECTED_IP { public boolean isSetable(){ return false;} public String toString() { return "i2p.router.net.ssu.detectedip"; }},
|
||||
TCP_PORT { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.ntcp.port"; }},
|
||||
TCP_HOSTNAME { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.ntcp.hostname"; }},
|
||||
TCP_AUTOIP { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.ntcp.autoip"; }},
|
||||
UDP_PORT { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.ssu.port"; }},
|
||||
UDP_HOSTNAME { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.ssu.hostname"; }},
|
||||
UDP_AUTO_IP { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.ssu.autoip"; }},
|
||||
UPNP { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.upnp"; }},
|
||||
BW_SHARE { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.bw.share"; }},
|
||||
BW_IN { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.bw.in"; }},
|
||||
BW_OUT { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.bw.out"; }},
|
||||
LAPTOP_MODE { public boolean isSetable(){ return true;} public String toString() { return "i2p.router.net.laptopmode"; }}
|
||||
};
|
||||
private final static HashMap<String,NETWORK_INFO> enumMap;
|
||||
|
||||
static {
|
||||
_log = LogFactory.getLog(JSONInterface.class);
|
||||
_conf = ConfigurationManager.getInstance();
|
||||
Random rnd = new Random();
|
||||
nonce = rnd.nextInt();
|
||||
setupSession();
|
||||
enumMap = new HashMap<String,NETWORK_INFO>();
|
||||
for (NETWORK_INFO n : NETWORK_INFO.values()){
|
||||
enumMap.put(n.toString(), n);
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized int incrNonce() {
|
||||
@ -55,131 +96,204 @@ public class JSONInterface {
|
||||
}
|
||||
|
||||
private static JSONRPC2Response sendReq(JSONRPC2Request req)
|
||||
throws InvalidPasswordException, UnrecoverableFailedRequestException{
|
||||
throws InvalidPasswordException, UnrecoverableFailedRequestException,
|
||||
InvalidParametersException, JSONRPC2SessionException{
|
||||
return sendReq(req, 1);
|
||||
}
|
||||
|
||||
private static JSONRPC2Response sendReq(JSONRPC2Request req, int tryNbr)
|
||||
throws InvalidPasswordException, UnrecoverableFailedRequestException{
|
||||
if (tryNbr <= MAX_NBR_RETRIES){
|
||||
HashMap outParams = (HashMap) req.getParams();
|
||||
outParams.put("token", token); // Add authentication token
|
||||
req.setParams(outParams);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = session.send(req);
|
||||
JSONRPC2Error err = resp.getError();
|
||||
if (err != null) {
|
||||
switch (err.getCode()) {
|
||||
case -32700:
|
||||
// Parse error
|
||||
break;
|
||||
case -32600:
|
||||
// Invalid request
|
||||
break;
|
||||
case -32601:
|
||||
// Method not found
|
||||
break;
|
||||
case -32602:
|
||||
// Invalid params
|
||||
break;
|
||||
case -32603:
|
||||
// Internal error
|
||||
break;
|
||||
|
||||
// Custom errors (as defined by the I2PControl API)
|
||||
case -32001:
|
||||
// Invalid password
|
||||
throw new InvalidPasswordException();
|
||||
// break;
|
||||
case -32002:
|
||||
// No token
|
||||
token = getNewToken();
|
||||
throw new FailedRequestException();
|
||||
// break;
|
||||
case -32003:
|
||||
// Invalid token
|
||||
token = getNewToken();
|
||||
throw new FailedRequestException();
|
||||
//break;
|
||||
case -32004:
|
||||
// Token expired
|
||||
token = getNewToken();
|
||||
throw new FailedRequestException();
|
||||
// break;
|
||||
}
|
||||
throws InvalidPasswordException, UnrecoverableFailedRequestException,
|
||||
InvalidParametersException, JSONRPC2SessionException {
|
||||
if (tryNbr > MAX_NBR_RETRIES){
|
||||
throw new UnrecoverableFailedRequestException(); // Max retries reached. Throw exception.
|
||||
}
|
||||
HashMap outParams = (HashMap) req.getParams();
|
||||
outParams.put("Token", token); // Add authentication token
|
||||
req.setParams(outParams);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = session.send(req);
|
||||
JSONRPC2Error err = resp.getError();
|
||||
if (err != null) {
|
||||
switch (err.getCode()) {
|
||||
case -32700:
|
||||
// Parse error
|
||||
_log.error(err.getMessage());
|
||||
break;
|
||||
case -32600:
|
||||
// Invalid request
|
||||
_log.error(err.getMessage());
|
||||
break;
|
||||
case -32601:
|
||||
// Method not found
|
||||
_log.error(err.getMessage());
|
||||
break;
|
||||
case -32602:
|
||||
// Invalid params
|
||||
_log.error(err.getMessage());
|
||||
throw new InvalidParametersException();
|
||||
//break;
|
||||
case -32603:
|
||||
// Internal error
|
||||
_log.error("Remote host: " + err.getMessage());
|
||||
break;
|
||||
|
||||
// Custom errors (as defined by the I2PControl API)
|
||||
case -32001:
|
||||
// Invalid password
|
||||
_log.info("Provided password was rejected by the remote host");
|
||||
throw new InvalidPasswordException();
|
||||
// break;
|
||||
case -32002:
|
||||
// No token
|
||||
token = getNewToken();
|
||||
throw new FailedRequestException();
|
||||
// break;
|
||||
case -32003:
|
||||
// Invalid token
|
||||
token = getNewToken();
|
||||
throw new FailedRequestException();
|
||||
//break;
|
||||
case -32004:
|
||||
// Token expired
|
||||
token = getNewToken();
|
||||
throw new FailedRequestException();
|
||||
// break;
|
||||
}
|
||||
} catch (JSONRPC2SessionException e) {
|
||||
_log.error(req.toString(), e);
|
||||
} catch (FailedRequestException e) {
|
||||
// Try sending the same request again with a current authentication token.
|
||||
return sendReq(req, ++tryNbr);
|
||||
}
|
||||
return resp;
|
||||
} else {
|
||||
throw new UnrecoverableFailedRequestException(); // Max retries reached. Throw exception.
|
||||
}catch (FailedRequestException e) {
|
||||
return sendReq(req, ++tryNbr);
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized String getNewToken()
|
||||
throws InvalidPasswordException {
|
||||
JSONRPC2Request req = new JSONRPC2Request("authenticate", incrNonce());
|
||||
throws InvalidPasswordException, JSONRPC2SessionException {
|
||||
JSONRPC2Request req = new JSONRPC2Request("Authenticate", incrNonce());
|
||||
|
||||
Map outParams = new HashMap();
|
||||
outParams.put("password",
|
||||
outParams.put("Password",
|
||||
_conf.getConf("server.password", DEFAULT_PASSWORD));
|
||||
req.setParams(outParams);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = sendReq(req);
|
||||
Map inParams = (HashMap) resp.getResult();
|
||||
return (String) inParams.get("Token");
|
||||
}catch (UnrecoverableFailedRequestException e) {
|
||||
return null; // Shouldn't normaly happen.
|
||||
return null; // Shouldn't normally happen.
|
||||
} catch (InvalidParametersException e) {
|
||||
_log.error("getNewToken() invalid parameters used");
|
||||
}
|
||||
Map inParams = (HashMap) resp.getResult();
|
||||
return (String) inParams.get("token");
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Double getRateStat(String stat, long period)
|
||||
throws InvalidPasswordException {
|
||||
throws InvalidPasswordException, JSONRPC2SessionException, InvalidParametersException {
|
||||
|
||||
JSONRPC2Request req = new JSONRPC2Request("getRate", incrNonce());
|
||||
JSONRPC2Request req = new JSONRPC2Request("GetRate", incrNonce());
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map params = new HashMap();
|
||||
params.put("stat", stat);
|
||||
params.put("period", period);
|
||||
params.put("Stat", stat);
|
||||
params.put("Period", period);
|
||||
req.setParams(params);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = sendReq(req);
|
||||
Map inParams = (HashMap) resp.getResult();
|
||||
return (Double) inParams.get("Result");
|
||||
}catch (UnrecoverableFailedRequestException e) {
|
||||
_log.error("getRateStat failed.", e);
|
||||
}
|
||||
|
||||
Map inParams = (HashMap) resp.getResult();
|
||||
return (Double) inParams.get("result");
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String getEcho(String str) throws InvalidPasswordException {
|
||||
public static String getEcho(String str)
|
||||
throws InvalidPasswordException, JSONRPC2SessionException {
|
||||
|
||||
JSONRPC2Request req = new JSONRPC2Request("echo", incrNonce());
|
||||
JSONRPC2Request req = new JSONRPC2Request("Echo", incrNonce());
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map params = new HashMap();
|
||||
params.put("echo", str);
|
||||
params.put("Echo", str);
|
||||
req.setParams(params);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = sendReq(req);
|
||||
Map inParams = (HashMap) resp.getResult();
|
||||
return (String) inParams.get("Result");
|
||||
} catch (UnrecoverableFailedRequestException e) {
|
||||
_log.error("getEcho failed.", e);
|
||||
_log.error("GetEcho failed.", e);
|
||||
} catch (InvalidParametersException e) {
|
||||
_log.error("Remote host rejected provided parameters: " + req.toJSON().toJSONString());
|
||||
}
|
||||
System.out.println("Response: " + resp.toJSON().toJSONString());
|
||||
Map inParams = (HashMap) resp.getResult();
|
||||
return (String) inParams.get("result");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashMap getNetworkInfo(NETWORK_INFO ... options)
|
||||
throws InvalidPasswordException, JSONRPC2SessionException{
|
||||
|
||||
JSONRPC2Request req = new JSONRPC2Request("NetworkSetting", incrNonce());
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map outParams = new HashMap();
|
||||
List<NETWORK_INFO> list = Arrays.asList(options);
|
||||
|
||||
for (NETWORK_INFO i : list){
|
||||
outParams.put(i.toString(), null);
|
||||
}
|
||||
|
||||
req.setParams(outParams);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = sendReq(req);
|
||||
HashMap map = (HashMap) resp.getResult();
|
||||
if (map != null){
|
||||
Set<Entry> set = map.entrySet();
|
||||
HashMap output = new HashMap();
|
||||
for (Entry e: set){
|
||||
output.put(enumMap.get(e.getKey()), e.getValue());
|
||||
}
|
||||
return map;
|
||||
} else {
|
||||
return new HashMap();
|
||||
}
|
||||
} catch (UnrecoverableFailedRequestException e) {
|
||||
_log.error("getNetworkInfo failed.", e);
|
||||
} catch (InvalidParametersException e) {
|
||||
_log.error("Remote host rejected provided parameters: " + req.toJSON().toJSONString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashMap<NETWORK_INFO, Boolean> setNetworkSetting(Map<NETWORK_INFO,String> settings)
|
||||
throws InvalidPasswordException, JSONRPC2SessionException, InvalidParametersException{
|
||||
|
||||
JSONRPC2Request req = new JSONRPC2Request("NetworkSetting", incrNonce());
|
||||
|
||||
Map outParams = new HashMap();
|
||||
|
||||
Set<Entry<NETWORK_INFO,String>> set = settings.entrySet();
|
||||
for (Entry<NETWORK_INFO,String> e : set){
|
||||
if(e.getKey().isSetable()){
|
||||
outParams.put(e.getKey().toString(), e.getValue());
|
||||
}
|
||||
}
|
||||
req.setParams(outParams);
|
||||
|
||||
JSONRPC2Response resp = null;
|
||||
try {
|
||||
resp = sendReq(req);
|
||||
HashMap map = (HashMap) resp.getResult();
|
||||
return map;
|
||||
} catch (UnrecoverableFailedRequestException e) {
|
||||
_log.error("setNetworkInfo failed.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user