forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p' (head e02e6d733a703970e20e732e5156cbabc394e88e)
to branch 'i2p.i2p.str4d.eddsa' (head 3910d01bed7c5a216f52bfd1d9fd96b59f058745)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ? "" : "&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);
|
||||
|
||||
@@ -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}" />
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 %>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
112
apps/ministreaming/java/bundle-messages.sh
Executable file
112
apps/ministreaming/java/bundle-messages.sh
Executable 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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
85
apps/ministreaming/locale/messages_en.po
Normal file
85
apps/ministreaming/locale/messages_en.po
Normal 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 ""
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -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>");
|
||||
|
||||
@@ -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++;
|
||||
|
||||
28
apps/routerconsole/jsp/events.jsp
Normal file
28
apps/routerconsole/jsp/events.jsp
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -74,7 +74,7 @@ class StandardServerSocket extends ServerSocket {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null always, see AcceptingChannelImpl for more info
|
||||
* @return null always, unimplemented
|
||||
*/
|
||||
@Override
|
||||
public ServerSocketChannel getChannel() {
|
||||
|
||||
@@ -68,7 +68,7 @@ class StandardSocket extends Socket {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null always, see MessageChannel for more info
|
||||
* @return null always, unimplemented
|
||||
*/
|
||||
@Override
|
||||
public SocketChannel getChannel() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
254
build.xml
@@ -67,6 +67,54 @@
|
||||
<echo message="Once the dependencies are installed, run "ant debian""/>
|
||||
<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>
|
||||
|
||||
@@ -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" >
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -210,7 +210,7 @@ public enum SigType {
|
||||
return getByCode(code);
|
||||
} catch (NumberFormatException nfe) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
39
history.txt
39
history.txt
@@ -1,3 +1,42 @@
|
||||
2014-07-03 zzz
|
||||
* Base64:
|
||||
- Catch numerous decoding errors that were previously misdecoded (ticket #1318)
|
||||
- Improve decoding efficiency, reduce copies
|
||||
- encode(String) now uses UTF-8 encoding
|
||||
- decode() now accepts short strings without trailing '='
|
||||
- whitespace in decode will now cause an error, was previously ignored
|
||||
* Console: Add event log viewer (ticket #1117)
|
||||
|
||||
2014-07-02 kytv
|
||||
* Update Java Service Wrapper to v3.5.25
|
||||
- Windows: x86 and x64 versions self-compiled with VS2010 in
|
||||
Windows 7. The icon has been changed from Tanuki's default to Itoopie.
|
||||
- Linux ARMv6: Compiled on a RaspberryPi using gcc 4.6.3-14+rpi1,
|
||||
Oracle Java 1.7.0+update40 and stripped
|
||||
- All other binaries are from the "community edition" deltapack offered by
|
||||
Tanuki.
|
||||
|
||||
2014-06-29 zzz
|
||||
* NetDB: Fix handling reseed URLs with ports (ticket #1278)
|
||||
|
||||
2014-06-28 zzz
|
||||
* NetDB: Add support for reseeding with su3 files (ticket #934)
|
||||
* SAM:
|
||||
- Support SIGNATURE_TYPE, bump to 3.1 (ticket #1318)
|
||||
- Private key checking fixes (ticket #1318)
|
||||
- Parameter parsing fixes (ticket #1325)
|
||||
- Cleanups
|
||||
|
||||
2014-06-24 zzz
|
||||
* Streaming; Drop the preliminary channel implementations,
|
||||
as they don't work and can't ever work as designed.
|
||||
|
||||
2014-06-23 zzz
|
||||
* Streaming:
|
||||
- Bundle new socket messages for translation
|
||||
- Fix connection error message
|
||||
* Tunnels: Reject participating tunnels when hidden (ticket #1314)
|
||||
|
||||
2014-06-21 zzz
|
||||
* i2psnark:
|
||||
- Display webapp name in html title (ticket #1311)
|
||||
|
||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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
Reference in New Issue
Block a user