forked from I2P_Developers/i2p.i2p
Includes mods to use org.json.simple package. See licenses/LICENSE-Apache2.0.txt Includes jBCrypt: Copyright (c) 2006 Damien Miller <djm@mindrot.org> See licenses/LICENSE-jBCrypt.txt Includes jsonrpc2 libs: See licenses/LICENSE-Apache2.0.txt http://software.dzhuvinov.com/json-rpc-2.0-server.html Jars from maven central: jsonrpc2-base-1.38.1-sources.jar 22-Oct-2017 jsonrpc2-server-1.11-sources.jar 16-Mar-2015
214 lines
9.0 KiB
Java
214 lines
9.0 KiB
Java
package net.i2p.i2pcontrol.servlets.jsonrpc2handlers;
|
|
|
|
import com.thetransactioncompany.jsonrpc2.JSONRPC2Error;
|
|
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.router.CommSystemFacade;
|
|
import net.i2p.router.Router;
|
|
import net.i2p.router.RouterContext;
|
|
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 java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/*
|
|
* Copyright 2011 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.
|
|
*
|
|
*/
|
|
|
|
public class RouterInfoHandler implements RequestHandler {
|
|
private final JSONRPC2Helper _helper;
|
|
private final RouterContext _context;
|
|
|
|
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" };
|
|
}
|
|
|
|
// Processes the requests
|
|
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
|
if (req.getMethod().equals("RouterInfo")) {
|
|
return process(req);
|
|
} else {
|
|
// Method name not supported
|
|
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND,
|
|
req.getID());
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private JSONRPC2Response process(JSONRPC2Request req) {
|
|
JSONRPC2Error err = _helper.validateParams(null, 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());
|
|
}
|
|
Map<String, Object> inParams = req.getNamedParams();
|
|
Map outParams = new HashMap();
|
|
|
|
if (inParams.containsKey("i2p.router.version")) {
|
|
try {
|
|
Class rvClass = Class.forName("net.i2p.router.RouterVersion");
|
|
java.lang.reflect.Field field = rvClass.getDeclaredField("FULL_VERSION");
|
|
String fullVersion = (String) field.get(new RouterVersion());
|
|
outParams.put("i2p.router.version", fullVersion);
|
|
} catch (Exception e) {} // Ignore
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.uptime")) {
|
|
Router router = _context.router();
|
|
if (router == null) {
|
|
outParams.put("i2p.router.uptime", 0);
|
|
} else {
|
|
outParams.put("i2p.router.uptime", router.getUptime());
|
|
}
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.status")) {
|
|
outParams.put("i2p.router.status", _context.throttle().getTunnelStatus());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.net.status")) {
|
|
outParams.put("i2p.router.net.status", getNetworkStatus().ordinal());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.net.bw.inbound.1s")) {
|
|
outParams.put("i2p.router.net.bw.inbound.1s", _context.bandwidthLimiter().getReceiveBps());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.net.bw.outbound.1s")) {
|
|
outParams.put("i2p.router.net.bw.outbound.1s", _context.bandwidthLimiter().getSendBps());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.net.bw.inbound.15s")) {
|
|
outParams.put("i2p.router.net.bw.inbound.15s", _context.bandwidthLimiter().getReceiveBps15s());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.net.bw.outbound.15s")) {
|
|
outParams.put("i2p.router.net.bw.outbound.15s", _context.bandwidthLimiter().getSendBps15s());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.net.tunnels.participating")) {
|
|
outParams.put("i2p.router.net.tunnels.participating", _context.tunnelManager().getParticipatingCount());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.netdb.knownpeers")) {
|
|
// Why max(-1, 0) is used I don't know, it is the implementation used in the router console.
|
|
outParams.put("i2p.router.netdb.knownpeers", Math.max(_context.netDb().getKnownRouters() - 1, 0));
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.netdb.activepeers")) {
|
|
outParams.put("i2p.router.netdb.activepeers", _context.commSystem().countActivePeers());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.netdb.fastpeers")) {
|
|
outParams.put("i2p.router.netdb.fastpeers", _context.profileOrganizer().countFastPeers());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.netdb.highcapacitypeers")) {
|
|
outParams.put("i2p.router.netdb.highcapacitypeers", _context.profileOrganizer().countHighCapacityPeers());
|
|
}
|
|
|
|
if (inParams.containsKey("i2p.router.netdb.isreseeding")) {
|
|
outParams.put("i2p.router.netdb.isreseeding", Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue());
|
|
}
|
|
return new JSONRPC2Response(outParams, req.getID());
|
|
}
|
|
|
|
private static enum NETWORK_STATUS {
|
|
OK,
|
|
TESTING,
|
|
FIREWALLED,
|
|
HIDDEN,
|
|
WARN_FIREWALLED_AND_FAST,
|
|
WARN_FIREWALLED_AND_FLOODFILL,
|
|
WARN_FIREWALLED_WITH_INBOUND_TCP,
|
|
WARN_FIREWALLED_WITH_UDP_DISABLED,
|
|
ERROR_I2CP,
|
|
ERROR_CLOCK_SKEW,
|
|
ERROR_PRIVATE_TCP_ADDRESS,
|
|
ERROR_SYMMETRIC_NAT,
|
|
ERROR_UDP_PORT_IN_USE,
|
|
ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL,
|
|
ERROR_UDP_DISABLED_AND_TCP_UNSET,
|
|
};
|
|
|
|
// Ripped out of SummaryHelper.java
|
|
private NETWORK_STATUS getNetworkStatus() {
|
|
if (_context.router().getUptime() > 60 * 1000
|
|
&& (!_context.router().gracefulShutdownInProgress())
|
|
&& !_context.clientManager().isAlive())
|
|
return (NETWORK_STATUS.ERROR_I2CP);
|
|
long skew = _context.commSystem().getFramedAveragePeerClockSkew(33);
|
|
// Display the actual skew, not the offset
|
|
if (Math.abs(skew) > 60 * 1000)
|
|
return NETWORK_STATUS.ERROR_CLOCK_SKEW;
|
|
if (_context.router().isHidden())
|
|
return (NETWORK_STATUS.HIDDEN);
|
|
|
|
int status = _context.commSystem().getStatus().getCode();
|
|
switch (status) {
|
|
case CommSystemFacade.STATUS_OK:
|
|
RouterAddress ra = _context.router().getRouterInfo().getTargetAddress("NTCP");
|
|
if (ra == null || TransportUtil.isPubliclyRoutable(ra.getIP(), true))
|
|
return NETWORK_STATUS.OK;
|
|
return NETWORK_STATUS.ERROR_PRIVATE_TCP_ADDRESS;
|
|
case CommSystemFacade.STATUS_DIFFERENT:
|
|
return NETWORK_STATUS.ERROR_SYMMETRIC_NAT;
|
|
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
|
|
if (_context.router().getRouterInfo().getTargetAddress("NTCP") != null)
|
|
return NETWORK_STATUS.WARN_FIREWALLED_WITH_INBOUND_TCP;
|
|
if (((FloodfillNetworkDatabaseFacade) _context.netDb()).floodfillEnabled())
|
|
return NETWORK_STATUS.WARN_FIREWALLED_AND_FLOODFILL;
|
|
if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)
|
|
return NETWORK_STATUS.WARN_FIREWALLED_AND_FAST;
|
|
return NETWORK_STATUS.FIREWALLED;
|
|
case CommSystemFacade.STATUS_HOSED:
|
|
return NETWORK_STATUS.ERROR_UDP_PORT_IN_USE;
|
|
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
|
|
default:
|
|
ra = _context.router().getRouterInfo().getTargetAddress("SSU");
|
|
if (ra == null && _context.router().getUptime() > 5 * 60 * 1000) {
|
|
if (_context.commSystem().countActivePeers() <= 0)
|
|
return NETWORK_STATUS.ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL;
|
|
else if (_context.getProperty(NTCPTransport.PROP_I2NP_NTCP_HOSTNAME) == null || _context.getProperty(NTCPTransport.PROP_I2NP_NTCP_PORT) == null)
|
|
return NETWORK_STATUS.ERROR_UDP_DISABLED_AND_TCP_UNSET;
|
|
else
|
|
return NETWORK_STATUS.WARN_FIREWALLED_WITH_UDP_DISABLED;
|
|
}
|
|
return NETWORK_STATUS.TESTING;
|
|
}
|
|
}
|
|
}
|