diff --git a/.tx/config b/.tx/config index 912deece3..1374640b0 100644 --- a/.tx/config +++ b/.tx/config @@ -271,6 +271,10 @@ trans.ru_RU = core/java/src/gnu/getopt/MessagesBundle_ru.properties trans.sk = core/java/src/gnu/getopt/MessagesBundle_sk.properties trans.zh_CN = core/java/src/gnu/getopt/MessagesBundle_zh.properties +[I2P.streaming] +source_file = apps/ministreaming/locale/messages_en.po +source_lang = en + [main] host = https://www.transifex.com diff --git a/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java b/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java index d514f314a..cc0516bd6 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java @@ -78,7 +78,7 @@ public class ConfigurationManager { * @return The value of a configuration: true if found, defaultValue if not found. */ public boolean getBooleanConfiguration(String arg, boolean defaultValue) { - Boolean value = ((Boolean) booleanConfigurations.get("startWithI2P")); + Boolean value = booleanConfigurations.get("startWithI2P"); System.out.println(value); if(value != null) { return value; diff --git a/apps/i2psnark/java/src/org/klomp/snark/Peer.java b/apps/i2psnark/java/src/org/klomp/snark/Peer.java index 683b3f221..ab15bb85c 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Peer.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Peer.java @@ -194,9 +194,8 @@ public class Peer implements Comparable * Compares the PeerIDs. * @deprecated unused? */ - public int compareTo(Peer o) + public int compareTo(Peer p) { - Peer p = (Peer)o; int rv = peerID.compareTo(p.peerID); if (rv == 0) { if (_id > p._id) return 1; diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java index 09b5b64fc..0de45da06 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java @@ -62,7 +62,7 @@ class TrackerInfo private TrackerInfo(Map m, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util) throws IOException { - BEValue reason = (BEValue)m.get("failure reason"); + BEValue reason = m.get("failure reason"); if (reason != null) { failure_reason = reason.getString(); @@ -72,13 +72,13 @@ class TrackerInfo else { failure_reason = null; - BEValue beInterval = (BEValue)m.get("interval"); + BEValue beInterval = m.get("interval"); if (beInterval == null) throw new InvalidBEncodingException("No interval given"); else interval = beInterval.getInt(); - BEValue bePeers = (BEValue)m.get("peers"); + BEValue bePeers = m.get("peers"); if (bePeers == null) { peers = Collections.emptySet(); } else { @@ -93,14 +93,14 @@ class TrackerInfo peers = p; } - BEValue bev = (BEValue)m.get("complete"); + BEValue bev = m.get("complete"); if (bev != null) try { complete = bev.getInt(); if (complete < 0) complete = 0; } catch (InvalidBEncodingException ibe) {} - bev = (BEValue)m.get("incomplete"); + bev = m.get("incomplete"); if (bev != null) try { incomplete = bev.getInt(); if (incomplete < 0) diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index ae39a7937..db5ec397f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -204,8 +204,7 @@ public class I2PSnarkServlet extends BasicServlet { resp.sendError(404); } else { String base = addPaths(req.getRequestURI(), "/"); - @SuppressWarnings("unchecked") // TODO-Java6: Remove cast, return type is correct - String listing = getListHTML(resource, base, true, method.equals("POST") ? (Map) req.getParameterMap() : null); + String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null); if (method.equals("POST")) { // P-R-G sendRedirect(req, resp, ""); @@ -547,7 +546,7 @@ public class I2PSnarkServlet extends BasicServlet { String stParamStr = stParam == null ? "" : "&st=" + stParam; for (int i = 0; i < total; i++) { - Snark snark = (Snark)snarks.get(i); + Snark snark = snarks.get(i); boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.getInfoHash()).equals(peerParam); boolean hide = i < start || i >= start + pageSize; displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, noThinsp, showDebug, hide, stParamStr); diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml index 25a5f79c7..c7bd9af95 100644 --- a/apps/i2ptunnel/java/build.xml +++ b/apps/i2ptunnel/java/build.xml @@ -25,6 +25,7 @@ + @@ -34,7 +35,7 @@ @@ -281,7 +282,7 @@ - diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 27077c320..625ae863a 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -1247,11 +1247,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(host.length() == 60 && host.toLowerCase(Locale.US).endsWith(".b32.i2p")) { return host; } - Destination _dest = _context.namingService().lookup(host); - if(_dest == null) { + Destination dest = _context.namingService().lookup(host); + if (dest == null) return "i2p"; - } - return Base32.encode(_dest.calculateHash().getData()) + ".b32.i2p"; + return dest.toBase32(); } public static final String DEFAULT_JUMP_SERVERS = diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java index f87068f3a..4813fa2a1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java @@ -646,7 +646,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem /** * @param jumpServers comma- or space-separated list, or null - * @param msg extra message + * @param extraMessage extra message * @since 0.9.14 */ protected void writeErrorMessage(byte[] errMessage, String extraMessage, diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java index c199b5075..128b1565d 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java @@ -30,7 +30,6 @@ import net.i2p.util.ByteCache; import net.i2p.util.EventDispatcher; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; -import net.i2p.data.Base32; /** * Simple extension to the I2PTunnelServer that filters the HTTP @@ -249,7 +248,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { } addEntry(headers, HASH_HEADER, peerHash.toBase64()); - addEntry(headers, DEST32_HEADER, Base32.encode(peerHash.getData()) + ".b32.i2p"); + addEntry(headers, DEST32_HEADER, socket.getPeerDestination().toBase32()); addEntry(headers, DEST64_HEADER, socket.getPeerDestination().toBase64()); // Port-specific spoofhost diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java index c74dad266..3915ae688 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java @@ -10,7 +10,6 @@ import java.util.StringTokenizer; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketAddress; -import net.i2p.data.Base32; import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.i2ptunnel.irc.DCCClientManager; @@ -239,7 +238,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { } public String getB32Hostname() { - return Base32.encode(sockMgr.getSession().getMyDestination().calculateHash().getData()) + ".b32.i2p"; + return sockMgr.getSession().getMyDestination().toBase32(); } public byte[] getLocalAddress() { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java index 8488c1e5a..96fab6213 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java @@ -14,7 +14,6 @@ import net.i2p.client.I2PClient; import net.i2p.client.I2PClientFactory; import net.i2p.client.I2PSession; import net.i2p.crypto.SigType; -import net.i2p.data.Base32; import net.i2p.data.Destination; import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel; import net.i2p.util.FileUtil; @@ -156,7 +155,7 @@ public class TunnelController implements Logging { log("Private key created and saved in " + keyFile.getAbsolutePath()); log("You should backup this file in a secure place."); log("New destination: " + destStr); - String b32 = Base32.encode(dest.calculateHash().getData()) + ".b32.i2p"; + String b32 = dest.toBase32(); log("Base32: " + b32); File backupDir = new SecureFile(I2PAppContext.getGlobalContext().getConfigDir(), KEY_BACKUP_DIR); if (backupDir.isDirectory() || backupDir.mkdir()) { @@ -633,6 +632,9 @@ public class TunnelController implements Logging { return null; } + /** + * @return "{52 chars}.b32.i2p" or null + */ public String getMyDestHashBase32() { if (_tunnel != null) { List sessions = _tunnel.getSessions(); @@ -640,7 +642,7 @@ public class TunnelController implements Logging { I2PSession session = sessions.get(i); Destination dest = session.getMyDestination(); if (dest != null) - return Base32.encode(dest.calculateHash().getData()); + return dest.toBase32(); } } return null; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java index f2b35a34d..e2e7edc72 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java @@ -1,7 +1,6 @@ package net.i2p.i2ptunnel.socks; import net.i2p.I2PAppContext; -import net.i2p.data.Base32; import net.i2p.data.Destination; /** @@ -44,7 +43,7 @@ public class SOCKSHeader { } private static final byte[] beg = {0,0,0,3,60}; - private static final byte[] end = {'.','b','3','2','.','i','2','p',0,0}; + private static final byte[] end = {0,0}; /** * Make a dummy header from a dest, @@ -52,11 +51,11 @@ public class SOCKSHeader { * Unused for now. */ public SOCKSHeader(Destination dest) { - this.header = new byte[beg.length + 52 + end.length]; + this.header = new byte[beg.length + 60 + end.length]; System.arraycopy(this.header, 0, beg, 0, beg.length); - String b32 = Base32.encode(dest.calculateHash().getData()); - System.arraycopy(this.header, beg.length, b32.getBytes(), 0, 52); - System.arraycopy(this.header, beg.length + 52, end, 0, end.length); + String b32 = dest.toBase32(); + System.arraycopy(this.header, beg.length, b32.getBytes(), 0, 60); + System.arraycopy(this.header, beg.length + 60, end, 0, end.length); } public String getHost() { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java index 698c3cd42..fc5ca687b 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java @@ -25,7 +25,6 @@ import net.i2p.I2PAppContext; import net.i2p.app.ClientAppManager; import net.i2p.app.Outproxy; import net.i2p.client.I2PClient; -import net.i2p.data.Base32; import net.i2p.data.Certificate; import net.i2p.data.Destination; import net.i2p.data.PrivateKeyFile; @@ -649,6 +648,9 @@ public class IndexBean { return ""; } + /** + * @return "{52 chars}.b32.i2p" or "" + */ public String getDestHashBase32(int tunnel) { TunnelController tun = getController(tunnel); if (tun != null) { @@ -1127,7 +1129,7 @@ public class IndexBean { return "Modification failed: " + e; } return "Destination modified - " + - "New Base32 is " + Base32.encode(newdest.calculateHash().getData()) + ".b32.i2p " + + "New Base32 is " + newdest.toBase32() + "New Destination is " + newdest.toBase64(); } diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp index 90a83ff64..46d6090e1 100644 --- a/apps/i2ptunnel/jsp/editClient.jsp +++ b/apps/i2ptunnel/jsp/editClient.jsp @@ -440,7 +440,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
- <%=editBean.getDestHashBase32(curTunnel)%>.b32.i2p + <%=editBean.getDestHashBase32(curTunnel)%>
<% } // if destb64 %> diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp index 4f59fde0a..5f7140a21 100644 --- a/apps/i2ptunnel/jsp/index.jsp +++ b/apps/i2ptunnel/jsp/index.jsp @@ -134,10 +134,10 @@ <% if (("httpserver".equals(indexBean.getInternalType(curServer)) || ("httpbidirserver".equals(indexBean.getInternalType(curServer)))) && indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) { %> - <%=intl._("Preview")%> + <%=intl._("Preview")%> <% } else if (indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) { - %><%=intl._("Base32 Address")%>:
<%=indexBean.getDestHashBase32(curServer)%>.b32.i2p
+ %><%=intl._("Base32 Address")%>:
<%=indexBean.getDestHashBase32(curServer)%>
<% } else { %><%=intl._("No Preview")%> diff --git a/apps/ministreaming/java/build.xml b/apps/ministreaming/java/build.xml index 71dc5a465..4d9ebf2bb 100644 --- a/apps/ministreaming/java/build.xml +++ b/apps/ministreaming/java/build.xml @@ -19,12 +19,21 @@ + + + + + + + + + - @@ -36,7 +45,7 @@ @@ -62,7 +71,7 @@ - + @@ -89,6 +98,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/ministreaming/java/bundle-messages.sh b/apps/ministreaming/java/bundle-messages.sh new file mode 100755 index 000000000..82974403c --- /dev/null +++ b/apps/ministreaming/java/bundle-messages.sh @@ -0,0 +1,112 @@ +#!/bin/sh +# +# Update messages_xx.po and messages_xx.class files, +# from both java and jsp sources. +# Requires installed programs xgettext, msgfmt, msgmerge, and find. +# +# usage: +# bundle-messages.sh (generates the resource bundle from the .po file) +# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle) +# +# zzz - public domain +# +CLASS=net.i2p.client.streaming.messages +TMPFILE=build/javafiles.txt +export TZ=UTC +RC=0 + +if ! $(which javac > /dev/null 2>&1); then + export JAVAC=${JAVA_HOME}/../bin/javac +fi + +if [ "$1" = "-p" ] +then + POUPDATE=1 +fi + +# on windows, one must specify the path of commnad find +# since windows has its own retarded version of find. +if which find|grep -q -i windows ; then + export PATH=.:/bin:/usr/local/bin:$PATH +fi +# Fast mode - update ondemond +# set LG2 to the language you need in envrionment varibales to enable this + +# add ../java/ so the refs will work in the po file +JPATHS="../java/src" +for i in ../locale/messages_*.po +do + # get language + LG=${i#../locale/messages_} + LG=${LG%.po} + + # skip, if specified + if [ $LG2 ]; then + [ $LG != $LG2 ] && continue || echo INFO: Language update is set to [$LG2] only. + fi + + if [ "$POUPDATE" = "1" ] + then + # make list of java files newer than the .po file + find $JPATHS -name *.java -newer $i > $TMPFILE + fi + + if [ -s build/obj/net/i2p/streaming/messages_$LG.class -a \ + build/obj/net/i2p/streaming/messages_$LG.class -nt $i -a \ + ! -s $TMPFILE ] + then + continue + fi + + if [ "$POUPDATE" = "1" ] + then + echo "Updating the $i file from the tags..." + # extract strings from java and jsp files, and update messages.po files + # translate calls must be one of the forms: + # _("foo") + # _x("foo") + # To start a new translation, copy the header from an old translation to the new .po file, + # then ant distclean poupdate. + find $JPATHS -name *.java > $TMPFILE + xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\ + --keyword=_ --keyword=_x \ + -o ${i}t + if [ $? -ne 0 ] + then + echo "ERROR - xgettext failed on ${i}, not updating translations" + rm -f ${i}t + RC=1 + break + fi + msgmerge -U --backup=none $i ${i}t + if [ $? -ne 0 ] + then + echo "ERROR - msgmerge failed on ${i}, not updating translations" + rm -f ${i}t + RC=1 + break + fi + rm -f ${i}t + # so we don't do this again + touch $i + fi + + if [ "$LG" != "en" ] + then + # only generate for non-source language + echo "Generating ${CLASS}_$LG ResourceBundle..." + + # convert to class files in build/obj + msgfmt --java --statistics -r $CLASS -l $LG -d build/obj $i + if [ $? -ne 0 ] + then + echo "ERROR - msgfmt failed on ${i}, not updating translations" + # msgfmt leaves the class file there so the build would work the next time + find build/obj -name messages_${LG}.class -exec rm -f {} \; + RC=1 + break + fi + fi +done +rm -f $TMPFILE +exit $RC diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java b/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java index 3cf5949db..43f392dba 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java @@ -1,7 +1,5 @@ package net.i2p.client.streaming; -import net.i2p.client.streaming.I2PSocket; -import net.i2p.client.streaming.I2PSocketManager; import net.i2p.I2PException; import java.net.ConnectException; import java.nio.channels.SelectableChannel; @@ -12,6 +10,8 @@ import java.nio.channels.SelectableChannel; * * Warning, this interface and implementation is preliminary and subject to change without notice. * + * Unimplemented, unlikely to ever be implemented. + * * @since 0.8.11 */ public abstract class AcceptingChannel extends SelectableChannel { diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java index 6a8e3a6cf..35fb68daa 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java @@ -32,6 +32,10 @@ public interface I2PServerSocket { public I2PSocket accept() throws I2PException, ConnectException, SocketTimeoutException; /** + * Unimplemented, unlikely to ever be implemented. + * + * @deprecated + * @return null always * @since 0.8.11 */ public AcceptingChannel getChannel(); diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocket.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocket.java index 3ddcb9533..f84fad967 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocket.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocket.java @@ -43,6 +43,10 @@ public interface I2PSocket extends Closeable { public OutputStream getOutputStream() throws IOException; /** + * Unimplemented, unlikely to ever be implemented. + * + * @deprecated + * @return null always * @since 0.8.9 */ public SelectableChannel getChannel() throws IOException; diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketException.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketException.java index e1f9f0cb3..db4f863dd 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketException.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketException.java @@ -109,7 +109,8 @@ public class I2PSocketException extends SocketException { return super.getMessage(); default: - return "Failure code: " + _status; + // Translate this one here, can't do it later + return _("Failure code") + ": " + _status; } } @@ -121,6 +122,13 @@ public class I2PSocketException extends SocketException { String s = getMessage(); if (s == null) return null; + return _(s); + } + + /** + * Translate + */ + private static String _(String s) { return Translate.getString(s, I2PAppContext.getGlobalContext(), BUNDLE_NAME); } diff --git a/apps/ministreaming/locale/messages_en.po b/apps/ministreaming/locale/messages_en.po new file mode 100644 index 000000000..ca8625519 --- /dev/null +++ b/apps/ministreaming/locale/messages_en.po @@ -0,0 +1,85 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +msgid "" +msgstr "" +"Project-Id-Version: I2P streaming\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "" diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java index b9d3beffb..21be2aa59 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigServiceHandler.java @@ -25,6 +25,7 @@ public class ConfigServiceHandler extends FormHandler { private static WrapperListener _wrapperListener; private static final String LISTENER_AVAILABLE = "3.2.0"; + private static final String PROPERTIES_AVAILABLE = "3.2.0"; /** * Register two shutdown hooks, one to rekey and/or tell the wrapper we are stopping, @@ -72,19 +73,20 @@ public class ConfigServiceHandler extends FormHandler { ContextHelper.getContext(null).router().killKeys(); if (_tellWrapper) { int wait = WAIT; - // getProperties() not available on old wrappers, - // TODO find out what version and test - try { - Properties props = WrapperManager.getProperties(); - String tmout = props.getProperty("wrapper.jvm_exit.timeout"); - if (tmout != null) { - try { - int cwait = Integer.parseInt(tmout) * 1000; - if (cwait > wait) - wait = cwait; - } catch (NumberFormatException nfe) {} - } - } catch (Throwable t) {} + String wv = System.getProperty("wrapper.version"); + if (wv != null && VersionComparator.comp(wv, PROPERTIES_AVAILABLE) >= 0) { + try { + Properties props = WrapperManager.getProperties(); + String tmout = props.getProperty("wrapper.jvm_exit.timeout"); + if (tmout != null) { + try { + int cwait = Integer.parseInt(tmout) * 1000; + if (cwait > wait) + wait = cwait; + } catch (NumberFormatException nfe) {} + } + } catch (Throwable t) {} + } WrapperManager.signalStopping(wait); } } catch (Throwable t) { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java new file mode 100644 index 000000000..1b9e86fa2 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java @@ -0,0 +1,217 @@ +package net.i2p.router.web; + +import java.io.IOException; +import java.io.Writer; +import java.text.Collator; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; + +import net.i2p.data.DataHelper; +import net.i2p.router.util.EventLog; + +/** + * /events.jsp + */ +public class EventLogHelper extends FormHandler { + protected Writer _out; + private long _from, _age; + //private long _to = Long.MAX_VALUE; + private String _event = ALL; + // EventLog name to translated display string + private final Map _xevents; + + private static final String ALL = "all"; + private static final String[] _events = new String[] { + EventLog.ABORTED, _x("Aborted startup"), + EventLog.CHANGE_IP, _x("Changed IP"), + EventLog.CHANGE_PORT, _x("Changed port"), + EventLog.CLOCK_SHIFT, _x("Clock shifted"), + EventLog.CRASHED, _x("Crashed"), + EventLog.CRITICAL, _x("Critical error"), + EventLog.INSTALLED, _x("Installed new version"), + EventLog.INSTALL_FAILED, _x("Install failed"), + EventLog.NETWORK, _x("Network error"), + EventLog.NEW_IDENT, _x("New router identity"), + EventLog.OOM, _x("Out of memory error"), + EventLog.REKEYED, _x("New router identity"), + EventLog.RESEED, _x("Reseeded router"), + EventLog.SOFT_RESTART, _x("Soft restart"), + EventLog.STARTED, _x("Started router"), + EventLog.STOPPED, _x("Stopped router"), + EventLog.UPDATED, _x("Updated router"), + EventLog.WATCHDOG, _x("Watchdog warning") + }; + private static final long DAY = 24*60*60*1000L; + private static final long[] _times = { 0, DAY, 7*DAY, 30*DAY, 365*DAY }; + + public EventLogHelper() { + super(); + _xevents = new HashMap(1 + (_events.length / 2)); + } + + /** set the defaults after we have a context */ + @Override + public void setContextId(String contextId) { + super.setContextId(contextId); + for (int i = 0; i < _events.length; i += 2) { + _xevents.put(_events[i], _(_events[i + 1])); + } + } + + public void storeWriter(Writer out) { _out = out; } + + public void setFrom(String s) { + try { + _age = Long.parseLong(s); + if (_age > 0) + _from = _context.clock().now() - _age; + else + _from = 0; + } catch (NumberFormatException nfe) { + _age = 0; + _from = 0; + } + } + + //public void setTo(String s) { + // _to = s; + //} + + public void setType(String s) { + _event = s; + } + + public String getForm() { + // too hard to use the standard formhandler.jsi / FormHandler.java session nonces + // since graphs.jsp needs the refresh value in its . + // So just use the "shared/console nonce". + String nonce = CSSHelper.getNonce(); + try { + _out.write("

" + _("Display Events") + "

"); + _out.write("
\n" + + "\n" + + "\n"); + _out.write(_("Events since") + ":
"); + _out.write(_("Event type") + ": " + + "
"); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + return ""; + } + + private void writeOption(String key, String val) throws IOException { + _out.write("\n"); + } + + private void writeOption(long age) throws IOException { + _out.write("\n"); + } + + public String getEvents() { + EventLog ev = _context.router().eventLog(); + // oldest first + Map events; + boolean isAll = ALL.equals(_event); + if (isAll) + events = ev.getEvents(_from); + else + events = ev.getEvents(_event, _from); + String xev = _xevents.get(_event); + if (xev == null) + xev = _event; + if (events.isEmpty()) { + if (isAll) { + if (_age == 0) + return _("No events found"); + return _("No events found in previous {0}", DataHelper.formatDuration2(_age)); + } + if (_age == 0) + return _("No \"{0}\" events found", xev); + return _("No \"{0}\" events found in previous {1}", xev, DataHelper.formatDuration2(_age)); + } + StringBuilder buf = new StringBuilder(2048); + buf.append(""); + + SimpleDateFormat fmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); + // the router sets the JVM time zone to UTC but saves the original here so we can get it + String systemTimeZone = _context.getProperty("i2p.systemTimeZone"); + if (systemTimeZone != null) + fmt.setTimeZone(TimeZone.getTimeZone(systemTimeZone)); + + List> entries = new ArrayList>(events.entrySet()); + Collections.reverse(entries); + for (Map.Entry e : entries) { + long time = e.getKey().longValue(); + String event = e.getValue(); + buf.append(""); + } + buf.append("
"); + buf.append(_("Time")); + buf.append(""); + if (isAll) { + buf.append(_("Event")); + buf.append(""); + buf.append(_("Details")); + } else { + buf.append(xev); + } + buf.append("
"); + buf.append(fmt.format(new Date(time))); + buf.append(""); + if (isAll) { + String[] s = event.split(" ", 2); + String xs = _xevents.get(s[0]); + if (xs == null) + xs = s[0]; + buf.append(xs); + buf.append(""); + if (s.length > 1) + buf.append(s[1]); + } else { + buf.append(event); + } + buf.append("
"); + return buf.toString(); + } +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java index 99064c7cc..b4d147bcc 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -267,4 +267,14 @@ public abstract class FormHandler { public String _(String s, Object o, Object o2) { return Messages.getString(s, o, o2, _context); } + + /** + * Mark a string for extraction by xgettext and translation. + * Use this only in static initializers. + * It does not translate! + * @return s + */ + public static String _x(String s) { + return s; + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java index e0abfb363..eff8dc3e3 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java @@ -13,6 +13,9 @@ import java.util.TreeSet; import net.i2p.data.DataHelper; import net.i2p.stat.Rate; +/** + * /graphs.jsp, including form, and /graph.jsp + */ public class GraphHelper extends FormHandler { protected Writer _out; private int _periodCount; @@ -31,7 +34,7 @@ public class GraphHelper extends FormHandler { private static final String PROP_EVENTS = "routerconsole.graphEvents"; public static final int DEFAULT_X = 250; public static final int DEFAULT_Y = 100; - private static final int DEFAULT_REFRESH = 60; + private static final int DEFAULT_REFRESH = 5*60; private static final int DEFAULT_PERIODS = 60; static final int MAX_X = 2048; static final int MAX_Y = 1024; diff --git a/apps/routerconsole/java/src/net/i2p/router/web/HomeHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/HomeHelper.java index 9572e8a31..7f395631d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/HomeHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/HomeHelper.java @@ -58,7 +58,7 @@ public class HomeHelper extends HelperBase { _x("Plugins") + S + _x("Add-on directory") + S + "http://plugins.i2p/" + S + I + "plugin.png" + S + _x("Postman's Tracker") + S + _x("Bittorrent tracker") + S + "http://tracker2.postman.i2p/" + S + I + "magnet.png" + S + _x("Project Website") + S + _x("I2P home page") + S + "http://i2p-projekt.i2p/" + S + I + "info_rhombus.png" + S + - "Salt" + S + "salt.i2p" + S + "http://salt.i2p/" + S + I + "salt_console.png" + S + + //"Salt" + S + "salt.i2p" + S + "http://salt.i2p/" + S + I + "salt_console.png" + S + "stats.i2p" + S + _x("I2P Network Statistics") + S + "http://stats.i2p/cgi-bin/dashboard.cgi" + S + I + "chart_line.png" + S + _x("Technical Docs") + S + _x("Technical documentation") + S + "http://i2p-projekt.i2p/how" + S + I + "education.png" + S + _x("Trac Wiki") + S + S + "http://trac.i2p2.i2p/" + S + I + "billiard_marker.png" + S + diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java index e2b480ef5..9fae3ab93 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java @@ -24,7 +24,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; -import net.i2p.data.Base32; import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.Hash; @@ -172,7 +171,7 @@ public class NetDbRenderer { median = dist; } buf.append(" Dist: ").append(fmt.format(biLog2(dist))).append("
"); - buf.append(Base32.encode(key.getData())).append(".b32.i2p
"); + buf.append(dest.toBase32()).append("
"); buf.append("Sig type: ").append(dest.getSigningPublicKey().getType()).append("
"); buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64()); buf.append("
"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java index af61baae3..b9f02e5df 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java @@ -78,7 +78,7 @@ public class TunnelRenderer { int inactive = 0; int displayed = 0; for (int i = 0; i < participating.size(); i++) { - HopConfig cfg = (HopConfig)participating.get(i); + HopConfig cfg = participating.get(i); long count = cfg.getProcessedMessagesCount(); if (count <= 0) { inactive++; diff --git a/apps/routerconsole/jsp/events.jsp b/apps/routerconsole/jsp/events.jsp new file mode 100644 index 000000000..b67aa5dd5 --- /dev/null +++ b/apps/routerconsole/jsp/events.jsp @@ -0,0 +1,28 @@ +<%@page contentType="text/html"%> +<%@page trimDirectiveWhitespaces="true"%> +<%@page pageEncoding="UTF-8"%> + + + +<%@include file="css.jsi" %> +<%=intl.title("events")%> + + " /> +<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %> + +<% + eventHelper.storeWriter(out); + eventHelper.storeMethod(request.getMethod()); +%> + +<%@include file="summaryajax.jsi" %> + +<%@include file="summary.jsi" %> +

<%=intl._("I2P Event Log")%>

+
+
+
+ + + +
diff --git a/apps/routerconsole/jsp/logs.jsp b/apps/routerconsole/jsp/logs.jsp index 538ae2abf..a028d9334 100644 --- a/apps/routerconsole/jsp/logs.jsp +++ b/apps/routerconsole/jsp/logs.jsp @@ -37,10 +37,10 @@

<%=intl._("Note that system information, log timestamps, and log messages may provide clues to your location; please review everything you include in a bug report.")%>

<%=intl._("Critical Logs")%>

-

<%=intl._("Router Logs")%> (<%=intl._("configure")%>)

-
+

<%=intl._("Event Logs")%>

+ <%=intl._("View event logs")%>

<%=intl._("Service (Wrapper) Logs")%>

-
+ diff --git a/apps/sam/java/src/net/i2p/sam/SAMBridge.java b/apps/sam/java/src/net/i2p/sam/SAMBridge.java index 580f5e88e..1894c9719 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMBridge.java +++ b/apps/sam/java/src/net/i2p/sam/SAMBridge.java @@ -33,6 +33,7 @@ import net.i2p.util.Log; /** * SAM bridge implementation. + * This is the main entry point for SAM. * * @author human */ @@ -340,7 +341,7 @@ public class SAMBridge implements Runnable, ClientApp { ////// end ClientApp helpers - static class HelpRequested extends Exception {static final long serialVersionUID=0x1;} + private static class HelpRequestedException extends Exception {static final long serialVersionUID=0x1;} /** * Usage: @@ -438,11 +439,11 @@ public class SAMBridge implements Runnable, ClientApp { return new Options(host, port, opts, keyfile); } - private static Properties parseOptions(String args[], int startArgs) throws HelpRequested { + private static Properties parseOptions(String args[], int startArgs) throws HelpRequestedException { Properties props = new Properties(); // skip over first few options for (int i = startArgs; i < args.length; i++) { - if (args[i].equals("-h")) throw new HelpRequested(); + if (args[i].equals("-h")) throw new HelpRequestedException(); int eq = args[i].indexOf('='); if (eq <= 0) continue; if (eq >= args[i].length()-1) continue; @@ -494,12 +495,14 @@ public class SAMBridge implements Runnable, ClientApp { + s.socket().getPort()); class HelloHandler implements Runnable { - SocketChannel s ; - SAMBridge parent ; + private final SocketChannel s; + private final SAMBridge parent; + HelloHandler(SocketChannel s, SAMBridge parent) { this.s = s ; this.parent = parent ; } + public void run() { try { SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps); @@ -516,13 +519,8 @@ public class SAMBridge implements Runnable, ClientApp { } catch (SAMException e) { if (_log.shouldLog(Log.ERROR)) _log.error("SAM error: " + e.getMessage(), e); - try { - String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n"; - s.write(ByteBuffer.wrap(reply.getBytes("ISO-8859-1"))); - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("SAM Error sending error reply", ioe); - } + String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n"; + SAMHandler.writeString(reply, s); try { s.close(); } catch (IOException ioe) {} } catch (Exception ee) { try { s.close(); } catch (IOException ioe) {} diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java index 53d0b6594..68971af31 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java @@ -15,7 +15,7 @@ import net.i2p.data.Destination; /** * Interface for sending raw data to a SAM client */ -public interface SAMDatagramReceiver { +interface SAMDatagramReceiver { /** * Send a byte array to a SAM client. diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java index 499f88dd3..b9367e24d 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java @@ -25,7 +25,7 @@ import net.i2p.util.Log; * * @author human */ -public class SAMDatagramSession extends SAMMessageSession { +class SAMDatagramSession extends SAMMessageSession { public static final int DGRAM_SIZE_MAX = 31*1024; diff --git a/apps/sam/java/src/net/i2p/sam/SAMException.java b/apps/sam/java/src/net/i2p/sam/SAMException.java index ae965a4c8..a2c251882 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMException.java +++ b/apps/sam/java/src/net/i2p/sam/SAMException.java @@ -13,9 +13,9 @@ package net.i2p.sam; * * @author human */ -public class SAMException extends Exception { +class SAMException extends Exception { - static final long serialVersionUID = 1 ; + private static final long serialVersionUID = 1; public SAMException() { super(); @@ -24,4 +24,9 @@ public class SAMException extends Exception { public SAMException(String s) { super(s); } + + /** @since 0.9.14 */ + public SAMException(String s, Throwable cause) { + super(s, cause); + } } diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandler.java b/apps/sam/java/src/net/i2p/sam/SAMHandler.java index 75e92e0c9..be4d99dab 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandler.java @@ -13,6 +13,7 @@ import java.nio.channels.SocketChannel; import java.nio.ByteBuffer; import java.util.Properties; +import net.i2p.data.DataHelper; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; @@ -23,7 +24,7 @@ import net.i2p.util.Log; * * @author human */ -public abstract class SAMHandler implements Runnable { +abstract class SAMHandler implements Runnable { protected final Log _log; @@ -132,10 +133,11 @@ public abstract class SAMHandler implements Runnable { } } + /** @return success */ public static boolean writeString(String str, SocketChannel out) { try { - writeBytes(ByteBuffer.wrap(str.getBytes("ISO-8859-1")), out); + writeBytes(ByteBuffer.wrap(DataHelper.getASCII(str)), out); } catch (IOException e) { //_log.debug("Caught IOException", e); return false; diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java index c6f27c133..4da579238 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java @@ -17,12 +17,14 @@ import java.util.StringTokenizer; import net.i2p.data.DataHelper; import net.i2p.util.Log; +import net.i2p.util.VersionComparator; /** * SAM handler factory class. */ -public class SAMHandlerFactory { +class SAMHandlerFactory { + private static final String VERSION = "3.1"; /** * Return the right SAM handler depending on the protocol version @@ -46,62 +48,45 @@ public class SAMHandlerFactory { } tok = new StringTokenizer(line.trim(), " "); } catch (IOException e) { - throw new SAMException("Error reading from socket: " - + e.getMessage()); + throw new SAMException("Error reading from socket", e); } catch (Exception e) { - throw new SAMException("Unexpected error: " + e.getMessage()); + throw new SAMException("Unexpected error", e); } - // Message format: HELLO VERSION MIN=v1 MAX=v2 - if (tok.countTokens() != 4) { - throw new SAMException("Bad format in HELLO message"); + // Message format: HELLO VERSION [MIN=v1] [MAX=v2] + if (tok.countTokens() < 2) { + throw new SAMException("Must start with HELLO VERSION"); } - if (!tok.nextToken().equals("HELLO")) { - throw new SAMException("Bad domain in HELLO message"); - } - { - String opcode; - if (!(opcode = tok.nextToken()).equals("VERSION")) { - throw new SAMException("Unrecognized HELLO message opcode: '" - + opcode + "'"); - } + if (!tok.nextToken().equals("HELLO") || + !tok.nextToken().equals("VERSION")) { + throw new SAMException("Must start with HELLO VERSION"); } - Properties props; - props = SAMUtils.parseParams(tok); - if (props == null) { - throw new SAMException("No parameters in HELLO VERSION message"); - } + Properties props = SAMUtils.parseParams(tok); String minVer = props.getProperty("MIN"); if (minVer == null) { - throw new SAMException("Missing MIN parameter in HELLO VERSION message"); + //throw new SAMException("Missing MIN parameter in HELLO VERSION message"); + // MIN optional as of 0.9.14 + minVer = "1"; } String maxVer = props.getProperty("MAX"); if (maxVer == null) { - throw new SAMException("Missing MAX parameter in HELLO VERSION message"); + //throw new SAMException("Missing MAX parameter in HELLO VERSION message"); + // MAX optional as of 0.9.14 + maxVer = "99.99"; } String ver = chooseBestVersion(minVer, maxVer); - try { - if (ver == null) { - s.write(ByteBuffer.wrap(("HELLO REPLY RESULT=NOVERSION\n").getBytes("ISO-8859-1"))); - return null ; - } - // Let's answer positively - s.write(ByteBuffer.wrap(("HELLO REPLY RESULT=OK VERSION=" - + ver + "\n").getBytes("ISO-8859-1"))); - } catch (UnsupportedEncodingException e) { - log.error("Caught UnsupportedEncodingException (" - + e.getMessage() + ")"); - throw new SAMException("Character encoding error: " - + e.getMessage()); - } catch (IOException e) { - throw new SAMException("Error writing to socket: " - + e.getMessage()); + if (ver == null) { + SAMHandler.writeString("HELLO REPLY RESULT=NOVERSION\n", s); + return null; } + // Let's answer positively + if (!SAMHandler.writeString("HELLO REPLY RESULT=OK VERSION=" + ver + "\n", s)) + throw new SAMException("Error writing to socket"); // ...and instantiate the right SAM handler int verMajor = getMajor(ver); @@ -130,48 +115,44 @@ public class SAMHandlerFactory { return handler; } - /* Return the best version we can use, or null on failure */ + /* + * @return "x.y" the best version we can use, or null on failure + */ private static String chooseBestVersion(String minVer, String maxVer) { - - int minMajor = getMajor(minVer), minMinor = getMinor(minVer); - int maxMajor = getMajor(maxVer), maxMinor = getMinor(maxVer); - - // Consistency checks - if ((minMajor == -1) || (minMinor == -1) - || (maxMajor == -1) || (maxMinor == -1)) { - return null; - } - - if ((minMinor >= 10) || (maxMinor >= 10)) return null ; - - float fminVer = minMajor + (float) minMinor / 10 ; - float fmaxVer = maxMajor + (float) maxMinor / 10 ; - - - if ( ( fminVer <= 3.0 ) && ( fmaxVer >= 3.0 ) ) return "3.0" ; - - if ( ( fminVer <= 2.0 ) && ( fmaxVer >= 2.0 ) ) return "2.0" ; - - if ( ( fminVer <= 1.0 ) && ( fmaxVer >= 1.0 ) ) return "1.0" ; - + if (VersionComparator.comp(VERSION, minVer) >= 0 && + VersionComparator.comp(VERSION, maxVer) <= 0) + return VERSION; + // in VersionComparator, "3" < "3.0" so + // use comparisons carefully + if (VersionComparator.comp("3.0", minVer) >= 0 && + VersionComparator.comp("3", maxVer) <= 0) + return "3.0"; + if (VersionComparator.comp("2.0", minVer) >= 0 && + VersionComparator.comp("2", maxVer) <= 0) + return "2.0"; + if (VersionComparator.comp("1.0", minVer) >= 0 && + VersionComparator.comp("1", maxVer) <= 0) + return "1.0"; return null; } - /* Get the major protocol version from a string */ + /* Get the major protocol version from a string, or -1 */ private static int getMajor(String ver) { - if ( (ver == null) || (ver.indexOf('.') < 0) ) + if (ver == null) return -1; + int dot = ver.indexOf("."); + if (dot == 0) + return -1; + if (dot > 0) + ver = ver.substring(0, dot); try { - String major = ver.substring(0, ver.indexOf(".")); - return Integer.parseInt(major); + return Integer.parseInt(ver); } catch (NumberFormatException e) { return -1; - } catch (ArrayIndexOutOfBoundsException e) { - return -1; } } - /* Get the minor protocol version from a string */ + /* Get the minor protocol version from a string, or -1 */ private static int getMinor(String ver) { if ( (ver == null) || (ver.indexOf('.') < 0) ) return -1; diff --git a/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java b/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java index cd1c6b1a5..498cef4b8 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java +++ b/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java @@ -14,8 +14,8 @@ package net.i2p.sam; * * @author human */ -public class SAMInvalidDirectionException extends Exception { - static final long serialVersionUID = 1 ; +class SAMInvalidDirectionException extends Exception { + private static final long serialVersionUID = 1; public SAMInvalidDirectionException() { super(); diff --git a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java index 64895c9c6..452bbe0fb 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java @@ -30,7 +30,7 @@ import net.i2p.util.Log; * * @author human */ -public abstract class SAMMessageSession { +abstract class SAMMessageSession { protected final Log _log; @@ -41,7 +41,7 @@ public abstract class SAMMessageSession { /** * Initialize a new SAM message-based session. * - * @param dest Base64-encoded destination (private key) + * @param dest Base64-encoded destination and private keys (same format as PrivateKeyFile) * @param props Properties to setup the I2P session * @throws IOException * @throws DataFormatException @@ -56,7 +56,7 @@ public abstract class SAMMessageSession { /** * Initialize a new SAM message-based session. * - * @param destStream Input stream containing the destination keys + * @param destStream Input stream containing the destination and private keys (same format as PrivateKeyFile) * @param props Properties to setup the I2P session * @throws IOException * @throws DataFormatException @@ -68,7 +68,8 @@ public abstract class SAMMessageSession { } private void initSAMMessageSession (InputStream destStream, Properties props) throws IOException, DataFormatException, I2PSessionException { - _log.debug("Initializing SAM message-based session"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Initializing SAM message-based session"); handler = new SAMMessageSessionHandler(destStream, props); @@ -155,7 +156,7 @@ public abstract class SAMMessageSession { * * @author human */ - public class SAMMessageSessionHandler implements Runnable, I2PSessionListener { + class SAMMessageSessionHandler implements Runnable, I2PSessionListener { private final Object runningLock = new Object(); private volatile boolean stillRunning = true; @@ -168,14 +169,17 @@ public abstract class SAMMessageSession { * @throws I2PSessionException */ public SAMMessageSessionHandler(InputStream destStream, Properties props) throws I2PSessionException { - _log.debug("Instantiating new SAM message-based session handler"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Instantiating new SAM message-based session handler"); I2PClient client = I2PClientFactory.createClient(); session = client.createSession(destStream, props); - _log.debug("Connecting I2P session..."); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connecting I2P session..."); session.connect(); - _log.debug("I2P session connected"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("I2P session connected"); session.setSessionListener(this); } @@ -193,7 +197,8 @@ public abstract class SAMMessageSession { public void run() { - _log.debug("SAM message-based session handler running"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM message-based session handler running"); synchronized (runningLock) { while (stillRunning) { @@ -203,27 +208,32 @@ public abstract class SAMMessageSession { } } - _log.debug("Shutting down SAM message-based session handler"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Shutting down SAM message-based session handler"); shutDown(); try { - _log.debug("Destroying I2P session..."); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Destroying I2P session..."); session.destroySession(); - _log.debug("I2P session destroyed"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("I2P session destroyed"); } catch (I2PSessionException e) { _log.error("Error destroying I2P session", e); } } public void disconnected(I2PSession session) { - _log.debug("I2P session disconnected"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("I2P session disconnected"); stopRunning(); } public void errorOccurred(I2PSession session, String message, Throwable error) { - _log.debug("I2P error: " + message, error); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("I2P error: " + message, error); stopRunning(); } diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java b/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java index 3d7c1ef31..96ebe45d0 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java @@ -13,7 +13,7 @@ import java.io.IOException; /** * Interface for sending raw data to a SAM client */ -public interface SAMRawReceiver { +interface SAMRawReceiver { /** * Send a byte array to a SAM client, without informations diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java index b811e6403..08e98c258 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java @@ -21,7 +21,7 @@ import net.i2p.util.Log; * * @author human */ -public class SAMRawSession extends SAMMessageSession { +class SAMRawSession extends SAMMessageSession { public static final int RAW_SIZE_MAX = 32*1024; @@ -31,7 +31,7 @@ public class SAMRawSession extends SAMMessageSession { /** * Create a new SAM RAW session. * - * @param dest Base64-encoded destination (private key) + * @param dest Base64-encoded destination and private keys (same format as PrivateKeyFile) * @param props Properties to setup the I2P session * @param recv Object that will receive incoming data * @throws IOException @@ -48,7 +48,7 @@ public class SAMRawSession extends SAMMessageSession { /** * Create a new SAM RAW session. * - * @param destStream Input stream containing the destination keys + * @param destStream Input stream containing the destination and private keys (same format as PrivateKeyFile) * @param props Properties to setup the I2P session * @param recv Object that will receive incoming data * @throws IOException diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java b/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java index a57ddd681..a6e47ad7a 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java +++ b/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java @@ -17,7 +17,7 @@ import net.i2p.data.Destination; * Interface for sending streaming data to a SAM client */ -public interface SAMStreamReceiver { +interface SAMStreamReceiver { /** * Sends the result of a stream send operation * @param id Stream ID diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java index 41163e8f2..db5d39d49 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java @@ -46,7 +46,7 @@ import net.i2p.util.Log; * * @author human */ -public class SAMStreamSession { +class SAMStreamSession { protected final Log _log; @@ -80,7 +80,7 @@ public class SAMStreamSession { /** * Create a new SAM STREAM session. * - * @param dest Base64-encoded destination (private key) + * @param dest Base64-encoded destination and private keys (same format as PrivateKeyFile) * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH") * @param props Properties to setup the I2P session * @param recv Object that will receive incoming data @@ -96,7 +96,7 @@ public class SAMStreamSession { /** * Create a new SAM STREAM session. * - * @param destStream Input stream containing the destination keys + * @param destStream Input stream containing the destination and private keys (same format as PrivateKeyFile) * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH") * @param props Properties to setup the I2P session * @param recv Object that will receive incoming data @@ -108,7 +108,8 @@ public class SAMStreamSession { Properties props, SAMStreamReceiver recv) throws IOException, DataFormatException, SAMException { this.recv = recv; _log = new Log(getClass()); - _log.debug("SAM STREAM session instantiated"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM STREAM session instantiated"); Properties allprops = (Properties) System.getProperties().clone(); allprops.putAll(props); @@ -122,7 +123,8 @@ public class SAMStreamSession { throw new SAMException("Invalid I2CP port specified [" + port + "]"); } - _log.debug("Creating I2PSocketManager..."); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Creating I2PSocketManager..."); socketMgr = I2PSocketManagerFactory.createManager(destStream, i2cpHost, i2cpPort, @@ -193,12 +195,14 @@ public class SAMStreamSession { */ public boolean connect ( int id, String dest, Properties props ) throws I2PException, ConnectException, NoRouteToHostException, DataFormatException, InterruptedIOException, SAMInvalidDirectionException, IOException { if (!canCreate) { - _log.debug("Trying to create an outgoing connection using a receive-only session"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Trying to create an outgoing connection using a receive-only session"); throw new SAMInvalidDirectionException("Trying to create connections through a receive-only session"); } if (checkSocketHandlerId(id)) { - _log.debug("The specified id (" + id + ") is already in use"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("The specified id (" + id + ") is already in use"); return false; } @@ -209,7 +213,8 @@ public class SAMStreamSession { if (props.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null) opts.setConnectTimeout(60 * 1000); - _log.debug("Connecting new I2PSocket..."); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connecting new I2PSocket..."); // blocking connection (SAMv1) @@ -271,7 +276,8 @@ public class SAMStreamSession { */ public boolean closeConnection(int id) { if (!checkSocketHandlerId(id)) { - _log.debug("The specified id (" + id + ") does not exist!"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("The specified id (" + id + ") does not exist!"); return false; } removeSocketHandler(id); @@ -368,7 +374,8 @@ public class SAMStreamSession { reader.stopRunning(); if (sender != null) sender.shutDownGracefully(); - _log.debug("Removed SAM STREAM session socket handler (gracefully) " + id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Removed SAM STREAM session socket handler (gracefully) " + id); } /** @@ -413,7 +420,8 @@ public class SAMStreamSession { * */ public SAMStreamSessionServer() { - _log.debug("Instantiating new SAM STREAM session server"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Instantiating new SAM STREAM session server"); serverSocket = socketMgr.getServerSocket(); } @@ -423,7 +431,8 @@ public class SAMStreamSession { * */ public void stopRunning() { - _log.debug("SAMStreamSessionServer.stopRunning() invoked"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAMStreamSessionServer.stopRunning() invoked"); synchronized (runningLock) { if (stillRunning) { stillRunning = false; @@ -437,7 +446,8 @@ public class SAMStreamSession { } public void run() { - _log.debug("SAM STREAM session server running"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM STREAM session server running"); I2PSocket i2ps; while (stillRunning) { @@ -446,7 +456,8 @@ public class SAMStreamSession { if (i2ps == null) break; - _log.debug("New incoming connection"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("New incoming connection"); int id = createSocketHandler(i2ps, 0); if (id == 0) { @@ -455,14 +466,17 @@ public class SAMStreamSession { continue; } - _log.debug("New connection id: " + id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("New connection id: " + id); recv.notifyStreamIncomingConnection ( id, i2ps.getPeerDestination() ); } catch (I2PException e) { - _log.debug("Caught I2PException", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught I2PException", e); break; } catch (IOException e) { - _log.debug("Caught IOException", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException", e); break; } } @@ -470,12 +484,14 @@ public class SAMStreamSession { try { serverSocket.close(); // In case it wasn't closed, yet } catch (I2PException e) { - _log.debug("Caught I2PException", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught I2PException", e); } close(); - _log.debug("Shutting down SAM STREAM session server"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Shutting down SAM STREAM session server"); } } @@ -483,7 +499,8 @@ public class SAMStreamSession { boolean setReceiveLimit ( int id, long limit, boolean nolimit ) { - _log.debug ( "Protocol v1 does not support a receive limit for streams" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Protocol v1 does not support a receive limit for streams" ); return false ; } @@ -540,7 +557,8 @@ public class SAMStreamSession { public SAMv1StreamSessionSocketReader ( I2PSocket s, int id ) throws IOException { super(s, id); - _log.debug("Instantiating new SAM STREAM session socket reader"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Instantiating new SAM STREAM session socket reader"); } /** @@ -549,7 +567,8 @@ public class SAMStreamSession { */ @Override public void stopRunning() { - _log.debug("stopRunning() invoked on socket reader " + id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("stopRunning() invoked on socket reader " + id); synchronized (runningLock) { if (stillRunning) { stillRunning = false; @@ -560,7 +579,8 @@ public class SAMStreamSession { @Override public void run() { - _log.debug("run() called for socket reader " + id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("run() called for socket reader " + id); int read = -1; ByteBuffer data = ByteBuffer.allocate(SOCKET_HANDLER_BUF_SIZE); @@ -572,20 +592,23 @@ public class SAMStreamSession { data.clear(); read = Channels.newChannel(in).read(data); if (read == -1) { - _log.debug("Handler " + id + ": connection closed"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Handler " + id + ": connection closed"); break; } data.flip(); recv.receiveStreamBytes(id, data); } } catch (IOException e) { - _log.debug("Caught IOException", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException", e); } try { i2pSocket.close(); } catch (IOException e) { - _log.debug("Caught IOException", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException", e); } if (stillRunning) { @@ -594,12 +617,14 @@ public class SAMStreamSession { try { recv.notifyStreamDisconnection(id, "OK", null); } catch (IOException e) { - _log.debug("Error sending disconnection notice for handler " + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Error sending disconnection notice for handler " + id, e); } } - _log.debug("Shutting down SAM STREAM session socket handler " +id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Shutting down SAM STREAM session socket handler " +id); } } @@ -691,14 +716,16 @@ public class SAMStreamSession { */ @Override public void stopRunning() { - _log.debug("stopRunning() invoked on socket sender " + _id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("stopRunning() invoked on socket sender " + _id); synchronized (runningLock) { if (_stillRunning) { _stillRunning = false; try { i2pSocket.close(); } catch (IOException e) { - _log.debug("Caught IOException", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException", e); } synchronized (_data) { _data.clear(); @@ -714,13 +741,15 @@ public class SAMStreamSession { */ @Override public void shutDownGracefully() { - _log.debug("shutDownGracefully() invoked on socket sender " + _id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("shutDownGracefully() invoked on socket sender " + _id); _shuttingDownGracefully = true; } @Override public void run() { - _log.debug("run() called for socket sender " + _id); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("run() called for socket sender " + _id); ByteArray data = null; while (_stillRunning) { data = null; diff --git a/apps/sam/java/src/net/i2p/sam/SAMUtils.java b/apps/sam/java/src/net/i2p/sam/SAMUtils.java index 12bdb858a..15ecb1143 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMUtils.java +++ b/apps/sam/java/src/net/i2p/sam/SAMUtils.java @@ -20,6 +20,7 @@ import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.I2PClientFactory; import net.i2p.client.naming.NamingService; +import net.i2p.crypto.SigType; import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; @@ -32,21 +33,35 @@ import net.i2p.util.Log; * * @author human */ -public class SAMUtils { +class SAMUtils { //private final static Log _log = new Log(SAMUtils.class); /** - * Generate a random destination key + * Generate a random destination key using DSA_SHA1 signature type. + * Caller must close streams. Fails silently. * - * @param priv Stream used to write the private key - * @param pub Stream used to write the public key (may be null) + * @param priv Stream used to write the destination and private keys + * @param pub Stream used to write the destination (may be null) */ public static void genRandomKey(OutputStream priv, OutputStream pub) { + genRandomKey(priv, pub, SigType.DSA_SHA1); + } + + /** + * Generate a random destination key. + * Caller must close streams. Fails silently. + * + * @param priv Stream used to write the destination and private keys + * @param pub Stream used to write the destination (may be null) + * @param sigType what signature type + * @since 0.9.14 + */ + public static void genRandomKey(OutputStream priv, OutputStream pub, SigType sigType) { //_log.debug("Generating random keys..."); try { I2PClient c = I2PClientFactory.createClient(); - Destination d = c.createDestination(priv); + Destination d = c.createDestination(priv, sigType); priv.flush(); if (pub != null) { @@ -77,20 +92,30 @@ public class SAMUtils { return false; } } - - public static class InvalidDestination extends Exception { - static final long serialVersionUID = 0x1 ; - } - public static void checkPrivateDestination(String dest) throws InvalidDestination { - ByteArrayInputStream destKeyStream = new ByteArrayInputStream(Base64.decode(dest)); + /** + * Check whether a base64-encoded {dest,privkey,signingprivkey} is valid + * + * @param dest The base64-encoded destination and keys to be checked (same format as PrivateKeyFile) + * @return true if valid + */ + public static boolean checkPrivateDestination(String dest) { + byte[] b = Base64.decode(dest); + if (b == null || b.length < 663) + return false; + ByteArrayInputStream destKeyStream = new ByteArrayInputStream(b); try { - new Destination().readBytes(destKeyStream); + Destination d = new Destination(); + d.readBytes(destKeyStream); new PrivateKey().readBytes(destKeyStream); - new SigningPrivateKey().readBytes(destKeyStream); - } catch (Exception e) { - throw new InvalidDestination(); + SigningPrivateKey spk = new SigningPrivateKey(d.getSigningPublicKey().getType()); + spk.readBytes(destKeyStream); + } catch (DataFormatException e) { + return false; + } catch (IOException e) { + return false; } + return destKeyStream.available() == 0; } @@ -148,26 +173,34 @@ public class SAMUtils { * @param tok A StringTokenizer pointing to the SAM parameters * * @throws SAMException if the data was formatted incorrectly - * @return Properties with the parsed SAM params + * @return Properties with the parsed SAM params, never null */ public static Properties parseParams(StringTokenizer tok) throws SAMException { - int pos, ntoks = tok.countTokens(); - String token, param; + int ntoks = tok.countTokens(); Properties props = new Properties(); StringBuilder value = new StringBuilder(); for (int i = 0; i < ntoks; ++i) { - token = tok.nextToken(); + String token = tok.nextToken(); - pos = token.indexOf("="); - if (pos == -1) { + int pos = token.indexOf("="); + if (pos <= 0) { //_log.debug("Error in params format"); - throw new SAMException("Bad formatting for param [" + token + "]"); + if (pos == 0) { + throw new SAMException("No param specified [" + token + "]"); + } else { + throw new SAMException("Bad formatting for param [" + token + "]"); + } } - param = token.substring(0, pos); + + String param = token.substring(0, pos); value.append(token.substring(pos+1)); if (value.length() == 0) - throw new SAMException("Empty value for param "+param); + throw new SAMException("Empty value for param " + param); + + // FIXME: The following code does not take into account that there + // may have been multiple subsequent space chars in the input that + // StringTokenizer treates as one. if (value.charAt(0) == '"') { while ( (i < ntoks) && (value.lastIndexOf("\"") <= 0) ) { value.append(' ').append(tok.nextToken()); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java index ea36e573c..2ffba654f 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java @@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicLong; import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.I2PSessionException; +import net.i2p.crypto.SigType; import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; @@ -35,7 +36,7 @@ import net.i2p.util.Log; * * @author human */ -public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramReceiver, SAMStreamReceiver { +class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramReceiver, SAMStreamReceiver { protected SAMRawSession rawSession; protected SAMDatagramSession datagramSession; @@ -77,16 +78,17 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag public SAMv1Handler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps) throws SAMException, IOException { super(s, verMajor, verMinor, i2cpProps); _id = __id.incrementAndGet(); - _log.debug("SAM version 1 handler instantiated"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM version 1 handler instantiated"); if ( ! verifVersion() ) { throw new SAMException("BUG! Wrong protocol version!"); } } - public boolean verifVersion() { - return ( verMajor == 1 && verMinor == 0 ) ; - } + public boolean verifVersion() { + return (verMajor == 1); + } public void handle() { String msg = null; @@ -97,12 +99,14 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag Properties props; this.thread.setName("SAMv1Handler " + _id); - _log.debug("SAM handling started"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM handling started"); try { while (true) { if (shouldStop()) { - _log.debug("Stop request found"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Stop request found"); break; } @@ -132,14 +136,16 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } if(msg.equals("")) { - _log.debug("Ignoring newline"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Ignoring newline"); continue; } tok = new StringTokenizer(msg, " "); if (tok.countTokens() < 2) { // This is not a correct message, for sure - _log.debug("Error in message format"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Error in message format"); break; } domain = tok.nextToken(); @@ -165,7 +171,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } else if (domain.equals("NAMING")) { canContinue = execNamingMessage(opcode, props); } else { - _log.debug("Unrecognized message domain: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized message domain: \"" + domain + "\""); break; } @@ -175,12 +182,14 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } } } catch (IOException e) { - _log.debug("Caught IOException (" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException (" + e.getMessage() + ") for message [" + msg + "]", e); } catch (Exception e) { _log.error("Unexpected exception for message [" + msg + "]", e); } finally { - _log.debug("Stopping handler"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Stopping handler"); try { closeClientSocket(); } catch (IOException e) { @@ -207,17 +216,20 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag if (opcode.equals("CREATE")) { if ((getRawSession() != null) || (getDatagramSession() != null) || (getStreamSession() != null)) { - _log.debug("Trying to create a session, but one still exists"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Trying to create a session, but one still exists"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n"); } - if (props == null) { - _log.debug("No parameters specified in SESSION CREATE message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in SESSION CREATE message"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No parameters for SESSION CREATE\"\n"); } dest = props.getProperty("DESTINATION"); if (dest == null) { - _log.debug("SESSION DESTINATION parameter not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION DESTINATION parameter not specified"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"DESTINATION not specified\"\n"); } props.remove("DESTINATION"); @@ -247,7 +259,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag String style = props.getProperty("STYLE"); if (style == null) { - _log.debug("SESSION STYLE parameter not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION STYLE parameter not specified"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No SESSION STYLE specified\"\n"); } props.remove("STYLE"); @@ -264,33 +277,39 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } else if (style.equals("STREAM")) { String dir = props.getProperty("DIRECTION"); if (dir == null) { - _log.debug("No DIRECTION parameter in STREAM session, defaulting to BOTH"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No DIRECTION parameter in STREAM session, defaulting to BOTH"); dir = "BOTH"; } if (!dir.equals("CREATE") && !dir.equals("RECEIVE") && !dir.equals("BOTH")) { - _log.debug("Unknow DIRECTION parameter value: [" + dir + "]"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unknow DIRECTION parameter value: [" + dir + "]"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown DIRECTION parameter\"\n"); } props.remove("DIRECTION"); streamSession = newSAMStreamSession(destKeystream, dir,props); } else { - _log.debug("Unrecognized SESSION STYLE: \"" + style +"\""); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized SESSION STYLE: \"" + style +"\""); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized SESSION STYLE\"\n"); } return writeString("SESSION STATUS RESULT=OK DESTINATION=" + dest + "\n"); } else { - _log.debug("Unrecognized SESSION message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized SESSION message opcode: \"" + opcode + "\""); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized opcode\"\n"); } } catch (DataFormatException e) { - _log.debug("Invalid destination specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid destination specified"); return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); } catch (I2PSessionException e) { - _log.debug("I2P error when instantiating session", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("I2P error when instantiating session", e); return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); } catch (SAMException e) { _log.error("Unexpected SAM error", e); @@ -302,7 +321,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } - SAMStreamSession newSAMStreamSession(String destKeystream, String direction, Properties props ) + private SAMStreamSession newSAMStreamSession(String destKeystream, String direction, Properties props ) throws IOException, DataFormatException, SAMException { return new SAMStreamSession(destKeystream, direction, props, this) ; @@ -312,15 +331,23 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag protected boolean execDestMessage(String opcode, Properties props) { if (opcode.equals("GENERATE")) { - if (!props.isEmpty()) { - _log.debug("Properties specified in DEST GENERATE message"); - return false; + String sigTypeStr = props.getProperty("SIGNATURE_TYPE"); + SigType sigType; + if (sigTypeStr != null) { + sigType = SigType.parseSigType(sigTypeStr); + if (sigType == null) { + writeString("DEST REPLY RESULT=I2P_ERROR MESSAGE=\"SIGNATURE_TYPE " + + sigTypeStr + " unsupported\"\n"); + return false; + } + } else { + sigType = SigType.DSA_SHA1; } - ByteArrayOutputStream priv = new ByteArrayOutputStream(); - ByteArrayOutputStream pub = new ByteArrayOutputStream(); + ByteArrayOutputStream priv = new ByteArrayOutputStream(663); + ByteArrayOutputStream pub = new ByteArrayOutputStream(387); - SAMUtils.genRandomKey(priv, pub); + SAMUtils.genRandomKey(priv, pub, sigType); return writeString("DEST REPLY" + " PUB=" + Base64.encode(pub.toByteArray()) @@ -328,7 +355,9 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag + Base64.encode(priv.toByteArray()) + "\n"); } else { - _log.debug("Unrecognized DEST message opcode: \"" + opcode + "\""); + writeString("DEST REPLY RESULT=I2P_ERROR MESSAGE=\"DEST GENERATE required\""); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized DEST message opcode: \"" + opcode + "\""); return false; } } @@ -336,14 +365,15 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag /* Parse and execute a NAMING message */ protected boolean execNamingMessage(String opcode, Properties props) { if (opcode.equals("LOOKUP")) { - if (props == null) { + if (props.isEmpty()) { _log.debug("No parameters specified in NAMING LOOKUP message"); return false; } String name = props.getProperty("NAME"); if (name == null) { - _log.debug("Name to resolve not specified in NAMING message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Name to resolve not specified in NAMING message"); return false; } @@ -356,7 +386,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } else if (getDatagramSession() != null) { dest = getDatagramSession().getDestination(); } else { - _log.debug("Lookup for SESSION destination, but session is null"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Lookup for SESSION destination, but session is null"); return false; } } else { @@ -375,7 +406,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag + dest.toBase64() + "\n"); } else { - _log.debug("Unrecognized NAMING message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized NAMING message opcode: \"" + opcode + "\""); return false; } @@ -390,14 +422,16 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } if (opcode.equals("SEND")) { - if (props == null) { - _log.debug("No parameters specified in DATAGRAM SEND message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in DATAGRAM SEND message"); return false; } String dest = props.getProperty("DESTINATION"); if (dest == null) { - _log.debug("Destination not specified in DATAGRAM SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Destination not specified in DATAGRAM SEND message"); return false; } @@ -405,17 +439,20 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag { String strsize = props.getProperty("SIZE"); if (strsize == null) { - _log.debug("Size not specified in DATAGRAM SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Size not specified in DATAGRAM SEND message"); return false; } try { size = Integer.parseInt(strsize); } catch (NumberFormatException e) { - _log.debug("Invalid DATAGRAM SEND size specified: " + strsize); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid DATAGRAM SEND size specified: " + strsize); return false; } if (!checkDatagramSize(size)) { - _log.debug("Specified size (" + size + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Specified size (" + size + ") is out of protocol limits"); return false; } @@ -434,20 +471,24 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag return true; } catch (EOFException e) { - _log.debug("Too few bytes with DATAGRAM SEND message (expected: " + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Too few bytes with DATAGRAM SEND message (expected: " + size); return false; } catch (IOException e) { - _log.debug("Caught IOException while parsing DATAGRAM SEND message", + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException while parsing DATAGRAM SEND message", e); return false; } catch (DataFormatException e) { - _log.debug("Invalid key specified with DATAGRAM SEND message", + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid key specified with DATAGRAM SEND message", e); return false; } } else { - _log.debug("Unrecognized DATAGRAM message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized DATAGRAM message opcode: \"" + opcode + "\""); return false; } @@ -461,14 +502,16 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } if (opcode.equals("SEND")) { - if (props == null) { - _log.debug("No parameters specified in RAW SEND message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in RAW SEND message"); return false; } String dest = props.getProperty("DESTINATION"); if (dest == null) { - _log.debug("Destination not specified in RAW SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Destination not specified in RAW SEND message"); return false; } @@ -476,17 +519,20 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag { String strsize = props.getProperty("SIZE"); if (strsize == null) { - _log.debug("Size not specified in RAW SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Size not specified in RAW SEND message"); return false; } try { size = Integer.parseInt(strsize); } catch (NumberFormatException e) { - _log.debug("Invalid RAW SEND size specified: " + strsize); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid RAW SEND size specified: " + strsize); return false; } if (!checkSize(size)) { - _log.debug("Specified size (" + size + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Specified size (" + size + ") is out of protocol limits"); return false; } @@ -505,20 +551,24 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag return true; } catch (EOFException e) { - _log.debug("Too few bytes with RAW SEND message (expected: " + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Too few bytes with RAW SEND message (expected: " + size); return false; } catch (IOException e) { - _log.debug("Caught IOException while parsing RAW SEND message", + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException while parsing RAW SEND message", e); return false; } catch (DataFormatException e) { - _log.debug("Invalid key specified with RAW SEND message", + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid key specified with RAW SEND message", e); return false; } } else { - _log.debug("Unrecognized RAW message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized RAW message opcode: \"" + opcode + "\""); return false; } @@ -538,15 +588,17 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } else if (opcode.equals("CLOSE")) { return execStreamClose(props); } else { - _log.debug("Unrecognized RAW message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized RAW message opcode: \"" + opcode + "\""); return false; } } protected boolean execStreamSend(Properties props) { - if (props == null) { - _log.debug("No parameters specified in STREAM SEND message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in STREAM SEND message"); return false; } @@ -554,13 +606,15 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag { String strid = props.getProperty("ID"); if (strid == null) { - _log.debug("ID not specified in STREAM SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("ID not specified in STREAM SEND message"); return false; } try { id = Integer.parseInt(strid); } catch (NumberFormatException e) { - _log.debug("Invalid STREAM SEND ID specified: " + strid); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid STREAM SEND ID specified: " + strid); return false; } } @@ -569,17 +623,20 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag { String strsize = props.getProperty("SIZE"); if (strsize == null) { - _log.debug("Size not specified in STREAM SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Size not specified in STREAM SEND message"); return false; } try { size = Integer.parseInt(strsize); } catch (NumberFormatException e) { - _log.debug("Invalid STREAM SEND size specified: "+strsize); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid STREAM SEND size specified: "+strsize); return false; } if (!checkSize(size)) { - _log.debug("Specified size (" + size + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Specified size (" + size + ") is out of protocol limits"); return false; } @@ -596,19 +653,22 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag return true; } catch (EOFException e) { - _log.debug("Too few bytes with STREAM SEND message (expected: " + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Too few bytes with STREAM SEND message (expected: " + size); return false; } catch (IOException e) { - _log.debug("Caught IOException while parsing STREAM SEND message", + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException while parsing STREAM SEND message", e); return false; } } protected boolean execStreamConnect(Properties props) { - if (props == null) { - _log.debug("No parameters specified in STREAM CONNECT message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in STREAM CONNECT message"); return false; } @@ -616,17 +676,20 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag { String strid = props.getProperty("ID"); if (strid == null) { - _log.debug("ID not specified in STREAM SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("ID not specified in STREAM SEND message"); return false; } try { id = Integer.parseInt(strid); } catch (NumberFormatException e) { - _log.debug("Invalid STREAM CONNECT ID specified: " +strid); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid STREAM CONNECT ID specified: " +strid); return false; } if (id < 1) { - _log.debug("Invalid STREAM CONNECT ID specified: " +strid); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid STREAM CONNECT ID specified: " +strid); return false; } props.remove("ID"); @@ -642,26 +705,33 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag try { try { if (!getStreamSession().connect(id, dest, props)) { - _log.debug("STREAM connection failed"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM connection failed"); return false; } } catch (DataFormatException e) { - _log.debug("Invalid destination in STREAM CONNECT message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid destination in STREAM CONNECT message"); notifyStreamOutgoingConnection ( id, "INVALID_KEY", null ); } catch (SAMInvalidDirectionException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamOutgoingConnection ( id, "INVALID_DIRECTION", null ); } catch (ConnectException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamOutgoingConnection ( id, "CONNECTION_REFUSED", null ); } catch (NoRouteToHostException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamOutgoingConnection ( id, "CANT_REACH_PEER", null ); } catch (InterruptedIOException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamOutgoingConnection ( id, "TIMEOUT", null ); } catch (I2PException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamOutgoingConnection ( id, "I2P_ERROR", null ); } } catch (IOException e) { @@ -672,8 +742,9 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } protected boolean execStreamClose(Properties props) { - if (props == null) { - _log.debug("No parameters specified in STREAM CLOSE message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in STREAM CLOSE message"); return false; } @@ -681,13 +752,15 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag { String strid = props.getProperty("ID"); if (strid == null) { - _log.debug("ID not specified in STREAM CLOSE message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("ID not specified in STREAM CLOSE message"); return false; } try { id = Integer.parseInt(strid); } catch (NumberFormatException e) { - _log.debug("Invalid STREAM CLOSE ID specified: " +strid); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid STREAM CLOSE ID specified: " +strid); return false; } } @@ -718,9 +791,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag ByteArrayOutputStream msg = new ByteArrayOutputStream(); String msgText = "RAW RECEIVED SIZE=" + data.length + "\n"; - msg.write(msgText.getBytes("ISO-8859-1")); + msg.write(DataHelper.getASCII(msgText)); msg.write(data); - msg.flush(); if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); @@ -729,7 +801,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } public void stopRawReceiving() { - _log.debug("stopRawReceiving() invoked"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("stopRawReceiving() invoked"); if (getRawSession() == null) { _log.error("BUG! Got raw receiving stop, but session is null!"); @@ -755,7 +828,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag String msgText = "DATAGRAM RECEIVED DESTINATION=" + sender.toBase64() + " SIZE=" + data.length + "\n"; - msg.write(msgText.getBytes("ISO-8859-1")); + msg.write(DataHelper.getASCII(msgText)); if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); @@ -765,7 +838,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } public void stopDatagramReceiving() { - _log.debug("stopDatagramReceiving() invoked"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("stopDatagramReceiving() invoked"); if (getDatagramSession() == null) { _log.error("BUG! Got datagram receiving stop, but session is null!"); @@ -860,7 +934,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); - ByteBuffer prefix = ByteBuffer.wrap(msgText.getBytes("ISO-8859-1")); + ByteBuffer prefix = ByteBuffer.wrap(DataHelper.getASCII(msgText)); Object writeLock = getWriteLock(); synchronized (writeLock) { @@ -885,7 +959,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } public void stopStreamReceiving() { - _log.debug("stopStreamReceiving() invoked", new Exception("stopped")); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("stopStreamReceiving() invoked", new Exception("stopped")); if (getStreamSession() == null) { _log.error("BUG! Got stream receiving stop, but session is null!"); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java index 7ac4ba691..d96d82cb1 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java @@ -21,7 +21,7 @@ import net.i2p.util.Log; * @author mkvore */ -public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDatagramReceiver, SAMStreamReceiver +class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDatagramReceiver, SAMStreamReceiver { @@ -55,9 +55,10 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat super ( s, verMajor, verMinor, i2cpProps ); } + @Override public boolean verifVersion() { - return (verMajor == 2 && verMinor == 0) ; + return (verMajor == 2); } SAMStreamSession newSAMStreamSession(String destKeystream, String direction, Properties props ) @@ -68,6 +69,7 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat /* Parse and execute a STREAM message */ + @Override protected boolean execStreamMessage ( String opcode, Properties props ) { if ( getStreamSession() == null ) @@ -94,7 +96,8 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat } else { - _log.debug ( "Unrecognized RAW message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Unrecognized RAW message opcode: \"" + opcode + "\"" ); return false; } @@ -106,9 +109,10 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat private boolean execStreamReceive ( Properties props ) { - if ( props == null ) + if (props.isEmpty()) { - _log.debug ( "No parameters specified in STREAM RECEIVE message" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "No parameters specified in STREAM RECEIVE message" ); return false; } @@ -119,7 +123,8 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat if ( strid == null ) { - _log.debug ( "ID not specified in STREAM RECEIVE message" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "ID not specified in STREAM RECEIVE message" ); return false; } @@ -129,7 +134,8 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat } catch ( NumberFormatException e ) { - _log.debug ( "Invalid STREAM RECEIVE ID specified: " + strid ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Invalid STREAM RECEIVE ID specified: " + strid ); return false; } } @@ -142,7 +148,8 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat if ( strsize == null ) { - _log.debug ( "Limit not specified in STREAM RECEIVE message" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Limit not specified in STREAM RECEIVE message" ); return false; } @@ -158,13 +165,15 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat } catch ( NumberFormatException e ) { - _log.debug ( "Invalid STREAM RECEIVE size specified: " + strsize ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Invalid STREAM RECEIVE size specified: " + strsize ); return false; } if ( limit < 0 ) { - _log.debug ( "Specified limit (" + limit + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Specified limit (" + limit + ") is out of protocol limits" ); return false; } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java index edbd80dba..b579812c2 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java @@ -37,13 +37,13 @@ import net.i2p.util.Log; * @author mkvore */ -public class SAMv2StreamSession extends SAMStreamSession +class SAMv2StreamSession extends SAMStreamSession { /** * Create a new SAM STREAM session. * - * @param dest Base64-encoded destination (private key) + * @param dest Base64-encoded destination and private keys (same format as PrivateKeyFile) * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH") * @param props Properties to setup the I2P session * @param recv Object that will receive incoming data @@ -60,7 +60,7 @@ public class SAMv2StreamSession extends SAMStreamSession /** * Create a new SAM STREAM session. * - * @param destStream Input stream containing the destination keys + * @param destStream Input stream containing the destination and private keys (same format as PrivateKeyFile) * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH") * @param props Properties to setup the I2P session * @param recv Object that will receive incoming data @@ -93,13 +93,15 @@ public class SAMv2StreamSession extends SAMStreamSession { if ( !canCreate ) { - _log.debug ( "Trying to create an outgoing connection using a receive-only session" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Trying to create an outgoing connection using a receive-only session" ); throw new SAMInvalidDirectionException ( "Trying to create connections through a receive-only session" ); } if ( checkSocketHandlerId ( id ) ) { - _log.debug ( "The specified id (" + id + ") is already in use" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "The specified id (" + id + ") is already in use" ); return false ; } @@ -112,7 +114,8 @@ public class SAMv2StreamSession extends SAMStreamSession if ( props.getProperty ( I2PSocketOptions.PROP_CONNECT_TIMEOUT ) == null ) opts.setConnectTimeout ( 60 * 1000 ); - _log.debug ( "Connecting new I2PSocket..." ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Connecting new I2PSocket..." ); // non-blocking connection (SAMv2) @@ -155,7 +158,8 @@ public class SAMv2StreamSession extends SAMStreamSession public StreamConnector ( int id, Destination dest, I2PSocketOptions opts )// throws IOException { - _log.debug ( "Instantiating new SAM STREAM connector" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Instantiating new SAM STREAM connector" ); this.id = id ; this.opts = opts ; @@ -165,7 +169,8 @@ public class SAMv2StreamSession extends SAMStreamSession public void run() { - _log.debug ( "run() called for socket connector " + id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "run() called for socket connector " + id ); try { @@ -180,37 +185,44 @@ public class SAMv2StreamSession extends SAMStreamSession catch ( DataFormatException e ) { - _log.debug ( "Invalid destination in STREAM CONNECT message" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Invalid destination in STREAM CONNECT message" ); recv.notifyStreamOutgoingConnection ( id, "INVALID_KEY", e.getMessage() ); } catch ( ConnectException e ) { - _log.debug ( "STREAM CONNECT failed: " + e.getMessage() ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); recv.notifyStreamOutgoingConnection ( id, "CONNECTION_REFUSED", e.getMessage() ); } catch ( NoRouteToHostException e ) { - _log.debug ( "STREAM CONNECT failed: " + e.getMessage() ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); recv.notifyStreamOutgoingConnection ( id, "CANT_REACH_PEER", e.getMessage() ); } catch ( InterruptedIOException e ) { - _log.debug ( "STREAM CONNECT failed: " + e.getMessage() ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); recv.notifyStreamOutgoingConnection ( id, "TIMEOUT", e.getMessage() ); } catch ( I2PException e ) { - _log.debug ( "STREAM CONNECT failed: " + e.getMessage() ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); recv.notifyStreamOutgoingConnection ( id, "I2P_ERROR", e.getMessage() ); } } catch ( IOException e ) { - _log.debug ( "Error sending disconnection notice for handler " + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Error sending disconnection notice for handler " + id, e ); } - _log.debug ( "Shutting down SAM STREAM session connector " + id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Shutting down SAM STREAM session connector " + id ); } } @@ -312,7 +324,8 @@ public class SAMv2StreamSession extends SAMStreamSession @Override public void stopRunning() { - _log.debug ( "stopRunning() invoked on socket sender " + _id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "stopRunning() invoked on socket sender " + _id ); synchronized ( runningLock ) { @@ -326,7 +339,8 @@ public class SAMv2StreamSession extends SAMStreamSession } catch ( IOException e ) { - _log.debug ( "Caught IOException", e ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Caught IOException", e ); } synchronized ( _data ) @@ -345,14 +359,16 @@ public class SAMv2StreamSession extends SAMStreamSession @Override public void shutDownGracefully() { - _log.debug ( "shutDownGracefully() invoked on socket sender " + _id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "shutDownGracefully() invoked on socket sender " + _id ); _shuttingDownGracefully = true; } @Override public void run() { - _log.debug ( "run() called for socket sender " + _id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "run() called for socket sender " + _id ); ByteArray data = null; while ( _stillRunning ) @@ -491,13 +507,15 @@ public class SAMv2StreamSession extends SAMStreamSession this.nolimit = nolimit ; runningLock.notify() ; } - _log.debug ( "new limit set for socket reader " + id + " : " + (nolimit ? "NOLIMIT" : limit + " bytes" ) ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "new limit set for socket reader " + id + " : " + (nolimit ? "NOLIMIT" : limit + " bytes" ) ); } @Override public void run() { - _log.debug ( "run() called for socket reader " + id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "run() called for socket reader " + id ); int read = -1; ByteBuffer data = ByteBuffer.allocate(SOCKET_HANDLER_BUF_SIZE); @@ -527,7 +545,8 @@ public class SAMv2StreamSession extends SAMStreamSession if ( read == -1 ) { - _log.debug ( "Handler " + id + ": connection closed" ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Handler " + id + ": connection closed" ); break; } @@ -538,7 +557,8 @@ public class SAMv2StreamSession extends SAMStreamSession } catch ( IOException e ) { - _log.debug ( "Caught IOException", e ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Caught IOException", e ); } try @@ -547,7 +567,8 @@ public class SAMv2StreamSession extends SAMStreamSession } catch ( IOException e ) { - _log.debug ( "Caught IOException", e ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Caught IOException", e ); } if ( stillRunning ) @@ -561,12 +582,14 @@ public class SAMv2StreamSession extends SAMStreamSession } catch ( IOException e ) { - _log.debug ( "Error sending disconnection notice for handler " + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Error sending disconnection notice for handler " + id, e ); } } - _log.debug ( "Shutting down SAM STREAM session socket handler " + id ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Shutting down SAM STREAM session socket handler " + id ); } } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java index 37d335cad..a16c92327 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java @@ -10,6 +10,7 @@ import java.util.Properties; import net.i2p.client.I2PSessionException; import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.util.Log; @@ -17,7 +18,7 @@ import java.net.InetSocketAddress; import java.net.SocketAddress ; import java.nio.ByteBuffer; -public class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Session, SAMDatagramReceiver { +class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Session, SAMDatagramReceiver { private final SAMv3Handler handler; private final SAMv3Handler.DatagramServer server; @@ -76,7 +77,7 @@ public class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Han } else { String msg = sender.toBase64()+"\n"; ByteBuffer msgBuf = ByteBuffer.allocate(msg.length()+data.length); - msgBuf.put(msg.getBytes("ISO-8859-1")); + msgBuf.put(DataHelper.getASCII(msg)); msgBuf.put(data); msgBuf.flip(); this.server.send(this.clientAddress, msgBuf); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index 201aee928..6a5bf7fa3 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -28,6 +28,7 @@ import java.util.StringTokenizer; import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.I2PSessionException; +import net.i2p.crypto.SigType; import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; @@ -41,10 +42,14 @@ import net.i2p.util.I2PAppThread; * @author mkvore */ -public class SAMv3Handler extends SAMv1Handler +class SAMv3Handler extends SAMv1Handler { private Session session; + public static final SessionsDB sSessionsHash = new SessionsDB(); + private boolean stolenSocket; + private boolean streamForwardingSocket; + interface Session { String getNick(); @@ -80,12 +85,14 @@ public class SAMv3Handler extends SAMv1Handler public SAMv3Handler ( SocketChannel s, int verMajor, int verMinor, Properties i2cpProps ) throws SAMException, IOException { super ( s, verMajor, verMinor, i2cpProps ); - _log.debug("SAM version 3 handler instantiated"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM version 3 handler instantiated"); } + @Override public boolean verifVersion() { - return (verMajor == 3 && verMinor == 0) ; + return (verMajor == 3); } public static class DatagramServer { @@ -217,24 +224,28 @@ public class SAMv3Handler extends SAMv1Handler m_handler = in.getHandler(); } - synchronized public String getDest() + public String getDest() { return m_dest; } + synchronized public Properties getProps() { Properties p = new Properties(); p.putAll(m_props); return m_props; } - synchronized public SAMv3Handler getHandler() + + public SAMv3Handler getHandler() { return m_handler ; } + synchronized public ThreadGroup getThreadGroup() { return m_threadgroup ; } + synchronized public void createThreadGroup(String name) { if (m_threadgroup == null) @@ -244,13 +255,14 @@ public class SAMv3Handler extends SAMv1Handler public static class SessionsDB { - static final long serialVersionUID = 0x1 ; + private static final long serialVersionUID = 0x1; - static class ExistingId extends Exception { - static final long serialVersionUID = 0x1 ; + static class ExistingIdException extends Exception { + private static final long serialVersionUID = 0x1; } - static class ExistingDest extends Exception { - static final long serialVersionUID = 0x1 ; + + static class ExistingDestException extends Exception { + private static final long serialVersionUID = 0x1; } private final HashMap map; @@ -259,14 +271,15 @@ public class SAMv3Handler extends SAMv1Handler map = new HashMap() ; } - synchronized public boolean put( String nick, SessionRecord session ) throws ExistingId, ExistingDest + synchronized public boolean put( String nick, SessionRecord session ) + throws ExistingIdException, ExistingDestException { if ( map.containsKey(nick) ) { - throw new ExistingId(); + throw new ExistingIdException(); } for ( SessionRecord r : map.values() ) { if (r.getDest().equals(session.getDest())) { - throw new ExistingDest(); + throw new ExistingDestException(); } } @@ -278,6 +291,7 @@ public class SAMv3Handler extends SAMv1Handler else return false ; } + synchronized public boolean del( String nick ) { SessionRecord rec = map.get(nick); @@ -293,22 +307,18 @@ public class SAMv3Handler extends SAMv1Handler { return map.get(nick); } + synchronized public boolean containsKey( String nick ) { return map.containsKey(nick); } } - public static final SessionsDB sSessionsHash = new SessionsDB() ; - public String getClientIP() { return this.socket.socket().getInetAddress().getHostAddress(); } - private boolean stolenSocket; - private boolean streamForwardingSocket; - public void stealSocket() { stolenSocket = true ; @@ -324,36 +334,42 @@ public class SAMv3Handler extends SAMv1Handler Properties props; this.thread.setName("SAMv3Handler " + _id); - _log.debug("SAM handling started"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM handling started"); try { InputStream in = getClientSocket().socket().getInputStream(); while (true) { if (shouldStop()) { - _log.debug("Stop request found"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Stop request found"); break; } String line = DataHelper.readLine(in) ; if (line==null) { - _log.debug("Connection closed by client (line read : null)"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connection closed by client (line read : null)"); break; } msg = line.trim(); if (_log.shouldLog(Log.DEBUG)) { - _log.debug("New message received: [" + msg + "]"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("New message received: [" + msg + "]"); } if(msg.equals("")) { - _log.debug("Ignoring newline"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Ignoring newline"); continue; } tok = new StringTokenizer(msg, " "); if (tok.countTokens() < 2) { // This is not a correct message, for sure - _log.debug("Error in message format"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Error in message format"); break; } domain = tok.nextToken(); @@ -377,7 +393,8 @@ public class SAMv3Handler extends SAMv1Handler } else if (domain.equals("DATAGRAM")) { canContinue = execDatagramMessage(opcode, props); } else { - _log.debug("Unrecognized message domain: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized message domain: \"" + domain + "\""); break; } @@ -387,12 +404,14 @@ public class SAMv3Handler extends SAMv1Handler } } } catch (IOException e) { - _log.debug("Caught IOException (" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Caught IOException (" + e.getMessage() + ") for message [" + msg + "]", e); } catch (Exception e) { _log.error("Unexpected exception for message [" + msg + "]", e); } finally { - _log.debug("Stopping handler"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Stopping handler"); if (!this.stolenSocket) { @@ -451,41 +470,55 @@ public class SAMv3Handler extends SAMv1Handler if (opcode.equals("CREATE")) { if ((this.getRawSession()!= null) || (this.getDatagramSession() != null) || (this.getStreamSession() != null)) { - _log.debug("Trying to create a session, but one still exists"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Trying to create a session, but one still exists"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n"); } - if (props == null) { - _log.debug("No parameters specified in SESSION CREATE message"); + if (props.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in SESSION CREATE message"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No parameters for SESSION CREATE\"\n"); } dest = props.getProperty("DESTINATION"); if (dest == null) { - _log.debug("SESSION DESTINATION parameter not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION DESTINATION parameter not specified"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"DESTINATION not specified\"\n"); } props.remove("DESTINATION"); - if (dest.equals("TRANSIENT")) { - _log.debug("TRANSIENT destination requested"); - ByteArrayOutputStream priv = new ByteArrayOutputStream(640); - SAMUtils.genRandomKey(priv, null); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("TRANSIENT destination requested"); + String sigTypeStr = props.getProperty("SIGNATURE_TYPE"); + SigType sigType; + if (sigTypeStr != null) { + sigType = SigType.parseSigType(sigTypeStr); + if (sigType == null) { + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"SIGNATURE_TYPE " + + sigTypeStr + " unsupported\"\n"); + } + props.remove("SIGNATURE_TYPE"); + } else { + sigType = SigType.DSA_SHA1; + } + ByteArrayOutputStream priv = new ByteArrayOutputStream(663); + SAMUtils.genRandomKey(priv, null, sigType); dest = Base64.encode(priv.toByteArray()); } else { - _log.debug("Custom destination specified [" + dest + "]"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Custom destination specified [" + dest + "]"); + if (!SAMUtils.checkPrivateDestination(dest)) + return writeString("SESSION STATUS RESULT=INVALID_KEY\n"); } - try { - SAMUtils.checkPrivateDestination(dest); - } catch ( SAMUtils.InvalidDestination e ) { - return writeString("SESSION STATUS RESULT=INVALID_KEY\n"); - } nick = props.getProperty("ID"); if (nick == null) { - _log.debug("SESSION ID parameter not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION ID parameter not specified"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"ID not specified\"\n"); } props.remove("ID"); @@ -493,7 +526,8 @@ public class SAMv3Handler extends SAMv1Handler String style = props.getProperty("STYLE"); if (style == null) { - _log.debug("SESSION STYLE parameter not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION STYLE parameter not specified"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No SESSION STYLE specified\"\n"); } props.remove("STYLE"); @@ -511,10 +545,11 @@ public class SAMv3Handler extends SAMv1Handler try { sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ; - } catch (SessionsDB.ExistingId e) { - _log.debug("SESSION ID parameter already in use"); + } catch (SessionsDB.ExistingIdException e) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION ID parameter already in use"); return writeString("SESSION STATUS RESULT=DUPLICATED_ID\n"); - } catch (SessionsDB.ExistingDest e) { + } catch (SessionsDB.ExistingDestException e) { return writeString("SESSION STATUS RESULT=DUPLICATED_DEST\n"); } @@ -536,25 +571,30 @@ public class SAMv3Handler extends SAMv1Handler streamSession = v3; this.session = v3; } else { - _log.debug("Unrecognized SESSION STYLE: \"" + style +"\""); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized SESSION STYLE: \"" + style +"\""); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized SESSION STYLE\"\n"); } ok = true ; return writeString("SESSION STATUS RESULT=OK DESTINATION=" + dest + "\n"); } else { - _log.debug("Unrecognized SESSION message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Unrecognized SESSION message opcode: \"" + opcode + "\""); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized opcode\"\n"); } } catch (DataFormatException e) { - _log.debug("Invalid destination specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid destination specified"); return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); } catch (I2PSessionException e) { - _log.debug("I2P error when instantiating session", e); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("I2P error when instantiating session", e); return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); } catch (SAMException e) { - _log.info("Funny SAM error", e); + if (_log.shouldLog(Log.INFO)) + _log.info("Funny SAM error", e); return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); } catch (IOException e) { _log.error("Unexpected IOException", e); @@ -571,25 +611,26 @@ public class SAMv3Handler extends SAMv1Handler /** * @throws NPE if login nickname is not registered */ - private SAMv3StreamSession newSAMStreamSession(String login ) - throws IOException, DataFormatException, SAMException + private static SAMv3StreamSession newSAMStreamSession(String login ) + throws IOException, DataFormatException, SAMException { return new SAMv3StreamSession( login ) ; } - private SAMv3RawSession newSAMRawSession(String login ) - throws IOException, DataFormatException, SAMException, I2PSessionException + private static SAMv3RawSession newSAMRawSession(String login ) + throws IOException, DataFormatException, SAMException, I2PSessionException { return new SAMv3RawSession( login ) ; } - private SAMv3DatagramSession newSAMDatagramSession(String login ) - throws IOException, DataFormatException, SAMException, I2PSessionException + private static SAMv3DatagramSession newSAMDatagramSession(String login ) + throws IOException, DataFormatException, SAMException, I2PSessionException { return new SAMv3DatagramSession( login ) ; } /* Parse and execute a STREAM message */ + @Override protected boolean execStreamMessage ( String opcode, Properties props ) { String nick = null ; @@ -607,7 +648,8 @@ public class SAMv3Handler extends SAMv1Handler nick = props.getProperty("ID"); if (nick == null) { - _log.debug("SESSION ID parameter not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SESSION ID parameter not specified"); try { notifyStreamResult(true, "I2P_ERROR", "ID not specified"); } catch (IOException e) {} @@ -618,7 +660,8 @@ public class SAMv3Handler extends SAMv1Handler rec = sSessionsHash.get(nick); if ( rec==null ) { - _log.debug("STREAM SESSION ID does not exist"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM SESSION ID does not exist"); try { notifyStreamResult(true, "INVALID_ID", "STREAM SESSION ID does not exist"); } catch (IOException e) {} @@ -628,7 +671,8 @@ public class SAMv3Handler extends SAMv1Handler streamSession = rec.getHandler().streamSession ; if (streamSession==null) { - _log.debug("specified ID is not a stream session"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("specified ID is not a stream session"); try { notifyStreamResult(true, "I2P_ERROR", "specified ID is not a STREAM session"); } catch (IOException e) {} @@ -649,7 +693,8 @@ public class SAMv3Handler extends SAMv1Handler } else { - _log.debug ( "Unrecognized RAW message opcode: \"" + if (_log.shouldLog(Log.DEBUG)) + _log.debug ( "Unrecognized RAW message opcode: \"" + opcode + "\"" ); try { notifyStreamResult(true, "I2P_ERROR", "Unrecognized RAW message opcode: "+opcode ); @@ -658,12 +703,13 @@ public class SAMv3Handler extends SAMv1Handler } } - + @Override protected boolean execStreamConnect( Properties props) { try { - if (props == null) { + if (props.isEmpty()) { notifyStreamResult(true,"I2P_ERROR","No parameters specified in STREAM CONNECT message"); - _log.debug("No parameters specified in STREAM CONNECT message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No parameters specified in STREAM CONNECT message"); return false; } boolean verbose = props.getProperty("SILENT","false").equals("false"); @@ -671,7 +717,8 @@ public class SAMv3Handler extends SAMv1Handler String dest = props.getProperty("DESTINATION"); if (dest == null) { notifyStreamResult(verbose, "I2P_ERROR", "Destination not specified in RAW SEND message"); - _log.debug("Destination not specified in RAW SEND message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Destination not specified in RAW SEND message"); return false; } props.remove("DESTINATION"); @@ -680,19 +727,24 @@ public class SAMv3Handler extends SAMv1Handler ((SAMv3StreamSession)streamSession).connect( this, dest, props ); return true ; } catch (DataFormatException e) { - _log.debug("Invalid destination in STREAM CONNECT message"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Invalid destination in STREAM CONNECT message"); notifyStreamResult ( verbose, "INVALID_KEY", null ); } catch (ConnectException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamResult ( verbose, "CONNECTION_REFUSED", null ); } catch (NoRouteToHostException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamResult ( verbose, "CANT_REACH_PEER", null ); } catch (InterruptedIOException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamResult ( verbose, "TIMEOUT", null ); } catch (I2PException e) { - _log.debug("STREAM CONNECT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM CONNECT failed", e); notifyStreamResult ( verbose, "I2P_ERROR", e.getMessage() ); } } catch (IOException e) { @@ -708,7 +760,8 @@ public class SAMv3Handler extends SAMv1Handler notifyStreamResult( true, "OK", null ); return true ; } catch (SAMException e) { - _log.debug("Forwarding STREAM connections failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Forwarding STREAM connections failed", e); notifyStreamResult ( true, "I2P_ERROR", "Forwarding failed : " + e.getMessage() ); } } catch (IOException e) { @@ -725,13 +778,16 @@ public class SAMv3Handler extends SAMv1Handler ((SAMv3StreamSession)streamSession).accept(this, verbose); return true ; } catch (InterruptedIOException e) { - _log.debug("STREAM ACCEPT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM ACCEPT failed", e); notifyStreamResult( verbose, "TIMEOUT", e.getMessage() ); } catch (I2PException e) { - _log.debug("STREAM ACCEPT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM ACCEPT failed", e); notifyStreamResult ( verbose, "I2P_ERROR", e.getMessage() ); } catch (SAMException e) { - _log.debug("STREAM ACCEPT failed: " + e.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("STREAM ACCEPT failed", e); notifyStreamResult ( verbose, "ALREADY_ACCEPTING", null ); } } catch (IOException e) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java index dd5c79fc5..90eae76f9 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java @@ -18,7 +18,7 @@ import net.i2p.util.Log; * @author MKVore * */ -public class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Session, SAMRawReceiver { +class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Session, SAMRawReceiver { private final String nick; private final SAMv3Handler handler; @@ -57,7 +57,8 @@ public class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Sess String portStr = props.getProperty("PORT") ; if ( portStr==null ) { - _log.debug("receiver port not specified. Current socket will be used."); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("receiver port not specified. Current socket will be used."); this.clientAddress = null; } else { @@ -67,7 +68,8 @@ public class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Sess if ( host==null ) { host = rec.getHandler().getClientIP(); - _log.debug("no host specified. Taken from the client socket : " + host +':'+port); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("no host specified. Taken from the client socket : " + host +':'+port); } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java index 8354d6404..45002e4cd 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java @@ -25,7 +25,7 @@ import net.i2p.util.Log; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; -import java.nio.ByteBuffer ; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; /** @@ -34,7 +34,7 @@ import java.nio.channels.SocketChannel; * @author mkvore */ -public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Session +class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Session { private static final int BUFFER_SIZE = 1024 ; @@ -97,7 +97,8 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle if (props.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null) opts.setConnectTimeout(60 * 1000); - _log.debug("Connecting new I2PSocket..."); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connecting new I2PSocket..."); // blocking connection (SAMv3) @@ -142,7 +143,8 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle synchronized( this.socketServerLock ) { if (this.socketServer!=null) { - _log.debug("a socket server is already defined for this destination"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("a socket server is already defined for this destination"); throw new SAMException("a socket server is already defined for this destination"); } this.socketServer = this.socketMgr.getServerSocket(); @@ -183,7 +185,8 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle String portStr = props.getProperty("PORT") ; if ( portStr==null ) { - _log.debug("receiver port not specified"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("receiver port not specified"); throw new SAMException("receiver port not specified"); } int port = Integer.parseInt(portStr); @@ -191,14 +194,16 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle String host = props.getProperty("HOST"); if ( host==null ) { host = rec.getHandler().getClientIP(); - _log.debug("no host specified. Taken from the client socket : " + host +':'+port); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("no host specified. Taken from the client socket : " + host +':'+port); } synchronized( this.socketServerLock ) { if (this.socketServer!=null) { - _log.debug("a socket server is already defined for this destination"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("a socket server is already defined for this destination"); throw new SAMException("a socket server is already defined for this destination"); } this.socketServer = this.socketMgr.getServerSocket(); @@ -337,12 +342,14 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle synchronized( this.socketServerLock ) { if (this.socketServer==null) { - _log.debug("no socket server is defined for this destination"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("no socket server is defined for this destination"); throw new SAMException("no socket server is defined for this destination"); } server = this.socketServer ; this.socketServer = null ; - _log.debug("nulling socketServer in stopForwardingIncoming. Object " + this ); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("nulling socketServer in stopForwardingIncoming. Object " + this ); } try { server.close(); diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java index cd70161eb..40629bf83 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java @@ -61,15 +61,19 @@ public class SAMStreamSend { } public void startup() { - _log.debug("Starting up"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Starting up"); boolean ok = connect(); - _log.debug("Connected: " + ok); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connected: " + ok); if (ok) { _reader = new SAMReader(_context, _samIn, _eventHandler); _reader.startReading(); - _log.debug("Reader created"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Reader created"); String ourDest = handshake(); - _log.debug("Handshake complete. we are " + ourDest); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Handshake complete. we are " + ourDest); if (ourDest != null) { send(); } @@ -85,7 +89,8 @@ public class SAMStreamSend { } if (sender != null) { sender.closed(); - _log.debug("Connection " + sender.getConnectionId() + " closed to " + sender.getDestination()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connection " + sender.getConnectionId() + " closed to " + sender.getDestination()); } else { _log.error("wtf, not connected to " + id + " but we were just closed?"); } @@ -109,24 +114,30 @@ public class SAMStreamSend { try { _samOut.write("HELLO VERSION MIN=1.0 MAX=1.0\n".getBytes()); _samOut.flush(); - _log.debug("Hello sent"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Hello sent"); boolean ok = _eventHandler.waitForHelloReply(); - _log.debug("Hello reply found: " + ok); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Hello reply found: " + ok); if (!ok) throw new IOException("wtf, hello failed?"); String req = "SESSION CREATE STYLE=STREAM DESTINATION=TRANSIENT " + _conOptions + "\n"; _samOut.write(req.getBytes()); _samOut.flush(); - _log.debug("Session create sent"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Session create sent"); ok = _eventHandler.waitForSessionCreateReply(); - _log.debug("Session create reply found: " + ok); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Session create reply found: " + ok); req = "NAMING LOOKUP NAME=ME\n"; _samOut.write(req.getBytes()); _samOut.flush(); - _log.debug("Naming lookup sent"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Naming lookup sent"); String destination = _eventHandler.waitForNamingReply("ME"); - _log.debug("Naming lookup reply found: " + destination); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Naming lookup reply found: " + destination); if (destination == null) { _log.error("No naming lookup reply found!"); return null; @@ -213,10 +224,12 @@ public class SAMStreamSend { int read = _in.read(data); long now = _context.clock().now(); if (read == -1) { - _log.debug("EOF from the data for " + _connectionId + " after " + (now-lastSend)); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("EOF from the data for " + _connectionId + " after " + (now-lastSend)); break; } else if (read > 0) { - _log.debug("Sending " + read + " on " + _connectionId + " after " + (now-lastSend)); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Sending " + read + " on " + _connectionId + " after " + (now-lastSend)); lastSend = now; byte msg[] = ("STREAM SEND ID=" + _connectionId + " SIZE=" + read + "\n").getBytes(); @@ -247,4 +260,4 @@ public class SAMStreamSend { closed(); } } -} \ No newline at end of file +} diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java index 31d983ee1..666b7116d 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java @@ -60,26 +60,33 @@ public class SAMStreamSink { } public void startup() { - _log.debug("Starting up"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Starting up"); boolean ok = connect(); - _log.debug("Connected: " + ok); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connected: " + ok); if (ok) { _reader = new SAMReader(_context, _samIn, _eventHandler); _reader.startReading(); - _log.debug("Reader created"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Reader created"); String ourDest = handshake(); - _log.debug("Handshake complete. we are " + ourDest); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Handshake complete. we are " + ourDest); if (ourDest != null) { //boolean written = - writeDest(ourDest); - _log.debug("Dest written"); + writeDest(ourDest); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Dest written"); } } } private class SinkEventHandler extends SAMEventHandler { + public SinkEventHandler(I2PAppContext ctx) { super(ctx); } - @Override + + @Override public void streamClosedReceived(String result, int id, String message) { Sink sink = null; synchronized (_remotePeers) { @@ -87,12 +94,14 @@ public class SAMStreamSink { } if (sink != null) { sink.closed(); - _log.debug("Connection " + sink.getConnectionId() + " closed to " + sink.getDestination()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connection " + sink.getConnectionId() + " closed to " + sink.getDestination()); } else { _log.error("wtf, not connected to " + id + " but we were just closed?"); } } - @Override + + @Override public void streamDataReceived(int id, byte data[], int offset, int length) { Sink sink = null; synchronized (_remotePeers) { @@ -104,9 +113,11 @@ public class SAMStreamSink { _log.error("wtf, not connected to " + id + " but we received " + length + "?"); } } - @Override + + @Override public void streamConnectedReceived(String dest, int id) { - _log.debug("Connection " + id + " received from " + dest); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Connection " + id + " received from " + dest); try { Sink sink = new Sink(id, dest); @@ -136,24 +147,30 @@ public class SAMStreamSink { try { _samOut.write("HELLO VERSION MIN=1.0 MAX=1.0\n".getBytes()); _samOut.flush(); - _log.debug("Hello sent"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Hello sent"); boolean ok = _eventHandler.waitForHelloReply(); - _log.debug("Hello reply found: " + ok); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Hello reply found: " + ok); if (!ok) throw new IOException("wtf, hello failed?"); String req = "SESSION CREATE STYLE=STREAM DESTINATION=" + _destFile + " " + _conOptions + "\n"; _samOut.write(req.getBytes()); _samOut.flush(); - _log.debug("Session create sent"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Session create sent"); ok = _eventHandler.waitForSessionCreateReply(); - _log.debug("Session create reply found: " + ok); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Session create reply found: " + ok); req = "NAMING LOOKUP NAME=ME\n"; _samOut.write(req.getBytes()); _samOut.flush(); - _log.debug("Naming lookup sent"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Naming lookup sent"); String destination = _eventHandler.waitForNamingReply("ME"); - _log.debug("Naming lookup reply found: " + destination); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Naming lookup reply found: " + destination); if (destination == null) { _log.error("No naming lookup reply found!"); return null; @@ -230,10 +247,11 @@ public class SAMStreamSink { closed(); return; } - _log.debug("Received " + len + " on " + _connectionId + " after " + (_context.clock().now()-_lastReceivedOn) + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Received " + len + " on " + _connectionId + " after " + (_context.clock().now()-_lastReceivedOn) + "ms with " + _remoteDestination.substring(0,6)); _lastReceivedOn = _context.clock().now(); } } -} \ No newline at end of file +} diff --git a/apps/streaming/java/build.xml b/apps/streaming/java/build.xml index abffdc30b..73cbeb9fa 100644 --- a/apps/streaming/java/build.xml +++ b/apps/streaming/java/build.xml @@ -20,13 +20,17 @@
+ + + + @@ -51,7 +55,7 @@ diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/AcceptingChannelImpl.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/AcceptingChannelImpl.java deleted file mode 100644 index b4952438d..000000000 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/AcceptingChannelImpl.java +++ /dev/null @@ -1,157 +0,0 @@ -package net.i2p.client.streaming.impl; - -import java.net.SocketTimeoutException; -import java.net.ConnectException; -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.spi.AbstractSelectionKey; -import java.nio.channels.spi.SelectorProvider; - -import net.i2p.I2PException; -import net.i2p.client.streaming.AcceptingChannel; -import net.i2p.client.streaming.I2PServerSocket; -import net.i2p.client.streaming.I2PSocket; -import net.i2p.client.streaming.I2PSocketManager; - -/** - * As this does not (yet) extend ServerSocketChannel it cannot be returned by StandardServerSocket.getChannel(), - * until we implement an I2P SocketAddress class. - * - * Warning, this interface and implementation is preliminary and subject to change without notice. - * - * @since 0.8.11 - */ -class AcceptingChannelImpl extends AcceptingChannel { - private boolean _isRegistered; - private SelectionKey whichKey; - private SelectorProvider provider; - private Selector sel; - private Object lock; - private volatile I2PSocket next; - private final I2PServerSocket socket; - - protected I2PSocket accept() throws I2PException, ConnectException { - I2PSocket sock; - try { - sock = socket.accept(); - } catch(SocketTimeoutException ex) { - return null; - } - synchronized (this) { - I2PSocket temp = next; - next = sock; - return temp; - } - } - - protected AcceptingChannelImpl(I2PSocketManager manager) { - super(manager); - // this cheats and just sets the manager timeout low in order to repeatedly poll it. - // that means we can "only" accept one new connection every 100 milliseconds. - socket = manager.getServerSocket(); - socket.setSoTimeout(100); - } - - @Override - public SelectorProvider provider() { - return provider; - } - - @Override - public int validOps() { - return SelectionKey.OP_ACCEPT; - } - - @Override - public boolean isRegistered() { - return _isRegistered; - } - - @Override - public SelectionKey keyFor(Selector arg0) { - return whichKey; - } - - @Override - public SelectionKey register(final Selector sel, final int ops, Object lock) throws ClosedChannelException { - this.sel = sel; - this.provider = sel.provider(); - this.lock = lock; - this._isRegistered = true; - final AcceptingChannel that = this; // lol java - SelectionKey key = new AbstractSelectionKey() { - int operations = ops; - @Override - public SelectableChannel channel() { - return that; - } - - @Override - public Selector selector() { - return sel; - } - - @Override - public int interestOps() { - return this.operations; - } - - @Override - public SelectionKey interestOps(int ops) { - this.operations = ops; - return this; - } - - @Override - public int readyOps() { - if((operations & OP_ACCEPT) != 0) { - if(next != null) { - return OP_ACCEPT; - } else { - try { - accept(); // ping it again. - } catch(I2PException ex) { - } catch(ConnectException ex) {} - if(next != null) - return OP_ACCEPT; - } - } - return 0; - } - }; - key.attach(lock); - // I... THINK this is right? - sel.keys().add(key); - return key; - } - - @Override - public SelectableChannel configureBlocking(boolean blocking) throws IOException { - if (blocking == false) { - return this; - } - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean isBlocking() { - return false; - } - - @Override - public Object blockingLock() { - return this.lock; - } - - @Override - protected void implCloseChannel() throws IOException { - I2PSocket nxt = next; - if(nxt != null) { - nxt.close(); - } - _socketManager.destroySocketManager(); - } -} diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PServerSocketFull.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PServerSocketFull.java index bf673667c..c41c5082e 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PServerSocketFull.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PServerSocketFull.java @@ -14,7 +14,6 @@ import net.i2p.client.streaming.I2PSocketManager; */ class I2PServerSocketFull implements I2PServerSocket { private final I2PSocketManagerFull _socketManager; - private volatile AcceptingChannel _channel; public I2PServerSocketFull(I2PSocketManagerFull mgr) { _socketManager = mgr; @@ -32,12 +31,14 @@ class I2PServerSocketFull implements I2PServerSocket { } /** + * Unimplemented, unlikely to ever be implemented. + * + * @deprecated + * @return null always * @since 0.8.11 */ public synchronized AcceptingChannel getChannel() { - if (_channel == null) - _channel = new AcceptingChannelImpl(_socketManager); - return _channel; + return null; } public long getSoTimeout() { diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PSocketFull.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PSocketFull.java index 6e59ab1bb..2885db4c9 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PSocketFull.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/I2PSocketFull.java @@ -22,7 +22,6 @@ class I2PSocketFull implements I2PSocket { private volatile Connection _connection; private final Destination _remotePeer; private final Destination _localPeer; - private volatile MessageChannel _channel; private final AtomicBoolean _closed = new AtomicBoolean(); public I2PSocketFull(Connection con, I2PAppContext context) { @@ -89,12 +88,14 @@ class I2PSocketFull implements I2PSocket { } /** + * Unimplemented, unlikely to ever be implemented. + * + * @deprecated + * @return null always * @since 0.8.9 */ public synchronized SelectableChannel getChannel() { - if (_channel == null) - _channel = new MessageChannel(this); - return _channel; + return null; } /** diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/MessageChannel.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/MessageChannel.java deleted file mode 100644 index 5e3cecacd..000000000 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/MessageChannel.java +++ /dev/null @@ -1,194 +0,0 @@ -package net.i2p.client.streaming.impl; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.WritableByteChannel; -import java.nio.channels.spi.AbstractSelectionKey; -import java.nio.channels.spi.SelectorProvider; -import java.util.logging.Level; -import java.util.logging.Logger; - -import net.i2p.client.streaming.I2PSocket; - -/** - * As this does not (yet) extend SocketChannel it cannot be returned by StandardSocket.getChannel(), - * until we implement an I2P SocketAddress class. - * - * Warning, this interface and implementation is preliminary and subject to change without notice. - * - * @since 0.8.9 - */ -public class MessageChannel extends SelectableChannel implements ReadableByteChannel, WritableByteChannel { - - private final MessageInputStream in; - private final MessageOutputStream out; - private boolean _isRegistered; - private SelectionKey whichKey; - private SelectorProvider provider; - private Selector sel; - private Object lock; - private final I2PSocket socket; - - MessageChannel(I2PSocket socket) { - try { - this.socket = socket; - in = (MessageInputStream) socket.getInputStream(); - out = (MessageOutputStream) socket.getOutputStream(); - in.setReadTimeout(0); - out.setWriteTimeout(0); - out.setBufferSize(0x1000); - } catch (IOException ex) { - Logger.getLogger(MessageChannel.class.getName()).log(Level.SEVERE, null, ex); - // dunno what to do with this for now - throw new RuntimeException(ex); - } - } - - @Override - public SelectorProvider provider() { - return provider; - } - - @Override - public int validOps() { - return SelectionKey.OP_READ | SelectionKey.OP_WRITE; - } - - @Override - public boolean isRegistered() { - return _isRegistered; - } - - @Override - public SelectionKey keyFor(Selector arg0) { - return whichKey; - } - - @Override - public SelectionKey register(final Selector sel, final int ops, Object lock) throws ClosedChannelException { - this.sel = sel; - this.provider = sel.provider(); - this.lock = lock; - this._isRegistered = true; - final MessageChannel that = this; // lol java - SelectionKey key = new AbstractSelectionKey() { - int operations = ops; - @Override - public SelectableChannel channel() { - return that; - } - - @Override - public Selector selector() { - return sel; - } - - @Override - public int interestOps() { - return this.operations; - } - - @Override - public SelectionKey interestOps(int ops) { - this.operations = ops; - return this; - } - - @Override - public int readyOps() { - int readyOps = 0; - if((operations & OP_READ) != 0) { - try { - // check the input stream - if (in.available() > 0) { - readyOps |= OP_READ; - } - } catch (IOException ex) {} - } - if((operations & OP_WRITE) != 0) { - if(!out.getClosed()) - readyOps |= OP_WRITE; - } - return readyOps; - } - }; - key.attach(lock); - // I... THINK this is right? - sel.keys().add(key); - return key; - } - - @Override - public SelectableChannel configureBlocking(boolean blocking) throws IOException { - if (blocking == false) { - return this; - } - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean isBlocking() { - return false; - } - - @Override - public Object blockingLock() { - return this.lock; - } - - @Override - protected void implCloseChannel() throws IOException { - this.socket.close(); - } - - /* Read no more than buf.remaining() - * Continue to read until that, or in.read - * returns 0, which happens when there's - * no more data available. - */ - public int read(ByteBuffer buf) throws IOException { - int amount = 0; - for (;;) { - // TODO if buf.hasArray() ... getArray() ... getArrayOffset() ... - byte[] lbuf = new byte[buf.remaining()]; - int samount = in.read(lbuf); - if (samount <= 0) { - this.close(); - } - if (samount == 0) { - break; - } - amount += samount; - buf.put(lbuf, 0, samount); - } - return amount; - } - - /* Write in 0x1000 increments, the MessageOutputStream's - * already set buffer size. Once it starts to fail - * (wait timeout is 0) then put the bytes back and return. - */ - public int write(ByteBuffer buf) throws IOException { - int written = 0; - for (;;) { - if(buf.remaining()==0) - return written; - // TODO if buf.hasArray() ... getArray() ... getArrayOffset() ... - byte[] lbuf = new byte[Math.min(buf.remaining(), 0x1000)]; - buf.get(lbuf); - try { - out.write(lbuf, 0, lbuf.length); - written += lbuf.length; - } catch(InterruptedIOException ex) { - buf.put(lbuf); - return written; - } - } - } -} diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketQueue.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketQueue.java index 214e1c2cd..1fdbb943f 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketQueue.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/PacketQueue.java @@ -216,7 +216,7 @@ class PacketQueue implements SendMessageStatusListener { _connectionManager.getPacketHandler().displayPacket(packet, "SEND", suffix); if (I2PSocketManagerFull.pcapWriter != null && _context.getBooleanProperty(I2PSocketManagerFull.PROP_PCAP)) - ((PacketLocal)packet).logTCPDump(); + packet.logTCPDump(); } if ( (packet.getSequenceNum() == 0) && (!packet.isFlagSet(Packet.FLAG_SYNCHRONIZE)) ) { @@ -295,7 +295,7 @@ class PacketQueue implements SendMessageStatusListener { IOException ioe = new I2PSocketException(status); con.getOutputStream().streamErrorOccurred(ioe); con.getInputStream().streamErrorOccurred(ioe); - con.setConnectionError("failure code " + status); + con.setConnectionError(ioe.getLocalizedMessage()); con.disconnect(false); } break; diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardServerSocket.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardServerSocket.java index 3bcf53a4d..aaab086f0 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardServerSocket.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardServerSocket.java @@ -74,7 +74,7 @@ class StandardServerSocket extends ServerSocket { } /** - * @return null always, see AcceptingChannelImpl for more info + * @return null always, unimplemented */ @Override public ServerSocketChannel getChannel() { diff --git a/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardSocket.java b/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardSocket.java index 549df289a..686eadd98 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardSocket.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/impl/StandardSocket.java @@ -68,7 +68,7 @@ class StandardSocket extends Socket { } /** - * @return null always, see MessageChannel for more info + * @return null always, unimplemented */ @Override public SocketChannel getChannel() { diff --git a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java b/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java index aa45beeed..1e3cdb70b 100644 --- a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java +++ b/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java @@ -154,7 +154,7 @@ class RequestWrapper { { String result = defaultValue; if( multiPartRequest != null ) { - String str = (String)cache.get( name ); + String str = cache.get(name); if( str != null ) { result = str; } diff --git a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java index b2b3797a6..eee7e9fbc 100644 --- a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java +++ b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java @@ -1211,7 +1211,7 @@ public class WebMail extends HttpServlet for (Integer item : getCheckedItems(request)) { int n = item.intValue(); for( int i = 0; i < sessionObject.attachments.size(); i++ ) { - Attachment attachment = (Attachment)sessionObject.attachments.get( i ); + Attachment attachment = sessionObject.attachments.get(i); if( attachment.hashCode() == n ) { sessionObject.attachments.remove( i ); break; diff --git a/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java b/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java index c6987ebae..88bc0296d 100644 --- a/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java +++ b/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java @@ -290,7 +290,7 @@ public class MultiPartRequest { String key = line.substring(0,c).trim().toLowerCase(); String value = line.substring(c+1,line.length()).trim(); - String ev = (String) part._headers.get(key); + String ev = part._headers.get(key); part._headers.put(key,(ev!=null)?(ev+';'+value):value); //if(log.isDebugEnabled())log.debug(key+": "+value); if (key.equals("content-disposition")) diff --git a/build.xml b/build.xml index 2b60302b8..670efa628 100644 --- a/build.xml +++ b/build.xml @@ -67,6 +67,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -91,22 +139,28 @@ + + + + + + @@ -116,15 +170,19 @@ + + + + @@ -132,6 +190,7 @@ --> + @@ -140,18 +199,24 @@ + + + + + + @@ -174,10 +239,27 @@ - + + + + + + + + + + + + + + + + + + @@ -235,26 +317,6 @@ match='(^\s+public\s+final\s+static\s+long\s+BUILD\s+=\s+)[0-9]+;' replace='\1${new.i2p.build.number};'/> - - - - - - - - - - - - - - - - - - - - @@ -298,25 +360,17 @@ classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" /> - - - - - - - + + + - - - - - - - - - - - + + + + @@ -466,6 +520,7 @@ + @@ -543,8 +598,8 @@ - + @@ -552,7 +607,9 @@ - + + + @@ -580,8 +637,10 @@ - + @@ -696,7 +755,7 @@ - + @@ -1321,7 +1380,7 @@ - + @@ -1501,11 +1560,11 @@ - + - + @@ -1671,48 +1730,20 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -1729,43 +1760,20 @@ - - - - - - - - - + + + + + + + - - - - - - - - + - - - - - - - - + - - - - - - - - + diff --git a/core/java/build.xml b/core/java/build.xml index 0d3f10dec..032d400d9 100644 --- a/core/java/build.xml +++ b/core/java/build.xml @@ -15,13 +15,16 @@ destdir="./build/obj" > + + + - @@ -103,7 +106,7 @@ - diff --git a/core/java/src/gnu/crypto/prng/FortunaStandalone.java b/core/java/src/gnu/crypto/prng/FortunaStandalone.java index 1cff8d71e..931649ec0 100644 --- a/core/java/src/gnu/crypto/prng/FortunaStandalone.java +++ b/core/java/src/gnu/crypto/prng/FortunaStandalone.java @@ -317,7 +317,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl seeded = false; Arrays.fill(key, (byte) 0); Arrays.fill(counter, (byte) 0); - byte[] seed = (byte[]) attributes.get(SEED); + byte[] seed = attributes.get(SEED); if (seed != null) addRandomBytes(seed); } diff --git a/core/java/src/net/i2p/client/I2PSession.java b/core/java/src/net/i2p/client/I2PSession.java index 2d535c25a..da67e2c02 100644 --- a/core/java/src/net/i2p/client/I2PSession.java +++ b/core/java/src/net/i2p/client/I2PSession.java @@ -132,7 +132,7 @@ public interface I2PSession { * @since 0.7.1 */ public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, - int proto, int fromport, int toport) throws I2PSessionException; + int proto, int fromPort, int toPort) throws I2PSessionException; /** * See I2PSessionMuxedImpl for proto/port details. @@ -151,7 +151,7 @@ public interface I2PSession { * @since 0.7.1 */ public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expire, - int proto, int fromport, int toport) throws I2PSessionException; + int proto, int fromPort, int toPort) throws I2PSessionException; /** * See I2PSessionMuxedImpl for proto/port details. @@ -170,7 +170,7 @@ public interface I2PSession { * @since 0.8.4 */ public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expire, - int proto, int fromport, int toport, int flags) throws I2PSessionException; + int proto, int fromPort, int toPort, int flags) throws I2PSessionException; /** * See I2PSessionMuxedImpl for proto/port details. @@ -188,7 +188,7 @@ public interface I2PSession { * @since 0.9.2 */ public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, - int proto, int fromport, int toport, SendMessageOptions options) throws I2PSessionException; + int proto, int fromPort, int toPort, SendMessageOptions options) throws I2PSessionException; /** * Send a message and request an asynchronous notification of delivery status. @@ -211,7 +211,7 @@ public interface I2PSession { * @since 0.9.14 */ public long sendMessage(Destination dest, byte[] payload, int offset, int size, - int proto, int fromport, int toport, + int proto, int fromPort, int toPort, SendMessageOptions options, SendMessageStatusListener listener) throws I2PSessionException; /** Receive a message that the router has notified the client about, returning diff --git a/core/java/src/net/i2p/client/naming/BlockfileNamingService.java b/core/java/src/net/i2p/client/naming/BlockfileNamingService.java index 9194d81aa..d7860a727 100644 --- a/core/java/src/net/i2p/client/naming/BlockfileNamingService.java +++ b/core/java/src/net/i2p/client/naming/BlockfileNamingService.java @@ -240,7 +240,7 @@ public class BlockfileNamingService extends DummyNamingService { if (line.length() < split + 1) continue; } - String b64 = line.substring(split+1); //.trim() ?????????????? + String b64 = line.substring(split+1).trim(); Destination d = lookupBase64(b64); if (d != null) { addEntry(rv, hostsfile, key, d, sourceMsg); diff --git a/core/java/src/net/i2p/client/naming/EepGetNamingService.java b/core/java/src/net/i2p/client/naming/EepGetNamingService.java index 69af4e5ca..3bc62a4d5 100644 --- a/core/java/src/net/i2p/client/naming/EepGetNamingService.java +++ b/core/java/src/net/i2p/client/naming/EepGetNamingService.java @@ -85,7 +85,7 @@ public class EepGetNamingService extends DummyNamingService { // lookup for (int i = 0; i < URLs.size(); i++) { - String url = (String)URLs.get(i); + String url = URLs.get(i); String key = fetchAddr(url, hostname); if (key != null) { _log.error("Success: " + url + hostname); diff --git a/core/java/src/net/i2p/crypto/KeyGenerator.java b/core/java/src/net/i2p/crypto/KeyGenerator.java index 69f53f71c..f078aaa5c 100644 --- a/core/java/src/net/i2p/crypto/KeyGenerator.java +++ b/core/java/src/net/i2p/crypto/KeyGenerator.java @@ -159,6 +159,7 @@ public class KeyGenerator { /** Convert a PrivateKey to its corresponding PublicKey * @param priv PrivateKey object * @return the corresponding PublicKey object + * @throws IllegalArgumentException on bad key */ public static PublicKey getPublicKey(PrivateKey priv) { BigInteger a = new NativeBigInteger(1, priv.toByteArray()); @@ -271,8 +272,11 @@ public class KeyGenerator { * * @param priv a SigningPrivateKey object * @return a SigningPublicKey object + * @throws IllegalArgumentException on bad key */ public static SigningPublicKey getSigningPublicKey(SigningPrivateKey priv) { + if (priv.getType() != SigType.DSA_SHA1) + throw new IllegalArgumentException(); BigInteger x = new NativeBigInteger(1, priv.toByteArray()); BigInteger y = CryptoConstants.dsag.modPow(x, CryptoConstants.dsap); SigningPublicKey pub = new SigningPublicKey(); diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index 6647c8d45..0c7adc465 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -513,7 +513,7 @@ public class SU3File { /** @since 0.9.9 */ private static String dumpTypes() { StringBuilder buf = new StringBuilder(256); - buf.append("Available signature types:\n"); + buf.append("Available signature types (-t):\n"); for (SigType t : EnumSet.allOf(SigType.class)) { if (!t.isAvailable()) continue; @@ -522,9 +522,11 @@ public class SU3File { buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')'); if (t.getCode() == DEFAULT_SIG_CODE) buf.append(" DEFAULT"); + if (!t.isAvailable()) + buf.append(" UNAVAILABLE"); buf.append('\n'); } - buf.append("Available content types:\n"); + buf.append("Available content types (-c):\n"); for (ContentType t : EnumSet.allOf(ContentType.class)) { buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')'); if (t == DEFAULT_CONTENT_TYPE) diff --git a/core/java/src/net/i2p/crypto/SessionKeyManager.java b/core/java/src/net/i2p/crypto/SessionKeyManager.java index 1b2e4326f..cb67c9f3f 100644 --- a/core/java/src/net/i2p/crypto/SessionKeyManager.java +++ b/core/java/src/net/i2p/crypto/SessionKeyManager.java @@ -22,17 +22,27 @@ import net.i2p.data.SessionTag; * Manage the session keys and session tags used for encryption and decryption. * This base implementation simply ignores sessions and acts as if everything is * unknown (and hence always forces a full ElGamal encryption for each message). - * A more intelligent subclass should manage and persist keys and tags. + * See TransientSessionKeyManager subclass which manages and persists keys and tags. * - * TODO if we aren't going to use this for testing, make it abstract. */ public class SessionKeyManager { /** - * Make this public if you need a dummy SessionKeyManager for testing + * A dummy SessionKeyManager for testing or for passing to + * ElGamalAESEngine.encrypt() + * + * @since 0.9.14 */ - protected SessionKeyManager(I2PAppContext context) { // nop - } + public SessionKeyManager() {} + + /** + * A dummy SessionKeyManager for testing or for passing to + * ElGamalAESEngine.encrypt() + * + * @param context unused + * @since public since 0.9.14; protected before that + */ + public SessionKeyManager(I2PAppContext context) {} /** * Retrieve the session key currently associated with encryption to the target, diff --git a/core/java/src/net/i2p/crypto/SigType.java b/core/java/src/net/i2p/crypto/SigType.java index a5fe5304e..fbeafee50 100644 --- a/core/java/src/net/i2p/crypto/SigType.java +++ b/core/java/src/net/i2p/crypto/SigType.java @@ -210,7 +210,7 @@ public enum SigType { return getByCode(code); } catch (NumberFormatException nfe) { return null; - } + } } } } diff --git a/core/java/src/net/i2p/data/Base64.java b/core/java/src/net/i2p/data/Base64.java index 8fb72e1c0..578dadda2 100644 --- a/core/java/src/net/i2p/data/Base64.java +++ b/core/java/src/net/i2p/data/Base64.java @@ -42,13 +42,17 @@ public class Base64 { //private final static Log _log = new Log(Base64.class); /** + * Output will be a multiple of 4 chars, including 0-2 trailing '=' + * As of 0.9.14, encodes the UTF-8 encoding of source. Prior to that, used the platform's encoding. + * * @param source if null will return "" */ public static String encode(String source) { - return (source != null ? encode(source.getBytes()) : ""); + return (source != null ? encode(DataHelper.getUTF8(source)) : ""); } /** + * Output will be a multiple of 4 chars, including 0-2 trailing '=' * @param source if null will return "" */ public static String encode(byte[] source) { @@ -56,6 +60,7 @@ public class Base64 { } /** + * Output will be a multiple of 4 chars, including 0-2 trailing '=' * @param source if null will return "" */ public static String encode(byte[] source, int off, int len) { @@ -63,6 +68,7 @@ public class Base64 { } /** + * Output will be a multiple of 4 chars, including 0-2 trailing '=' * @param source if null will return "" * @param useStandardAlphabet Warning, must be false for I2P compatibility */ @@ -71,6 +77,7 @@ public class Base64 { } /** + * Output will be a multiple of 4 chars, including 0-2 trailing '=' * @param source if null will return "" * @param useStandardAlphabet Warning, must be false for I2P compatibility */ @@ -79,7 +86,17 @@ public class Base64 { } /** - * Decodes data from Base64 notation. + * Decodes data from Base64 notation using the I2P alphabet. + * + * As of 0.9.14, does not require trailing '=' if remaining bits are zero. + * Prior to that, trailing 1, 2, or 3 chars were ignored. + * + * As of 0.9.14, trailing garbage after an '=' will cause an error. + * Prior to that, it was ignored. + * + * As of 0.9.14, whitespace will cause an error. + * Prior to that, it was ignored. + * * @param s Base 64 encoded string using the I2P alphabet A-Z, a-z, 0-9, -, ~ * @return the decoded data, null on error */ @@ -122,6 +139,7 @@ public class Base64 { /** * Translates a Base64 value to either its 6-bit reconstruction value * or a negative number indicating some other meaning. + * As of 0.9.14 this is the decoding for the I2P alphabet. See safeDecode(). **/ private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 -5, -5, // Whitespace: Tab and Linefeed @@ -131,9 +149,8 @@ public class Base64 { -9, -9, -9, -9, -9, // Decimal 27 - 31 -5, // Whitespace: Space -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9, -9, -9, // Decimal 44 - 46 - 63, // Slash at decimal 47 + //62, -9, -9, -9, 63, // + , - . / (43-47) NON-I2P + -9, -9, 62, -9, -9, // + , - . / (43-47) I2P 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine -9, -9, -9, // Decimal 58 - 60 -1, // Equals sign at decimal 61 @@ -143,8 +160,9 @@ public class Base64 { -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9 // Decimal 123 - 126 - /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + //-9, -9, -9, -9 // Decimal 123 - 126 (126 is '~') NON-I2P + -9, -9, -9, 63 // Decimal 123 - 126 (126 is '~') I2P + ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 @@ -153,9 +171,10 @@ public class Base64 { -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 }; + private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding @@ -167,7 +186,6 @@ public class Base64 { //test(); if (args.length == 0) { help(); - return; } runApp(args); } @@ -175,22 +193,36 @@ public class Base64 { private static void runApp(String args[]) { String cmd = args[0].toLowerCase(Locale.US); if ("encodestring".equals(cmd)) { - System.out.println(encode(args[1].getBytes())); + if (args.length != 2) + help(); + System.out.println(encode(DataHelper.getUTF8(args[1]))); return; } if ("decodestring".equals(cmd)) { + if (args.length != 2) + help(); byte[] dec = decode(args[1]); if (dec != null) { try { System.out.write(dec); } catch (IOException ioe) { System.err.println("output error " + ioe); + System.exit(1); } } else { System.err.println("decode error"); + System.exit(1); } return; } + if ("test".equals(cmd)) { + System.err.println("test disabled"); + System.exit(1); + } + if (!("encode".equals(cmd) || "decode".equals(cmd))) { + System.err.println("unknown command " + cmd); + System.exit(1); + } InputStream in = System.in; OutputStream out = System.out; try { @@ -202,11 +234,8 @@ public class Base64 { } if ("encode".equals(cmd)) { encode(in, out); - return; - } - if ("decode".equals(cmd)) { + } else { decode(in, out); - return; } } catch (IOException ioe) { ioe.printStackTrace(System.err); @@ -238,16 +267,18 @@ public class Base64 { out.write(decoded); } + /** exits 1, never returns */ private static void help() { - System.out.println("Syntax: Base64 encode "); - System.out.println("or : Base64 encode "); - System.out.println("or : Base64 encode"); - System.out.println("or : Base64 decode "); - System.out.println("or : Base64 decode "); - System.out.println("or : Base64 decode"); - System.out.println("or : Base64 encodestring 'string to encode'"); - System.out.println("or : Base64 decodestring 'string to decode'"); - System.out.println("or : Base64 test"); + System.err.println("Usage: Base64 encode "); + System.err.println(" Base64 encode "); + System.err.println(" Base64 encode (stdin to stdout)"); + System.err.println(" Base64 decode "); + System.err.println(" Base64 decode "); + System.err.println(" Base64 decode (stdin to stdout)"); + System.err.println(" Base64 encodestring 'string to encode'"); + System.err.println(" Base64 decodestring 'string to decode'"); + System.err.println(" Base64 test"); + System.exit(1); } /******* @@ -458,12 +489,15 @@ public class Base64 { */ private static byte[] safeDecode(String source, boolean useStandardAlphabet) { if (source == null) return null; - String toDecode = null; + String toDecode; if (useStandardAlphabet) { - toDecode = source; + //toDecode = source; + toDecode = source.replace('/', '~'); + toDecode = toDecode.replace('+', '-'); } else { - toDecode = source.replace('~', '/'); - toDecode = toDecode.replace('-', '+'); + //toDecode = source.replace('~', '/'); + //toDecode = toDecode.replace('-', '+'); + toDecode = source; } return standardDecode(toDecode); } @@ -600,76 +634,75 @@ public class Base64 { * @param srcOffset the index where conversion begins * @param destination the array to hold the conversion * @param destOffset the index where output will be put - * @return the number of decoded bytes converted + * @return the number of decoded bytes converted 1-3, or -1 on error, never zero * @since 1.3 */ private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) { - // Example: Dk== - if (source[srcOffset + 2] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12); + byte decode0 = DECODABET[source[srcOffset++]]; + byte decode1 = DECODABET[source[srcOffset++]]; + if (decode0 < 0 || decode1 < 0) + return -1; - destination[destOffset] = (byte) (outBuff >>> 16); + // Example: Dk== + if (source[srcOffset] == EQUALS_SIGN) { + if (source[srcOffset + 1] != EQUALS_SIGN) + return -1; + // verify no extra bits + if ((decode1 & 0x0f) != 0) + return -1; + int outBuff = (decode0 << 18) + | (decode1 << 12); + destination[destOffset] = (byte) (outBuff >> 16); return 1; } // Example: DkL= - else if (source[srcOffset + 3] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) - // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6); - - destination[destOffset] = (byte) (outBuff >>> 16); - destination[destOffset + 1] = (byte) (outBuff >>> 8); + else if (source[srcOffset + 1] == EQUALS_SIGN) { + byte decode2 = DECODABET[source[srcOffset]]; + if (decode2 < 0) + return -1; + // verify no extra bits + if ((decode2 & 0x03) != 0) + return -1; + int outBuff = (decode0 << 18) + | (decode1 << 12) + | (decode2 << 6); + destination[destOffset++] = (byte) (outBuff >> 16); + destination[destOffset] = (byte) (outBuff >> 8); return 2; } // Example: DkLE else { - try { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) - // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) - // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) - | ((DECODABET[source[srcOffset + 3]] & 0xFF)); - - destination[destOffset] = (byte) (outBuff >> 16); - destination[destOffset + 1] = (byte) (outBuff >> 8); - destination[destOffset + 2] = (byte) (outBuff); - - return 3; - } catch (Exception e) { - System.out.println("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]])); - System.out.println("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]])); - System.out.println("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]])); - System.out.println("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]])); + byte decode2 = DECODABET[source[srcOffset++]]; + byte decode3 = DECODABET[source[srcOffset]]; + if (decode2 < 0 || decode3 < 0) return -1; - } //e nd catch + int outBuff = (decode0 << 18) + | (decode1 << 12) + | (decode2 << 6) + | decode3; + destination[destOffset++] = (byte) (outBuff >> 16); + destination[destOffset++] = (byte) (outBuff >> 8); + destination[destOffset] = (byte) (outBuff); + return 3; } } // end decodeToBytes /** * Decodes data from Base64 notation. + * As of 0.9.14, this uses the I2P alphabet, so it is not "standard". * * @param s the string to decode * @return the decoded data, null on error * @since 1.4 */ private static byte[] standardDecode(String s) { - byte[] bytes = new byte[s.length()]; - for (int i = 0; i < bytes.length; i++) - bytes[i] = (byte)(s.charAt(i) & 0xFF); + // We use getUTF8() instead of getASCII() so we may verify + // there's no UTF-8 in there. + byte[] bytes = DataHelper.getUTF8(s); + if (bytes.length != s.length()) + return null; return decode(bytes, 0, bytes.length); } // end decode @@ -678,21 +711,43 @@ public class Base64 { * returns it as a string. * Equivlaent to calling * new String( decode( s ) ) - * WARNING this uses the locale's encoding, it may not be what you want. + * + * As of 0.9.14, decodes as UTF-8. Prior to that, it used the platform's encoding. + * For best results, decoded data should be 7 bit. + * + * As of 0.9.14, does not require trailing '=' if remaining bits are zero. + * Prior to that, trailing 1, 2, or 3 chars were ignored. + * + * As of 0.9.14, trailing garbage after an '=' will cause an error. + * Prior to that, it was ignored. + * + * As of 0.9.14, whitespace will cause an error. + * Prior to that, it was ignored. * * @param s the strind to decode - * @return The data as a string + * @return The data as a string, or null on error * @since 1.4 - * @throws NPE on error? */ public static String decodeToString(String s) { - return new String(decode(s)); + byte[] b = decode(s); + if (b == null) + return null; + return DataHelper.getUTF8(b); } // end decodeToString /** * Decodes Base64 content in byte array format and returns * the decoded byte array. * + * As of 0.9.14, does not require trailing '=' if remaining bits are zero. + * Prior to that, trailing 1, 2, or 3 chars were ignored. + * + * As of 0.9.14, trailing garbage after an '=' will cause an error. + * Prior to that, it was ignored. + * + * As of 0.9.14, whitespace will cause an error. + * Prior to that, it was ignored. + * * @param source The Base64 encoded data * @param off The offset of where to begin decoding * @param len The length of characters to decode @@ -701,39 +756,47 @@ public class Base64 { */ private static byte[] decode(byte[] source, int off, int len) { int len34 = len * 3 / 4; - byte[] outBuff = new byte[len34]; // Upper limit on size of output + byte[] outBuff = new byte[len34]; // size of output int outBuffPosn = 0; - byte[] b4 = new byte[4]; - int b4Posn = 0; - int i = 0; - byte sbiCrop = 0; - byte sbiDecode = 0; - for (i = 0; i < len; i++) { - sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits - sbiDecode = DECODABET[sbiCrop]; - - if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or better - { - if (sbiDecode >= EQUALS_SIGN_ENC) { - b4[b4Posn++] = sbiCrop; - if (b4Posn > 3) { - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn); - b4Posn = 0; - - // If that was the equals sign, break out of 'for' loop - if (sbiCrop == EQUALS_SIGN) break; - } // end if: quartet built - - } // end if: equals sign or better - - } // end if: white space, equals sign or better - else { - //_log.warn("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)"); + int i = off; + int end = off + len; + int converted = 0; + while (i + 3 < end) { + converted = decode4to3(source, i, outBuff, outBuffPosn); + if (converted < 0) return null; - } // end else: - } // each input character + outBuffPosn += converted; + i += 4; + if (converted < 3) + break; + } + // process any remaining without '=' + int remaining = end - i; + if (remaining > 0) { + if (converted > 0 && converted < 3) + return null; + if (remaining == 1 || remaining > 3) + return null; + byte[] b4 = new byte[4]; + b4[0] = source[i++]; + b4[1] = source[i++]; + if (remaining == 3) + b4[2] = source[i]; + else + b4[2] = EQUALS_SIGN; + b4[3] = EQUALS_SIGN; + converted = decode4to3(b4, 0, outBuff, outBuffPosn); + if (converted < 0) + return null; + outBuffPosn += converted; + } + + // don't copy unless we have to + if (outBuffPosn == outBuff.length) + return outBuff; + // and we shouldn't ever... would have returned null before byte[] out = new byte[outBuffPosn]; System.arraycopy(outBuff, 0, out, 0, outBuffPosn); return out; diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index e84df4a38..efc66a2c6 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -554,7 +554,7 @@ public class DataHelper { /** * Positive decimal without leading zeros. - * @param data may be null (returns "0") + * @param buf may be null (returns "0") * @param len unused * @return (new BigInteger(1, buf)).toString() * @deprecated unused diff --git a/core/java/src/net/i2p/data/DataStructureImpl.java b/core/java/src/net/i2p/data/DataStructureImpl.java index 26e655af7..cc70f56a0 100644 --- a/core/java/src/net/i2p/data/DataStructureImpl.java +++ b/core/java/src/net/i2p/data/DataStructureImpl.java @@ -37,6 +37,7 @@ public abstract class DataStructureImpl implements DataStructure, Serializable { public void fromBase64(String data) throws DataFormatException { if (data == null) throw new DataFormatException("Null data passed in"); byte bytes[] = Base64.decode(data); + if (bytes == null) throw new DataFormatException("Bad Base64 \"" + data + '"'); fromByteArray(bytes); } diff --git a/core/java/src/net/i2p/data/Destination.java b/core/java/src/net/i2p/data/Destination.java index 491e738f8..07bf1ad6c 100644 --- a/core/java/src/net/i2p/data/Destination.java +++ b/core/java/src/net/i2p/data/Destination.java @@ -172,6 +172,19 @@ public class Destination extends KeysAndCert { return _cachedB64; } + /** + * For convenience. + * @return "{52 chars}.b32.i2p" or null if fields not set. + * @since 0.9.14 + */ + public String toBase32() { + try { + return Base32.encode(getHash().getData()) + ".b32.i2p"; + } catch (IllegalStateException ise) { + return null; + } + } + /** * Clear the cache. * @since 0.9.9 diff --git a/core/java/src/net/i2p/data/Hash.java b/core/java/src/net/i2p/data/Hash.java index 627f02c39..23d466d68 100644 --- a/core/java/src/net/i2p/data/Hash.java +++ b/core/java/src/net/i2p/data/Hash.java @@ -30,6 +30,14 @@ public class Hash extends SimpleDataStructure { /** * Pull from cache or return new + * + * WARNING - If the SDS is found in the cache, the passed-in + * byte array will be returned to the SimpleByteCache for reuse. + * Do NOT save a reference to the passed-in data, or use or modify it, + * after this call. + * + * Ignore this warning and you WILL corrupt the cache or other data structures. + * * @throws IllegalArgumentException if data is not the correct number of bytes * @since 0.8.3 */ diff --git a/core/java/src/net/i2p/data/PrivateKeyFile.java b/core/java/src/net/i2p/data/PrivateKeyFile.java index 6d5eb403b..012310b9f 100644 --- a/core/java/src/net/i2p/data/PrivateKeyFile.java +++ b/core/java/src/net/i2p/data/PrivateKeyFile.java @@ -37,7 +37,7 @@ import net.i2p.util.RandomSource; * - Cert. length (2 bytes) * - Certificate if length != 0 * - Private key (256 bytes) - * - Signing Private key (20 bytes) + * - Signing Private key (20 bytes, or length specified by key certificate) * Total 663 bytes * * @@ -45,6 +45,15 @@ import net.i2p.util.RandomSource; */ public class PrivateKeyFile { + + private static final int HASH_EFFORT = VerifiedDestination.MIN_HASHCASH_EFFORT; + + private final File file; + private final I2PClient client; + private Destination dest; + private PrivateKey privKey; + private SigningPrivateKey signingPrivKey; + /** * Create a new PrivateKeyFile, or modify an existing one, with various * types of Certificates. @@ -188,9 +197,6 @@ public class PrivateKeyFile { public PrivateKeyFile(File file, I2PClient client) { this.file = file; this.client = client; - this.dest = null; - this.privKey = null; - this.signingPrivKey = null; } /** @since 0.8.9 */ @@ -198,8 +204,13 @@ public class PrivateKeyFile { this(file, session.getMyDestination(), session.getDecryptionKey(), session.getPrivateKey()); } - /** @since 0.8.9 */ + /** + * @throws IllegalArgumentException on mismatch of spubkey and spk types + * @since 0.8.9 + */ public PrivateKeyFile(File file, Destination dest, PrivateKey pk, SigningPrivateKey spk) { + if (dest.getSigningPublicKey().getType() != spk.getType()) + throw new IllegalArgumentException("Signing key type mismatch"); this.file = file; this.client = null; this.dest = dest; @@ -207,9 +218,14 @@ public class PrivateKeyFile { this.signingPrivKey = spk; } - /** @since 0.8.9 */ + /** + * @throws IllegalArgumentException on mismatch of spubkey and spk types + * @since 0.8.9 + */ public PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert, PrivateKey pk, SigningPrivateKey spk) { + if (spubkey.getType() != spk.getType()) + throw new IllegalArgumentException("Signing key type mismatch"); this.file = file; this.client = null; this.dest = new Destination(); @@ -382,6 +398,7 @@ public class PrivateKeyFile { public PrivateKey getPrivKey() { return this.privKey; } + public SigningPrivateKey getSigningPrivKey() { return this.signingPrivKey; } @@ -427,7 +444,7 @@ public class PrivateKeyFile { s.append("Dest: "); s.append(this.dest != null ? this.dest.toBase64() : "null"); s.append("\nB32: "); - s.append(this.dest != null ? Base32.encode(this.dest.calculateHash().getData()) + ".b32.i2p" : "null"); + s.append(this.dest != null ? this.dest.toBase32() : "null"); s.append("\nContains: "); s.append(this.dest); s.append("\nPrivate Key: "); @@ -544,13 +561,4 @@ public class PrivateKeyFile { public static boolean checkSignature(Signature s, byte[] data, SigningPublicKey spk) { return DSAEngine.getInstance().verifySignature(s, data, spk); } - - - private static final int HASH_EFFORT = VerifiedDestination.MIN_HASHCASH_EFFORT; - - private final File file; - private final I2PClient client; - private Destination dest; - private PrivateKey privKey; - private SigningPrivateKey signingPrivKey; } diff --git a/core/java/src/net/i2p/util/EepGet.java b/core/java/src/net/i2p/util/EepGet.java index 2f59baeac..87af550ef 100644 --- a/core/java/src/net/i2p/util/EepGet.java +++ b/core/java/src/net/i2p/util/EepGet.java @@ -117,27 +117,34 @@ public class EepGet { this(ctx, false, null, -1, numRetries, outputFile, url, allowCaching, null); } - public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) { + public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, + int numRetries, String outputFile, String url) { this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, outputFile, url, true, null); } - public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, String postData) { + public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, + int numRetries, String outputFile, String url, String postData) { this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, true, null, postData); } - public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag) { + public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, + int numRetries, String outputFile, String url, boolean allowCaching, String etag) { this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, allowCaching, etag, null); } - public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag, String lastModified) { + public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, + int numRetries, String outputFile, String url, boolean allowCaching, String etag, String lastModified) { this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, allowCaching, etag, lastModified, null); } - public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) { + public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, + int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, + String url, boolean allowCaching, String etag, String postData) { this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, minSize, maxSize, outputFile, outputStream, url, allowCaching, etag, null, postData); } - public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, + public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, + int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String lastModified, String postData) { _context = ctx; @@ -1254,12 +1261,27 @@ public class EepGet { buf.append("Cache-control: no-cache\r\n" + "Pragma: no-cache\r\n"); } - if ((_etag != null) && (_alreadyTransferred <= 0)) { + boolean uaOverridden = false; + boolean etagOverridden = false; + boolean lastmodOverridden = false; + if (_extraHeaders != null) { + for (String hdr : _extraHeaders) { + String hlc = hdr.toLowerCase(Locale.US); + if (hlc.startsWith("user-agent: ")) + uaOverridden = true; + else if (hlc.startsWith("if-none-match: ")) + etagOverridden = true; + else if (hlc.startsWith("if-modified-since: ")) + lastmodOverridden = true; + buf.append(hdr).append("\r\n"); + } + } + if ((_etag != null) && (_alreadyTransferred <= 0) && !etagOverridden) { buf.append("If-None-Match: "); buf.append(_etag); buf.append("\r\n"); } - if ((_lastModified != null) && (_alreadyTransferred <= 0)) { + if ((_lastModified != null) && (_alreadyTransferred <= 0) && !lastmodOverridden) { buf.append("If-Modified-Since: "); buf.append(_lastModified); buf.append("\r\n"); @@ -1274,14 +1296,6 @@ public class EepGet { (!path.endsWith(".gz")) && (!path.endsWith(".tgz"))) buf.append("gzip"); buf.append("\r\n"); - boolean uaOverridden = false; - if (_extraHeaders != null) { - for (String hdr : _extraHeaders) { - if (hdr.toLowerCase(Locale.US).startsWith("user-agent: ")) - uaOverridden = true; - buf.append(hdr).append("\r\n"); - } - } if(!uaOverridden) buf.append("User-Agent: " + USER_AGENT + "\r\n"); if (_authState != null && _shouldProxy && _authState.authMode != AUTH_MODE.NONE) { @@ -1366,6 +1380,8 @@ public class EepGet { * Must be called before fetch(). * Not supported by EepHead. * As of 0.9.10, If name is User-Agent, this will replace the default User-Agent header. + * As of 0.9.14, If name is If-None-Match or If-Modified-Since, + * this will replace the etag or last-modified value given in the constructor. * Note that headers may be subsequently modified or removed in the I2PTunnel HTTP Client proxy. * * @since 0.8.8 diff --git a/core/java/src/net/metanotion/io/block/BlockFile.java b/core/java/src/net/metanotion/io/block/BlockFile.java index a73c92252..d9613653f 100644 --- a/core/java/src/net/metanotion/io/block/BlockFile.java +++ b/core/java/src/net/metanotion/io/block/BlockFile.java @@ -425,7 +425,7 @@ public class BlockFile { */ public BSkipList getIndex(String name, Serializer key, Serializer val) throws IOException { // added I2P - BSkipList bsl = (BSkipList) openIndices.get(name); + BSkipList bsl = openIndices.get(name); if (bsl != null) return bsl; @@ -465,7 +465,7 @@ public class BlockFile { * Added I2P */ public void closeIndex(String name) { - BSkipList bsl = (BSkipList) openIndices.remove(name); + BSkipList bsl = openIndices.remove(name); if (bsl != null) bsl.flush(); } diff --git a/history.txt b/history.txt index 1864712ce..5fcdc5897 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,42 @@ +2014-07-03 zzz + * Base64: + - Catch numerous decoding errors that were previously misdecoded (ticket #1318) + - Improve decoding efficiency, reduce copies + - encode(String) now uses UTF-8 encoding + - decode() now accepts short strings without trailing '=' + - whitespace in decode will now cause an error, was previously ignored + * Console: Add event log viewer (ticket #1117) + +2014-07-02 kytv + * Update Java Service Wrapper to v3.5.25 + - Windows: x86 and x64 versions self-compiled with VS2010 in + Windows 7. The icon has been changed from Tanuki's default to Itoopie. + - Linux ARMv6: Compiled on a RaspberryPi using gcc 4.6.3-14+rpi1, + Oracle Java 1.7.0+update40 and stripped + - All other binaries are from the "community edition" deltapack offered by + Tanuki. + +2014-06-29 zzz + * NetDB: Fix handling reseed URLs with ports (ticket #1278) + +2014-06-28 zzz + * NetDB: Add support for reseeding with su3 files (ticket #934) + * SAM: + - Support SIGNATURE_TYPE, bump to 3.1 (ticket #1318) + - Private key checking fixes (ticket #1318) + - Parameter parsing fixes (ticket #1325) + - Cleanups + +2014-06-24 zzz + * Streaming; Drop the preliminary channel implementations, + as they don't work and can't ever work as designed. + +2014-06-23 zzz + * Streaming: + - Bundle new socket messages for translation + - Fix connection error message + * Tunnels: Reject participating tunnels when hidden (ticket #1314) + 2014-06-21 zzz * i2psnark: - Display webapp name in html title (ticket #1311) diff --git a/installer/java/build.xml b/installer/java/build.xml index be911236a..89a4ff6cc 100644 --- a/installer/java/build.xml +++ b/installer/java/build.xml @@ -15,13 +15,16 @@ destdir="./build/obj" > + + + - diff --git a/installer/lib/wrapper/all/wrapper.jar b/installer/lib/wrapper/all/wrapper.jar index 9b163866e..a47bc1747 100644 Binary files a/installer/lib/wrapper/all/wrapper.jar and b/installer/lib/wrapper/all/wrapper.jar differ diff --git a/installer/lib/wrapper/freebsd/i2psvc b/installer/lib/wrapper/freebsd/i2psvc index b5f664add..d01778a53 100644 Binary files a/installer/lib/wrapper/freebsd/i2psvc and b/installer/lib/wrapper/freebsd/i2psvc differ diff --git a/installer/lib/wrapper/freebsd/libwrapper.so b/installer/lib/wrapper/freebsd/libwrapper.so index bcbed8524..0e2513fa7 100644 Binary files a/installer/lib/wrapper/freebsd/libwrapper.so and b/installer/lib/wrapper/freebsd/libwrapper.so differ diff --git a/installer/lib/wrapper/freebsd64/i2psvc b/installer/lib/wrapper/freebsd64/i2psvc index 0d9b7ec94..d5b8f0327 100644 Binary files a/installer/lib/wrapper/freebsd64/i2psvc and b/installer/lib/wrapper/freebsd64/i2psvc differ diff --git a/installer/lib/wrapper/freebsd64/libwrapper.so b/installer/lib/wrapper/freebsd64/libwrapper.so index 800ad5617..635219850 100644 Binary files a/installer/lib/wrapper/freebsd64/libwrapper.so and b/installer/lib/wrapper/freebsd64/libwrapper.so differ diff --git a/installer/lib/wrapper/linux-armv5/i2psvc b/installer/lib/wrapper/linux-armv5/i2psvc index f3b4511c4..952d8506d 100644 Binary files a/installer/lib/wrapper/linux-armv5/i2psvc and b/installer/lib/wrapper/linux-armv5/i2psvc differ diff --git a/installer/lib/wrapper/linux-armv5/libwrapper.so b/installer/lib/wrapper/linux-armv5/libwrapper.so index 144599f33..3161cbc08 100644 Binary files a/installer/lib/wrapper/linux-armv5/libwrapper.so and b/installer/lib/wrapper/linux-armv5/libwrapper.so differ diff --git a/installer/lib/wrapper/linux-armv6/i2psvc b/installer/lib/wrapper/linux-armv6/i2psvc index 7b88c0575..f0036b2d6 100644 Binary files a/installer/lib/wrapper/linux-armv6/i2psvc and b/installer/lib/wrapper/linux-armv6/i2psvc differ diff --git a/installer/lib/wrapper/linux-armv6/libwrapper.so b/installer/lib/wrapper/linux-armv6/libwrapper.so index bb32f4b45..c052c54e2 100644 Binary files a/installer/lib/wrapper/linux-armv6/libwrapper.so and b/installer/lib/wrapper/linux-armv6/libwrapper.so differ diff --git a/installer/lib/wrapper/linux-ppc/i2psvc b/installer/lib/wrapper/linux-ppc/i2psvc index 3992d29e5..23b17b8a3 100644 Binary files a/installer/lib/wrapper/linux-ppc/i2psvc and b/installer/lib/wrapper/linux-ppc/i2psvc differ diff --git a/installer/lib/wrapper/linux-ppc/libwrapper.so b/installer/lib/wrapper/linux-ppc/libwrapper.so index 8378d8eb7..e9d2602a0 100644 Binary files a/installer/lib/wrapper/linux-ppc/libwrapper.so and b/installer/lib/wrapper/linux-ppc/libwrapper.so differ diff --git a/installer/lib/wrapper/linux/i2psvc b/installer/lib/wrapper/linux/i2psvc index aa272f52d..5fa8e2afd 100644 Binary files a/installer/lib/wrapper/linux/i2psvc and b/installer/lib/wrapper/linux/i2psvc differ diff --git a/installer/lib/wrapper/linux/libwrapper.so b/installer/lib/wrapper/linux/libwrapper.so index 3efcf4501..05b12e780 100644 Binary files a/installer/lib/wrapper/linux/libwrapper.so and b/installer/lib/wrapper/linux/libwrapper.so differ diff --git a/installer/lib/wrapper/linux64/i2psvc b/installer/lib/wrapper/linux64/i2psvc index fa2255e86..3d9c1940b 100644 Binary files a/installer/lib/wrapper/linux64/i2psvc and b/installer/lib/wrapper/linux64/i2psvc differ diff --git a/installer/lib/wrapper/linux64/libwrapper.so b/installer/lib/wrapper/linux64/libwrapper.so index 57a1550fe..65e6878a6 100644 Binary files a/installer/lib/wrapper/linux64/libwrapper.so and b/installer/lib/wrapper/linux64/libwrapper.so differ diff --git a/installer/lib/wrapper/macosx/i2psvc-macosx-universal-32 b/installer/lib/wrapper/macosx/i2psvc-macosx-universal-32 index f64f442f3..57fdb5663 100644 Binary files a/installer/lib/wrapper/macosx/i2psvc-macosx-universal-32 and b/installer/lib/wrapper/macosx/i2psvc-macosx-universal-32 differ diff --git a/installer/lib/wrapper/macosx/i2psvc-macosx-universal-64 b/installer/lib/wrapper/macosx/i2psvc-macosx-universal-64 index f556a9886..1c2fff181 100644 Binary files a/installer/lib/wrapper/macosx/i2psvc-macosx-universal-64 and b/installer/lib/wrapper/macosx/i2psvc-macosx-universal-64 differ diff --git a/installer/lib/wrapper/macosx/libwrapper-macosx-universal-32.jnilib b/installer/lib/wrapper/macosx/libwrapper-macosx-universal-32.jnilib index f2d50cb7d..52da8f372 100644 Binary files a/installer/lib/wrapper/macosx/libwrapper-macosx-universal-32.jnilib and b/installer/lib/wrapper/macosx/libwrapper-macosx-universal-32.jnilib differ diff --git a/installer/lib/wrapper/macosx/libwrapper-macosx-universal-64.jnilib b/installer/lib/wrapper/macosx/libwrapper-macosx-universal-64.jnilib index a1350becf..27c96d72f 100644 Binary files a/installer/lib/wrapper/macosx/libwrapper-macosx-universal-64.jnilib and b/installer/lib/wrapper/macosx/libwrapper-macosx-universal-64.jnilib differ diff --git a/installer/lib/wrapper/solaris/i2psvc b/installer/lib/wrapper/solaris/i2psvc index 8ebc87695..369a07db8 100644 Binary files a/installer/lib/wrapper/solaris/i2psvc and b/installer/lib/wrapper/solaris/i2psvc differ diff --git a/installer/lib/wrapper/solaris/libwrapper.so b/installer/lib/wrapper/solaris/libwrapper.so index 19a95591c..f3f7e6e4f 100644 Binary files a/installer/lib/wrapper/solaris/libwrapper.so and b/installer/lib/wrapper/solaris/libwrapper.so differ diff --git a/installer/lib/wrapper/win32/I2Psvc.exe b/installer/lib/wrapper/win32/I2Psvc.exe index 2eda7d78b..79f7eb2cb 100644 Binary files a/installer/lib/wrapper/win32/I2Psvc.exe and b/installer/lib/wrapper/win32/I2Psvc.exe differ diff --git a/installer/lib/wrapper/win32/wrapper.dll b/installer/lib/wrapper/win32/wrapper.dll index 95b61f4e1..80bf9bf49 100644 Binary files a/installer/lib/wrapper/win32/wrapper.dll and b/installer/lib/wrapper/win32/wrapper.dll differ diff --git a/installer/lib/wrapper/win64/I2Psvc.exe b/installer/lib/wrapper/win64/I2Psvc.exe index b442e10a5..a208d13c8 100644 Binary files a/installer/lib/wrapper/win64/I2Psvc.exe and b/installer/lib/wrapper/win64/I2Psvc.exe differ diff --git a/installer/lib/wrapper/win64/Makefile-windows-x86-64.nmake b/installer/lib/wrapper/win64/Makefile-windows-x86-64.nmake index 0e3f87ad9..67670fada 100644 --- a/installer/lib/wrapper/win64/Makefile-windows-x86-64.nmake +++ b/installer/lib/wrapper/win64/Makefile-windows-x86-64.nmake @@ -16,7 +16,7 @@ RC = rc # EXE Definitions EXE_OUTDIR = $(PROJ)32_VC8__Win64_Release -EXE_OBJS = $(EXE_OUTDIR)\wrapper.obj $(EXE_OUTDIR)\wrapperinfo.obj $(EXE_OUTDIR)\wrappereventloop.obj $(EXE_OUTDIR)\wrapper_win.obj $(EXE_OUTDIR)\property.obj $(EXE_OUTDIR)\logger.obj $(EXE_OUTDIR)\wrapper_file.obj $(EXE_OUTDIR)\wrapper_i18n.obj $(EXE_OUTDIR)\test.obj $(EXE_OUTDIR)\wrapper_hashmap.obj +EXE_OBJS = $(EXE_OUTDIR)\wrapper.obj $(EXE_OUTDIR)\wrapperinfo.obj $(EXE_OUTDIR)\wrappereventloop.obj $(EXE_OUTDIR)\wrapper_win.obj $(EXE_OUTDIR)\property.obj $(EXE_OUTDIR)\logger.obj $(EXE_OUTDIR)\wrapper_file.obj $(EXE_OUTDIR)\wrapper_i18n.obj $(EXE_OUTDIR)\wrapper_hashmap.obj EXE_LIBS = mpr.lib shell32.lib netapi32.lib wsock32.lib shlwapi.lib advapi32.lib user32.lib Crypt32.lib Wintrust.lib pdh.lib EXE_COMPILE_OPTS = /O2 /GL /D "_CONSOLE" EXE_LINK_OPTS = /INCREMENTAL:NO /SUBSYSTEM:CONSOLE /MANIFESTFILE:"$(EXE_OUTDIR)\$(PROJ).exe.intermediate.manifest" /PDB:"$(EXE_OUTDIR)\$(PROJ).pdb" /OPT:REF /OPT:ICF /LTCG diff --git a/installer/lib/wrapper/win64/README-x64-win.txt b/installer/lib/wrapper/win64/README-x64-win.txt index 614b72ff8..6afc2d096 100644 --- a/installer/lib/wrapper/win64/README-x64-win.txt +++ b/installer/lib/wrapper/win64/README-x64-win.txt @@ -1,4 +1,4 @@ -Changes may be needed for newer versions than 3.5.23. +Changes may be needed for newer versions than 3.5.25. Copy Makefile-windows-x86-64.nmake to src\c. diff --git a/installer/lib/wrapper/win64/wrapper.dll b/installer/lib/wrapper/win64/wrapper.dll index 14f717dbf..afa5a8d5d 100644 Binary files a/installer/lib/wrapper/win64/wrapper.dll and b/installer/lib/wrapper/win64/wrapper.dll differ diff --git a/installer/resources/certificates/reseed/backup_at_mail.i2p.crt b/installer/resources/certificates/reseed/backup_at_mail.i2p.crt new file mode 100644 index 000000000..73b08eaa8 --- /dev/null +++ b/installer/resources/certificates/reseed/backup_at_mail.i2p.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfTCCA2WgAwIBAgIEOprmhjANBgkqhkiG9w0BAQ0FADBvMQswCQYDVQQGEwJY +WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt +b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEYMBYGA1UEAwwPYmFja3VwQG1haWwu +aTJwMB4XDTEzMTAxMzEzNDQ1NVoXDTIzMTAxMzEzNDQ1NVowbzELMAkGA1UEBhMC +WFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255 +bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGDAWBgNVBAMMD2JhY2t1cEBtYWls +LmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIoAkobXwk/Enf1d +roHyqCyvcJfZJVTwb/LgYWAvCBMCr+RGqlSgtk3g69Y3I0xU08fD2kGt3r5Pwsbr +omXIbJAcccyLqmQ5QX6QgL+X9VpMDp9C4h2RogCrqLBAWw4cuZ4RS9VCpP1Yis7H +uejYqENP86p7BsRnuW/4cYnfunAdMpss4LpRGQXt1nTX+kfgCYgnKFbFqwAHt7yV +Ds+Pe6FuBHPlp+sc1amKRcUnSvhXLsv43VicnT7xYL/kUsN83wrtHA3B4aGDx3aA +3/EzuRmIXQB0BlTZILMEyYwG/nc4OsW82QYrvEZ9BIg9A4lF/wS/KZCICPxLF2zo +dGjnmlgkiA4s8eO+va/ElHyELjckVXqmG1eXHhSkEsDvOQJy01IUuwLinvq7cUbJ +HfJBZJllEg+sLDCv3FkEqN+XjBNFfQN4oNew4w6IPY6YH1INVB9LL0Cmdu4DudLv +TY8OcI8eSfez3hmm+pYQ23PJRYYnvRDnRECyIWBegkckWRh8U/WvZUYUvETK6EDl +/0KpTtfzX6MqHA5D6bTAB8Y3ijGMLrZ/B5vj5yCoZbLiGme9X2moR2k1LEhdhtzV +exsqezCpg6dn48FTX7mHjvR5/r4kz2jqBGmdPUWIIxnjFUzDUK3llVQiHihleHpe +jL4LqnhBGKWFRTaVwaIkBG4zAfIzAgMBAAGjITAfMB0GA1UdDgQWBBQNkfW7bSMl +1/4KDbgwrkf9x1Zu/TANBgkqhkiG9w0BAQ0FAAOCAgEAGg3a3rTf0EznQocmio0T +5gCoL0n8h6yKW/PyPAIELrd9wiYjhJFcWvMTcJJJnVqmAL5vpvhaAFVtAfx70MGa +0DZ7FvytK5hEfF4IqOFDyEEVGJR5rIpVK4MeI1nmwEsxdbW+FhODjtRzgYO8XBME +Xj4aY1FWg9vxc3reUj6PSFsZtsB0aLiRgL9JDovJIiRw0Uqr1v2wXBte5yVCxDge +vTREZtpK4cKetoOa68pwSXI32JwKE18j6bfdKVBCcYQKlKP/3gHGduaDrQv3w32S +DRym5s6MREeTUOtAw4wq46KpdOX8yyAqJPrCfMwS6ORd3t+egqOw0PUnsqb97w4O +lUtrRYvb2cOj60SmRx4vJvItyuHbKqIK7o2e1RcUZPXYoAVx2ww4XB2Wk4D7LSAs +cS7nLj8yAqzJ2qqtBzxu+zILJtkVa12dKF0xmS0BxBp4sCYiBtmAVE8AWQqEuSHA +FrMWqoXcjcfdvvyX487FFWWUE7ZBIn0hee2sK9J9+SPtqczJaN7TF3K3nzo65WJG +1epltmq2Ugjb67Gz7v4y7H23DJ/qhm8yLtCHTj69HTta5I08j6Kut924WLZaiMO/ +4YoEL5AE63X0sxYibKFQiq7FW5nUJA280GRlY3xSMFzlB2ggazrUV3YAWVDhfdnI +flpzWXkFM2D36OUaubfe9YY= +-----END CERTIFICATE----- diff --git a/installer/resources/certificates/reseed/echelon_at_mail.i2p.crt b/installer/resources/certificates/reseed/echelon_at_mail.i2p.crt new file mode 100644 index 000000000..52ac1c380 --- /dev/null +++ b/installer/resources/certificates/reseed/echelon_at_mail.i2p.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIEcpgq/jANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY +WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt +b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQZWNoZWxvbkBtYWls +LmkycDAeFw0xNDA2MjcxNTQwMTJaFw0yNDA2MjYxNTQwMTJaMHAxCzAJBgNVBAYT +AlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9u +eW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQDDBBlY2hlbG9uQG1h +aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgcD+2Ma/q1zo +Ae9Iurlxj6YwyUTtd6P1ctAOvw9bpgSLW0wMRnRhaCj3d0BWUOY5/42KDvX2JXiO +kz/VuYy29bMHK1pdJZuY1FGFrKudFYJ6qOr+xkiEk5YT8D/RLxWQ1oibFL18nJwd +pSlOT6XhP0uZAdrZy/CaRmIKKZwAcsdUXt+hNVVoyCJHM2x4d5eqahEgjI/39IY/ +5a3kBZDiZI55jDJKsUr4jyq392W6TY03mTeacJzIyMIW6/ut0JkphrZaRY5dtB3i +1RMUWhjuCyg+zHrETSlwIgGhuzxVJLXlSpmCk3UiCsu79lUulZ2ReuifdACJ/e3A +oet2fyjOp+siPaGzdTJ4MjAoMl0uzd1+D4tiq8ajneoEPYxhaeYjeRwPEUcihHjP +cgOKZiV/zUQPoYD3YQ4rwM07sfKLoHO+jxN21t3qXFHce6NwMuiid6mGzl5gVHvq +mt8nI3gJCIfbhUPWyUvdMtMbSHvWnKSwtLthOGLuXrwYMiV/6x5l68+y8waagjkH +fI1H/tKmUT7wcHCldxsQaXbmoEGbboEsjpcm+7+wbk5sTxkqrGxWFrMtlvnBH0fj +dQX/UeG1IPpDi2QqWmPdrIOdKng1a+CMMyDJZX0LcEBmVZzNhRKvZmqAe1vhf+LF +s8adUCnpPm1p3quLrIvoKb2YS4VIl50CAwEAAaMhMB8wHQYDVR0OBBYEFFeW8HLy +KaFZ71umI2XnnddzJO8rMA0GCSqGSIb3DQEBDQUAA4ICAQAKXytX51clQl1jYwGE +in+nUo/XdTIKXlT322SHS36Keg2SlFTnlREIFkuI5J1TM+lILxwgCm+JrN/lknd4 +ZMzJ4RGOMqBhqQG1x/Dgde52pamQqFMeLkh3GiwWYcHfekUt66PqxtQizuG4UNFc +Le98hpLNQoF2p/zW/5f4CtSs/HsO1lGlO9LB0zQtjbegmIZnwj4WOL+qpRbsDeZi +jf1gW0qyLeiQNyXW/e+sujNYe4PIioGombeKrzPoABKD0x2gsI5SVr7e8X3HgtkK +kDUXsQqevRFrifHvF1TjVC1J3YqnuTwYKXqA2d72icLp1U2OY2RFYgJPLZgbj2MK +32EZ1YW4rEf5gfPosN5NBIIsmsxfkji8vC7pe8UeJzxTjM/EuVTTiGjPZbpz/PHY +YliGKKFOe1tStq2zo7FxGRAlH9OGuKtBSw/WyN+NyTTsndOO6RXz4jIf0PBvtyjS +FoyV3W6x7R5WjjlyQOVLEgAfJkEjoACuI6rz48/FKjnyxSRlRo7+9/LfgwiU8ye3 +IuEmA0W2lSSY8lSeJA7p9utKT6zuQwCkgL69u0QSK4GD0G6dteVTlpd99c5xwgVu +cEGSP30XpQMrSknKwv2KHv7nBqRJSPO7JYMl4TjbKr8BM1q5AK8pfYPFgMjFTCwT +/hCfobYS9FLpJCFkIMcnYrhM8g== +-----END CERTIFICATE----- diff --git a/installer/resources/certificates/reseed/meeh_at_mail.i2p.crt b/installer/resources/certificates/reseed/meeh_at_mail.i2p.crt new file mode 100644 index 000000000..6014c96f7 --- /dev/null +++ b/installer/resources/certificates/reseed/meeh_at_mail.i2p.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFeTCCA2GgAwIBAgIEZZozujANBgkqhkiG9w0BAQ0FADBtMQswCQYDVQQGEwJY +WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt +b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwNbWVlaEBtYWlsLmky +cDAeFw0xNDA2MjgyMjQ5MDlaFw0yNDA2MjcyMjQ5MDlaMG0xCzAJBgNVBAYTAlhY +MQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1v +dXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1tZWVoQG1haWwuaTJw +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnVnmPE4uUvCky0yCnnVH +cJEDqzwDPupx0zr0YDlhZk5VOPPecx5haayJ/V6nXPc1aVVWn+CHfedcF2aBgN4K +5aBueS/l6l5WHcv02DofAqlTmyAws3oQeR1qoTuW24cKRtLR7h5bxv63f6bgp6e+ +RihFNez6UxErnRPuJOJEO2Im6EgVp6fz7tQ7R35zxAUeES2YILPySvzy2vYm/EEG +jXX7Ap2A5svVo90xCMOeUZ/55vLsjyIshN+tV87U4xwvAkUmwsmWVHm3BQpHkI6z +zMJie6epB8Bqm0GYm0EcElJH4OCxGTvDLoghpswbuUO7iy3JSfoL7ZCnoiQdK9K4 +yVVChj8lG+r7KaTowK96iZep+sZefjOt5VFGuW2Fi/WBv3ldiLlJAo/ZfrUM4+vG +fyNBXbl6bX87uTCGOT1p3dazo+zJMsAZ+Y93DlM/mDEWFa1kKNrs74syzaWEqF4L +KQE6VoYn80OOzafSigTVQgSwUtQtB0XGhMzJhyxU2XHWe1LFIy7Pta0B+lDiZj7c +I8nXxYjsDfEu/Elj/Ra9N6bH0awmgB5JDa+Tbir+oEM5SyDfpSaCGuatdGxjweGI +kVmFU0SqCZV/8TXbIu6MUVzTZMZVT94edifFSRad4fqw7eZbSXlPu++3d1/btn6h +ibM04nkv0mm+FxCKB/wdAkECAwEAAaMhMB8wHQYDVR0OBBYEFO7jIkSRkoXyJcho +9/Q0gDOINa5EMA0GCSqGSIb3DQEBDQUAA4ICAQBzfWO7+8HWOKLaYWToJ6XZbpNF +3wXv1yC4W/HRR80m4JSsq9r0d7838Nvd7vLVP6MY6MaVb/JnV76FdQ5WQ6ticD0Y +o3zmpqqbKVSspN0lrkig4surT88AjfVQz/vEIzKNQEbpzc3hC2LCiE2u+cK/ix4j +b9RohnaPvwLnew5RNQRpcmk+XejaNITISr2yQIwXL7TEYy8HdGCfzFSSFhKe9vkb +GsWS5ASrUzRoprswmlgRe8gEHI+d51Z7mWgna0/5mBz9bH/3QXtpxlLWm3bVV+kt +pZjQDTHE0GqG2YsD1Gmp4LU/JFhCojMTtiPCXmr9KFtpiVlx06DuKm5PC8Ak+5w+ +m/DQYYfv9z+AA5Y430bjnzwg67bhqVyyek4wcDQinFswv3h4bIB7CJujDcEqXXza +lhG1ufPPCUTMrVjh7AShohZraqlSlyQPY9vEppLwD4W1d+MqDHM7ljOH7gQYaUPi +wE30AdXEOxLZcT3aRKxkKf2esNofSuUC/+NXQvPjpuI4UJKO3eegi+M9dbnKoNWs +MPPLPpycecWPheFYM5K6Ao63cjlUY2wYwCfDTFgjA5q8i/Rp7i6Z6fLE3YWJ4VdR +WOFB7hlluQ//jMW6M1qz6IYXmlUjcXl81VEvlOH/QBNrPvX3I3SYXYgVRnVGUudB +o3eNsanvTU+TIFBh2Q== +-----END CERTIFICATE----- diff --git a/installer/resources/certificates/ssl/jp.reseed.i2p2.no.crt b/installer/resources/certificates/ssl/jp.reseed.i2p2.no.crt new file mode 100644 index 000000000..1cb5abec5 --- /dev/null +++ b/installer/resources/certificates/ssl/jp.reseed.i2p2.no.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIJAPsJOCng4aEOMA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMQ4wDAYDVQQHDAVKYXBhbjEMMAoGA1UECgwD +STJQMRMwEQYDVQQLDApJMlAgUmVzZWVkMRowGAYDVQQDDBFqcC5yZXNlZWQuaTJw +Mi5ubzAeFw0xNDA2MjgyMDQ3MThaFw0yNDA2MjUyMDQ3MThaMGsxCzAJBgNVBAYT +Ak5PMQ0wCwYDVQQIDARPc2xvMQ4wDAYDVQQHDAVKYXBhbjEMMAoGA1UECgwDSTJQ +MRMwEQYDVQQLDApJMlAgUmVzZWVkMRowGAYDVQQDDBFqcC5yZXNlZWQuaTJwMi5u +bzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALlZBIbb4MHqLPpUy298 +PG5z7RFo4bO7CxW2LO8DgE93KNbdkZuYpt6KcAW/gkDfKCiXTxDjyqmzZeBeIbcS +ea96jFc/pTknkiiSm9NX4ATcyRwvKXn6DR/iOiofP3G/sEkxgIdv3BgEYsF5jPQY +KefG0Jvl612cIX+1jC3lRRePYPUZnWxIuokXglLApeyhNzTK/KHIsLzR+56ScltM +pwGlroTky5ekPx4ZnJCxI+qFXWcgqdoNixPUkOtceYm7u5gd1D+mQDuCB5zfB+Pw +Iy9BTARot9M3fMrcRRVfEIGWwN1+bRnZvr0A/sqYMUqGPiUVOMi/mzyqZVQ14CGy +0idRhUKdOb/HNSmcep0Jwp0cP+VD/nCNU4JLptTLdErpTJrmDn+zkuQPPSMTzTWg +Fh3ktRsJ5zKfrnrBGxeKbciZgRkVHyWpv3+0AgbD8C3HvDj4qpkIO6D2gf+TREyM +frDXN6luqkThQcUFv+huMaL3Iul2doYqw5YPAdel6/cCD12n/FoEj5UJ47O/77DA +ITYfKCFRKDh/Ew7Ih3bH66uNaUUp+a0Sd6fNXLmWWr7gcn5B5CvrXhjPPror+Xyz +EZVByPTTfU1BkMQuxv20GG65M9g9wtXrD79N8di2wOfr4EG5i6L9ZvNTThwgWGGd +9f745WCnPL/ulLT9Glnlfk01AgMBAAGjUDBOMB0GA1UdDgQWBBR5Ed38JID7+JwB +hpOLi1Xt1ORyoTAfBgNVHSMEGDAWgBR5Ed38JID7+JwBhpOLi1Xt1ORyoTAMBgNV +HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQBRT/ourx4xT0n/qHF1vy8Ii02v +Hg5lHmzmiVn/3/S4q+t4HrOF6MSjjvVzVNk6JIIYb3+hwGUO31OLNZX60JfSMW+C +ffPiaNDLm/xE4yt4B/QZZDs0kv0RMjGau6k2XJPGvxVNl6LhM6LLvzMEtOGzBr0J +Ai4ZU+WqHk3nnXYHbg7C7Iuu8CT8tBpkaeW/VEN82dcLEulHFxA5Ia6HlwqrgvIW +w77oaOhOh5LKkdS8uHx4OUP8Mv25H2cMBblUdubbeqREyOGRGTkVXfRekD8K95ol +PfT9PhnhUXKRaSwy0nRqvRMiwk/CyIJTbMMflDET1P785diSvtJP0fOhkev9Uprz +FvLsPUTvANUz+vd2KJiLuGbR/d/LaJm18vdWx13vKVO60TBnyFQDS4RZbeuNp73v +x5fPTmiiPZYZj13m2xyes7SXJqhVbms0F39soThpuYrjCaHXyFgqah27+9Ivmbhu +EefPgLmkOx3v0kSfXdJYdji/mrKxERmqT1L34U6M32tCoSbjO7lakAV2opisbHEw +EehCuI83cGp/m3z8yjMoWV8Z4VoB+qMzxzgrXc5C2lxYAT4JggAV2SGcY9MszETI +/S7y5UypV4rutyJvHFrlJZKtp2B7Xi8N8n2NG1WGppYh9UShbFhDaVIMQpjZokAg +MHk7ixe0rSbnHcNF8g== +-----END CERTIFICATE----- diff --git a/installer/resources/certificates/ssl/reseed.pkol.de.crt b/installer/resources/certificates/ssl/reseed.pkol.de.crt deleted file mode 100644 index c560b64f6..000000000 --- a/installer/resources/certificates/ssl/reseed.pkol.de.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC/jCCAmegAwIBAgIJALLizEjOqx6kMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV -BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMTDnJlc2VlZC5wa29sLmRlMB4XDTEzMDcy -MjE3MjAwN1oXDTI0MDcwNDE3MjAwN1owXjELMAkGA1UEBhMCQVUxEzARBgNVBAgT -ClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEX -MBUGA1UEAxMOcmVzZWVkLnBrb2wuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ -AoGBAKcGetxR5BVrCjUe/sCvMfGiMoyhATjPGVdN+j5qxFdSOhbsC6KAhqL5GNyu -so8VKpHkIKaD5NeCAonUDLNXB+YOtR+YAHQRsKoR7ApQ5mwpNBsnbUthg1WK3Y/0 -DrYsN7q7rzhLZ1eKm9qy09Ym2c8GnMy/4WpJzwVMji86+p9rAgMBAAGjgcMwgcAw -HQYDVR0OBBYEFIzPJdHcn4B0CbPOisqt/JLb+BQ/MIGQBgNVHSMEgYgwgYWAFIzP -JdHcn4B0CbPOisqt/JLb+BQ/oWKkYDBeMQswCQYDVQQGEwJBVTETMBEGA1UECBMK -U29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRcw -FQYDVQQDEw5yZXNlZWQucGtvbC5kZYIJALLizEjOqx6kMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADgYEAMhy4JVAsTdmkcdxb3x1JNgD7ftWEPl5T2vKrRYCR -LD24FgLLdTGoXEB/NeH8qD3i5xwqc8h9oAvsFx5lp8DhcsZ0YMIuqmRDwmxAVOJ7 -Ke3UR9Zu40ql7u8K4dXtjTyCi6J7twTY76JA/fAhTzgPJoGVBysVQCoW97ukY2jR -PGk= ------END CERTIFICATE----- diff --git a/installer/resources/certificates/ssl/uk.reseed.i2p2.no.crt b/installer/resources/certificates/ssl/uk.reseed.i2p2.no.crt index e7831438a..84f3f073d 100644 --- a/installer/resources/certificates/ssl/uk.reseed.i2p2.no.crt +++ b/installer/resources/certificates/ssl/uk.reseed.i2p2.no.crt @@ -1,23 +1,33 @@ -----BEGIN CERTIFICATE----- -MIID5TCCAs2gAwIBAgIJAIsiec+JiBqiMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD -VQQGEwJVSzEPMA0GA1UECAwGTG9uZG9uMQ8wDQYDVQQHDAZMb25kb24xDDAKBgNV -BAoMA0kyUDEMMAoGA1UECwwDSTJQMRowGAYDVQQDDBF1ay5yZXNlZWQuaTJwMi5u -bzEfMB0GCSqGSIb3DQEJARYQbWVlaEBpMnBtYWlsLm9yZzAeFw0xNDAxMjAyMjQ4 -NDZaFw0yNDAxMTgyMjQ4NDZaMIGIMQswCQYDVQQGEwJVSzEPMA0GA1UECAwGTG9u -ZG9uMQ8wDQYDVQQHDAZMb25kb24xDDAKBgNVBAoMA0kyUDEMMAoGA1UECwwDSTJQ -MRowGAYDVQQDDBF1ay5yZXNlZWQuaTJwMi5ubzEfMB0GCSqGSIb3DQEJARYQbWVl -aEBpMnBtYWlsLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPEs -VAb/fEaICbJyO3Unys2QgtmhNpvI5OORjrk9/l5YUdUb28SUQq4iCC+5NfphdrCe -sSHsrbTBJZtoVBMMgtaqZGW+qR7cRz14H+Ckkxmqu4cbR6AmA0bI4HdccdPmdWUb -eB1SJPtFbwgI+o0sHisiWuMbcNPJKB64JklVCFJzk0Wh4qxQEIEJUcessPzO02TY -tfOcE0QkiDF9MXXWM/Dibf8oAa8HjzACHhrIOKYhf+wdnb0sq2a8cVwvUzneLBrZ -B2ysz63S5YilmM2PKqXBowVwFVeRrlsmSwMI/5k0cUzZngKTLxsC2lNAwGtx+tq0 -2O6z6bstkvEVGBcpwPECAwEAAaNQME4wHQYDVR0OBBYEFJnTRG38DRRT3V5SN78w -1IDB1NGjMB8GA1UdIwQYMBaAFJnTRG38DRRT3V5SN78w1IDB1NGjMAwGA1UdEwQF -MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEVmxLtWRInU+a0H4IiQCYUdxE/N0nxk -47enX+EuUJw4B4qjdv51zRwDNdx15PUYlxTpMWKZWVfvfsb+qRNs3CDhKd0eHqUD -rM7ssWzeCRtOLLPy01QuwwcJrP1bju3pDUNuYCW/EnHAsksIvnGKA03TFgspzFO2 -WHeCVvJeDxLV91fxtjlsX2J2OtwYxkGvkRliL9Y18Ar418KDhewSKe++1CXSy+3z -BJ2lBKzyInwIY/75uQPfyTnmF+9lbx6CX0q4CiqJe1WH4sFQB5syrL7M38yRnsnZ -2UFbcyviKSLx2Lkf1BErZD+5OQ904qClB/g3x52Jgj96tu1W52jPlbY= +MIIFsTCCA5mgAwIBAgIJANgzPow6thRuMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMQswCQYDVQQHDAJVSzETMBEGA1UECgwKSTJQ +IFJlc2VlZDETMBEGA1UECwwKSTJQIFJlc2VlZDEaMBgGA1UEAwwRdWsucmVzZWVk +LmkycDIubm8wHhcNMTQwNjI4MjA0OTA3WhcNMjQwNjI1MjA0OTA3WjBvMQswCQYD +VQQGEwJOTzENMAsGA1UECAwET3NsbzELMAkGA1UEBwwCVUsxEzARBgNVBAoMCkky +UCBSZXNlZWQxEzARBgNVBAsMCkkyUCBSZXNlZWQxGjAYBgNVBAMMEXVrLnJlc2Vl +ZC5pMnAyLm5vMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxlVlXWn5 +Ham6ZqM6FkH6ZoXeXbncY/PnF669mCPcrPH56V2xZXwpeCXHWfu7YiHuhXXZSmzP +zwRrawHZTJulHt4e6j27JnDuEj69gmFpyi4B1djQ0kav0aJeagwCPG2do/UD7Cbr +4nITkU4CifLe47IUW/2K/EBI6bZGsRIDHJ3A+fAQmLnvehEkpvLN+cvtkpJOtZYx +6WvbwLsirkISnaio4//UY8M4poIu9mSG5pvNLagn9uoRPUSuj8jDEysB1Nmh12Zu +gFnt2XcxQB9/0krB5GnDTodrgfsz/UPbk44l4kFmQoLv5ACFndH69RKftogisauj +VVUrqCL3l9TcNsx8GLqZkeWhCwdZycZFjBhK01zihTYPEiU2HXfCNWhzLqxrM2Hh +r1ci+56fyNdn/ssO4o3hrGaWPDiayiHlEGEJxaG/ueKX2c3c0UJKkIGBPTEcdBjW +q42n/7EhY/ISaieQXPRK+gVm18I1OlGUH5FEYELO20bL88J8pr/bYuJyJnC8fiMP +YzKZuiVhey6dPr0zZgNDHyRbOlZqQllzKd1wbzbE4xqdUZfBWYwtRpdOJKDw4eoi +M69TwPQFfudeiudnMcR1gN37OkxS7UTEdsYIB5urgLb6qQD+tYFsxpcVPkedJw62 +3TobhZjucaEZWzePd4u9faT9mQBXBAgY6VcCAwEAAaNQME4wHQYDVR0OBBYEFDTN +QRqhzaLc6XX2gFg26K//e0+8MB8GA1UdIwQYMBaAFDTNQRqhzaLc6XX2gFg26K// +e0+8MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggIBACcJ99Z45ghglvL3 +/yMnx6IkOSneEm2/ADQoOabBQSC2grRAMBescKUiqpgbpBFalIPbPJUVrlH9tXYB +izNhqWETBY2tNy7AEHcJcCsAFuC2gOhaFH7FLgPA8V5IJmZ+McjB8REyowcN+CP4 +GDY8s5/yr9S3HpKLD80UV18UX/j5m4b6I1w61QceMOSt6ahTtlnyvNBonFW94L1c +RmkdbhxYWn2eeUas62Q/+9bjr24E0weDKqopa3bbO7MWJ3mKkS4rua42j8GG3Q3q +UWPGh4zm+2+Ncjmz0Ho73RyYDDcp9IjwlAEv+NW86rz/5Pdkhoy+SzQwFYAwNgaQ +FRKb6ltpslxmu3tUdZ7Ydrj6MBGQyH2gRVm9qByro7WGI4UsyzsjP009Iu6dbhdC +2ddTGMisXF3dOmdRWh8dlggmW6gV4iaVgZkzLtrc9S0SK66utKMVXa4EUTm6XogX +F5ImPnVzIMo2qF2pP31aGDzKqJF3GNjGj+xHRVau5whz0a4ESY6V14PLTEL4Vc/H +J9uLCySifvqN+jzs5iY2QvNXjg2zPaTJbnjxxpYQJVSQHX6SyRcszhChqQzxnbyo ++S19BRclqzufRq6pp6VcOiID0BB7qPcrUHM9h1ingMXcZZlGBgHew9cY7tb5TAox +o+aTNc4k/7E543FVbs40dpOD2Fcr -----END CERTIFICATE----- diff --git a/installer/resources/certificates/ssl/us.reseed.i2p2.no.crt b/installer/resources/certificates/ssl/us.reseed.i2p2.no.crt new file mode 100644 index 000000000..eae724e96 --- /dev/null +++ b/installer/resources/certificates/ssl/us.reseed.i2p2.no.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUDCCAjgCCQCkTcCJMdZV7zANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJO +TzENMAsGA1UECAwET3NsbzENMAsGA1UEBwwET3NsbzENMAsGA1UECgwET3NsbzES +MBAGA1UECwwJTm9yZGNsb3VkMRowGAYDVQQDDBF1cy5yZXNlZWQuaTJwMi5ubzAe +Fw0xNDA2MjcyMjQxMjFaFw0yNDA2MjQyMjQxMjFaMGoxCzAJBgNVBAYTAk5PMQ0w +CwYDVQQIDARPc2xvMQ0wCwYDVQQHDARPc2xvMQ0wCwYDVQQKDARPc2xvMRIwEAYD +VQQLDAlOb3JkY2xvdWQxGjAYBgNVBAMMEXVzLnJlc2VlZC5pMnAyLm5vMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomVoBEc53jzy3xGMfgRaKyX6MaGG +KAmwu0uMTX6bVzGjy56JMMq3luoxOrpvgrNZF52lu7i36Tejo0HM75AHoea1es55 +DNLmrlDeqzlBU2WibOnizbB8G+tlMEbx8eAGAWk/Wv/vH8CAKmxjImslmbajzZC2 +LEH7inp3J5T2sVV7zmXeL9OEPKNyohbu6Mrno2IAlEOr8cu+lWAaFWzpknnR1gBX +NkB/8+7vK5Fq4MT7B0qnXPxmaWDbUOepPPni8u+2L9+qt19vZH4/6KNuH7xd7JLz +FfIdol6jy2cBQyAK7cVKWDHNk7ceB4Dl0mjBDbBIRTtLK+rfdnVmfWn8aQIDAQAB +MA0GCSqGSIb3DQEBBQUAA4IBAQCQH4QJMp5xneh2ah7fiuVdtKbiv6QNunRz7nb/ +mWYyqmBX7EHL8jOG5qmPELDgDt58HmnaYMo05nEJb9JhAoviEDXSYw0s6eN4n4nc +MKqgR/HLLSiXPwT+Wi1MI57OYim5AFTUCYTSaWFUT+dZKYb0QPE1XjGpQXi3ppsJ +3TJG71tOzJmZT6vRPmdTHJO70v6ZEhr5w4SiGx07gNmcgO8WRyb5ajOwSHiGKrj6 +UsuRNhtCyZaAEmelR9mfKBR1J2Nb+9jTz6mJtpT82WY3bst6mFk+A+mMWBQy7Hjt +gpdSDBCcFx9if+AKINGLgFvFKV2q8UzbfXms19NsVt9Hu7W3 +-----END CERTIFICATE----- diff --git a/installer/resources/deletelist.txt b/installer/resources/deletelist.txt index 8fa4d94ae..513bfe167 100644 --- a/installer/resources/deletelist.txt +++ b/installer/resources/deletelist.txt @@ -4,6 +4,7 @@ certificates/r31453.ovh.net certificates/75.145.125.59.crt certificates/forum.i2p2.de.crt certificates/cowpuncher.drollette.com.crt +certificates/ssl/reseed.pkol.de.crt # old translated proxy error pages docs/ahelper-conflict-header_ar.ht docs/ahelper-conflict-header_de.ht diff --git a/installer/resources/eepsite/docroot/help/index.html b/installer/resources/eepsite/docroot/help/index.html index 3a8f6626f..f04c20e48 100644 --- a/installer/resources/eepsite/docroot/help/index.html +++ b/installer/resources/eepsite/docroot/help/index.html @@ -10,18 +10,17 @@

I2P Anonymous Webserver

- -English -中文 -Deutsch -Français + +English +中文 +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska

Quick Guide to Anonymous Webserving on I2P

diff --git a/installer/resources/eepsite/docroot/help/index_de.html b/installer/resources/eepsite/docroot/help/index_de.html index 70876e505..585f64f61 100644 --- a/installer/resources/eepsite/docroot/help/index_de.html +++ b/installer/resources/eepsite/docroot/help/index_de.html @@ -11,17 +11,18 @@

Anonymer Webserver im I2P

- -English -中文 -Deutsch -Français + +English +中文 +Deutsch Español -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska +

Kurzanleitung zum anonymen Hosten von Webseiten in I2P

diff --git a/installer/resources/eepsite/docroot/help/index_es.html b/installer/resources/eepsite/docroot/help/index_es.html index 26d4016b8..0ffd46164 100644 --- a/installer/resources/eepsite/docroot/help/index_es.html +++ b/installer/resources/eepsite/docroot/help/index_es.html @@ -10,17 +10,17 @@

Servidor web anónimo I2P

- + English -中文 -Deutsch +中文 +Deutsch +Español Français -Italiano -Nederlands -Русский -Svenska فارسی 日本語 +Nederlands +Русский +Svenska

Guía rápida para crear el servidor web en I2P

Esta es tu eepsite, tu propio servidor web anónimo en I2P - simplemente edita los archivos dentro de ~/.i2p/eepsite/docroot/ (en Linux) o %APPDATA%\I2P\eepsite\docroot\ (en Windows) diff --git a/installer/resources/eepsite/docroot/help/index_fr.html b/installer/resources/eepsite/docroot/help/index_fr.html index 10de2b3f7..499dde0f4 100644 --- a/installer/resources/eepsite/docroot/help/index_fr.html +++ b/installer/resources/eepsite/docroot/help/index_fr.html @@ -10,18 +10,17 @@

Serveur web anonyme I2P

- -English -中文 -Deutsch -Français + +English +中文 +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska

Guide rapide pour faire un serveur web anonyme dans I2P

diff --git a/installer/resources/eepsite/docroot/help/index_na.html b/installer/resources/eepsite/docroot/help/index_na.html index e97eecf84..7a5edc3ba 100644 --- a/installer/resources/eepsite/docroot/help/index_na.html +++ b/installer/resources/eepsite/docroot/help/index_na.html @@ -9,18 +9,17 @@

I2P Anonymous Webserver

- -English -中文 -Deutsch -Français + +English中文 +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska

Help translate this page into your language!

diff --git a/installer/resources/eepsite/docroot/help/index_nl.html b/installer/resources/eepsite/docroot/help/index_nl.html index 5fa5d5243..8572db447 100644 --- a/installer/resources/eepsite/docroot/help/index_nl.html +++ b/installer/resources/eepsite/docroot/help/index_nl.html @@ -10,18 +10,17 @@

I2P Anonieme Webserver

- -English -中文 -Deutsch -Français + +English +中文 +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska

Korte Handleiding voor Anoniem Webhosten op I2P

diff --git a/installer/resources/eepsite/docroot/help/index_ru.html b/installer/resources/eepsite/docroot/help/index_ru.html index 30a51e5e7..9a5d94c50 100644 --- a/installer/resources/eepsite/docroot/help/index_ru.html +++ b/installer/resources/eepsite/docroot/help/index_ru.html @@ -10,18 +10,17 @@

Анонимный I2P веб-сервер

- -English -中文 -Deutsch -Français + +English +中文 +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska

Краткое руководство по анонимному хостингу сайтов в I2P

diff --git a/installer/resources/eepsite/docroot/help/index_sv.html b/installer/resources/eepsite/docroot/help/index_sv.html index 6d9548296..fad62fe66 100644 --- a/installer/resources/eepsite/docroot/help/index_sv.html +++ b/installer/resources/eepsite/docroot/help/index_sv.html @@ -10,18 +10,17 @@

I2P Anonym Webbserver

- -English -中文 -Deutsch -Français + +English +中文 +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 +Nederlands +Русский +Svenska

Snabb vägledning till anonym webbservning på I2P

diff --git a/installer/resources/eepsite/docroot/help/index_zh.html b/installer/resources/eepsite/docroot/help/index_zh.html new file mode 100644 index 000000000..71ff20512 --- /dev/null +++ b/installer/resources/eepsite/docroot/help/index_zh.html @@ -0,0 +1,108 @@ + + + I2P匿名网页服务器|欢迎来到您的eepsite + + + + + +
+
+

I2P匿名网页服务器

+
+ +English +中文 +Deutsch +Español +Français +فارسی +日本語 +Nederlands +Русский +Svenska +
+

I2P匿名网页服务快速指南

+ +

这是您的eepsite,您自己的匿名I2P网络服务器 - 只要编辑 ~/.i2p/eepsite/docroot/ (Linux) 或 %APPDATA%\I2P\eepsite\docroot\ (Windows) 下的文件,并且按照以下说明操作后,别人就可以访问了. + 在I2P,eepsites是用一个很长的Base64字串"密钥"来寻址访问的. + (这"密钥"有点类似于IP地址,且会显示在eepsite的I2PTunnel上 + 配置页). + 以下说明详细解释了如何为您的密钥分配像"mysite.i2p"的名称并启动您的 eepsite

+

您可以通过 + http://127.0.0.1:7658/在本地访问您的eepsite. +

+ +

如何设置和宣告您的eepsite

+ 默认情况下,您的eepsite是停止运行的. + 您启动它后,它将很难被其他人找到,因为它没有名称,其他人也没有您的很长的Base64密钥. + 您可以告诉别人那真的很长的密钥,但值得庆幸的是,I2P有一个地址簿和几个简单的方法来告诉其他人您eepsite.这是详细说明. +
    +
  • 为您的eepsite选个名称(something.i2p).全部用小写字母. + 您可能要先在这里检查自己路由器的地址簿, + 或检查文件i2p/hosts.txt里,看看是否您的名称已经被占用. + 在eepsite i2ptunnel 配置页的“网站名称”部分输入您eepsite的新名称。这将替换缺省的"mysite.i2p". + 同时,选中“自动启动”框。现在每次启动您的路由器时,您的eepsite也将启动. + 请点击“保存”.
  • +
  • 在 + 主i2ptunnel配置页,点击您的eepsite启动按钮. + 在 + I2P路由器控制台的左侧,您应该可以看到"eepsite"列在"本地目标"下面. + 您的 eepsite 现在正在运行了.
  • +
  • 在 + eepsite i2ptunnel 配置页,突出显示全部的"本地目的地"的密钥. + 并将它复制以备以后粘贴. 确保您复制到了完整的密钥 - 它有超过 500 个字符,必须以"AAAA"为结束符.
  • +
  • 在您的 + 主地址簿内,输入名称并粘贴目标密钥. + 单击"添加",将目标添加到您的址簿内。
  • +
  • 在您的浏览器内,输入您的 eepsite名称 (something.i2p)您应该会立刻返回这里. 希望它能生效.
  • +
  • 在您向全世界宣告您的新eepsite前,您应该增加一些内容. +到~/.i2p/eepsite/docroot/ (Linux) 或 %APPDATA%\I2P\eepsite\docroot\ (Windows) 并用自己的内容替换掉index.html重定向页面.虚拟文件夹会起作用,这样您就可以从一个子目录中提供文件服务而不用明确需要提供链接到文件的一个页面.如果您需要一个基本的网站模板, 请自由借来并适用 本页内容 !
  • +
+

注册自己的.I2P域名

    +
  • 现在,是时候把您的eepsite加入到其它网站的I2P地址簿了 + 比如stats.i2pno.i2p. + 就是,您必须在一个或多个这样网站的网页界面输入您eepsite的名称和密钥. + 这是在stats.i2p的密钥输入表格. + 再说一次, 您的密钥是在 + eepsite i2ptunnel 配置页面上的整个"本地目标"密钥. + 确保您复制到了以"AAAA"为结束的符完整的密钥. + 不要忘记点击“添加一个密钥”. + 检查看看是否报告密钥有添加. + 由于许多路由器周期性地从这些网站获取更新地址簿,在几个小时内其他人就能够通过在他们的浏览器里简单的输入 something.i2p 来找到您的网站.
  • +

添加地址簿订阅

    +
  • 说到地址簿更新,这会是个很好的时机来添加些更多的地址簿到您自己的订阅列表. 到您的订阅配置页面,并添加以下内容以自动更新新主机列表: +
  • 若您很匆忙不能等待几个小时,您可以告诉别人用“跳转”地址助手重定向服务. + 这将会在您输入密钥到同一个网站上的地址簿内的几分钟内起作用. + 自己先测试一下,在您的浏览器里输入 + http://stats.i2p/cgi-bin/jump.cgi?a=something.i2p + 或 http://i2host.i2p/cgi-bin/i2hostjump?something.i2p + 一旦开始工作,那么您就可以告诉别人来使用它.
  • +
  • 有些人会检查eepsite列表,如 + inproxy.tino.i2p/status.phpperv.i2p 以获取新eepsites,所以开始您可能会有几个访客. 但也有很多其他的方式来告诉人们.这里有一些点子: + + 请注意,有些网站推荐贴那很长的目标密钥. 若您愿意您可以-但是,如果您已成功在添加密钥服务里发布您的密钥,使用跳转服务测试过了,并等待了24个小时以便地址簿更新传播给他人,这应该不是很必要.
+

更进一步的援助

+注: 本页, 网站和控制台都需要翻译成您的语言,如果不是已经完成或在进展中,请考虑奉献您的时间来翻译 以帮助项目的成长. 请通过上面列出的IRC频道联系项目组. 先谢谢了!
+
+文件最后编辑:2014.06
+
+ + diff --git a/installer/resources/eepsite/docroot/help/pagetemplate.html b/installer/resources/eepsite/docroot/help/pagetemplate.html index 892c20f49..31793baf7 100644 --- a/installer/resources/eepsite/docroot/help/pagetemplate.html +++ b/installer/resources/eepsite/docroot/help/pagetemplate.html @@ -9,20 +9,17 @@

MY EEPSITE

- -English -中文 -Deutsch -Français + +English +Deutsch Español -Italiano -Nederlands -Русский -Svenska +Français فارسی 日本語 - - +Nederlands +Русский +Svenska +中文

Words and pictures and stuff

Your cool stuff here... diff --git a/installer/resources/hosts.txt b/installer/resources/hosts.txt index bcf3e9d10..527653924 100644 --- a/installer/resources/hosts.txt +++ b/installer/resources/hosts.txt @@ -13,7 +13,7 @@ squid.i2p=8fiWZbRjOEzrj5n4jSqjN9UN54wTrsgEjqn7GRUQpLx1svf8lwckXPV5buP2VEYGo~83ft fillament.i2p=Pa50z7pU~ni5nWwUdaDZ5CJxG0fYjoarm9wlxnkgX~wHMX9RPgQAXz~r0Rr1Nadt2OA~dr9RMHswrMok0hutK3JZuFD707D7FjmWW2w979Ee9I3zxKyx9W5A2eE49PPT131NLa3uINXLXOYVA5frfDOmM75Dmvm533r8e2kloemJyj22HpvRiSXiQYgqYJGDMH3Hlnwk884eRkQu7P8DJL~hcuKpyY0FzLZtfxTNsdSavGjl7rKPMzJeP02-9TS5TkdHokZrstVM5Cn9ay1c8DQrMds7SPXJy13Ut34QRjb65JxRV0mrnY3teXewW6QFvFMXJCsf5C3i46t-9Fufy5D1H8cSd2Tx~Xl71MC5-1AJCcIS01Od23E9tFY3dU7IOSRhKC~FiAslyk3x-BnBSpKxbgl1w~LArBm5plNiCiUemJU88xYdn1UyukLer~yNrEHAWspckCRkXFwmUtPkaGNTvfwBSYns-skNHSd7MAUUoS-ewStBdmtnDgRkwSG9AAAA eco.i2p=KhRG6BGxVPh-BUDDfIgy0570cppTdighytcaGVR0HzQo46tgRMBp9Shlpax5FQX4nLHn6qHQbdFFpFbAwe7CiDhURCVF9-CxYmPurGadxlMPHMjz9O3jHX0CQiv2iULsk4XPrYXF3PqBc4t1J6vVyBVO7uTUhDi0gF6sN1Ro-1GLcWcsoR8Kx-hb~Z4WqGD0QAROOBPHnSRSb236qVBkhFvSkfigfBq3jFgEsttadYJA9ZLSUj1XrFFRBjz~xkRra8kJQSZl5dbfg-eZMlL49h61U6Uta5n1~tL6sarmnl9CaTl2Qo27SKB1OmMLeZEteA5G0-~LiOjN0nxaKpwrCjKIOyvwbQy2QqE-GEb9m8SN8nC2bwYK9fH15pTMHY8GvPYGcUukbF6RhefwzkEJLZ~PaAECrZYuLsn9KE5C35uRnlWJiuJlJ25hG7da5tFMyDB95efzq5IMxPeI0pMigRfuVfRSaGDpNos6JxjfEIX8umk3jIJUPhz1d8gP4QgrAAAA aum.i2p=09hSo56PTtkFLUEt1iUTO7zYTnO-B~ogsIsyyPWif6q1Iz4wz4JoBflAWZtedPmwGmH0nly4HYUS0gAADoUmBUnXwemmO6dxT-hPQkfEW-A7b3uEvYQWIN~kyFyg0Pa~FN6TaD9kGFttBN-GE4wxiHhXmWdzWNDVb0q5PVGnxMm6Jleik8xkd2Lgeexze8rIv8LCocAWx074USVkbCVQwoFi2P7EnjLq8odSz1cJAntbuCFeUZcjbslE3qmlcTFMCNCZXWKVzn7d5m4oszCQ83NidgekwxJ-S~iS6mBwIS0XKI--4iXiKXzzCFf0KtYfEWpvKCuqNJOcU8vQWAA2-i7~K28aLPzccDQn7acXWLKRTXF3tf0i6e-lSx-X6WTSWK-fuNitjAtKu~jqO10d~bCk7y~UPL-XwdH1XSTbk-Phhk7UoBTDiHY6zQHdD~iAzXER~9JXsJ4UoIrGFVabg7frzSt82CN7Ek5Li4AMz5gg3wq9H9HUa7xM5QfGIJpXAAAA -mp3.aum.i2p=vBOu1caCAajaL5WRMuwk4LwfXrlcn0WzA6iHUKV5ULhaBpJb9pR3SZpnQms2Ot2c5Fvu5I6Rp7WF6QRcyasAhUmC915ap~2~VG8KCDP0z3Quh1-eqGcmzErsIfXdh09j3CWuxN~fH84hd~KswqGudFkWtFTM9RcuQUGSC1efG7uF03uaDI-DKu7eb4VUV-hmpXb3Lqntgo5qSMBMmjyUND-f6RBoXnqM005mUZJpMoYfsBhnUEq37GG8u6P9T94nlMmtz9R3gNURpBJJKPlnEqCBN4mlE5rwspQ0ovxAlogVMhSCpQ4jr6cyWIbNx-nMzKGDj~hMQ0ndbVnWw3EDC3KsPnRnDv0yVz8Fc1YpoPwerHej7VnTupDKxc4T-j8XNA1dN8SfPmaKYEPfavlmy7HFAGcsbmeRZOq-PVvlDdrKNflug8Ysodd5XkDbh7y2k1pRDjwNBQ1EgDVAtL05-i9jerqekHkbFKJ6DlT76f06vj1R2v9qlQzAYjpcKbI3AAAA +mp3.aum.i2p=vBOu1caCAajaL5WRMuwk4LwfXrlcn0WzA6iHUKV5ULhaBpJb9pR3SZpnQms2Ot2c5Fvu5I6Rp7WF6QRcyasAhUmC915ap~2~VG8KCDP0z3Quh1-eqGcmzErsIfXdh09j3CWuxN~fH84hd~KswqGudFkWtFTM9RcuQUGSC1efG7uF03uaDI-DKu7eb4VUV-hmpXb3Lqntgo5qSMBMmjyUND-f6RBoXnqM005mUZJpMoYfsBhnUEq37GG8u6P9T94nlMmtz9R3gNURpBJJKPlnEqCBN4mlE5rwspQ0ovxAlogVMhSCpQ4jr6cyWIbNx-nMzKGDj~hMQ0ndbVnWw3EDC3KsPnRnDv0yVz8Fc1YpoPwerHej7VnTupDKxc4T-j8XNA1dN8SfPmaKYEPfavlmy7HFAGcsbmeRZOq-PVvlDdrKNflug8Ysodd5XkDbh7y2k1pRDjwNBQ1EgDVAtL05-i9jerqekHkbFKJ6DlT76f06vj1R2v9qlQzAYjpcKbI3AAAA ogg.aum.i2p=wR2ETKWn-mxsTurWwmSujvjpOiIjLg5TsldFUa4YFTgiRZdFIB-bXuK59shfnchlEgAZR0IR3~hH-O8bZ~j6wVBdZWq7bGTmyTxQ3MeYPdqK7wH7Jp147YUabFlqJkyI~DluwBDylJrIUyc2qw~ogJ67x-KyzIF7JLnoCC4E-T8Z0vmTAFWSa3XC-ncghrdZQCqEXaCMlG9PN~a7dcDq~qdWoNoyFcgLd0IQfE8JuJ1wSvmWUNEd9vkB2Zuu3EoSoDv4C53Fc0YhVACNug~VEEL-ZBGcCBcpVNud8dOMq-CbavkD5yKqHlvq~uzRi6BY5ajHI77uepJygkHcsm-8T0PXWXdc5ib4TtUI03tPkTar4Y2iVocY~oLk2jh7pQKZNioHJT4StWv9Pj8EWaVX4-emQB5kZOBwZItjo~EAGEoBT14NSM7CmKClgc6sg7fpvWF~-cNHkZsurBndni~~FKmUeWoO0FRQRF9Ao~C1DOt2V9oBbEW1~n6anjL5V~IyAAAA fcp.entropy.i2p=jy0D13oJVmxSa1MltstV3FOfA5e2WAEEZJiYOJIZSUOcNnAkaR3ghE-AX4vuqyQPyOEUydpauD6cS8vfx4iZkb2U3ddlLcOU3YrFKdLrySpGtD~V126VO-9nOJFwDQOOaKAsiVGRKtMPLC64GkpU6TWSIhiVYWb7WmeAHXLLlR71DtgamAxEIlP3VhytxlS3vuvAoEH9ItsBwkv4N~7jec60WMQINl~c7uDDsuzKFY8wQlkHnLFQJCQ0VExfNYqK9nZ3x8TXNPmNKTMMQ1CUCowgwR783U7UAYqsxNrpkuWvTleadn7QcR9i2v4~L9zOeHd4nHBy8PAjO29g6nf6DIsYhg4c2HYnPYzktQ1NIElytmW83BhbXJXLgNBs1eI9gDaQmOiXi74FMgfg63IcXCYWeqCdwEzSouSphaXEHDcZZVTx7DE9R-1Bi4Dt~KvPOFsAoOqsjHCpHq1gS0u5HiL0hkSm1I1EMk4JBY0j4rM1nAt7e0ix~WiOz5jXlTVSAAAA http.entropy.i2p=ON2Ud-B0-pJKbTR0Obpjp9wEG8grUpu55gEn5Mz3-dkVkPhHvHK6iLasr~P~Rf4kPPZvn-eK7z6rAVfsAytAJ9pcTH3lXERTjkd9FzVJJ0twbZSQ~XzX5d-24IPIMf00KegjnDkRJ82cRMKa-u4H-ayei~Y7xsSx64zC1eHv6qFxavtql3zRrS~du41~EHtpjqOtOo9Ea3lfFjhm2jUIJpYyVHqve3WbTfMBlguVALwGZIfenph7oQ1Hx~OnEtaviWuOEpupjm11LS9xqCNsccaEpJGvGt6ijxd9hrEuQZ5Ja~C0fNxf3xNtgRaUhakA8Xoo~jz8rCkV2vYQo58kj0E5xYrUQczomj8y-eDBZyq29BP8pfe2G1u3hpHA1z470LUeMPk8qVx8Cx8ZKmSK9XCvOl7WCnFS2~UUfzxbxSxPn9LfzxDZp05AVi9t~hJg-zkrL2n1wfEnScuUFapxarwK90rlAxNSnau-K61WfcXqyVMwDxl3leJOeVdHqhpbAAAA diff --git a/installer/resources/osid b/installer/resources/osid index 235906dfb..4d3ffb909 100644 --- a/installer/resources/osid +++ b/installer/resources/osid @@ -4,7 +4,7 @@ # # osid # 2004 The I2P Project -# http://www.i2p2.de/ +# https://geti2p.net # This code is public domain. # # author: hypercubus diff --git a/installer/resources/postinstall.sh b/installer/resources/postinstall.sh index 60c80d2c9..a58a19223 100644 --- a/installer/resources/postinstall.sh +++ b/installer/resources/postinstall.sh @@ -4,23 +4,21 @@ # # postinstall # 2004 The I2P Project -# http://www.i2p2.de/ +# https://geti2p.net # This code is public domain. # # author: hypercubus # # Installs the appropriate set of Java Service Wrapper support files for the -# user's OS then launches the I2P router as a background service. +# user's OS if [ ! "X$1" = "X" ]; then cd $1 fi chmod 755 ./i2prouter -# chmod 755 ./install_i2p_service_unix chmod 755 ./osid chmod 755 ./runplain.sh -# chmod 755 ./uninstall_i2p_service_unix ERROR_MSG="Cannot determine operating system type. From the subdirectory in lib/wrapper matching your operating system, please move i2psvc to your base I2P directory, and move the remaining two files to the lib directory." LOGFILE=./postinstall.log @@ -44,36 +42,30 @@ case $HOST_OS in # Wrapper we built for Raspberry Pi does not work on Trimslice armv7. if [ `echo $OS_ARCH |grep armv7` ]; then wrapperpath="./lib/wrapper/linux-armv5" - cp ${wrapperpath}/libwrapper.so ./lib/ elif [ `echo $OS_ARCH |grep armv6` ]; then wrapperpath="./lib/wrapper/linux-armv6" - cp ${wrapperpath}/libwrapper.so ./lib/ elif [ `echo $OS_ARCH |grep arm` ]; then wrapperpath="./lib/wrapper/linux-armv5" - cp ${wrapperpath}/libwrapper.so ./lib/ elif [ `echo $OS_ARCH |grep ppc` ]; then wrapperpath="./lib/wrapper/linux-ppc" - cp ${wrapperpath}/libwrapper.so ./lib/ elif [ "X$X86_64" = "X" ]; then wrapperpath="./lib/wrapper/linux" - cp ${wrapperpath}/libwrapper.so ./lib/ else wrapperpath="./lib/wrapper/linux64" - cp ${wrapperpath}/libwrapper.so ./lib # the 32bit libwrapper.so will be needed if a 32 bit jvm is used cp ./lib/wrapper/linux/libwrapper.so ./lib/libwrapper-linux-x86-32.so fi + cp ${wrapperpath}/libwrapper.so ./lib/ ;; freebsd ) if [ ! `echo $OS_ARCH | grep amd64` ]; then wrapperpath="./lib/wrapper/freebsd" - cp ${wrapperpath}/libwrapper.so ./lib/ else wrapperpath="./lib/wrapper/freebsd64" - cp ${wrapperpath}/libwrapper.so ./lib/ # the 32bit libwrapper.so will be needed if a 32 bit jvm is used cp ./lib/wrapper/freebsd/libwrapper.so ./lib/libwrapper-freebsd-x86-32.so fi + cp ${wrapperpath}/libwrapper.so ./lib/ ;; osx ) wrapperpath="./lib/wrapper/macosx" @@ -90,7 +82,7 @@ case $HOST_OS in # FIXME # This isn't displayed when installing, but if we fall back to the "*)" # choice, no cleanup happens and users are advised to copy the wrapper - # in place...but there is no wrapper. Figuring how how to display this, + # in place...but there is no wrapper. Figuring out how to display this, # such as when doing a headless installation would be good. echo "The java wrapper is not supported on this platform." echo "Please use `pwd`/runplain.sh to start I2P." @@ -111,13 +103,8 @@ if [ ! "X$wrapperpath" = "x" ]; then fi chmod 755 ./eepget -rm -rf ./icons -rm -rf ./lib/wrapper -rm -f ./lib/*.dll -rm -f ./*.bat -rm -f ./*.cmd -rm -f ./*.exe -rm -rf ./utility.jar +rm -rf ./icons ./lib/wrapper +rm -f ./lib/*.dll /*.bat ./*.cmd ./*.exe ./utility.jar if [ ! `echo $HOST_OS |grep osx` ]; then rm -rf ./Start\ I2P\ Router.app diff --git a/router/java/build.xml b/router/java/build.xml index 46ec22e49..01f7148fd 100644 --- a/router/java/build.xml +++ b/router/java/build.xml @@ -27,12 +27,15 @@ + + + - @@ -127,7 +130,7 @@ - diff --git a/router/java/src/net/i2p/router/InNetMessagePool.java b/router/java/src/net/i2p/router/InNetMessagePool.java index 9e7ad2e9c..28296cebb 100644 --- a/router/java/src/net/i2p/router/InNetMessagePool.java +++ b/router/java/src/net/i2p/router/InNetMessagePool.java @@ -379,8 +379,8 @@ public class InNetMessagePool implements Service { Hash from = null; synchronized (_pendingDataMessages) { if (!_pendingDataMessages.isEmpty()) { - msg = (I2NPMessage)_pendingDataMessages.remove(0); - from = (Hash)_pendingDataMessagesFrom.remove(0); + msg = _pendingDataMessages.remove(0); + from = _pendingDataMessagesFrom.remove(0); } remaining = _pendingDataMessages.size(); } @@ -402,7 +402,7 @@ public class InNetMessagePool implements Service { int remaining = 0; synchronized (_pendingGatewayMessages) { if (!_pendingGatewayMessages.isEmpty()) - msg = (I2NPMessage)_pendingGatewayMessages.remove(0); + msg = _pendingGatewayMessages.remove(0); remaining = _pendingGatewayMessages.size(); } if (msg != null) @@ -422,7 +422,7 @@ public class InNetMessagePool implements Service { if (_pendingGatewayMessages.isEmpty()) _pendingGatewayMessages.wait(); else - msg = (I2NPMessage)_pendingGatewayMessages.remove(0); + msg = _pendingGatewayMessages.remove(0); } if (msg != null) { long before = _context.clock().now(); @@ -453,8 +453,8 @@ public class InNetMessagePool implements Service { if (_pendingDataMessages.isEmpty()) { _pendingDataMessages.wait(); } else { - msg = (I2NPMessage)_pendingDataMessages.remove(0); - from = (Hash)_pendingDataMessagesFrom.remove(0); + msg = _pendingDataMessages.remove(0); + from = _pendingDataMessagesFrom.remove(0); } } if (msg != null) { diff --git a/router/java/src/net/i2p/router/MultiRouter.java b/router/java/src/net/i2p/router/MultiRouter.java index 6e4346807..5e8cb4760 100644 --- a/router/java/src/net/i2p/router/MultiRouter.java +++ b/router/java/src/net/i2p/router/MultiRouter.java @@ -240,7 +240,7 @@ public class MultiRouter { while (true) { int alive = 0; for (int i = 0; i < _routers.size(); i++) { - Router r = (Router)_routers.get(i); + Router r = _routers.get(i); if (!r.isAlive()) { _out.println("Router " + i + " is dead"); } else { diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index a6204817e..31c35f8c3 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 8; + public final static long BUILD = 14; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/dummy/DummyNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/dummy/DummyNetworkDatabaseFacade.java index a17cee907..11b9419f3 100644 --- a/router/java/src/net/i2p/router/dummy/DummyNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/dummy/DummyNetworkDatabaseFacade.java @@ -49,12 +49,12 @@ public class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade { else _context.jobQueue().addJob(onFindJob); } - public RouterInfo lookupRouterInfoLocally(Hash key) { return (RouterInfo)_routers.get(key); } + public RouterInfo lookupRouterInfoLocally(Hash key) { return _routers.get(key); } public void publish(LeaseSet localLeaseSet) {} public void publish(RouterInfo localRouterInfo) {} public LeaseSet store(Hash key, LeaseSet leaseSet) { return leaseSet; } public RouterInfo store(Hash key, RouterInfo routerInfo) { - RouterInfo rv = (RouterInfo)_routers.put(key, routerInfo); + RouterInfo rv = _routers.put(key, routerInfo); return rv; } public void unpublish(LeaseSet localLeaseSet) {} diff --git a/router/java/src/net/i2p/router/dummy/VMCommSystem.java b/router/java/src/net/i2p/router/dummy/VMCommSystem.java index 1d02d07b2..e6c310d7c 100644 --- a/router/java/src/net/i2p/router/dummy/VMCommSystem.java +++ b/router/java/src/net/i2p/router/dummy/VMCommSystem.java @@ -52,7 +52,7 @@ public class VMCommSystem extends CommSystemFacade { */ public void processMessage(OutNetMessage msg) { Hash peer = msg.getTarget().getIdentity().getHash(); - VMCommSystem peerSys = (VMCommSystem)_commSystemFacades.get(peer); + VMCommSystem peerSys = _commSystemFacades.get(peer); long now = _context.clock().now(); long sendTime = now - msg.getSendBegin(); diff --git a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java index 4b736cc7f..3bcb7d8d9 100644 --- a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java +++ b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java @@ -4,9 +4,11 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -17,6 +19,7 @@ import java.util.Set; import java.util.StringTokenizer; import net.i2p.I2PAppContext; +import net.i2p.crypto.SU3File; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.data.Hash; @@ -25,6 +28,7 @@ import net.i2p.router.RouterContext; import net.i2p.router.util.EventLog; import net.i2p.router.util.RFC822Date; import net.i2p.util.EepGet; +import net.i2p.util.FileUtil; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.SecureDirectory; @@ -49,12 +53,17 @@ public class Reseeder { // Reject unreasonably big files, because we download into a ByteArrayOutputStream. private static final long MAX_RESEED_RESPONSE_SIZE = 2 * 1024 * 1024; + private static final long MAX_SU3_RESPONSE_SIZE = 1024 * 1024; /** limit to spend on a single host, to avoid getting stuck on one that is seriously overloaded */ private static final int MAX_TIME_PER_HOST = 7 * 60 * 1000; + private static final long MAX_FILE_AGE = 30*24*60*60*1000L; + /** change to false if hosts not ready at release */ + private static final boolean ENABLE_SU3 = true; /** - * NOTE - URLs that are in both the standard and SSL groups must use the same hostname and path, + * NOTE - URLs that are in both the standard and SSL groups must use the same hostname, * so the reseed process will not download from both. + * Ports are supported as of 0.9.14. * * NOTE - Each seedURL must be a directory, it must end with a '/', * it can't end with 'index.html', for example. Both because of how individual file @@ -69,11 +78,11 @@ public class Reseeder { "http://193.150.121.66/netDb/" + "," + "http://netdb.i2p2.no/" + "," + "http://reseed.info/" + "," + - "http://reseed.pkol.de/" + "," + - //Temp disabled (ticket #1276) - //"http://uk.reseed.i2p2.no/" + "," + + "http://us.reseed.i2p2.no/" + "," + + "http://uk.reseed.i2p2.no/" + "," + + "http://jp.reseed.i2p2.no/" + "," + "http://i2p-netdb.innovatio.no/" + "," + - "http://ieb9oopo.mooo.com"; + "http://ieb9oopo.mooo.com/"; // Temp disabled since h2ik have been AWOL since 06-03-2013 //"http://i2p.feared.eu/"; @@ -87,14 +96,16 @@ public class Reseeder { "https://193.150.121.66/netDb/" + "," + "https://netdb.i2p2.no/" + "," + "https://reseed.info/" + "," + - "https://reseed.pkol.de/" + "," + - //Temp disabled (ticket #1276) - //"https://uk.reseed.i2p2.no/" + "," + + "https://us.reseed.i2p2.no:444/" + "," + + "https://uk.reseed.i2p2.no:444/" + "," + + "https://jp.reseed.i2p2.no:444/" + "," + "https://i2p-netdb.innovatio.no/" + "," + - "https://ieb9oopo.mooo.com"; + "https://ieb9oopo.mooo.com/"; // Temp disabled since h2ik have been AWOL since 06-03-2013 //"https://i2p.feared.eu/"; + private static final String SU3_FILENAME = "i2pseeds.su3"; + public static final String PROP_PROXY_HOST = "router.reseedProxyHost"; public static final String PROP_PROXY_PORT = "router.reseedProxyPort"; /** @since 0.8.2 */ @@ -257,7 +268,7 @@ public class Reseeder { * @return count of routerinfos successfully fetched */ private int reseed(boolean echoStatus) { - List URLList = new ArrayList(); + List URLList = new ArrayList(); String URLs = _context.getProperty(PROP_RESEED_URL); boolean defaulted = URLs == null; boolean SSLDisable = _context.getBooleanProperty(PROP_SSL_DISABLE); @@ -269,36 +280,53 @@ public class Reseeder { URLs = DEFAULT_SSL_SEED_URL; } StringTokenizer tok = new StringTokenizer(URLs, " ,"); - while (tok.hasMoreTokens()) - URLList.add(tok.nextToken().trim()); + while (tok.hasMoreTokens()) { + String u = tok.nextToken().trim(); + if (!u.endsWith("/")) + u = u + '/'; + try { + URLList.add(new URL(u)); + } catch (MalformedURLException mue) {} + } Collections.shuffle(URLList, _context.random()); if (defaulted && !SSLDisable && !SSLRequired) { // put the non-SSL at the end of the SSL - List URLList2 = new ArrayList(); + List URLList2 = new ArrayList(); tok = new StringTokenizer(DEFAULT_SEED_URL, " ,"); - while (tok.hasMoreTokens()) - URLList2.add(tok.nextToken().trim()); + while (tok.hasMoreTokens()) { + String u = tok.nextToken().trim(); + if (!u.endsWith("/")) + u = u + '/'; + try { + URLList2.add(new URL(u)); + } catch (MalformedURLException mue) {} + } Collections.shuffle(URLList2, _context.random()); URLList.addAll(URLList2); } int total = 0; for (int i = 0; i < URLList.size() && _isRunning; i++) { - String url = URLList.get(i); - int dl = reseedOne(url, echoStatus); + URL url = URLList.get(i); + int dl = 0; + if (ENABLE_SU3) { + try { + dl = reseedSU3(new URL(url.toString() + SU3_FILENAME), echoStatus); + } catch (MalformedURLException mue) {} + } + if (dl <= 0) + dl = reseedOne(url, echoStatus); if (dl > 0) { total += dl; // Don't go on to the next URL if we have enough if (total >= 100) break; - // remove alternate version if we haven't tried it yet - String alt; - if (url.startsWith("http://")) - alt = url.replace("http://", "https://"); - else - alt = url.replace("https://", "http://"); - int idx = URLList.indexOf(alt); - if (idx > i) - URLList.remove(i); + // remove alternate versions if we haven't tried them yet + for (int j = i + 1; j < URLList.size(); ) { + if (url.getHost().equals(URLList.get(j).getHost())) + URLList.remove(j); + else + j++; + } } } return total; @@ -321,17 +349,17 @@ public class Reseeder { * * We update the status here. * + * @param seedURL the URL of the directory, must end in '/' * @param echoStatus apparently always false * @return count of routerinfos successfully fetched **/ - private int reseedOne(String seedURL, boolean echoStatus) { + private int reseedOne(URL seedURL, boolean echoStatus) { try { // Don't use context clock as we may be adjusting the time final long timeLimit = System.currentTimeMillis() + MAX_TIME_PER_HOST; _checker.setStatus(_("Reseeding: fetching seed URL.")); System.err.println("Reseeding from " + seedURL); - URL dir = new URL(seedURL); - byte contentRaw[] = readURL(dir); + byte contentRaw[] = readURL(seedURL); if (contentRaw == null) { // Logging deprecated here since attemptFailed() provides better info _log.warn("Failed reading seed URL: " + seedURL); @@ -388,7 +416,7 @@ public class Reseeder { _checker.setStatus( _("Reseeding: fetching router info from seed URL ({0} successful, {1} errors).", fetched, errors)); - if (!fetchSeed(seedURL, iter.next())) + if (!fetchSeed(seedURL.toString(), iter.next())) continue; fetched++; if (echoStatus) { @@ -416,6 +444,112 @@ public class Reseeder { return 0; } } + + /** + * Fetch an su3 file containing routerInfo files + * + * We update the status here. + * + * @param seedURL the URL of the SU3 file + * @param echoStatus apparently always false + * @return count of routerinfos successfully fetched + * @since 0.9.14 + **/ + private int reseedSU3(URL seedURL, boolean echoStatus) { + int fetched = 0; + int errors = 0; + File contentRaw = null; + File zip = null; + File tmpDir = null; + try { + _checker.setStatus(_("Reseeding: fetching seed URL.")); + System.err.println("Reseeding from " + seedURL); + contentRaw = fetchURL(seedURL); + if (contentRaw == null) { + // Logging deprecated here since attemptFailed() provides better info + _log.warn("Failed reading seed URL: " + seedURL); + System.err.println("Reseed got no router infos from " + seedURL); + return 0; + } + SU3File su3 = new SU3File(_context, contentRaw); + zip = new File(_context.getTempDir(), "reseed-" + _context.random().nextInt() + ".zip"); + su3.verifyAndMigrate(zip); + int type = su3.getContentType(); + if (type != SU3File.CONTENT_RESEED) + throw new IOException("Bad content type " + type); + String version = su3.getVersionString(); + try { + Long ver = Long.parseLong(version.trim()); + if (ver >= 1400000000L) { + // preliminary code was using "3" + // new format is date +%s + ver *= 1000; + if (ver < _context.clock().now() - MAX_FILE_AGE) + throw new IOException("su3 file too old"); + } + } catch (NumberFormatException nfe) {} + tmpDir = new File(_context.getTempDir(), "reseeds-" + _context.random().nextInt()); + if (!FileUtil.extractZip(zip, tmpDir)) + throw new IOException("Bad zip file"); + + Hash ourHash = _context.routerHash(); + String ourB64 = ourHash != null ? ROUTERINFO_PREFIX + ourHash.toBase64() + ROUTERINFO_SUFFIX : ""; + + File[] files = tmpDir.listFiles(); + if (files == null || files.length == 0) + throw new IOException("No files in zip"); + List fList = Arrays.asList(files); + Collections.shuffle(fList, _context.random()); + long minTime = _context.clock().now() - MAX_FILE_AGE; + File netDbDir = new SecureDirectory(_context.getRouterDir(), "netDb"); + if (!netDbDir.exists()) + netDbDir.mkdirs(); + + // 400 max from one URL + for (Iterator iter = fList.iterator(); iter.hasNext() && fetched < 400; ) { + File f = iter.next(); + String name = f.getName(); + if (name.length() != ROUTERINFO_PREFIX.length() + 44 + ROUTERINFO_SUFFIX.length() || + name.equals(ourB64) || + f.length() > 10*1024 || + f.lastModified() < minTime || + !name.startsWith(ROUTERINFO_PREFIX) || + !name.endsWith(ROUTERINFO_SUFFIX) || + !f.isFile()) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Skipping " + f); + f.delete(); + errors++; + continue; + } + File to = new File(netDbDir, name); + if (FileUtil.rename(f, to)) { + fetched++; + } else { + f.delete(); + errors++; + } + // Give up on this host after lots of errors + if (errors >= 5) + break; + } + } catch (Throwable t) { + _log.warn("Error reseeding", t); + } finally { + if (contentRaw != null) + contentRaw.delete(); + if (zip != null) + zip.delete(); + if (tmpDir != null) + FileUtil.rmdir(tmpDir, false); + } + _checker.setStatus( + _("Reseeding: fetching router info from seed URL ({0} successful, {1} errors).", fetched, errors)); + System.err.println("Reseed got " + fetched + " router infos from " + seedURL + " with " + errors + " errors"); + if (fetched > 0) + _context.netDb().rescan(); + return fetched; + } /** * Always throws an exception if something fails. @@ -450,7 +584,6 @@ public class Reseeder { /** @return null on error */ private byte[] readURL(URL url) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024); - EepGet get; boolean ssl = url.toString().startsWith("https"); if (ssl) { @@ -478,12 +611,62 @@ public class Reseeder { get.addAuthorization(user, pass); } } + if (!url.toString().endsWith("/")) { + String minLastMod = RFC822Date.to822Date(_context.clock().now() - MAX_FILE_AGE); + get.addHeader("If-Modified-Since", minLastMod); + } get.addStatusListener(ReseedRunner.this); - if (get.fetch()) + if (get.fetch() && get.getStatusCode() == 200) return baos.toByteArray(); return null; } + /** + * Fetch a URL to a file. + * + * @return null on error + * @since 0.9.14 + */ + private File fetchURL(URL url) throws IOException { + File out = new File(_context.getTempDir(), "reseed-" + _context.random().nextInt() + ".tmp"); + EepGet get; + boolean ssl = url.toString().startsWith("https"); + if (ssl) { + SSLEepGet sslget; + // TODO SSL PROXY + if (_sslState == null) { + sslget = new SSLEepGet(I2PAppContext.getGlobalContext(), out.getPath(), url.toString()); + // save state for next time + _sslState = sslget.getSSLState(); + } else { + sslget = new SSLEepGet(I2PAppContext.getGlobalContext(), out.getPath(), url.toString(), _sslState); + } + get = sslget; + // TODO SSL PROXY AUTH + } else { + // Do a (probably) non-proxied eepget into file with 0 retries + boolean shouldProxy = _proxyHost != null && _proxyHost.length() > 0 && _proxyPort > 0; + get = new EepGet(I2PAppContext.getGlobalContext(), shouldProxy, _proxyHost, _proxyPort, 0, 0, MAX_SU3_RESPONSE_SIZE, + out.getPath(), null, url.toString(), false, null, null); + if (shouldProxy && _context.getBooleanProperty(PROP_PROXY_AUTH_ENABLE)) { + String user = _context.getProperty(PROP_PROXY_USERNAME); + String pass = _context.getProperty(PROP_PROXY_PASSWORD); + if (user != null && user.length() > 0 && + pass != null && pass.length() > 0) + get.addAuthorization(user, pass); + } + } + if (!url.toString().endsWith("/")) { + String minLastMod = RFC822Date.to822Date(_context.clock().now() - MAX_FILE_AGE); + get.addHeader("If-Modified-Since", minLastMod); + } + get.addStatusListener(ReseedRunner.this); + if (get.fetch() && get.getStatusCode() == 200) + return out; + out.delete(); + return null; + } + /** * @param name valid Base64 hash * @return true on success, false if skipped diff --git a/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java b/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java index 13b489d39..3fbfc381f 100644 --- a/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java +++ b/router/java/src/net/i2p/router/startup/LoadClientAppsJob.java @@ -43,7 +43,7 @@ public class LoadClientAppsJob extends JobImpl { return; } for(int i = 0; i < apps.size(); i++) { - ClientAppConfig app = (ClientAppConfig) apps.get(i); + ClientAppConfig app = apps.get(i); if (app.disabled) { if ("net.i2p.router.web.RouterConsoleRunner".equals(app.className)) { String s = "Warning - Router console is disabled. To enable,\n edit the file " + diff --git a/router/java/src/net/i2p/router/time/NtpClient.java b/router/java/src/net/i2p/router/time/NtpClient.java index 2b78263f1..4122ed9f9 100644 --- a/router/java/src/net/i2p/router/time/NtpClient.java +++ b/router/java/src/net/i2p/router/time/NtpClient.java @@ -70,7 +70,7 @@ class NtpClient { names.add(serverNames[i]); Collections.shuffle(names); for (int i = 0; i < names.size(); i++) { - long now = currentTime((String)names.get(i)); + long now = currentTime(names.get(i)); if (now > 0) return now; } @@ -92,7 +92,7 @@ class NtpClient { names.add(serverNames[i]); Collections.shuffle(names); for (int i = 0; i < names.size(); i++) { - long[] rv = currentTimeAndStratum((String)names.get(i)); + long[] rv = currentTimeAndStratum(names.get(i)); if (rv != null && rv[0] > 0) return rv; } diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index c9242305e..bc3ad9543 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -115,7 +115,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade { // Sum skew values long sum = 0; for (int i = first; i <= last; i++) { - long value = ((Long) (skews.get(i))).longValue(); + long value = skews.get(i).longValue(); //if (_log.shouldLog(Log.DEBUG)) // _log.debug("Adding clock skew " + i + " valued " + value + " s."); sum = sum + value; diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java index 0878ea7dc..0ad8d88a9 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java @@ -980,6 +980,11 @@ public class NTCPTransport extends TransportImpl { _log.info("old: " + ohost + " config: " + name + " auto: " + enabled + " ssuOK? " + ssuOK); if (enabled.equals("always") || (Boolean.parseBoolean(enabled) && ssuOK)) { + if (!ssuOK) { + if (_log.shouldLog(Log.WARN)) + _log.warn("null address with always config", new Exception()); + return; + } // ip non-null String nhost = Addresses.toString(ip); if (_log.shouldLog(Log.INFO)) diff --git a/router/java/src/net/i2p/router/transport/udp/MTU.java b/router/java/src/net/i2p/router/transport/udp/MTU.java index 641c12163..c6a2d1a2e 100644 --- a/router/java/src/net/i2p/router/transport/udp/MTU.java +++ b/router/java/src/net/i2p/router/transport/udp/MTU.java @@ -6,6 +6,8 @@ import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; +import net.i2p.I2PAppContext; +import net.i2p.util.Log; import net.i2p.util.SystemVersion; /** @@ -20,6 +22,12 @@ abstract class MTU { /** * The MTU for the socket interface, if available. * Not available for Java 5. + * + * Note that we don't return the value for the default interface if + * we can't find the address. Finding the default interface is hard, + * altough we could perhaps just look for the first non-loopback address. + * But the MTU of the default route probably isn't relevant. + * * @param ia null ok * @return 0 if Java 5, or if not bound to an address; * limited to range MIN_MTU to LARGE_MTU. @@ -43,7 +51,14 @@ abstract class MTU { // testing //return ifc.getMTU(); boolean isIPv6 = addr instanceof Inet6Address; - return rectify(isIPv6, ifc.getMTU()); + int mtu = ifc.getMTU(); + if ((isIPv6 && mtu < PeerState.MIN_IPV6_MTU) || + (!isIPv6 && mtu < PeerState.MIN_MTU)) { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(MTU.class); + log.logAlways(Log.WARN, "Unusually low MTU " + mtu + " for interface " + ia + + ", consider disabling"); + } + return rectify(isIPv6, mtu); } catch (SocketException se) { // ignore } catch (Throwable t) { diff --git a/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java b/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java index 3f03c133f..193c1751f 100644 --- a/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java +++ b/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java @@ -124,7 +124,7 @@ class TimedWeightedPriorityMessageQueue implements MessageQueue, OutboundMessage int currentQueue = (_nextQueue + i) % _queue.length; synchronized (_queue[currentQueue]) { for (int j = 0; j < _queue[currentQueue].size(); j++) { - OutNetMessage msg = (OutNetMessage)_queue[currentQueue].get(j); + OutNetMessage msg = _queue[currentQueue].get(j); Hash to = msg.getTarget().getIdentity().getHash(); if (_chokedPeers.contains(to)) continue; @@ -239,7 +239,7 @@ class TimedWeightedPriorityMessageQueue implements MessageQueue, OutboundMessage for (int i = 0; i < _queue.length; i++) { synchronized (_queue[i]) { for (int j = 0; j < _queue[i].size(); j++) { - OutNetMessage m = (OutNetMessage)_queue[i].get(j); + OutNetMessage m = _queue[i].get(j); if (m.getExpiration() < now) { _bytesQueued[i] -= m.getMessageSize(); removed.add(m); @@ -252,7 +252,7 @@ class TimedWeightedPriorityMessageQueue implements MessageQueue, OutboundMessage } for (int i = 0; i < removed.size(); i++) { - OutNetMessage m = (OutNetMessage)removed.get(i); + OutNetMessage m = removed.get(i); m.timestamp("expirer killed it"); _listener.failed(m, "expired before getting on the active pool"); } diff --git a/router/java/src/net/i2p/router/tunnel/BuildMessageGenerator.java b/router/java/src/net/i2p/router/tunnel/BuildMessageGenerator.java index 42aae3ce3..e2044305c 100644 --- a/router/java/src/net/i2p/router/tunnel/BuildMessageGenerator.java +++ b/router/java/src/net/i2p/router/tunnel/BuildMessageGenerator.java @@ -152,7 +152,7 @@ public abstract class BuildMessageGenerator { // encrypt the records so that the right elements will be visible at the right time for (int i = 0; i < msg.getRecordCount(); i++) { ByteArray rec = msg.getRecord(i); - Integer hopNum = (Integer)order.get(i); + Integer hopNum = order.get(i); int hop = hopNum.intValue(); if ( (isBlank(cfg, hop)) || (!cfg.isInbound() && hop == 1) ) { //if (log.shouldLog(Log.DEBUG)) diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java index 2142bee95..afe3940bf 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java @@ -593,7 +593,13 @@ class BuildHandler implements Runnable { long now = (_context.clock().now() / (60l*60l*1000l)) * (60*60*1000); int ourSlot = -1; - int response = _context.throttle().acceptTunnelRequest(); + int response; + if (_context.router().isHidden()) { + _context.throttle().setTunnelStatus(_x("Rejecting tunnels: Hidden mode")); + response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH; + } else { + response = _context.throttle().acceptTunnelRequest(); + } // This only checked OUR tunnels, so the log message was wrong. // Now checked by TunnelDispatcher.joinXXX() @@ -609,6 +615,7 @@ class BuildHandler implements Runnable { // response = TunnelHistory.TUNNEL_REJECT_PROBABALISTIC_REJECT; long recvDelay = _context.clock().now()-state.recvTime; + if (response == 0) { // unused //int proactiveDrops = countProactiveDrops(); diff --git a/router/java/src/net/i2p/router/util/EventLog.java b/router/java/src/net/i2p/router/util/EventLog.java index 1e6f166f8..086fbbdc5 100644 --- a/router/java/src/net/i2p/router/util/EventLog.java +++ b/router/java/src/net/i2p/router/util/EventLog.java @@ -144,4 +144,43 @@ public class EventLog { } return rv; } + + /** + * All events since a given time. + * Does not cache. Fails silently. + * Values in the returned map have the format "event[ info]". + * Events do not contain spaces. + * + * @param since since this time, 0 for all + * @return non-null, Map of times to info strings, sorted, earliest first, unmodifiable + * @since 0.9.14 + */ + public synchronized SortedMap getEvents(long since) { + SortedMap rv = new TreeMap(); + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader( + new FileInputStream(_file), "UTF-8")); + String line = null; + while ( (line = br.readLine()) != null) { + try { + String[] s = line.split(" ", 2); + if (s.length < 2) + continue; + long time = Long.parseLong(s[0]); + if (time <= since) + continue; + Long ltime = Long.valueOf(time); + rv.put(ltime, s[1]); + } catch (IndexOutOfBoundsException ioobe) { + } catch (NumberFormatException nfe) { + } + } + rv = Collections.unmodifiableSortedMap(rv); + } catch (IOException ioe) { + } finally { + if (br != null) try { br.close(); } catch (IOException ioe) {} + } + return rv; + } } diff --git a/tests/scripts/checkcerts.sh b/tests/scripts/checkcerts.sh index 60fe6537a..55820a213 100755 --- a/tests/scripts/checkcerts.sh +++ b/tests/scripts/checkcerts.sh @@ -95,7 +95,7 @@ checkcert() { # Certtool's format: Mon Mar 07 16:08:35 UTC 2022 DATA=$(certtool -i < "$1" | sed -e '/Not\sAfter/!d' -e 's/^.*:\s\(.*\)/\1/') # The formatting is normalized for passing to the date2julian function (if needed) - set -- `echo $DATA` + set -- $DATA DATA="$2 $3 $4 $6 GMT" fi echo $DATA @@ -128,7 +128,7 @@ compute_dates() { SECS=$(date -u -d "$EXPIRES" '+%s') DAYS="$(expr \( $SECS - $NOW \) / 86400)" else - set -- `echo $EXPIRES` + set -- $EXPIRES # date2julian needs the format mm dd yyyy SECS=$(date2julian `getmonth $1` $2 $4) DAYS=$(expr $SECS - $NOW) diff --git a/tests/scripts/checkpo.sh b/tests/scripts/checkpo.sh index 7e29b3f82..8979dc1b3 100755 --- a/tests/scripts/checkpo.sh +++ b/tests/scripts/checkpo.sh @@ -16,6 +16,7 @@ DIRS="\ apps/i2ptunnel/locale \ apps/i2ptunnel/locale-proxy \ apps/i2psnark/locale \ + apps/ministreaming/locale \ apps/susidns/locale \ apps/susimail/locale \ apps/desktopgui/locale \ diff --git a/tests/scripts/checkremotecerts.sh b/tests/scripts/checkremotecerts.sh index cf48848f2..87e212f99 100755 --- a/tests/scripts/checkremotecerts.sh +++ b/tests/scripts/checkremotecerts.sh @@ -4,7 +4,7 @@ set -u BASEDIR="$(dirname $0)/../../" cd "$BASEDIR" -RESEEDHOSTS=$(sed -e '/\s\+"https:\/\/[-a-z0-9.]/!d' -e 's/.*"https:\/\/\([-a-z0-9.]\+\).*/\1/' router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java) +RESEEDHOSTS=$(sed -e '/^\s\+"https:\/\/[-a-z0-9.]/!d' -e 's/.*"https:\/\/\([-a-z0-9.:]\+\).*/\1/' router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java) CERTHOME="installer/resources/certificates" CACERTS=$(mktemp) WORK=$(mktemp -d) @@ -81,9 +81,9 @@ normalize(){ connect() { if [ $OPENSSL -eq 1 ]; then - $OPENSSL_BIN s_client -connect "$1:443" -CAfile $CACERTS -servername $1 < /dev/null 2> /dev/null + $OPENSSL_BIN s_client -connect "$1:$2" -CAfile $CACERTS -servername $1 < /dev/null 2> /dev/null else - $GNUTLS_BIN --insecure --print-cert --x509cafile "$CACERTS" "$1" < /dev/null 2>/dev/null + $GNUTLS_BIN --insecure --print-cert --x509cafile "$CACERTS" "$1" -p "$2" < /dev/null 2>/dev/null fi } @@ -119,8 +119,20 @@ cleanup() { check_hosts() { for HOST in $RESEEDHOSTS; do - echo -n "Checking $HOST..." - if retry connect "$HOST" < /dev/null 1> "$WORK/$HOST"; then + if $(echo $HOST | grep -q ':'); then + OLDIFS=$IFS + IFS=":" + set -- $HOST + HOSTNAME=$1 + PORT=$2 + IFS=$OLDIFS + else + HOSTNAME=$HOST + PORT=443 + fi + + echo -n "Checking $HOSTNAME:$PORT..." + if retry connect "$HOSTNAME" "$PORT" < /dev/null 1> "$WORK/$HOST"; then # OpenSSL returns "return code: 0 (ok)" # GnuTLS returns "certificate is trusted" diff --git a/tests/scripts/checkutf8.sh b/tests/scripts/checkutf8.sh index cc99a569f..fa325036d 100755 --- a/tests/scripts/checkutf8.sh +++ b/tests/scripts/checkutf8.sh @@ -19,6 +19,7 @@ DIRS="\ apps/i2ptunnel/locale \ apps/i2ptunnel/locale-proxy \ apps/i2psnark/locale \ + apps/ministreaming/locale \ apps/susidns/locale \ apps/susimail/locale \ apps/desktopgui/locale \