merge of '6ac923b4b6f858e909094ff3d0fbfbbfba7ff9d4'
and '8b279c27b4d263a1c9cc02ab7fe2e448e652f469'
This commit is contained in:
@ -329,14 +329,18 @@ public class I2PSnarkServlet extends Default {
|
|||||||
|
|
||||||
// Opera and text-mode browsers: no   and no input type=image values submitted
|
// Opera and text-mode browsers: no   and no input type=image values submitted
|
||||||
String ua = req.getHeader("User-Agent");
|
String ua = req.getHeader("User-Agent");
|
||||||
boolean isDegraded = ua != null && (ua.startsWith("Opera") || ua.startsWith("Lynx") ||
|
boolean isDegraded = ua != null && (ua.startsWith("Lynx") ||
|
||||||
ua.startsWith("ELinks") || ua.startsWith("Dillo"));
|
ua.startsWith("ELinks") || ua.startsWith("Dillo"));
|
||||||
|
|
||||||
|
boolean noThinsp = isDegraded || ua.startsWith("Opera");
|
||||||
if (_manager.util().connected()) {
|
if (_manager.util().connected()) {
|
||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=StopAll&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=StopAll&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else {
|
||||||
out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
|
// http://www.onenaught.com/posts/382/firefox-4-change-input-type-image-only-submits-x-and-y-not-name
|
||||||
|
//out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
|
||||||
|
out.write("<input type=\"image\" name=\"action_StopAll\" value=\"foo\" title=\"");
|
||||||
|
}
|
||||||
out.write(_("Stop all torrents and the I2P tunnel"));
|
out.write(_("Stop all torrents and the I2P tunnel"));
|
||||||
out.write("\" src=\"" + _imgPath + "stop_all.png\" alt=\"");
|
out.write("\" src=\"" + _imgPath + "stop_all.png\" alt=\"");
|
||||||
out.write(_("Stop All"));
|
out.write(_("Stop All"));
|
||||||
@ -347,7 +351,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=StartAll&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=StartAll&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
out.write("<input type=\"image\" name=\"action\" value=\"StartAll\" title=\"");
|
out.write("<input type=\"image\" name=\"action_StartAll\" value=\"foo\" title=\"");
|
||||||
out.write(_("Start all torrents and the I2P tunnel"));
|
out.write(_("Start all torrents and the I2P tunnel"));
|
||||||
out.write("\" src=\"" + _imgPath + "start_all.png\" alt=\"");
|
out.write("\" src=\"" + _imgPath + "start_all.png\" alt=\"");
|
||||||
out.write(_("Start All"));
|
out.write(_("Start All"));
|
||||||
@ -362,7 +366,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
Snark snark = (Snark)snarks.get(i);
|
Snark snark = (Snark)snarks.get(i);
|
||||||
boolean showDebug = "2".equals(peerParam);
|
boolean showDebug = "2".equals(peerParam);
|
||||||
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
|
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
|
||||||
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, showDebug);
|
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, noThinsp, showDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snarks.isEmpty()) {
|
if (snarks.isEmpty()) {
|
||||||
@ -403,10 +407,21 @@ public class I2PSnarkServlet extends Default {
|
|||||||
*/
|
*/
|
||||||
private void processRequest(HttpServletRequest req) {
|
private void processRequest(HttpServletRequest req) {
|
||||||
String action = req.getParameter("action");
|
String action = req.getParameter("action");
|
||||||
|
if (action == null) {
|
||||||
|
// http://www.onenaught.com/posts/382/firefox-4-change-input-type-image-only-submits-x-and-y-not-name
|
||||||
|
Map params = req.getParameterMap();
|
||||||
|
for (Object o : params.keySet()) {
|
||||||
|
String key = (String) o;
|
||||||
|
if (key.startsWith("action_") && key.endsWith(".x")) {
|
||||||
|
action = key.substring(0, key.length() - 2).substring(7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
_manager.addMessage("No action specified");
|
_manager.addMessage("No action specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// sadly, Opera doesn't send value with input type=image, so we have to use GET there
|
// sadly, Opera doesn't send value with input type=image, so we have to use GET there
|
||||||
//if (!"POST".equals(req.getMethod())) {
|
//if (!"POST".equals(req.getMethod())) {
|
||||||
// _manager.addMessage("Action must be with POST");
|
// _manager.addMessage("Action must be with POST");
|
||||||
@ -698,7 +713,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 50;
|
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 50;
|
||||||
private static final int MAX_DISPLAYED_ERROR_LENGTH = 43;
|
private static final int MAX_DISPLAYED_ERROR_LENGTH = 43;
|
||||||
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers,
|
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers,
|
||||||
boolean isDegraded, boolean showDebug) throws IOException {
|
boolean isDegraded, boolean noThinsp, boolean showDebug) throws IOException {
|
||||||
String filename = snark.torrent;
|
String filename = snark.torrent;
|
||||||
File f = new File(filename);
|
File f = new File(filename);
|
||||||
filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name
|
filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name
|
||||||
@ -758,11 +773,11 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isRunning && curPeers > 0 && !showPeers)
|
if (isRunning && curPeers > 0 && !showPeers)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
||||||
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
||||||
curPeers + thinsp(isDegraded) +
|
curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
||||||
else if (isRunning)
|
else if (isRunning)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
||||||
": " + curPeers + thinsp(isDegraded) +
|
": " + curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers);
|
ngettext("1 peer", "{0} peers", knownPeers);
|
||||||
else {
|
else {
|
||||||
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
|
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
|
||||||
@ -774,11 +789,11 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isRunning && curPeers > 0 && !showPeers)
|
if (isRunning && curPeers > 0 && !showPeers)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
|
||||||
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
||||||
curPeers + thinsp(isDegraded) +
|
curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
||||||
else if (isRunning)
|
else if (isRunning)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
|
||||||
": " + curPeers + thinsp(isDegraded) +
|
": " + curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers);
|
ngettext("1 peer", "{0} peers", knownPeers);
|
||||||
else
|
else
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
|
||||||
@ -786,24 +801,24 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
|
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
|
||||||
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
||||||
curPeers + thinsp(isDegraded) +
|
curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
||||||
else if (isRunning && curPeers > 0 && downBps > 0)
|
else if (isRunning && curPeers > 0 && downBps > 0)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
|
||||||
": " + curPeers + thinsp(isDegraded) +
|
": " + curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers);
|
ngettext("1 peer", "{0} peers", knownPeers);
|
||||||
else if (isRunning && curPeers > 0 && !showPeers)
|
else if (isRunning && curPeers > 0 && !showPeers)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
|
||||||
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
|
||||||
curPeers + thinsp(isDegraded) +
|
curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
|
||||||
else if (isRunning && curPeers > 0)
|
else if (isRunning && curPeers > 0)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
|
||||||
": " + curPeers + thinsp(isDegraded) +
|
": " + curPeers + thinsp(noThinsp) +
|
||||||
ngettext("1 peer", "{0} peers", knownPeers);
|
ngettext("1 peer", "{0} peers", knownPeers);
|
||||||
else if (isRunning && knownPeers > 0)
|
else if (isRunning && knownPeers > 0)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers") +
|
||||||
": 0" + thinsp(isDegraded) + knownPeers ;
|
": 0" + thinsp(noThinsp) + knownPeers ;
|
||||||
else if (isRunning)
|
else if (isRunning)
|
||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers");
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers");
|
||||||
else
|
else
|
||||||
@ -880,7 +895,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write("</td>\n\t");
|
out.write("</td>\n\t");
|
||||||
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
|
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
|
||||||
if (remaining > 0)
|
if (remaining > 0)
|
||||||
out.write(formatSize(total-remaining) + thinsp(isDegraded) + formatSize(total));
|
out.write(formatSize(total-remaining) + thinsp(noThinsp) + formatSize(total));
|
||||||
else
|
else
|
||||||
out.write(formatSize(total)); // 3GB
|
out.write(formatSize(total)); // 3GB
|
||||||
out.write("</td>\n\t");
|
out.write("</td>\n\t");
|
||||||
@ -905,7 +920,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
out.write("<input type=\"image\" name=\"action\" value=\"Stop_" + b64 + "\" title=\"");
|
out.write("<input type=\"image\" name=\"action_Stop_" + b64 + "\" value=\"foo\" title=\"");
|
||||||
out.write(_("Stop the torrent"));
|
out.write(_("Stop the torrent"));
|
||||||
out.write("\" src=\"" + _imgPath + "stop.png\" alt=\"");
|
out.write("\" src=\"" + _imgPath + "stop.png\" alt=\"");
|
||||||
out.write(_("Stop"));
|
out.write(_("Stop"));
|
||||||
@ -917,7 +932,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
out.write("<input type=\"image\" name=\"action\" value=\"Start_" + b64 + "\" title=\"");
|
out.write("<input type=\"image\" name=\"action_Start_" + b64 + "\" value=\"foo\" title=\"");
|
||||||
out.write(_("Start the torrent"));
|
out.write(_("Start the torrent"));
|
||||||
out.write("\" src=\"" + _imgPath + "start.png\" alt=\"");
|
out.write("\" src=\"" + _imgPath + "start.png\" alt=\"");
|
||||||
out.write(_("Start"));
|
out.write(_("Start"));
|
||||||
@ -929,7 +944,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
out.write("<input type=\"image\" name=\"action\" value=\"Remove_" + b64 + "\" title=\"");
|
out.write("<input type=\"image\" name=\"action_Remove_" + b64 + "\" value=\"foo\" title=\"");
|
||||||
out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
|
out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
|
||||||
out.write("\" onclick=\"if (!confirm('");
|
out.write("\" onclick=\"if (!confirm('");
|
||||||
// Can't figure out how to escape double quotes inside the onclick string.
|
// Can't figure out how to escape double quotes inside the onclick string.
|
||||||
@ -946,7 +961,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
out.write("<input type=\"image\" name=\"action\" value=\"Delete_" + b64 + "\" title=\"");
|
out.write("<input type=\"image\" name=\"action_Delete_" + b64 + "\" value=\"foo\" title=\"");
|
||||||
out.write(_("Delete the .torrent file and the associated data file(s)"));
|
out.write(_("Delete the .torrent file and the associated data file(s)"));
|
||||||
out.write("\" onclick=\"if (!confirm('");
|
out.write("\" onclick=\"if (!confirm('");
|
||||||
// Can't figure out how to escape double quotes inside the onclick string.
|
// Can't figure out how to escape double quotes inside the onclick string.
|
||||||
@ -1384,7 +1399,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
private static String urlify(String s) {
|
private static String urlify(String s) {
|
||||||
StringBuilder buf = new StringBuilder(256);
|
StringBuilder buf = new StringBuilder(256);
|
||||||
// browsers seem to work without doing this but let's be strict
|
// browsers seem to work without doing this but let's be strict
|
||||||
String link = s.replace("&", "&");
|
String link = s.replace("&", "&").replace(" ", "%20");
|
||||||
buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
|
buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
@ -259,10 +259,9 @@ public class TunnelController implements Logging {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Streamr client is a UDP server, use the listenPort field for targetPort
|
* Streamr client is a UDP server, use the listenPort field for targetPort
|
||||||
* and the listenOnInterface field for the targetHost
|
|
||||||
*/
|
*/
|
||||||
private void startStreamrClient() {
|
private void startStreamrClient() {
|
||||||
String targetHost = getListenOnInterface();
|
String targetHost = getTargetHost();
|
||||||
String targetPort = getListenPort();
|
String targetPort = getListenPort();
|
||||||
String dest = getTargetDestination();
|
String dest = getTargetDestination();
|
||||||
_tunnel.runStreamrClient(new String[] { targetHost, targetPort, dest }, this);
|
_tunnel.runStreamrClient(new String[] { targetHost, targetPort, dest }, this);
|
||||||
@ -270,10 +269,9 @@ public class TunnelController implements Logging {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Streamr server is a UDP client, use the targetPort field for listenPort
|
* Streamr server is a UDP client, use the targetPort field for listenPort
|
||||||
* and the targetHost field for the listenOnInterface
|
|
||||||
*/
|
*/
|
||||||
private void startStreamrServer() {
|
private void startStreamrServer() {
|
||||||
String listenOn = getTargetHost();
|
String listenOn = getListenOnInterface();
|
||||||
if ( (listenOn != null) && (listenOn.length() > 0) ) {
|
if ( (listenOn != null) && (listenOn.length() > 0) ) {
|
||||||
_tunnel.runListenOn(new String[] { listenOn }, this);
|
_tunnel.runListenOn(new String[] { listenOn }, this);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
@ -22,6 +23,7 @@ import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
|
|||||||
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
|
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
|
||||||
import net.i2p.i2ptunnel.TunnelController;
|
import net.i2p.i2ptunnel.TunnelController;
|
||||||
import net.i2p.i2ptunnel.TunnelControllerGroup;
|
import net.i2p.i2ptunnel.TunnelControllerGroup;
|
||||||
|
import net.i2p.util.Addresses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ugly little accessor for the edit page
|
* Ugly little accessor for the edit page
|
||||||
@ -314,6 +316,11 @@ public class EditBean extends IndexBean {
|
|||||||
return _context.isRouterContext();
|
return _context.isRouterContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.3 */
|
||||||
|
public Set<String> interfaceSet() {
|
||||||
|
return Addresses.getAllAddresses();
|
||||||
|
}
|
||||||
|
|
||||||
public String getI2CPHost(int tunnel) {
|
public String getI2CPHost(int tunnel) {
|
||||||
if (_context.isRouterContext())
|
if (_context.isRouterContext())
|
||||||
return _("internal");
|
return _("internal");
|
||||||
|
@ -63,7 +63,6 @@ public class IndexBean {
|
|||||||
private String _proxyList;
|
private String _proxyList;
|
||||||
private String _port;
|
private String _port;
|
||||||
private String _reachableBy;
|
private String _reachableBy;
|
||||||
private String _reachableByOther;
|
|
||||||
private String _targetDestination;
|
private String _targetDestination;
|
||||||
private String _targetHost;
|
private String _targetHost;
|
||||||
private String _targetPort;
|
private String _targetPort;
|
||||||
@ -432,10 +431,13 @@ public class IndexBean {
|
|||||||
|
|
||||||
public String getClientInterface(int tunnel) {
|
public String getClientInterface(int tunnel) {
|
||||||
TunnelController tun = getController(tunnel);
|
TunnelController tun = getController(tunnel);
|
||||||
if (tun != null)
|
if (tun != null) {
|
||||||
return tun.getListenOnInterface();
|
if ("streamrclient".equals(tun.getType()))
|
||||||
|
return tun.getTargetHost();
|
||||||
else
|
else
|
||||||
return "";
|
return tun.getListenOnInterface();
|
||||||
|
} else
|
||||||
|
return "127.0.0.1";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTunnelStatus(int tunnel) {
|
public int getTunnelStatus(int tunnel) {
|
||||||
@ -478,11 +480,38 @@ public class IndexBean {
|
|||||||
return rv != null ? rv : "";
|
return rv != null ? rv : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this to see if it is ok to linkify getServerTarget()
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public boolean isServerTargetLinkValid(int tunnel) {
|
||||||
|
TunnelController tun = getController(tunnel);
|
||||||
|
return tun != null &&
|
||||||
|
"httpserver".equals(tun.getType()) &&
|
||||||
|
tun.getTargetHost() != null &&
|
||||||
|
tun.getTargetPort() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return valid host:port only if isServerTargetLinkValid() is true
|
||||||
|
*/
|
||||||
public String getServerTarget(int tunnel) {
|
public String getServerTarget(int tunnel) {
|
||||||
TunnelController tun = getController(tunnel);
|
TunnelController tun = getController(tunnel);
|
||||||
if (tun != null)
|
if (tun != null) {
|
||||||
return tun.getTargetHost() + ':' + tun.getTargetPort();
|
String host;
|
||||||
|
if ("streamrserver".equals(tun.getType()))
|
||||||
|
host = tun.getListenOnInterface();
|
||||||
else
|
else
|
||||||
|
host = tun.getTargetHost();
|
||||||
|
String port = tun.getTargetPort();
|
||||||
|
if (host == null)
|
||||||
|
host = "<font color=\"red\">" + _("Host not set") + "</font>";
|
||||||
|
else if (host.indexOf(':') >= 0)
|
||||||
|
host = '[' + host + ']';
|
||||||
|
if (port == null)
|
||||||
|
port = "<font color=\"red\">" + _("Port not set") + "</font>";
|
||||||
|
return host + ':' + port;
|
||||||
|
} else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,19 +604,11 @@ public class IndexBean {
|
|||||||
_port = (port != null ? port.trim() : null);
|
_port = (port != null ? port.trim() : null);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* what interface should this client/httpclient/ircclient listen on (unless
|
* what interface should this client/httpclient/ircclient listen on
|
||||||
* overridden by the setReachableByOther() field)
|
|
||||||
*/
|
*/
|
||||||
public void setReachableBy(String reachableBy) {
|
public void setReachableBy(String reachableBy) {
|
||||||
_reachableBy = (reachableBy != null ? reachableBy.trim() : null);
|
_reachableBy = (reachableBy != null ? reachableBy.trim() : null);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* If specified, defines the exact IP interface to listen for requests
|
|
||||||
* on (in the case of client/httpclient/ircclient tunnels)
|
|
||||||
*/
|
|
||||||
public void setReachableByOther(String reachableByOther) {
|
|
||||||
_reachableByOther = (reachableByOther != null ? reachableByOther.trim() : null);
|
|
||||||
}
|
|
||||||
/** What peer does this client tunnel point at */
|
/** What peer does this client tunnel point at */
|
||||||
public void setTargetDestination(String dest) {
|
public void setTargetDestination(String dest) {
|
||||||
_targetDestination = (dest != null ? dest.trim() : null);
|
_targetDestination = (dest != null ? dest.trim() : null);
|
||||||
@ -891,17 +912,22 @@ public class IndexBean {
|
|||||||
Properties config = new Properties();
|
Properties config = new Properties();
|
||||||
updateConfigGeneric(config);
|
updateConfigGeneric(config);
|
||||||
|
|
||||||
|
if ((isClient(_type) && !"streamrclient".equals(_type)) || "streamrserver".equals(_type)) {
|
||||||
|
// streamrserver uses interface
|
||||||
|
if (_reachableBy != null)
|
||||||
|
config.setProperty("interface", _reachableBy);
|
||||||
|
else
|
||||||
|
config.setProperty("interface", "");
|
||||||
|
} else {
|
||||||
|
// streamrclient uses targetHost
|
||||||
|
if (_targetHost != null)
|
||||||
|
config.setProperty("targetHost", _targetHost);
|
||||||
|
}
|
||||||
|
|
||||||
if (isClient(_type)) {
|
if (isClient(_type)) {
|
||||||
// generic client stuff
|
// generic client stuff
|
||||||
if (_port != null)
|
if (_port != null)
|
||||||
config.setProperty("listenPort", _port);
|
config.setProperty("listenPort", _port);
|
||||||
if (_reachableByOther != null)
|
|
||||||
config.setProperty("interface", _reachableByOther);
|
|
||||||
else if (_reachableBy != null)
|
|
||||||
config.setProperty("interface", _reachableBy);
|
|
||||||
else
|
|
||||||
config.setProperty("interface", "");
|
|
||||||
|
|
||||||
config.setProperty("sharedClient", _sharedClient + "");
|
config.setProperty("sharedClient", _sharedClient + "");
|
||||||
for (String p : _booleanClientOpts)
|
for (String p : _booleanClientOpts)
|
||||||
config.setProperty("option." + p, "" + _booleanOptions.contains(p));
|
config.setProperty("option." + p, "" + _booleanOptions.contains(p));
|
||||||
@ -910,8 +936,6 @@ public class IndexBean {
|
|||||||
config.setProperty("option." + p, _otherOptions.get(p));
|
config.setProperty("option." + p, _otherOptions.get(p));
|
||||||
} else {
|
} else {
|
||||||
// generic server stuff
|
// generic server stuff
|
||||||
if (_targetHost != null)
|
|
||||||
config.setProperty("targetHost", _targetHost);
|
|
||||||
if (_targetPort != null)
|
if (_targetPort != null)
|
||||||
config.setProperty("targetPort", _targetPort);
|
config.setProperty("targetPort", _targetPort);
|
||||||
for (String p : _booleanServerOpts)
|
for (String p : _booleanServerOpts)
|
||||||
@ -940,9 +964,7 @@ public class IndexBean {
|
|||||||
if ("httpbidirserver".equals(_type)) {
|
if ("httpbidirserver".equals(_type)) {
|
||||||
if (_port != null)
|
if (_port != null)
|
||||||
config.setProperty("listenPort", _port);
|
config.setProperty("listenPort", _port);
|
||||||
if (_reachableByOther != null)
|
if (_reachableBy != null)
|
||||||
config.setProperty("interface", _reachableByOther);
|
|
||||||
else if (_reachableBy != null)
|
|
||||||
config.setProperty("interface", _reachableBy);
|
config.setProperty("interface", _reachableBy);
|
||||||
else if (_targetHost != null)
|
else if (_targetHost != null)
|
||||||
config.setProperty("interface", _targetHost);
|
config.setProperty("interface", _targetHost);
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
<label><%=intl._("Target")%>:</label>
|
<label><%=intl._("Target")%>:</label>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<label><%=intl._("Access Point")%>:</label>
|
<label><%=intl._("Access Point")%>:</label>
|
||||||
<% } %>
|
<% } /* streamrclient */ %>
|
||||||
</div>
|
</div>
|
||||||
<div id="portField" class="rowItem">
|
<div id="portField" class="rowItem">
|
||||||
<label for="port" accesskey="P">
|
<label for="port" accesskey="P">
|
||||||
@ -95,44 +95,39 @@
|
|||||||
</label>
|
</label>
|
||||||
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
|
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
|
||||||
</div>
|
</div>
|
||||||
<% String otherInterface = "";
|
|
||||||
String clientInterface = editBean.getClientInterface(curTunnel);
|
|
||||||
if ("streamrclient".equals(tunnelType)) {
|
|
||||||
otherInterface = clientInterface;
|
|
||||||
} else { %>
|
|
||||||
<div id="reachField" class="rowItem">
|
<div id="reachField" class="rowItem">
|
||||||
<label for="reachableBy" accesskey="r">
|
<label for="reachableBy" accesskey="r">
|
||||||
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
|
<%
|
||||||
</label>
|
if ("streamrclient".equals(tunnelType)) {
|
||||||
<select id="reachableBy" name="reachableBy" title="Valid IP for Client Access" class="selectbox">
|
out.write("Host:");
|
||||||
<% if (!("127.0.0.1".equals(clientInterface)) &&
|
String targetHost = editBean.getTargetHost(curTunnel);
|
||||||
!("0.0.0.0".equals(clientInterface)) &&
|
if (targetHost == null || "".equals(targetHost.trim())) {
|
||||||
(clientInterface != null) &&
|
|
||||||
(clientInterface.trim().length() > 0)) {
|
|
||||||
otherInterface = clientInterface;
|
|
||||||
}
|
|
||||||
%><option value="127.0.0.1"<%=("127.0.0.1".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Locally (127.0.0.1)")%></option>
|
|
||||||
<option value="0.0.0.0"<%=("0.0.0.0".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Everyone (0.0.0.0)")%></option>
|
|
||||||
<option value="other"<%=(!("".equals(otherInterface)) ? " selected=\"selected\"" : "")%>><%=intl._("LAN Hosts (Please specify your LAN address)")%></option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<% } // streamrclient %>
|
|
||||||
<div id="otherField" class="rowItem">
|
|
||||||
<label for="reachableByOther" accesskey="O">
|
|
||||||
<% if ("streamrclient".equals(tunnelType)) { %>
|
|
||||||
Host:
|
|
||||||
<% String vvv = otherInterface;
|
|
||||||
if (vvv == null || "".equals(vvv.trim())) {
|
|
||||||
out.write(" <font color=\"red\">(");
|
out.write(" <font color=\"red\">(");
|
||||||
out.write(intl._("required"));
|
out.write(intl._("required"));
|
||||||
out.write(")</font>");
|
out.write(")</font>");
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
<% } else { %>
|
|
||||||
<%=intl._("Other")%>(<span class="accessKey">O</span>):
|
|
||||||
<% } %>
|
|
||||||
</label>
|
</label>
|
||||||
<input type="text" size="20" id="reachableByOther" name="reachableByOther" title="Alternative IP for Client Access" value="<%=otherInterface%>" class="freetext" />
|
<input type="text" size="20" id="targetHost" name="targetHost" title="Target Hostname or IP" value="<%=targetHost%>" class="freetext" />
|
||||||
|
<% } else { %>
|
||||||
|
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
|
||||||
|
</label>
|
||||||
|
<select id="reachableBy" name="reachableBy" title="IP for Client Access" class="selectbox">
|
||||||
|
<%
|
||||||
|
String clientInterface = editBean.getClientInterface(curTunnel);
|
||||||
|
for (String ifc : editBean.interfaceSet()) {
|
||||||
|
out.write("<option value=\"");
|
||||||
|
out.write(ifc);
|
||||||
|
out.write('\"');
|
||||||
|
if (ifc.equals(clientInterface))
|
||||||
|
out.write(" selected=\"selected\"");
|
||||||
|
out.write('>');
|
||||||
|
out.write(ifc);
|
||||||
|
out.write("</option>\n");
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
</select>
|
||||||
|
<% } /* streamrclient */ %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="subdivider">
|
<div class="subdivider">
|
||||||
|
@ -89,16 +89,14 @@
|
|||||||
<label><%=intl._("Target")%>:</label>
|
<label><%=intl._("Target")%>:</label>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
<% if (!"streamrserver".equals(tunnelType)) { %>
|
||||||
<div id="hostField" class="rowItem">
|
<div id="hostField" class="rowItem">
|
||||||
<label for="targetHost" accesskey="H">
|
<label for="targetHost" accesskey="H">
|
||||||
<% if ("streamrserver".equals(tunnelType)) { %>
|
|
||||||
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
|
|
||||||
<% } else { %>
|
|
||||||
<%=intl._("Host")%>(<span class="accessKey">H</span>):
|
<%=intl._("Host")%>(<span class="accessKey">H</span>):
|
||||||
<% } %>
|
|
||||||
</label>
|
</label>
|
||||||
<input type="text" size="20" id="targetHost" name="targetHost" title="Target Hostname or IP" value="<%=editBean.getTargetHost(curTunnel)%>" class="freetext" />
|
<input type="text" size="20" id="targetHost" name="targetHost" title="Target Hostname or IP" value="<%=editBean.getTargetHost(curTunnel)%>" class="freetext" />
|
||||||
</div>
|
</div>
|
||||||
|
<% } /* !streamrserver */ %>
|
||||||
<div id="portField" class="rowItem">
|
<div id="portField" class="rowItem">
|
||||||
<label for="targetPort" accesskey="P">
|
<label for="targetPort" accesskey="P">
|
||||||
<%=intl._("Port")%>(<span class="accessKey">P</span>):
|
<%=intl._("Port")%>(<span class="accessKey">P</span>):
|
||||||
@ -113,8 +111,7 @@
|
|||||||
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="Target Port Number" value="<%=editBean.getTargetPort(curTunnel)%>" class="freetext" />
|
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="Target Port Number" value="<%=editBean.getTargetPort(curTunnel)%>" class="freetext" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if ("httpbidirserver".equals(tunnelType)) {
|
<% if ("httpbidirserver".equals(tunnelType)) { %>
|
||||||
%>
|
|
||||||
<div class="subdivider">
|
<div class="subdivider">
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
@ -134,32 +131,30 @@
|
|||||||
</label>
|
</label>
|
||||||
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
|
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
|
||||||
</div>
|
</div>
|
||||||
<% String otherInterface = "";
|
<% } /* httpbidirserver */ %>
|
||||||
String clientInterface = editBean.getClientInterface(curTunnel);
|
<% if ("httpbidirserver".equals(tunnelType) || "streamrserver".equals(tunnelType)) { %>
|
||||||
%>
|
|
||||||
<div id="reachField" class="rowItem">
|
<div id="reachField" class="rowItem">
|
||||||
<label for="reachableBy" accesskey="r">
|
<label for="reachableBy" accesskey="r">
|
||||||
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
|
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
|
||||||
</label>
|
</label>
|
||||||
<select id="reachableBy" name="reachableBy" title="Valid IP for Client Access" class="selectbox">
|
<select id="reachableBy" name="reachableBy" title="IP for Client Access" class="selectbox">
|
||||||
<% if (!("127.0.0.1".equals(clientInterface)) &&
|
<%
|
||||||
!("0.0.0.0".equals(clientInterface)) &&
|
String clientInterface = editBean.getClientInterface(curTunnel);
|
||||||
(clientInterface != null) &&
|
for (String ifc : editBean.interfaceSet()) {
|
||||||
(clientInterface.trim().length() > 0)) {
|
out.write("<option value=\"");
|
||||||
otherInterface = clientInterface;
|
out.write(ifc);
|
||||||
|
out.write('\"');
|
||||||
|
if (ifc.equals(clientInterface))
|
||||||
|
out.write(" selected=\"selected\"");
|
||||||
|
out.write('>');
|
||||||
|
out.write(ifc);
|
||||||
|
out.write("</option>\n");
|
||||||
}
|
}
|
||||||
%><option value="127.0.0.1"<%=("127.0.0.1".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Locally (127.0.0.1)")%></option>
|
%>
|
||||||
<option value="0.0.0.0"<%=("0.0.0.0".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Everyone (0.0.0.0)")%></option>
|
|
||||||
<option value="other"<%=(!("".equals(otherInterface)) ? " selected=\"selected\"" : "")%>><%=intl._("LAN Hosts (Please specify your LAN address)")%></option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="otherField" class="rowItem">
|
<% } /* httpbidirserver || streamrserver */ %>
|
||||||
<label for="reachableByOther" accesskey="O">
|
|
||||||
<%=intl._("Other")%>(<span class="accessKey">O</span>):
|
|
||||||
</label>
|
|
||||||
<input type="text" size="20" id="reachableByOther" name="reachableByOther" title="Alternative IP for Client Access" value="<%=otherInterface%>" class="freetext" />
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
<div class="subdivider">
|
<div class="subdivider">
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
@ -302,7 +297,7 @@
|
|||||||
<div class="subdivider">
|
<div class="subdivider">
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
<% } // !streamrserver %>
|
<% } /* !streamrserver */ %>
|
||||||
|
|
||||||
<div id="optionsField" class="rowItem">
|
<div id="optionsField" class="rowItem">
|
||||||
<label><%=intl._("Router I2CP Address")%>:</label>
|
<label><%=intl._("Router I2CP Address")%>:</label>
|
||||||
|
@ -95,7 +95,7 @@
|
|||||||
<label><%=intl._("Points at")%>:</label>
|
<label><%=intl._("Points at")%>:</label>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<%
|
<%
|
||||||
if ("httpserver".equals(indexBean.getInternalType(curServer))) {
|
if (indexBean.isServerTargetLinkValid(curServer)) {
|
||||||
%>
|
%>
|
||||||
<a href="http://<%=indexBean.getServerTarget(curServer)%>/" title="Test HTTP server, bypassing I2P"><%=indexBean.getServerTarget(curServer)%></a>
|
<a href="http://<%=indexBean.getServerTarget(curServer)%>/" title="Test HTTP server, bypassing I2P"><%=indexBean.getServerTarget(curServer)%></a>
|
||||||
<%
|
<%
|
||||||
@ -213,7 +213,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="portField rowItem">
|
<div class="portField rowItem">
|
||||||
<label><%=intl._("Port")%>:</label>
|
<label><%=intl._("Port")%>:</label>
|
||||||
<span class="text"><%=indexBean.getClientPort(curClient)%></span>
|
<span class="text">
|
||||||
|
<%
|
||||||
|
String cPort= indexBean.getClientPort(curClient);
|
||||||
|
if ("".equals(cPort)) {
|
||||||
|
out.write("<font color=\"red\">");
|
||||||
|
out.write(intl._("Port not set"));
|
||||||
|
out.write("</font>");
|
||||||
|
} else {
|
||||||
|
out.write(cPort);
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="typeField rowItem">
|
<div class="typeField rowItem">
|
||||||
<label><%=intl._("Type")%>:</label>
|
<label><%=intl._("Type")%>:</label>
|
||||||
@ -221,7 +232,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="interfaceField rowItem">
|
<div class="interfaceField rowItem">
|
||||||
<label><%=intl._("Interface")%>:</label>
|
<label><%=intl._("Interface")%>:</label>
|
||||||
<span class="text"><%=indexBean.getClientInterface(curClient)%></span>
|
<span class="text">
|
||||||
|
<%
|
||||||
|
/* should only happen for streamr client */
|
||||||
|
String cHost= indexBean.getClientInterface(curClient);
|
||||||
|
if ("".equals(cHost)) {
|
||||||
|
out.write("<font color=\"red\">");
|
||||||
|
out.write(intl._("Hort not set"));
|
||||||
|
out.write("</font>");
|
||||||
|
} else {
|
||||||
|
out.write(cHost);
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="statusField rowItem">
|
<div class="statusField rowItem">
|
||||||
<label><%=intl._("Status")%>:</label>
|
<label><%=intl._("Status")%>:</label>
|
||||||
|
@ -327,11 +327,12 @@ public class ElGamalAESEngine {
|
|||||||
//_log.debug("len: " + len);
|
//_log.debug("len: " + len);
|
||||||
if ((len < 0) || (len > decrypted.length - cur - Hash.HASH_LENGTH - 1))
|
if ((len < 0) || (len > decrypted.length - cur - Hash.HASH_LENGTH - 1))
|
||||||
throw new Exception("Invalid size of payload (" + len + ", remaining " + (decrypted.length-cur) +")");
|
throw new Exception("Invalid size of payload (" + len + ", remaining " + (decrypted.length-cur) +")");
|
||||||
byte hashval[] = new byte[Hash.HASH_LENGTH];
|
//byte hashval[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(decrypted, cur, hashval, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(decrypted, cur, hashval, 0, Hash.HASH_LENGTH);
|
||||||
|
//readHash = new Hash();
|
||||||
|
//readHash.setData(hashval);
|
||||||
|
readHash = Hash.create(decrypted, cur);
|
||||||
cur += Hash.HASH_LENGTH;
|
cur += Hash.HASH_LENGTH;
|
||||||
readHash = new Hash();
|
|
||||||
readHash.setData(hashval);
|
|
||||||
byte flag = decrypted[cur++];
|
byte flag = decrypted[cur++];
|
||||||
if (flag == 0x01) {
|
if (flag == 0x01) {
|
||||||
byte rekeyVal[] = new byte[SessionKey.KEYSIZE_BYTES];
|
byte rekeyVal[] = new byte[SessionKey.KEYSIZE_BYTES];
|
||||||
|
@ -202,9 +202,10 @@ public class ElGamalEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//ByteArrayInputStream bais = new ByteArrayInputStream(val, i, val.length - i);
|
//ByteArrayInputStream bais = new ByteArrayInputStream(val, i, val.length - i);
|
||||||
byte hashData[] = new byte[Hash.HASH_LENGTH];
|
//byte hashData[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(val, i + 1, hashData, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(val, i + 1, hashData, 0, Hash.HASH_LENGTH);
|
||||||
Hash hash = new Hash(hashData);
|
//Hash hash = new Hash(hashData);
|
||||||
|
Hash hash = Hash.create(val, i + 1);
|
||||||
byte rv[] = new byte[payloadLen];
|
byte rv[] = new byte[payloadLen];
|
||||||
System.arraycopy(val, i + 1 + Hash.HASH_LENGTH, rv, 0, rv.length);
|
System.arraycopy(val, i + 1 + Hash.HASH_LENGTH, rv, 0, rv.length);
|
||||||
|
|
||||||
|
@ -35,7 +35,8 @@ public final class SHA256Generator {
|
|||||||
digest.update(source, start, len);
|
digest.update(source, start, len);
|
||||||
byte rv[] = digest.digest();
|
byte rv[] = digest.digest();
|
||||||
releaseGnu(digest);
|
releaseGnu(digest);
|
||||||
return new Hash(rv);
|
//return new Hash(rv);
|
||||||
|
return Hash.create(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void calculateHash(byte[] source, int start, int len, byte out[], int outOffset) {
|
public final void calculateHash(byte[] source, int start, int len, byte out[], int outOffset) {
|
||||||
|
@ -25,6 +25,33 @@ public class Hash extends SimpleDataStructure {
|
|||||||
|
|
||||||
public final static int HASH_LENGTH = 32;
|
public final static int HASH_LENGTH = 32;
|
||||||
public final static Hash FAKE_HASH = new Hash(new byte[HASH_LENGTH]);
|
public final static Hash FAKE_HASH = new Hash(new byte[HASH_LENGTH]);
|
||||||
|
private static final int CACHE_SIZE = 2048;
|
||||||
|
|
||||||
|
private static final SDSCache<Hash> _cache = new SDSCache(Hash.class, HASH_LENGTH, CACHE_SIZE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull from cache or return new
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public static Hash create(byte[] data) {
|
||||||
|
return _cache.get(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull from cache or return new
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public static Hash create(byte[] data, int off) {
|
||||||
|
return _cache.get(data, off);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull from cache or return new
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public static Hash create(InputStream in) throws IOException {
|
||||||
|
return _cache.get(in);
|
||||||
|
}
|
||||||
|
|
||||||
public Hash() {
|
public Hash() {
|
||||||
super();
|
super();
|
||||||
|
@ -61,10 +61,12 @@ public class KeysAndCert extends DataStructureImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||||
_publicKey = new PublicKey();
|
//_publicKey = new PublicKey();
|
||||||
_publicKey.readBytes(in);
|
//_publicKey.readBytes(in);
|
||||||
_signingKey = new SigningPublicKey();
|
_publicKey = PublicKey.create(in);
|
||||||
_signingKey.readBytes(in);
|
//_signingKey = new SigningPublicKey();
|
||||||
|
//_signingKey.readBytes(in);
|
||||||
|
_signingKey = SigningPublicKey.create(in);
|
||||||
//_certificate = new Certificate();
|
//_certificate = new Certificate();
|
||||||
//_certificate.readBytes(in);
|
//_certificate.readBytes(in);
|
||||||
_certificate = Certificate.create(in);
|
_certificate = Certificate.create(in);
|
||||||
|
@ -110,8 +110,9 @@ public class Lease extends DataStructureImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||||
_gateway = new Hash();
|
//_gateway = new Hash();
|
||||||
_gateway.readBytes(in);
|
//_gateway.readBytes(in);
|
||||||
|
_gateway = Hash.create(in);
|
||||||
_tunnelId = new TunnelId();
|
_tunnelId = new TunnelId();
|
||||||
_tunnelId.readBytes(in);
|
_tunnelId.readBytes(in);
|
||||||
_end = DataHelper.readDate(in);
|
_end = DataHelper.readDate(in);
|
||||||
|
@ -9,6 +9,9 @@ package net.i2p.data;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the PublicKey as defined by the I2P data structure spec.
|
* Defines the PublicKey as defined by the I2P data structure spec.
|
||||||
* A public key is 256byte Integer. The public key represents only the
|
* A public key is 256byte Integer. The public key represents only the
|
||||||
@ -18,6 +21,17 @@ package net.i2p.data;
|
|||||||
*/
|
*/
|
||||||
public class PublicKey extends SimpleDataStructure {
|
public class PublicKey extends SimpleDataStructure {
|
||||||
public final static int KEYSIZE_BYTES = 256;
|
public final static int KEYSIZE_BYTES = 256;
|
||||||
|
private static final int CACHE_SIZE = 256;
|
||||||
|
|
||||||
|
private static final SDSCache<PublicKey> _cache = new SDSCache(PublicKey.class, KEYSIZE_BYTES, CACHE_SIZE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull from cache or return new
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public static PublicKey create(InputStream in) throws IOException {
|
||||||
|
return _cache.get(in);
|
||||||
|
}
|
||||||
|
|
||||||
public PublicKey() {
|
public PublicKey() {
|
||||||
super();
|
super();
|
||||||
|
175
core/java/src/net/i2p/data/SDSCache.java
Normal file
175
core/java/src/net/i2p/data/SDSCache.java
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
package net.i2p.data;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.SimpleByteCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A least recently used cache with a max size, for SimpleDataStructures.
|
||||||
|
* The index to the cache is the first 4 bytes of the data, so
|
||||||
|
* the data must be sufficiently random.
|
||||||
|
*
|
||||||
|
* This caches the SDS objects, and also uses SimpleByteCache to cache
|
||||||
|
* the unused byte arrays themselves
|
||||||
|
*
|
||||||
|
* Following is sample usage:
|
||||||
|
* <pre>
|
||||||
|
|
||||||
|
private static final SDSCache<Foo> _cache = new SDSCache(Foo.class, LENGTH, 1024);
|
||||||
|
|
||||||
|
public static Foo create(byte[] data) {
|
||||||
|
return _cache.get(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Foo create(byte[] data, int off) {
|
||||||
|
return _cache.get(data, off);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Foo create(InputStream in) throws IOException {
|
||||||
|
return _cache.get(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
* </pre>
|
||||||
|
* @since 0.8.3
|
||||||
|
* @author zzz
|
||||||
|
*/
|
||||||
|
public class SDSCache<V extends SimpleDataStructure> {
|
||||||
|
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(SDSCache.class);
|
||||||
|
|
||||||
|
private static final Class[] conArg = new Class[] { byte[].class };
|
||||||
|
private static final double MIN_FACTOR = 0.25;
|
||||||
|
private static final double MAX_FACTOR = 3.0;
|
||||||
|
private static final double FACTOR;
|
||||||
|
static {
|
||||||
|
long maxMemory = Runtime.getRuntime().maxMemory();
|
||||||
|
FACTOR = Math.max(MIN_FACTOR, Math.min(MAX_FACTOR, maxMemory / (128*1024*1024d)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** the LRU cache */
|
||||||
|
private final Map<Integer, V> _cache;
|
||||||
|
/** the byte array length for the class we are caching */
|
||||||
|
private final int _datalen;
|
||||||
|
/** the constructor for the class we are caching */
|
||||||
|
private final Constructor<V> _rvCon;
|
||||||
|
private final String _statName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rvClass the class that we are storing, i.e. an extension of SimpleDataStructure
|
||||||
|
* @param len the length of the byte array in the SimpleDataStructure
|
||||||
|
* @param max maximum size of the cache assuming 128MB of mem.
|
||||||
|
* The actual max size will be scaled based on available memory.
|
||||||
|
*/
|
||||||
|
public SDSCache(Class<V> rvClass, int len, int max) {
|
||||||
|
int size = (int) (max * FACTOR);
|
||||||
|
_cache = new LHM(size);
|
||||||
|
_datalen = len;
|
||||||
|
try {
|
||||||
|
_rvCon = rvClass.getConstructor(conArg);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("SDSCache init error", e);
|
||||||
|
}
|
||||||
|
_statName = "SDSCache." + rvClass.getSimpleName();
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("New SDSCache for " + rvClass + " data size: " + len +
|
||||||
|
" max: " + size + " max mem: " + (len * size));
|
||||||
|
I2PAppContext.getGlobalContext().statManager().createRateStat(_statName, "Hit rate", "Router", new long[] { 10*60*1000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data non-null, the byte array for the SimpleDataStructure
|
||||||
|
* @return the cached value if available, otherwise
|
||||||
|
* makes a new object and returns it
|
||||||
|
* @throws IllegalArgumentException if data is not the correct number of bytes
|
||||||
|
* @throws NPE
|
||||||
|
*/
|
||||||
|
public V get(byte[] data) {
|
||||||
|
if (data == null)
|
||||||
|
throw new NullPointerException("Don't pull null data from the cache");
|
||||||
|
int found;
|
||||||
|
V rv;
|
||||||
|
Integer key = hashCodeOf(data);
|
||||||
|
synchronized(_cache) {
|
||||||
|
rv = _cache.get(key);
|
||||||
|
if (rv != null && DataHelper.eq(data, rv.getData())) {
|
||||||
|
// found it, we don't need the data passed in any more
|
||||||
|
SimpleByteCache.release(data);
|
||||||
|
found = 1;
|
||||||
|
} else {
|
||||||
|
// make a new one
|
||||||
|
try {
|
||||||
|
rv = _rvCon.newInstance(new Object[] { data } );
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new RuntimeException("SDSCache error", e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("SDSCache error", e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("SDSCache error", e);
|
||||||
|
}
|
||||||
|
_cache.put(key, rv);
|
||||||
|
found = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
I2PAppContext.getGlobalContext().statManager().addRateData(_statName, found, 0);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param b non-null byte array containing the data, data will be copied to not hold the reference
|
||||||
|
* @param off offset in the array to start reading from
|
||||||
|
* @return the cached value if available, otherwise
|
||||||
|
* makes a new object and returns it
|
||||||
|
* @throws AIOOBE if not enough bytes
|
||||||
|
* @throws NPE
|
||||||
|
*/
|
||||||
|
public V get(byte[] b, int off) {
|
||||||
|
byte[] data = SimpleByteCache.acquire(_datalen);
|
||||||
|
System.arraycopy(b, off, data, 0, _datalen);
|
||||||
|
return get(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param in a stream from which the bytes will be read
|
||||||
|
* @return the cached value if available, otherwise
|
||||||
|
* makes a new object and returns it
|
||||||
|
* @throws IOException if not enough bytes
|
||||||
|
*/
|
||||||
|
public V get(InputStream in) throws IOException {
|
||||||
|
byte[] data = SimpleByteCache.acquire(_datalen);
|
||||||
|
int read = DataHelper.read(in, data);
|
||||||
|
if (read != _datalen)
|
||||||
|
throw new EOFException("Not enough bytes to read the data");
|
||||||
|
return get(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We assume the data has enough randomness in it, so use the first 4 bytes for speed.
|
||||||
|
*/
|
||||||
|
private static Integer hashCodeOf(byte[] data) {
|
||||||
|
int rv = data[0];
|
||||||
|
for (int i = 1; i < 4; i++)
|
||||||
|
rv ^= (data[i] << (i*8));
|
||||||
|
return Integer.valueOf(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class LHM<K, V> extends LinkedHashMap<K, V> {
|
||||||
|
private final int _max;
|
||||||
|
|
||||||
|
public LHM(int max) {
|
||||||
|
super(max, 0.75f, true);
|
||||||
|
_max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||||
|
return size() > _max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,9 @@ package net.i2p.data;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the SigningPublicKey as defined by the I2P data structure spec.
|
* Defines the SigningPublicKey as defined by the I2P data structure spec.
|
||||||
* A public key is 256byte Integer. The public key represents only the
|
* A public key is 256byte Integer. The public key represents only the
|
||||||
@ -19,6 +22,17 @@ package net.i2p.data;
|
|||||||
*/
|
*/
|
||||||
public class SigningPublicKey extends SimpleDataStructure {
|
public class SigningPublicKey extends SimpleDataStructure {
|
||||||
public final static int KEYSIZE_BYTES = 128;
|
public final static int KEYSIZE_BYTES = 128;
|
||||||
|
private static final int CACHE_SIZE = 256;
|
||||||
|
|
||||||
|
private static final SDSCache<SigningPublicKey> _cache = new SDSCache(SigningPublicKey.class, KEYSIZE_BYTES, CACHE_SIZE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull from cache or return new
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public static SigningPublicKey create(InputStream in) throws IOException {
|
||||||
|
return _cache.get(in);
|
||||||
|
}
|
||||||
|
|
||||||
public SigningPublicKey() {
|
public SigningPublicKey() {
|
||||||
super();
|
super();
|
||||||
|
@ -33,13 +33,15 @@ public class DestLookupMessage extends I2CPMessageImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
|
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
|
||||||
Hash h = new Hash();
|
//Hash h = new Hash();
|
||||||
try {
|
try {
|
||||||
h.readBytes(in);
|
//h.readBytes(in);
|
||||||
} catch (DataFormatException dfe) {
|
_hash = Hash.create(in);
|
||||||
|
//} catch (DataFormatException dfe) {
|
||||||
|
} catch (IllegalArgumentException dfe) {
|
||||||
throw new I2CPMessageException("Unable to load the hash", dfe);
|
throw new I2CPMessageException("Unable to load the hash", dfe);
|
||||||
}
|
}
|
||||||
_hash = h;
|
//_hash = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
|
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
|
||||||
|
@ -86,8 +86,9 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
|
|||||||
int numTunnels = (int) DataHelper.readLong(in, 1);
|
int numTunnels = (int) DataHelper.readLong(in, 1);
|
||||||
_endpoints.clear();
|
_endpoints.clear();
|
||||||
for (int i = 0; i < numTunnels; i++) {
|
for (int i = 0; i < numTunnels; i++) {
|
||||||
Hash router = new Hash();
|
//Hash router = new Hash();
|
||||||
router.readBytes(in);
|
//router.readBytes(in);
|
||||||
|
Hash router = Hash.create(in);
|
||||||
TunnelId tunnel = new TunnelId();
|
TunnelId tunnel = new TunnelId();
|
||||||
tunnel.readBytes(in);
|
tunnel.readBytes(in);
|
||||||
_endpoints.add(new TunnelEndpoint(router, tunnel));
|
_endpoints.add(new TunnelEndpoint(router, tunnel));
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package net.i2p.util;
|
package net.i2p.util;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
@ -57,7 +57,8 @@ import net.i2p.data.ByteArray;
|
|||||||
*/
|
*/
|
||||||
public final class ByteCache {
|
public final class ByteCache {
|
||||||
|
|
||||||
private static final Map<Integer, ByteCache> _caches = new HashMap(16);
|
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
|
||||||
|
private static final Map<Integer, ByteCache> _caches = new ConcurrentHashMap(16);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* max size in bytes of each cache
|
* max size in bytes of each cache
|
||||||
@ -74,8 +75,9 @@ public final class ByteCache {
|
|||||||
/**
|
/**
|
||||||
* Get a cache responsible for objects of the given size
|
* Get a cache responsible for objects of the given size
|
||||||
*
|
*
|
||||||
* @param cacheSize how large we want the cache to grow before using on
|
* @param cacheSize how large we want the cache to grow
|
||||||
* demand allocation
|
* (number of objects, NOT memory size)
|
||||||
|
* before discarding released objects.
|
||||||
* Since 0.7.14, a limit of 1MB / size is enforced
|
* Since 0.7.14, a limit of 1MB / size is enforced
|
||||||
* for the typical 128MB max memory JVM
|
* for the typical 128MB max memory JVM
|
||||||
* @param size how large should the objects cached be?
|
* @param size how large should the objects cached be?
|
||||||
@ -84,12 +86,11 @@ public final class ByteCache {
|
|||||||
if (cacheSize * size > MAX_CACHE)
|
if (cacheSize * size > MAX_CACHE)
|
||||||
cacheSize = MAX_CACHE / size;
|
cacheSize = MAX_CACHE / size;
|
||||||
Integer sz = Integer.valueOf(size);
|
Integer sz = Integer.valueOf(size);
|
||||||
ByteCache cache = null;
|
ByteCache cache = _caches.get(sz);
|
||||||
synchronized (_caches) {
|
if (cache == null) {
|
||||||
if (!_caches.containsKey(sz))
|
cache = new ByteCache(cacheSize, size);
|
||||||
_caches.put(sz, new ByteCache(cacheSize, size));
|
_caches.put(sz, cache);
|
||||||
cache = _caches.get(sz);
|
; }
|
||||||
}
|
|
||||||
cache.resize(cacheSize);
|
cache.resize(cacheSize);
|
||||||
//I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class).error("ByteCache size: " + size + " max: " + cacheSize, new Exception("from"));
|
//I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class).error("ByteCache size: " + size + " max: " + cacheSize, new Exception("from"));
|
||||||
return cache;
|
return cache;
|
||||||
@ -102,10 +103,9 @@ public final class ByteCache {
|
|||||||
public static void clearAll() {
|
public static void clearAll() {
|
||||||
for (ByteCache bc : _caches.values())
|
for (ByteCache bc : _caches.values())
|
||||||
bc.clear();
|
bc.clear();
|
||||||
I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class).warn("WARNING: Low memory, clearing byte caches");
|
_log.warn("WARNING: Low memory, clearing byte caches");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Log _log;
|
|
||||||
/** list of available and available entries */
|
/** list of available and available entries */
|
||||||
private Queue<ByteArray> _available;
|
private Queue<ByteArray> _available;
|
||||||
private int _maxCached;
|
private int _maxCached;
|
||||||
@ -116,7 +116,7 @@ public final class ByteCache {
|
|||||||
private static final boolean _cache = true;
|
private static final boolean _cache = true;
|
||||||
|
|
||||||
/** how often do we cleanup the cache */
|
/** how often do we cleanup the cache */
|
||||||
private static final int CLEANUP_FREQUENCY = 30*1000;
|
private static final int CLEANUP_FREQUENCY = 33*1000;
|
||||||
/** if we haven't exceeded the cache size in 2 minutes, cut our cache in half */
|
/** if we haven't exceeded the cache size in 2 minutes, cut our cache in half */
|
||||||
private static final long EXPIRE_PERIOD = 2*60*1000;
|
private static final long EXPIRE_PERIOD = 2*60*1000;
|
||||||
|
|
||||||
@ -126,9 +126,8 @@ public final class ByteCache {
|
|||||||
_maxCached = maxCachedEntries;
|
_maxCached = maxCachedEntries;
|
||||||
_entrySize = entrySize;
|
_entrySize = entrySize;
|
||||||
_lastOverflow = -1;
|
_lastOverflow = -1;
|
||||||
SimpleScheduler.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY);
|
SimpleScheduler.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY + (entrySize % 7)); //stagger
|
||||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
|
I2PAppContext.getGlobalContext().statManager().createRateStat("byteCache.memory." + entrySize, "Memory usage (B)", "Router", new long[] { 10*60*1000 });
|
||||||
I2PAppContext.getGlobalContext().statManager().createRateStat("byteCache.memory." + entrySize, "Memory usage (B)", "Router", new long[] { 60*1000 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resize(int maxCachedEntries) {
|
private void resize(int maxCachedEntries) {
|
||||||
|
125
core/java/src/net/i2p/util/SimpleByteCache.java
Normal file
125
core/java/src/net/i2p/util/SimpleByteCache.java
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package net.i2p.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like ByteCache but works directly with byte arrays, not ByteArrays.
|
||||||
|
* These are designed to be small caches, so there's no cleaner task
|
||||||
|
* like there is in ByteCache. And we don't zero out the arrays here.
|
||||||
|
* Only the static methods are public here.
|
||||||
|
*
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
public final class SimpleByteCache {
|
||||||
|
|
||||||
|
private static final Map<Integer, SimpleByteCache> _caches = new ConcurrentHashMap(8);
|
||||||
|
|
||||||
|
private static final int DEFAULT_SIZE = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a cache responsible for arrays of the given size
|
||||||
|
*
|
||||||
|
* @param size how large should the objects cached be?
|
||||||
|
*/
|
||||||
|
public static SimpleByteCache getInstance(int size) {
|
||||||
|
return getInstance(DEFAULT_SIZE, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a cache responsible for objects of the given size
|
||||||
|
*
|
||||||
|
* @param cacheSize how large we want the cache to grow
|
||||||
|
* (number of objects, NOT memory size)
|
||||||
|
* before discarding released objects.
|
||||||
|
* @param size how large should the objects cached be?
|
||||||
|
*/
|
||||||
|
public static SimpleByteCache getInstance(int cacheSize, int size) {
|
||||||
|
Integer sz = Integer.valueOf(size);
|
||||||
|
SimpleByteCache cache = _caches.get(sz);
|
||||||
|
if (cache == null) {
|
||||||
|
cache = new SimpleByteCache(cacheSize, size);
|
||||||
|
_caches.put(sz, cache);
|
||||||
|
}
|
||||||
|
cache.resize(cacheSize);
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear everything (memory pressure)
|
||||||
|
*/
|
||||||
|
public static void clearAll() {
|
||||||
|
for (SimpleByteCache bc : _caches.values())
|
||||||
|
bc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** list of available and available entries */
|
||||||
|
private Queue<byte[]> _available;
|
||||||
|
private int _maxCached;
|
||||||
|
private int _entrySize;
|
||||||
|
|
||||||
|
private SimpleByteCache(int maxCachedEntries, int entrySize) {
|
||||||
|
_available = new LinkedBlockingQueue(maxCachedEntries);
|
||||||
|
_maxCached = maxCachedEntries;
|
||||||
|
_entrySize = entrySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resize(int maxCachedEntries) {
|
||||||
|
if (_maxCached >= maxCachedEntries) return;
|
||||||
|
_maxCached = maxCachedEntries;
|
||||||
|
// make a bigger one, move the cached items over
|
||||||
|
Queue<byte[]> newLBQ = new LinkedBlockingQueue(maxCachedEntries);
|
||||||
|
byte[] ba;
|
||||||
|
while ((ba = _available.poll()) != null)
|
||||||
|
newLBQ.offer(ba);
|
||||||
|
_available = newLBQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next available array, either from the cache or a brand new one
|
||||||
|
*/
|
||||||
|
public static byte[] acquire(int size) {
|
||||||
|
return getInstance(size).acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next available array, either from the cache or a brand new one
|
||||||
|
*/
|
||||||
|
private byte[] acquire() {
|
||||||
|
byte[] rv = _available.poll();
|
||||||
|
if (rv == null)
|
||||||
|
rv = new byte[_entrySize];
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put this array back onto the available cache for reuse
|
||||||
|
*/
|
||||||
|
public static void release(byte[] entry) {
|
||||||
|
SimpleByteCache cache = _caches.get(entry.length);
|
||||||
|
if (cache != null)
|
||||||
|
cache.releaseIt(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put this array back onto the available cache for reuse
|
||||||
|
*/
|
||||||
|
private void releaseIt(byte[] entry) {
|
||||||
|
if (entry == null || entry.length != _entrySize)
|
||||||
|
return;
|
||||||
|
// should be safe without this
|
||||||
|
//Arrays.fill(entry, (byte) 0);
|
||||||
|
_available.offer(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear everything (memory pressure)
|
||||||
|
*/
|
||||||
|
private void clear() {
|
||||||
|
_available.clear();
|
||||||
|
}
|
||||||
|
}
|
16
history.txt
16
history.txt
@ -1,3 +1,15 @@
|
|||||||
|
2010-12-30 zzz
|
||||||
|
* Data Structures:
|
||||||
|
- New SDSCache for SimpleDataStructures
|
||||||
|
- New SimpleByteCache for byte[]
|
||||||
|
- Cache Hash, PublicKey, and SigningPublicKey
|
||||||
|
- Remove global lock in ByteCache
|
||||||
|
* I2CP: Missing piece of parallel naming lookup
|
||||||
|
* i2psnark: Fix buttons on Firefox 4.0b
|
||||||
|
* i2ptunnel:
|
||||||
|
- Use dropdown box to select interface for clients
|
||||||
|
- Warn on index page if required fields not set
|
||||||
|
|
||||||
2010-12-29 zzz
|
2010-12-29 zzz
|
||||||
* Console: Add 500 error page
|
* Console: Add 500 error page
|
||||||
* DSAEngine: Restore variants of methods using a Hash argument,
|
* DSAEngine: Restore variants of methods using a Hash argument,
|
||||||
@ -42,7 +54,9 @@
|
|||||||
- Add support for specifying the timeout for DestLookups
|
- Add support for specifying the timeout for DestLookups
|
||||||
(can only be smaller than the router timeout for now)
|
(can only be smaller than the router timeout for now)
|
||||||
- Extend dest lookup router timeout from 10s to 15s
|
- Extend dest lookup router timeout from 10s to 15s
|
||||||
* i2psnark: Backport TrackerClient NPE fix
|
* i2psnark:
|
||||||
|
- Backport TrackerClient NPE fix
|
||||||
|
- Fix last piece length calculation for torrents > 2GB (ticket #361)
|
||||||
* i2ptunnel:
|
* i2ptunnel:
|
||||||
- Get Log from the logManager instead of instantiating,
|
- Get Log from the logManager instead of instantiating,
|
||||||
so we may adjust the levels on the fly
|
so we may adjust the levels on the fly
|
||||||
|
@ -93,9 +93,10 @@ public class BuildRequestRecord {
|
|||||||
* the gateway to which the reply should be sent.
|
* the gateway to which the reply should be sent.
|
||||||
*/
|
*/
|
||||||
public Hash readNextIdentity() {
|
public Hash readNextIdentity() {
|
||||||
byte rv[] = new byte[Hash.HASH_LENGTH];
|
//byte rv[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(_data.getData(), _data.getOffset() + OFF_SEND_IDENT, rv, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(_data.getData(), _data.getOffset() + OFF_SEND_IDENT, rv, 0, Hash.HASH_LENGTH);
|
||||||
return new Hash(rv);
|
//return new Hash(rv);
|
||||||
|
return Hash.create(_data.getData(), _data.getOffset() + OFF_SEND_IDENT);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Tunnel layer encryption key that the current hop should use
|
* Tunnel layer encryption key that the current hop should use
|
||||||
|
@ -133,15 +133,17 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
|
|||||||
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
||||||
int curIndex = offset;
|
int curIndex = offset;
|
||||||
|
|
||||||
byte keyData[] = new byte[Hash.HASH_LENGTH];
|
//byte keyData[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
|
||||||
|
_key = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
_key = new Hash(keyData);
|
//_key = new Hash(keyData);
|
||||||
|
|
||||||
byte fromData[] = new byte[Hash.HASH_LENGTH];
|
//byte fromData[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, fromData, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, fromData, 0, Hash.HASH_LENGTH);
|
||||||
|
_fromHash = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
_fromHash = new Hash(fromData);
|
//_fromHash = new Hash(fromData);
|
||||||
|
|
||||||
boolean tunnelSpecified = false;
|
boolean tunnelSpecified = false;
|
||||||
switch (data[curIndex]) {
|
switch (data[curIndex]) {
|
||||||
@ -168,10 +170,11 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
|
|||||||
throw new I2NPMessageException("Invalid number of peers - " + numPeers);
|
throw new I2NPMessageException("Invalid number of peers - " + numPeers);
|
||||||
Set<Hash> peers = new HashSet(numPeers);
|
Set<Hash> peers = new HashSet(numPeers);
|
||||||
for (int i = 0; i < numPeers; i++) {
|
for (int i = 0; i < numPeers; i++) {
|
||||||
byte peer[] = new byte[Hash.HASH_LENGTH];
|
//byte peer[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, peer, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, peer, 0, Hash.HASH_LENGTH);
|
||||||
|
Hash p = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
peers.add(new Hash(peer));
|
peers.add(p);
|
||||||
}
|
}
|
||||||
_dontIncludePeers = peers;
|
_dontIncludePeers = peers;
|
||||||
}
|
}
|
||||||
|
@ -55,26 +55,29 @@ public class DatabaseSearchReplyMessage extends I2NPMessageImpl {
|
|||||||
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
||||||
int curIndex = offset;
|
int curIndex = offset;
|
||||||
|
|
||||||
byte keyData[] = new byte[Hash.HASH_LENGTH];
|
//byte keyData[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
|
||||||
|
_key = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
_key = new Hash(keyData);
|
//_key = new Hash(keyData);
|
||||||
|
|
||||||
int num = (int)DataHelper.fromLong(data, curIndex, 1);
|
int num = (int)DataHelper.fromLong(data, curIndex, 1);
|
||||||
curIndex++;
|
curIndex++;
|
||||||
|
|
||||||
_peerHashes.clear();
|
_peerHashes.clear();
|
||||||
for (int i = 0; i < num; i++) {
|
for (int i = 0; i < num; i++) {
|
||||||
byte peer[] = new byte[Hash.HASH_LENGTH];
|
//byte peer[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, peer, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, peer, 0, Hash.HASH_LENGTH);
|
||||||
|
Hash p = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
addReply(new Hash(peer));
|
addReply(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte from[] = new byte[Hash.HASH_LENGTH];
|
//byte from[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, from, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, from, 0, Hash.HASH_LENGTH);
|
||||||
|
_from = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
_from = new Hash(from);
|
//_from = new Hash(from);
|
||||||
|
|
||||||
//_context.statManager().addRateData("netDb.searchReplyMessageReceive", num*32 + 64, 1);
|
//_context.statManager().addRateData("netDb.searchReplyMessageReceive", num*32 + 64, 1);
|
||||||
}
|
}
|
||||||
|
@ -113,10 +113,11 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
|
|||||||
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
||||||
int curIndex = offset;
|
int curIndex = offset;
|
||||||
|
|
||||||
byte keyData[] = new byte[Hash.HASH_LENGTH];
|
//byte keyData[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
|
||||||
|
_key = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
_key = new Hash(keyData);
|
//_key = new Hash(keyData);
|
||||||
|
|
||||||
_type = (int)DataHelper.fromLong(data, curIndex, 1);
|
_type = (int)DataHelper.fromLong(data, curIndex, 1);
|
||||||
curIndex++;
|
curIndex++;
|
||||||
@ -130,10 +131,11 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
|
|||||||
_replyTunnel = new TunnelId(tunnel);
|
_replyTunnel = new TunnelId(tunnel);
|
||||||
curIndex += 4;
|
curIndex += 4;
|
||||||
|
|
||||||
byte gw[] = new byte[Hash.HASH_LENGTH];
|
//byte gw[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, curIndex, gw, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, curIndex, gw, 0, Hash.HASH_LENGTH);
|
||||||
|
_replyGateway = Hash.create(data, curIndex);
|
||||||
curIndex += Hash.HASH_LENGTH;
|
curIndex += Hash.HASH_LENGTH;
|
||||||
_replyGateway = new Hash(gw);
|
//_replyGateway = new Hash(gw);
|
||||||
} else {
|
} else {
|
||||||
_replyTunnel = null;
|
_replyTunnel = null;
|
||||||
_replyGateway = null;
|
_replyGateway = null;
|
||||||
|
@ -90,18 +90,21 @@ public class DeliveryInstructions extends DataStructureImpl {
|
|||||||
case FLAG_MODE_LOCAL:
|
case FLAG_MODE_LOCAL:
|
||||||
break;
|
break;
|
||||||
case FLAG_MODE_DESTINATION:
|
case FLAG_MODE_DESTINATION:
|
||||||
Hash destHash = new Hash();
|
//Hash destHash = new Hash();
|
||||||
destHash.readBytes(in);
|
//destHash.readBytes(in);
|
||||||
|
Hash destHash = Hash.create(in);
|
||||||
setDestination(destHash);
|
setDestination(destHash);
|
||||||
break;
|
break;
|
||||||
case FLAG_MODE_ROUTER:
|
case FLAG_MODE_ROUTER:
|
||||||
Hash routerHash = new Hash();
|
//Hash routerHash = new Hash();
|
||||||
routerHash.readBytes(in);
|
//routerHash.readBytes(in);
|
||||||
|
Hash routerHash = Hash.create(in);
|
||||||
setRouter(routerHash);
|
setRouter(routerHash);
|
||||||
break;
|
break;
|
||||||
case FLAG_MODE_TUNNEL:
|
case FLAG_MODE_TUNNEL:
|
||||||
Hash tunnelRouterHash = new Hash();
|
//Hash tunnelRouterHash = new Hash();
|
||||||
tunnelRouterHash.readBytes(in);
|
//tunnelRouterHash.readBytes(in);
|
||||||
|
Hash tunnelRouterHash = Hash.create(in);
|
||||||
setRouter(tunnelRouterHash);
|
setRouter(tunnelRouterHash);
|
||||||
TunnelId id = new TunnelId();
|
TunnelId id = new TunnelId();
|
||||||
id.readBytes(in);
|
id.readBytes(in);
|
||||||
@ -140,22 +143,25 @@ public class DeliveryInstructions extends DataStructureImpl {
|
|||||||
case FLAG_MODE_LOCAL:
|
case FLAG_MODE_LOCAL:
|
||||||
break;
|
break;
|
||||||
case FLAG_MODE_DESTINATION:
|
case FLAG_MODE_DESTINATION:
|
||||||
byte destHash[] = new byte[Hash.HASH_LENGTH];
|
//byte destHash[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, cur, destHash, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, cur, destHash, 0, Hash.HASH_LENGTH);
|
||||||
|
Hash dh = Hash.create(data, cur);
|
||||||
cur += Hash.HASH_LENGTH;
|
cur += Hash.HASH_LENGTH;
|
||||||
setDestination(new Hash(destHash));
|
setDestination(dh);
|
||||||
break;
|
break;
|
||||||
case FLAG_MODE_ROUTER:
|
case FLAG_MODE_ROUTER:
|
||||||
byte routerHash[] = new byte[Hash.HASH_LENGTH];
|
//byte routerHash[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, cur, routerHash, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, cur, routerHash, 0, Hash.HASH_LENGTH);
|
||||||
|
Hash rh = Hash.create(data, cur);
|
||||||
cur += Hash.HASH_LENGTH;
|
cur += Hash.HASH_LENGTH;
|
||||||
setRouter(new Hash(routerHash));
|
setRouter(rh);
|
||||||
break;
|
break;
|
||||||
case FLAG_MODE_TUNNEL:
|
case FLAG_MODE_TUNNEL:
|
||||||
byte tunnelRouterHash[] = new byte[Hash.HASH_LENGTH];
|
//byte tunnelRouterHash[] = new byte[Hash.HASH_LENGTH];
|
||||||
System.arraycopy(data, cur, tunnelRouterHash, 0, Hash.HASH_LENGTH);
|
//System.arraycopy(data, cur, tunnelRouterHash, 0, Hash.HASH_LENGTH);
|
||||||
|
Hash trh = Hash.create(data, cur);
|
||||||
cur += Hash.HASH_LENGTH;
|
cur += Hash.HASH_LENGTH;
|
||||||
setRouter(new Hash(tunnelRouterHash));
|
setRouter(trh);
|
||||||
setTunnelId(new TunnelId(DataHelper.fromLong(data, cur, 4)));
|
setTunnelId(new TunnelId(DataHelper.fromLong(data, cur, 4)));
|
||||||
cur += 4;
|
cur += 4;
|
||||||
break;
|
break;
|
||||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 4;
|
public final static long BUILD = 5;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
@ -28,7 +28,8 @@ class LookupDestJob extends JobImpl {
|
|||||||
public String getName() { return "LeaseSet Lookup for Client"; }
|
public String getName() { return "LeaseSet Lookup for Client"; }
|
||||||
public void runJob() {
|
public void runJob() {
|
||||||
DoneJob done = new DoneJob(getContext());
|
DoneJob done = new DoneJob(getContext());
|
||||||
getContext().netDb().lookupLeaseSet(_hash, done, done, 10*1000);
|
// TODO add support for specifying the timeout in the lookup message
|
||||||
|
getContext().netDb().lookupLeaseSet(_hash, done, done, 15*1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DoneJob extends JobImpl {
|
private class DoneJob extends JobImpl {
|
||||||
@ -41,7 +42,7 @@ class LookupDestJob extends JobImpl {
|
|||||||
if (ls != null)
|
if (ls != null)
|
||||||
returnDest(ls.getDestination());
|
returnDest(ls.getDestination());
|
||||||
else
|
else
|
||||||
returnDest(null);
|
returnHash(_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,4 +52,15 @@ class LookupDestJob extends JobImpl {
|
|||||||
_runner.doSend(msg);
|
_runner.doSend(msg);
|
||||||
} catch (I2CPMessageException ime) {}
|
} catch (I2CPMessageException ime) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the failed hash so the client can correlate replies with requests
|
||||||
|
* @since 0.8.3
|
||||||
|
*/
|
||||||
|
private void returnHash(Hash h) {
|
||||||
|
DestReplyMessage msg = new DestReplyMessage(h);
|
||||||
|
try {
|
||||||
|
_runner.doSend(msg);
|
||||||
|
} catch (I2CPMessageException ime) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import java.util.Set;
|
|||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.DataFormatException;
|
import net.i2p.data.DataFormatException;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
@ -294,11 +295,15 @@ class ProfilePersistenceHelper {
|
|||||||
private Hash getHash(String name) {
|
private Hash getHash(String name) {
|
||||||
String key = name.substring("profile-".length());
|
String key = name.substring("profile-".length());
|
||||||
key = key.substring(0, key.length() - ".dat".length());
|
key = key.substring(0, key.length() - ".dat".length());
|
||||||
Hash h = new Hash();
|
//Hash h = new Hash();
|
||||||
try {
|
try {
|
||||||
h.fromBase64(key);
|
//h.fromBase64(key);
|
||||||
|
byte[] b = Base64.decode(key);
|
||||||
|
if (b == null)
|
||||||
|
return null;
|
||||||
|
Hash h = Hash.create(b);
|
||||||
return h;
|
return h;
|
||||||
} catch (DataFormatException dfe) {
|
} catch (Exception dfe) {
|
||||||
_log.warn("Invalid base64 [" + key + "]", dfe);
|
_log.warn("Invalid base64 [" + key + "]", dfe);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -327,11 +327,12 @@ public class FragmentHandler {
|
|||||||
offset += 4;
|
offset += 4;
|
||||||
}
|
}
|
||||||
if ( (type == TYPE_ROUTER) || (type == TYPE_TUNNEL) ) {
|
if ( (type == TYPE_ROUTER) || (type == TYPE_TUNNEL) ) {
|
||||||
byte h[] = new byte[Hash.HASH_LENGTH];
|
|
||||||
if (offset + Hash.HASH_LENGTH >= preprocessed.length)
|
if (offset + Hash.HASH_LENGTH >= preprocessed.length)
|
||||||
return -1;
|
return -1;
|
||||||
System.arraycopy(preprocessed, offset, h, 0, Hash.HASH_LENGTH);
|
//byte h[] = new byte[Hash.HASH_LENGTH];
|
||||||
router = new Hash(h);
|
//System.arraycopy(preprocessed, offset, h, 0, Hash.HASH_LENGTH);
|
||||||
|
//router = new Hash(h);
|
||||||
|
router = Hash.create(preprocessed, offset);
|
||||||
offset += Hash.HASH_LENGTH;
|
offset += Hash.HASH_LENGTH;
|
||||||
}
|
}
|
||||||
if (fragmented) {
|
if (fragmented) {
|
||||||
|
Reference in New Issue
Block a user