propagate from branch 'i2p.i2p' (head e02e6d733a703970e20e732e5156cbabc394e88e)

to branch 'i2p.i2p.str4d.eddsa' (head 3910d01bed7c5a216f52bfd1d9fd96b59f058745)
This commit is contained in:
str4d
2014-07-10 09:29:34 +00:00
152 changed files with 2430 additions and 1328 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -194,9 +194,8 @@ public class Peer implements Comparable<Peer>
* 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;

View File

@@ -62,7 +62,7 @@ class TrackerInfo
private TrackerInfo(Map<String, BEValue> 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)

View File

@@ -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<String, String[]>) 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 ? "" : "&amp;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);

View File

@@ -25,6 +25,7 @@
<isfalse value="${require.gettext}" />
</condition>
<!-- only used if not set by a higher build.xml -->
<property name="javac.compilerargs" value="" />
<property name="javac.version" value="1.6" />
<property name="require.gettext" value="true" />
@@ -34,7 +35,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true" deprecation="on" source="1.5" target="1.5"
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
destdir="./build/obj"
includeAntRuntime="false"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" >
@@ -281,7 +282,7 @@
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<!-- We need the ant runtime, as it includes junit -->
<javac srcdir="./src:./test/junit" debug="true" source="1.5" target="1.5"
<javac srcdir="./src:./test/junit" debug="true" source="${javac.version}" target="${javac.version}"
includeAntRuntime="true"
deprecation="on" destdir="./build/obj" >
<compilerarg line="${javac.compilerargs}" />

View File

@@ -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 =

View File

@@ -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,

View File

@@ -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

View File

@@ -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() {

View File

@@ -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<I2PSession> 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;

View File

@@ -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() {

View File

@@ -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();
}

View File

@@ -440,7 +440,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
</div>
<div id="destinationField" class="rowItem">
<label><%=intl._("Local Base 32")%>:</label>
<%=editBean.getDestHashBase32(curTunnel)%>.b32.i2p
<%=editBean.getDestHashBase32(curTunnel)%>
</div>
<% } // if destb64 %>

View File

@@ -134,10 +134,10 @@
<%
if (("httpserver".equals(indexBean.getInternalType(curServer)) || ("httpbidirserver".equals(indexBean.getInternalType(curServer)))) && indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
%><label><%=intl._("Preview")%>:</label>
<a class="control" title="Test HTTP server through I2P" href="http://<%=indexBean.getDestHashBase32(curServer)%>.b32.i2p" target="_top"><%=intl._("Preview")%></a>
<a class="control" title="Test HTTP server through I2P" href="http://<%=indexBean.getDestHashBase32(curServer)%>" target="_top"><%=intl._("Preview")%></a>
<%
} else if (indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
%><span class="text"><%=intl._("Base32 Address")%>:<br /><%=indexBean.getDestHashBase32(curServer)%>.b32.i2p</span>
%><span class="text"><%=intl._("Base32 Address")%>:<br /><%=indexBean.getDestHashBase32(curServer)%></span>
<%
} else {
%><span class="comment"><%=intl._("No Preview")%></span>

View File

@@ -19,12 +19,21 @@
</classpath>
</depend>
</target>
<!-- only used if not set by a higher build.xml -->
<property name="javac.compilerargs" value="" />
<property name="javac.version" value="1.6" />
<property name="require.gettext" value="true" />
<condition property="no.bundle">
<isfalse value="${require.gettext}" />
</condition>
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<!-- half of this is deprecated classes so turn deprecation off -->
<javac srcdir="./src" debug="true" deprecation="off" source="1.5" target="1.5"
<javac srcdir="./src" debug="true" deprecation="off" source="${javac.version}" target="${javac.version}"
includeAntRuntime="false"
destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" >
<compilerarg line="${javac.compilerargs}" />
@@ -36,7 +45,7 @@
<mkdir dir="./buildTest/obj" />
<javac
srcdir="./test/junit"
debug="true" deprecation="on" source="1.5" target="1.5"
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
includeAntRuntime="false"
destdir="./buildTest/obj"
classpath="../../../core/java/build/i2p.jar:./build/mstreaming.jar" >
@@ -62,7 +71,7 @@
</exec>
</target>
<target name="jar" depends="compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
<target name="jar" depends="compile, bundle, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" >
@@ -89,6 +98,35 @@
</and>
</condition>
</target>
<target name="bundle" depends="compile" unless="no.bundle">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="windows" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
</target>
<target name="poupdate" depends="builddep, compile">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="windows" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
</target>
<target name="javadoc">
<mkdir dir="./build" />

View File

@@ -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

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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 ""

View File

@@ -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) {

View File

@@ -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<String, String> _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<String, String>(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 <head>.
// So just use the "shared/console nonce".
String nonce = CSSHelper.getNonce();
try {
_out.write("<br><h3>" + _("Display Events") + "</h3>");
_out.write("<form action=\"events\" method=\"POST\">\n" +
"<input type=\"hidden\" name=\"action\" value=\"save\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
_out.write(_("Events since") + ": <select name=\"from\">");
for (int i = 0; i < _times.length; i++) {
writeOption(_times[i]);
}
_out.write("</select><br>");
_out.write(_("Event type") + ": <select name=\"type\">");
// sorted by translated display string
Map<String, String> events = new TreeMap<String, String>(Collator.getInstance());
for (int i = 0; i < _events.length; i += 2) {
events.put(_xevents.get(_events[i]), _events[i]);
}
writeOption(_("All events"), ALL);
for (Map.Entry<String, String> e : events.entrySet()) {
writeOption(e.getKey(), e.getValue());
}
_out.write("</select>" +
"<hr><div class=\"formaction\"><input type=\"submit\" class=\"accept\" value=\"" + _("Filter events") + "\"></div></form>");
} catch (IOException ioe) {
ioe.printStackTrace();
}
return "";
}
private void writeOption(String key, String val) throws IOException {
_out.write("<option value=\"");
_out.write(val);
_out.write("\"");
if (val.equals(_event))
_out.write(" selected=\"selected\"");
_out.write(">");
_out.write(key);
_out.write("</option>\n");
}
private void writeOption(long age) throws IOException {
_out.write("<option value=\"");
_out.write(Long.toString(age));
_out.write("\"");
if (age == _age)
_out.write(" selected=\"selected\"");
_out.write(">");
if (age == 0)
_out.write(_("All events"));
else
_out.write(DataHelper.formatDuration2(age));
_out.write("</option>\n");
}
public String getEvents() {
EventLog ev = _context.router().eventLog();
// oldest first
Map<Long, String> 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("<table><tr><th>");
buf.append(_("Time"));
buf.append("</th><th>");
if (isAll) {
buf.append(_("Event"));
buf.append("</th><th>");
buf.append(_("Details"));
} else {
buf.append(xev);
}
buf.append("</th></tr>");
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<Map.Entry<Long, String>> entries = new ArrayList<Map.Entry<Long, String>>(events.entrySet());
Collections.reverse(entries);
for (Map.Entry<Long, String> e : entries) {
long time = e.getKey().longValue();
String event = e.getValue();
buf.append("<tr><td>");
buf.append(fmt.format(new Date(time)));
buf.append("</td><td>");
if (isAll) {
String[] s = event.split(" ", 2);
String xs = _xevents.get(s[0]);
if (xs == null)
xs = s[0];
buf.append(xs);
buf.append("</td><td>");
if (s.length > 1)
buf.append(s[1]);
} else {
buf.append(event);
}
buf.append("</td></tr>");
}
buf.append("</table>");
return buf.toString();
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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 +

View File

@@ -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: <b>").append(fmt.format(biLog2(dist))).append("</b><br>");
buf.append(Base32.encode(key.getData())).append(".b32.i2p<br>");
buf.append(dest.toBase32()).append("<br>");
buf.append("Sig type: ").append(dest.getSigningPublicKey().getType()).append("<br>");
buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64());
buf.append("<br>");

View File

@@ -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++;

View File

@@ -0,0 +1,28 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<%@include file="css.jsi" %>
<%=intl.title("events")%>
<jsp:useBean class="net.i2p.router.web.EventLogHelper" id="eventHelper" scope="request" />
<jsp:setProperty name="eventHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
<jsp:setProperty name="eventHelper" property="*" />
<%
eventHelper.storeWriter(out);
eventHelper.storeMethod(request.getMethod());
%>
<script src="/js/ajax.js" type="text/javascript"></script>
<%@include file="summaryajax.jsi" %>
</head><body onload="initAjax()">
<%@include file="summary.jsi" %>
<h1><%=intl._("I2P Event Log")%></h1>
<div class="main" id="main">
<div class="eventspanel">
<div class="widepanel">
<jsp:getProperty name="eventHelper" property="allMessages" />
<jsp:getProperty name="eventHelper" property="form" />
<jsp:getProperty name="eventHelper" property="events" />
</div></div></div></body></html>

View File

@@ -37,10 +37,10 @@
<p><%=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.")%></p>
<h3><%=intl._("Critical Logs")%></h3><a name="criticallogs"> </a>
<jsp:getProperty name="logsHelper" property="criticalLogs" />
<hr>
<h3><%=intl._("Router Logs")%> (<a href="configlogging"><%=intl._("configure")%></a>)</h3>
<jsp:getProperty name="logsHelper" property="logs" />
<hr>
<h3><%=intl._("Event Logs")%></h3>
<a href="events"><%=intl._("View event logs")%></a>
<h3><%=intl._("Service (Wrapper) Logs")%></h3><a name="servicelogs"> </a>
<jsp:getProperty name="logsHelper" property="serviceLogs" />
</div><hr></div></body></html>
</div></div></body></html>

View File

@@ -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) {}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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());

View File

@@ -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!");

View File

@@ -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;
}

View File

@@ -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 );
}
}

View File

@@ -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);

View File

@@ -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<String, SessionRecord> map;
@@ -259,14 +271,15 @@ public class SAMv3Handler extends SAMv1Handler
map = new HashMap<String, SessionRecord>() ;
}
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) {

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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();
}
}
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -20,13 +20,17 @@
</classpath>
</depend>
</target>
<!-- only used if not set by a higher build.xml -->
<property name="javac.compilerargs" value="" />
<property name="javac.version" value="1.6" />
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true" deprecation="on" source="1.5" target="1.5"
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
includeAntRuntime="false"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" >
@@ -51,7 +55,7 @@
<javac
srcdir="./test/junit"
debug="true" deprecation="on" source="1.5" target="1.5"
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
includeAntRuntime="false"
destdir="./build/obj" >
<classpath>

View File

@@ -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();
}
}

View File

@@ -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() {

View File

@@ -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;
}
/**

View File

@@ -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;
}
}
}
}

View File

@@ -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;

View File

@@ -74,7 +74,7 @@ class StandardServerSocket extends ServerSocket {
}
/**
* @return null always, see AcceptingChannelImpl for more info
* @return null always, unimplemented
*/
@Override
public ServerSocketChannel getChannel() {

View File

@@ -68,7 +68,7 @@ class StandardSocket extends Socket {
}
/**
* @return null always, see MessageChannel for more info
* @return null always, unimplemented
*/
@Override
public SocketChannel getChannel() {

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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"))

254
build.xml
View File

@@ -67,6 +67,54 @@
<echo message="Once the dependencies are installed, run &quot;ant debian&quot;"/>
<echo message="to patch the source and build the packages." />
</target>
<macrodef name="gpgsign">
<attribute name="file" />
<sequential>
<delete file="@{file}.sig" quiet="true" />
<exec executable="gpg" failonerror="true">
<arg value="--default-key" />
<arg value="${release.gpg.keyid}" />
<arg value="-b" />
<arg value="@{file}" />
</exec>
<chmod type="file" perm="444">
<fileset dir="${basedir}">
<include name="@{file} @{file}.sig" />
</fileset>
</chmod>
</sequential>
</macrodef>
<macrodef name="mktorrent">
<attribute name="file" />
<sequential>
<delete file="@{file}.torrent" quiet="true"/>
<java classname="org.klomp.snark.Storage" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/i2psnark.jar" />
</classpath>
<arg value="@{file}" />
<arg value="http://tracker2.postman.i2p/announce.php" />
</java>
</sequential>
</macrodef>
<macrodef name="sha256sum">
<attribute name="file" />
<sequential>
<!--
Note: "local" only works with ant 1.8+. This limitation shouldn't be
a big deal since this macro is only called by the release
target.
-->
<local name="file-sum"/>
<checksum format="MD5SUM" file="@{file}" property="file-sum" algorithm="sha-256"/>
<echo message="${file-sum} @{file}" />
</sequential>
</macrodef>
<target name="dist" depends="pkg, javadoc" />
<target name="dist200" depends="pkg200, javadoc" />
<target name="build" depends="build2">
@@ -91,22 +139,28 @@
<target name="buildBOB" depends="buildStreaming" >
<ant dir="apps/BOB/" target="jar" />
<copy file="apps/BOB/dist/BOB.jar" todir="build/" />
</target>
<target name="buildSAM" depends="buildStreaming" >
<ant dir="apps/sam/java/" target="jar" />
<copy file="apps/sam/java/build/sam.jar" todir="build/" />
</target>
<target name="buildSusiMail" depends="buildCore, buildJetty" >
<ant dir="apps/susimail/" target="war" />
<copy file="apps/susimail/susimail.war" todir="build/" />
</target>
<target name="buildSusiDNS" depends="buildCore, buildJetty" >
<ant dir="apps/susidns/src" target="all" />
<copy file="apps/susidns/src/susidns.war" todir="build/" />
</target>
<target name="buildI2PSnark" depends="buildStreaming, buildJetty" >
<ant dir="apps/i2psnark/java/" target="war" />
<copy file="apps/i2psnark/i2psnark.war" todir="build/" />
<copy file="apps/i2psnark/java/build/i2psnark.jar" todir="build/" />
</target>
<!-- jar (not war) for Android -->
@@ -116,15 +170,19 @@
<target name="buildAddressbook" depends="buildCore, buildJetty" >
<ant dir="apps/addressbook/" target="war" />
<copy file="apps/addressbook/dist/addressbook.war" todir="build/" />
</target>
<!-- jar only (no war) for Android -->
<target name="buildI2PTunnelJar" depends="buildStreaming" >
<ant dir="apps/i2ptunnel/java/" target="jar" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.jar" todir="build/" />
</target>
<target name="buildI2PTunnel" depends="buildStreaming, buildJetty" >
<ant dir="apps/i2ptunnel/java/" target="build" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.jar" todir="build/" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.war" todir="build/" />
</target>
<target name="buildDesktopGui" depends="buildCore, buildrouter" >
@@ -132,6 +190,7 @@
<ant dir="apps/desktopgui" target="clean" />
-->
<ant dir="apps/desktopgui" target="jar" />
<copy file="apps/desktopgui/dist/desktopgui.jar" todir="build/" />
</target>
<target name="buildRouterConsole" depends="buildrouter, buildSystray, buildDesktopGui, buildJetty" >
@@ -140,18 +199,24 @@
<target name="buildJetty" depends="buildCore" >
<ant dir="apps/jetty" target="build" />
<copy todir="build/" >
<fileset dir="apps/jetty/jettylib" excludes="ant.jar" />
</copy>
</target>
<target name="buildSystray" depends="buildCore" >
<ant dir="apps/systray/java/" target="jar" />
<copy file="apps/systray/java/build/systray.jar" todir="build/" />
</target>
<target name="buildStreaming" depends="buildMinistreaming" >
<ant dir="apps/streaming/java/" target="jar" />
<copy file="apps/streaming/java/build/streaming.jar" todir="build/" />
</target>
<target name="buildMinistreaming" depends="buildCore" >
<ant dir="apps/ministreaming/java/" target="jar" />
<copy file="apps/ministreaming/java/build/mstreaming.jar" todir="build/" />
</target>
<target name="buildRouter" depends="buildrouter" />
@@ -174,10 +239,27 @@
<attribute name="Built-By" value="${build.built-by}" />
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
</manifest>
</manifest>
</jar>
</target>
<target name="buildProperties" depends="getMtnRev, getReleaseNumber, getBuildNumber" >
<!-- default if not set above -->
<property name="workspace.version" value="unknown" />
<tstamp>
<format property="build.timestamp" pattern="yyyy-MM-dd HH:mm:ss z" timezone="UTC" locale="en" />
</tstamp>
<property name="full.version" value="${release.number}-${i2p.build.number}${build.extra}" />
<echo message="Building version ${full.version} (mtn rev ${workspace.version})" />
</target>
<target name="buildWEB" depends="buildRouterConsole" >
<copy file="apps/routerconsole/java/build/routerconsole.jar" todir="build/" />
<copy file="apps/routerconsole/java/build/routerconsole.war" todir="build/" />
</target>
<!-- end of sub-build.xml targets -->
<target name="checkForMtn" >
<available property="mtn.available" file="_MTN" type="dir" />
</target>
@@ -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};'/>
</target>
<target name="buildProperties" depends="getMtnRev, getReleaseNumber, getBuildNumber" >
<!-- default if not set above -->
<property name="workspace.version" value="unknown" />
<tstamp>
<format property="build.timestamp" pattern="yyyy-MM-dd HH:mm:ss z" timezone="UTC" locale="en" />
</tstamp>
<property name="full.version" value="${release.number}-${i2p.build.number}${build.extra}" />
<echo message="Building version ${full.version} (mtn rev ${workspace.version})" />
</target>
<!-- end of sub-build.xml targets -->
<target name="buildWEB" depends="buildRouterConsole" >
<copy file="apps/routerconsole/java/build/routerconsole.jar" todir="build/" />
<copy file="apps/routerconsole/java/build/routerconsole.war" todir="build/" />
<copy todir="build/" >
<fileset dir="apps/jetty/jettylib" excludes="ant.jar" />
</copy>
</target>
<condition property="noExe">
<not>
<!-- We only have launch4j binaries for the following systems -->
@@ -298,25 +360,17 @@
classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" />
</target>
<target name="jar" depends="jarSmall" >
<copy file="apps/BOB/dist/BOB.jar" todir="build/" />
<copy file="apps/sam/java/build/sam.jar" todir="build/" />
<copy file="apps/susimail/susimail.war" todir="build/" />
<copy file="apps/susidns/src/susidns.war" todir="build/" />
<copy file="apps/i2psnark/i2psnark.war" todir="build/" />
<copy file="apps/i2psnark/java/build/i2psnark.jar" todir="build/" />
<!--
the files are now copied to the build directory
in the build* targets
-->
<target name="jar" depends="jarSmall" />
<target name="jarSmall" depends="builddepSmall, buildJrobin" />
</target>
<target name="jarSmall" depends="builddepSmall, buildJrobin" >
<copy file="core/java/build/i2p.jar" todir="build/" />
<copy file="router/java/build/router.jar" todir="build/" />
<copy file="apps/ministreaming/java/build/mstreaming.jar" todir="build/" />
<copy file="apps/streaming/java/build/streaming.jar" todir="build/" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.jar" todir="build/" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.war" todir="build/" />
<copy file="apps/systray/java/build/systray.jar" todir="build/" />
<copy file="apps/desktopgui/dist/desktopgui.jar" todir="build/" />
<copy file="apps/addressbook/dist/addressbook.war" todir="build/" />
<!-- Custom target to collect the jars that I2P-Bote needs to compile, so it can compile from source. -->
<target name="jarBote" depends="buildRouter, buildStreaming, buildJetty" >
<copy file="apps/susidns/src/WEB-INF/lib/jstl.jar" todir="build/" />
<copy file="apps/susidns/src/WEB-INF/lib/standard.jar" todir="build/" />
</target>
<target name="jbigi-list-changes" depends="checkForMtn" if="mtn.available">
@@ -466,6 +520,7 @@
<ant dir="apps/susimail/" target="poupdate" />
<ant dir="apps/desktopgui" target="poupdate" />
<ant dir="installer/resources/locale" target="poupdate" />
<ant dir="apps/ministreaming/" target="poupdate" />
</target>
<condition property="no.bundle">
@@ -543,8 +598,8 @@
<pathelement location="apps/jrobin/jrobin-1.5.9.1.jar" />
<pathelement location="installer/lib/wrapper/all/wrapper.jar" />
</classpath>
<!-- These variables are stored in build.properties.
End-users can override by creating the file override.properties -->
<!-- These variables are stored in build.properties.
End-users can override by creating the file override.properties -->
<link offline="true" href="${javasedocs.url}" packagelistLoc="installer/resources/package-lists/java/" />
<link offline="true" href="${javaeedocs.url}" packagelistLoc="installer/resources/package-lists/javaee/" />
<link offline="true" href="${jettydocs.url}" packagelistLoc="installer/resources/package-lists/jetty/" />
@@ -552,7 +607,9 @@
<link offline="true" href="${wrapperdocs.url}" packagelistLoc="installer/resources/package-lists/wrapper/" />
</javadoc>
<echo message="Warning, javadoc embeds timestamps in the output, run with 'TZ=UTC ant javadoc' if you plan to distribute" />
<zip destfile="javadoc.zip" basedir="build" level="9" includes="javadoc\**" />
</target>
<target name="javadoc-zip" depends="javadoc">
<zip destfile="javadoc.zip" basedir="build" level="9" includes="javadoc\**" />
</target>
<target name="javadoc-test" depends="buildRouter, javadoc" >
@@ -580,8 +637,10 @@
<pathelement location="build/router.jar" />
<pathelement location="${junit.home}/junit4.jar" />
</classpath>
<!-- These variables are stored in build.properties.
End-users can override by creating the file override.properties -->
<!--
These variables are stored in build.properties.
End-users can override by creating the file override.properties
-->
<link offline="true" href="${javasedocs.url}" packagelistLoc="installer/resources/package-lists/java/" />
<link offline="true" href="${junitdocs.url}" packagelistLoc="installer/resources/package-lists/junit/" />
<link offline="true" href="${i2pdocs.url}" packagelistLoc="build/javadoc/" />
@@ -696,7 +755,7 @@
<target name="distclean" depends="clean">
<delete failonerror="false" quiet="true">
<fileset dir="." includes="i2pinstall* *.deb i2p_*.bz2 i2pupdate* i2psource*" />
<fileset dir="." includes="i2pinstall* *.deb i2p_*.bz2 i2pupdate* i2psource* *.sig *.torrent" />
</delete>
<ant dir="core/java/" target="distclean" />
<ant dir="router/java/" target="distclean" />
@@ -1321,7 +1380,7 @@
<izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
<ant target="installerexe" />
<delete file="${basedir}/install.jar" />
<move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows-only.exe" />
<move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows.exe" />
</target>
<!-- this is broken as installer-xxx targets may delete (or not delete) things in pkg-temp -->
@@ -1501,11 +1560,11 @@
<!--
<target name="release" depends="distclean, updaterWithJettyFixesAndJbigi , updater200WithJettyFixes, preppkg, installer, getReleaseNumber" >
-->
<target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyRepack, updater200WithJetty, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows" >
<target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyRepack, updater200WithJetty, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows">
<echo message="New version number is ${release.number}" />
<copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" />
<copy file="i2pinstall_${full.version}_windows-only.exe" tofile="i2pinstall_${release.number}_windows.exe" />
<copy file="i2pinstall_${full.version}.jar" tofile="i2pinstall_${release.number}.jar" />
<copy file="i2pinstall_${full.version}_windows.exe" tofile="i2pinstall_${release.number}_windows.exe" />
<delete file="i2pupdate.sud" />
<delete file="i2pupdate.su2" />
<!-- make this a lot easier by putting release.privkey=/path/to/privkey in override.properties -->
@@ -1671,48 +1730,20 @@
<equals arg1="${release.gpg.keyid}" arg2=""/>
</condition>
</fail>
<delete file="i2pinstall_${release.number}_windows.exe.sig" />
<delete file="i2pinstall_${release.number}.jar.sig" />
<delete file="i2psource_${release.number}.tar.bz2.sig" />
<delete file="i2pupdate_${release.number}.zip.sig" />
<exec executable="gpg" failonerror="true">
<arg value="--default-key" />
<arg value="${release.gpg.keyid}" />
<arg value="-b" />
<arg value="i2pinstall_${release.number}_windows.exe" />
</exec>
<exec executable="gpg" failonerror="true">
<arg value="--default-key" />
<arg value="${release.gpg.keyid}" />
<arg value="-b" />
<arg value="i2pinstall_${release.number}.jar" />
</exec>
<exec executable="gpg" failonerror="true">
<arg value="--default-key" />
<arg value="${release.gpg.keyid}" />
<arg value="-b" />
<arg value="i2psource_${release.number}.tar.bz2" />
</exec>
<exec executable="gpg" failonerror="true">
<arg value="--default-key" />
<arg value="${release.gpg.keyid}" />
<arg value="-b" />
<arg value="i2pupdate_${release.number}.zip" />
</exec>
<exec executable="chmod" failonerror="true">
<arg value="444" />
<arg value="i2pinstall_${release.number}_windows.exe" />
<arg value="i2pinstall_${release.number}.jar" />
<arg value="i2psource_${release.number}.tar.bz2" />
<arg value="i2pupdate_${release.number}.zip" />
<arg value="i2pupdate.su2" />
<arg value="i2pupdate.su3" />
<arg value="i2pupdate.sud" />
<arg value="i2pinstall_${release.number}_windows.exe.sig" />
<arg value="i2pinstall_${release.number}.jar.sig" />
<arg value="i2psource_${release.number}.tar.bz2.sig" />
<arg value="i2pupdate_${release.number}.zip.sig" />
</exec>
<!-- the gpgsign macro sets the permission of signed files and the sigs themselves to 444 -->
<gpgsign file="i2pinstall_${release.number}_windows.exe" />
<gpgsign file="i2pinstall_${release.number}.jar" />
<gpgsign file="i2psource_${release.number}.tar.bz2" />
<gpgsign file="i2pupdate_${release.number}.zip" />
<chmod perm="444" type="file">
<fileset dir="${basedir}">
<include name="i2pupdate.su2" />
<include name="i2pupdate.su3" />
<include name="i2pupdate.sud" />
</fileset>
</chmod>
<echo message="File sizes:" />
<exec executable="ls" failonerror="true">
<arg value="-l" />
@@ -1729,43 +1760,20 @@
<arg value="i2pupdate_${release.number}.zip.sig" />
</exec>
<echo message="SHA256 sums:" />
<exec executable="sha256sum" failonerror="true">
<arg value="i2pinstall_${release.number}_windows.exe" />
<arg value="i2pinstall_${release.number}.jar" />
<arg value="i2psource_${release.number}.tar.bz2" />
<arg value="i2pupdate_${release.number}.zip" />
<arg value="i2pupdate.su2" />
<arg value="i2pupdate.su3" />
<arg value="i2pupdate.sud" />
</exec>
<sha256sum file="i2pinstall_${release.number}_windows.exe" />
<sha256sum file="i2pinstall_${release.number}.jar" />
<sha256sum file="i2psource_${release.number}.tar.bz2" />
<sha256sum file="i2pupdate_${release.number}.zip" />
<sha256sum file="i2pupdate.su2" />
<sha256sum file="i2pupdate.su3" />
<sha256sum file="i2pupdate.sud" />
<!-- make torrent files -->
<copy file="i2pupdate.sud" tofile="i2pupdate-${release.number}.sud" />
<java classname="org.klomp.snark.Storage" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/i2psnark.jar" />
</classpath>
<arg value="i2pupdate-${release.number}.sud" />
<arg value="http://tracker2.postman.i2p/announce.php" />
</java>
<mktorrent file="i2pupdate-${release.number}.sud" />
<copy file="i2pupdate.su2" tofile="i2pupdate-${release.number}.su2" />
<java classname="org.klomp.snark.Storage" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/i2psnark.jar" />
</classpath>
<arg value="i2pupdate-${release.number}.su2" />
<arg value="http://tracker2.postman.i2p/announce.php" />
</java>
<mktorrent file="i2pupdate-${release.number}.su2" />
<copy file="i2pupdate.su3" tofile="i2pupdate-${release.number}.su3" />
<java classname="org.klomp.snark.Storage" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/i2psnark.jar" />
</classpath>
<arg value="i2pupdate-${release.number}.su3" />
<arg value="http://tracker2.postman.i2p/announce.php" />
</java>
<mktorrent file="i2pupdate-${release.number}.su3" />
<echo message="Don't forget to mtn tag w: i2p-${release.number}" />
<echo message="... and mtn cert t:i2p-${release.number} branch i2p.i2p.release" />
</target>

View File

@@ -15,13 +15,16 @@
destdir="./build/obj" >
</depend>
</target>
<!-- only used if not set by a higher build.xml -->
<property name="javac.compilerargs" value="" />
<property name="javac.classpath" value="" />
<property name="javac.version" value="1.6" />
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" source="1.5" target="1.5" deprecation="on"
<javac srcdir="./src" debug="true" source="${javac.version}" target="${javac.version}" deprecation="on"
debuglevel="lines,vars,source"
includeAntRuntime="false"
destdir="./build/obj" classpath="${javac.classpath}" >
@@ -103,7 +106,7 @@
<!-- set hamcrest and junit homes to the old default unless overridden elsewhere -->
<property name="hamcrest.home" value="${ant.home}/lib/" />
<property name="junit.home" value="${ant.home}/lib/" />
<javac srcdir="./test/junit" debug="true" source="1.5" target="1.5" deprecation="on"
<javac srcdir="./test/junit" debug="true" source="${javac.version}" target="${javac.version}" deprecation="on"
debuglevel="lines,vars,source"
includeAntRuntime="true"
destdir="./build/obj" >

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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)

View File

@@ -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,

View File

@@ -210,7 +210,7 @@ public enum SigType {
return getByCode(code);
} catch (NumberFormatException nfe) {
return null;
}
}
}
}
}

View File

@@ -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 <inFile> <outFile>");
System.out.println("or : Base64 encode <inFile>");
System.out.println("or : Base64 encode");
System.out.println("or : Base64 decode <inFile> <outFile>");
System.out.println("or : Base64 decode <inFile>");
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 <inFile> <outFile>");
System.err.println(" Base64 encode <inFile>");
System.err.println(" Base64 encode (stdin to stdout)");
System.err.println(" Base64 decode <inFile> <outFile>");
System.err.println(" Base64 decode <inFile>");
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
* <code>new String( decode( s ) )</code>
* 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;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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
*</pre>
*
@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -15,13 +15,16 @@
destdir="./build/obj" >
</depend>
</target>
<!-- only used if not set by a higher build.xml -->
<property name="javac.compilerargs" value="" />
<property name="javac.classpath" value="" />
<property name="javac.version" value="1.6" />
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" source="1.5" target="1.5" deprecation="on"
<javac srcdir="./src" debug="true" source="${javac.version}" target="${javac.version}" deprecation="on"
includeAntRuntime="false"
destdir="./build/obj" classpath="${javac.classpath}:../../core/java/build/obj" >
<compilerarg line="${javac.compilerargs}" />

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More