Compare commits
230 Commits
Author | SHA1 | Date | |
---|---|---|---|
baebd1fdd2 | |||
28cfd8cffe | |||
a4468219c7 | |||
70f07e5bc7 | |||
173e8a0434 | |||
72fd42ef9b | |||
ba7dbf9064 | |||
807f0665b1 | |||
416b0e4540 | |||
011ded2ee4 | |||
f9faf3c70d | |||
0ea532c72e | |||
104cf8346e | |||
3e7e5d6113 | |||
0275c5e13b | |||
1c76d240e0 | |||
366da1b37c | |||
bdcb625e6d | |||
8296723533 | |||
957c809774 | |||
70b99cf4f9 | |||
05a6353142 | |||
85615b972b | |||
e3abea1ad2 | |||
bc54908a22 | |||
60bd9803f0 | |||
c3360cc3d7 | |||
aa71725159 | |||
574713e608 | |||
0aaae0b0da | |||
ed34964747 | |||
7b758d89d0 | |||
1c7111eca0 | |||
831f09c91a | |||
4f836a20e1 | |||
8faeaaa1ae | |||
7271289c1f | |||
8421ae1ed4 | |||
d042c6b921 | |||
e2e4516a8f | |||
efc604a25c | |||
5c1864ed5e | |||
debf92fd9b | |||
9477b139be | |||
53ce3c4802 | |||
d61af12867 | |||
908c542b40 | |||
ef998349cc | |||
44446d76e4 | |||
a616a5f1c9 | |||
c0b616e519 | |||
b4d3986006 | |||
ba9108f937 | |||
161379f004 | |||
841feaedff | |||
ba8de6c565 | |||
d6148db455 | |||
33b43f40b9 | |||
4336dc441e | |||
2d86e7cf60 | |||
219e96d416 | |||
0c72fe7383 | |||
369599fedd | |||
847c9dafce | |||
734818f651 | |||
dae6fd47d9 | |||
0956393cf3 | |||
d16f187394 | |||
962a8f6f49 | |||
9aa8707647 | |||
1fdd228a9d | |||
819d857550 | |||
04fb12932f | |||
703b6ed190 | |||
bd6c63cc7e | |||
7dbb13d6dc | |||
ebdc69cbc2 | |||
868fe90d7a | |||
9e39f34473 | |||
45ed744210 | |||
701904d119 | |||
dcf4bb595f | |||
e9f27c60dd | |||
321f11c055 | |||
85cebc7992 | |||
8e5c4a3e22 | |||
dff75de97a | |||
f1fd35265a | |||
b73b3fc5ac | |||
13d4ccf2e7 | |||
8c9ac941bf | |||
3fc698c7d3 | |||
15596c9230 | |||
7fdbe9b87b | |||
5acc56c184 | |||
c524231c6d | |||
5d4a7967cb | |||
01101f9867 | |||
c93ccd15eb | |||
73280ab834 | |||
6a3c52b7fa | |||
90983c8761 | |||
daac598bde | |||
41d98acc95 | |||
c8970c0fc6 | |||
4e5825c648 | |||
93f0092437 | |||
bad4c4a133 | |||
da9a4ce557 | |||
0ff8167425 | |||
9ae589449d | |||
134764b154 | |||
23699e46e5 | |||
fa23a7b066 | |||
de21a5ec48 | |||
b1a9dcf77e | |||
15e7783477 | |||
afa17a8c04 | |||
c7bb2e8f76 | |||
b4d299804b | |||
77f5dd2d14 | |||
c941d7bfa1 | |||
049d6b2fa8 | |||
98038e9282 | |||
6169904c76 | |||
04509f593a | |||
875dd65dcb | |||
b0ec6a0870 | |||
6ce2767514 | |||
5271838a14 | |||
9ec45bbcf5 | |||
c9cef19a68 | |||
9f57be5f03 | |||
1793b05784 | |||
f95c324832 | |||
016c843ad6 | |||
e52526b256 | |||
7722ab5f6f | |||
c024398b93 | |||
2e72ece384 | |||
2b8d59d9f4 | |||
28b4c92241 | |||
c9d9a83f73 | |||
7bf57870d6 | |||
d41b68438d | |||
c634e5005d | |||
e0926b8ccd | |||
5ea7adb857 | |||
bf12c5f9bf | |||
47d5e44b16 | |||
f6996c7d8b | |||
fb7f4f2d11 | |||
d89f97acd5 | |||
f3c9343c79 | |||
16ec091209 | |||
0b599c45ec | |||
7f3f6dfde3 | |||
d736b75dc2 | |||
fa2f06b1d8 | |||
4212858409 | |||
33221ce7fd | |||
fd5fcebae9 | |||
b743449715 | |||
2a08fc7a34 | |||
0c520de6e5 | |||
09b868e243 | |||
83801c9feb | |||
152f824779 | |||
68256930b9 | |||
622951c794 | |||
baa70299fc | |||
47856f312c | |||
b4c808918b | |||
e6e4c60a25 | |||
2dc699b382 | |||
22454a06d4 | |||
0e0459f88a | |||
20effe3a7f | |||
8a756a6e81 | |||
a7e876da1e | |||
06be4515e4 | |||
af630e9559 | |||
50c93e25c7 | |||
2d6007cf49 | |||
7aaed8e686 | |||
e2a1835142 | |||
078256da83 | |||
4f8d84e9e7 | |||
ae967d6ef4 | |||
3b46b16038 | |||
25bf6e59bc | |||
c4030f8dab | |||
e103f33c29 | |||
1c6b78a8da | |||
8117d0465c | |||
0ff846deee | |||
87a992bd3f | |||
41c38e64c3 | |||
ca5c15d4de | |||
f3f7537ec6 | |||
855293d673 | |||
4c2d4144d1 | |||
387587b0b6 | |||
43e95a70d1 | |||
ad56eb7220 | |||
d2d32f0ad1 | |||
0428726e30 | |||
2eb154c24c | |||
4ec82beec5 | |||
224ebb16d4 | |||
cb17fb8805 | |||
2c048d7465 | |||
00d537e5e4 | |||
5eef43d239 | |||
caaf0ccfc3 | |||
18d42ec925 | |||
872d2c48c9 | |||
a3b9345ff1 | |||
eae67a44f0 | |||
a988358ebb | |||
bb32672c11 | |||
f1c4a85991 | |||
0a5eeed370 | |||
5913d9ee4a | |||
61749aaaa9 | |||
b0313bd6bf | |||
dd7d993631 | |||
ee2fd32a97 | |||
fa5c7219d3 | |||
8d78a77a8c |
69
apps/BOB/Demos/echo/echoclient/build.xml
Normal file
69
apps/BOB/Demos/echo/echoclient/build.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<project name="echoclient" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project echoclient.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="echoclient-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
5
apps/BOB/Demos/echo/echoclient/client.sh
Executable file
5
apps/BOB/Demos/echo/echoclient/client.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
(
|
||||
cd dist
|
||||
java -jar echoclient.jar main 37338 testclient $1
|
||||
)
|
3
apps/BOB/Demos/echo/echoclient/manifest.mf
Normal file
3
apps/BOB/Demos/echo/echoclient/manifest.mf
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
629
apps/BOB/Demos/echo/echoclient/nbproject/build-impl.xml
Normal file
629
apps/BOB/Demos/echo/echoclient/nbproject/build-impl.xml
Normal file
@ -0,0 +1,629 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
*** GENERATED FROM project.xml - DO NOT EDIT ***
|
||||
*** EDIT ../build.xml INSTEAD ***
|
||||
|
||||
For the purpose of easier reading the script
|
||||
is divided into following sections:
|
||||
|
||||
- initialization
|
||||
- compilation
|
||||
- jar
|
||||
- execution
|
||||
- debugging
|
||||
- javadoc
|
||||
- junit compilation
|
||||
- junit execution
|
||||
- junit debugging
|
||||
- applet
|
||||
- cleanup
|
||||
|
||||
-->
|
||||
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="echoclient-impl">
|
||||
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
|
||||
<!--
|
||||
======================
|
||||
INITIALIZATION SECTION
|
||||
======================
|
||||
-->
|
||||
<target name="-pre-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init" name="-init-private">
|
||||
<property file="nbproject/private/config.properties"/>
|
||||
<property file="nbproject/private/configs/${config}.properties"/>
|
||||
<property file="nbproject/private/private.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private" name="-init-user">
|
||||
<property file="${user.properties.file}"/>
|
||||
<!-- The two properties below are usually overridden -->
|
||||
<!-- by the active platform. Just a fallback. -->
|
||||
<property name="default.javac.source" value="1.4"/>
|
||||
<property name="default.javac.target" value="1.4"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
|
||||
<property file="nbproject/configs/${config}.properties"/>
|
||||
<property file="nbproject/project.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
|
||||
<available file="${manifest.file}" property="manifest.available"/>
|
||||
<condition property="manifest.available+main.class">
|
||||
<and>
|
||||
<isset property="manifest.available"/>
|
||||
<isset property="main.class"/>
|
||||
<not>
|
||||
<equals arg1="${main.class}" arg2="" trim="true"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="manifest.available+main.class+mkdist.available">
|
||||
<and>
|
||||
<istrue value="${manifest.available+main.class}"/>
|
||||
<isset property="libs.CopyLibs.classpath"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="have.tests">
|
||||
<or>
|
||||
<available file="${test.src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="have.sources">
|
||||
<or>
|
||||
<available file="${src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="netbeans.home+have.tests">
|
||||
<and>
|
||||
<isset property="netbeans.home"/>
|
||||
<isset property="have.tests"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="no.javadoc.preview">
|
||||
<and>
|
||||
<isset property="javadoc.preview"/>
|
||||
<isfalse value="${javadoc.preview}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="run.jvmargs" value=""/>
|
||||
<property name="javac.compilerargs" value=""/>
|
||||
<property name="work.dir" value="${basedir}"/>
|
||||
<condition property="no.deps">
|
||||
<and>
|
||||
<istrue value="${no.dependencies}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javac.debug" value="true"/>
|
||||
<property name="javadoc.preview" value="true"/>
|
||||
<property name="application.args" value=""/>
|
||||
<property name="source.encoding" value="${file.encoding}"/>
|
||||
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
|
||||
<and>
|
||||
<isset property="javadoc.encoding"/>
|
||||
<not>
|
||||
<equals arg1="${javadoc.encoding}" arg2=""/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javadoc.encoding.used" value="${source.encoding}"/>
|
||||
<property name="includes" value="**"/>
|
||||
<property name="excludes" value=""/>
|
||||
<property name="do.depend" value="false"/>
|
||||
<condition property="do.depend.true">
|
||||
<istrue value="${do.depend}"/>
|
||||
</condition>
|
||||
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
|
||||
<and>
|
||||
<isset property="jaxws.endorsed.dir"/>
|
||||
<available file="nbproject/jaxws-build.xml"/>
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
<target name="-post-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
|
||||
<fail unless="src.dir">Must set src.dir</fail>
|
||||
<fail unless="test.src.dir">Must set test.src.dir</fail>
|
||||
<fail unless="build.dir">Must set build.dir</fail>
|
||||
<fail unless="dist.dir">Must set dist.dir</fail>
|
||||
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
|
||||
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
|
||||
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
|
||||
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
|
||||
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
|
||||
<fail unless="dist.jar">Must set dist.jar</fail>
|
||||
</target>
|
||||
<target name="-init-macrodef-property">
|
||||
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute name="name"/>
|
||||
<attribute name="value"/>
|
||||
<sequential>
|
||||
<property name="@{name}" value="${@{value}}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-javac">
|
||||
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="${javac.debug}" name="debug"/>
|
||||
<attribute default="" name="sourcepath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
|
||||
<customize/>
|
||||
</javac>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<sequential>
|
||||
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</depend>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<sequential>
|
||||
<fail unless="javac.includes">Must set javac.includes</fail>
|
||||
<pathconvert pathsep="," property="javac.includes.binary">
|
||||
<path>
|
||||
<filelist dir="@{destdir}" files="${javac.includes}"/>
|
||||
</path>
|
||||
<globmapper from="*.java" to="*.class"/>
|
||||
</pathconvert>
|
||||
<delete>
|
||||
<files includes="${javac.includes.binary}"/>
|
||||
</delete>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-junit">
|
||||
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="**" name="testincludes"/>
|
||||
<sequential>
|
||||
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
|
||||
<batchtest todir="${build.test.results.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
|
||||
<filename name="@{testincludes}"/>
|
||||
</fileset>
|
||||
</batchtest>
|
||||
<classpath>
|
||||
<path path="${run.test.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<formatter type="brief" usefile="false"/>
|
||||
<formatter type="xml"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
</junit>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-nbjpda">
|
||||
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="name"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<attribute default="" name="stopclassname"/>
|
||||
<sequential>
|
||||
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="dt_socket">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</nbjpdastart>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${build.classes.dir}" name="dir"/>
|
||||
<sequential>
|
||||
<nbjpdareload>
|
||||
<fileset dir="@{dir}" includes="${fix.classes}">
|
||||
<include name="${fix.includes}*.class"/>
|
||||
</fileset>
|
||||
</nbjpdareload>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-debug-args">
|
||||
<property name="version-output" value="java version "${ant.java.version}"/>
|
||||
<condition property="have-jdk-older-than-1.4">
|
||||
<or>
|
||||
<contains string="${version-output}" substring="java version "1.0"/>
|
||||
<contains string="${version-output}" substring="java version "1.1"/>
|
||||
<contains string="${version-output}" substring="java version "1.2"/>
|
||||
<contains string="${version-output}" substring="java version "1.3"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
|
||||
<istrue value="${have-jdk-older-than-1.4}"/>
|
||||
</condition>
|
||||
</target>
|
||||
<target depends="-init-debug-args" name="-init-macrodef-debug">
|
||||
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${debug-args-line}"/>
|
||||
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-java">
|
||||
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="${run.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-presetdef-jar">
|
||||
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<jar compress="${jar.compress}" jarfile="${dist.jar}">
|
||||
<j2seproject1:fileset dir="${build.classes.dir}"/>
|
||||
</jar>
|
||||
</presetdef>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
|
||||
<!--
|
||||
===================
|
||||
COMPILATION SECTION
|
||||
===================
|
||||
-->
|
||||
<target depends="init" name="deps-jar" unless="no.deps"/>
|
||||
<target depends="init,deps-jar" name="-pre-pre-compile">
|
||||
<mkdir dir="${build.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-depend">
|
||||
<j2seproject3:depend/>
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
|
||||
<j2seproject3:javac/>
|
||||
<copy todir="${build.classes.dir}">
|
||||
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
|
||||
<target name="-pre-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile/>
|
||||
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
|
||||
</target>
|
||||
<target name="-post-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
|
||||
<!--
|
||||
====================
|
||||
JAR BUILDING SECTION
|
||||
====================
|
||||
-->
|
||||
<target depends="init" name="-pre-pre-jar">
|
||||
<dirname file="${dist.jar}" property="dist.jar.dir"/>
|
||||
<mkdir dir="${dist.jar.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
|
||||
<j2seproject1:jar/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
|
||||
<j2seproject1:jar manifest="${manifest.file}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
|
||||
<j2seproject1:jar manifest="${manifest.file}">
|
||||
<j2seproject1:manifest>
|
||||
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
|
||||
</j2seproject1:manifest>
|
||||
</j2seproject1:jar>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<pathconvert property="run.classpath.with.dist.jar">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
|
||||
</pathconvert>
|
||||
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<pathconvert property="run.classpath.without.build.classes.dir">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to=""/>
|
||||
</pathconvert>
|
||||
<pathconvert pathsep=" " property="jar.classpath">
|
||||
<path path="${run.classpath.without.build.classes.dir}"/>
|
||||
<chainedmapper>
|
||||
<flattenmapper/>
|
||||
<globmapper from="*" to="lib/*"/>
|
||||
</chainedmapper>
|
||||
</pathconvert>
|
||||
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
|
||||
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main.class}"/>
|
||||
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||
</manifest>
|
||||
</copylibs>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<echo>java -jar "${dist.jar.resolved}"</echo>
|
||||
</target>
|
||||
<target name="-post-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
|
||||
<!--
|
||||
=================
|
||||
EXECUTION SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init,compile" description="Run a main class." name="run">
|
||||
<j2seproject1:java>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<target name="-do-not-recompile">
|
||||
<property name="javac.includes.binary" value=""/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single" name="run-single">
|
||||
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
|
||||
<j2seproject1:java classname="${run.class}"/>
|
||||
</target>
|
||||
<!--
|
||||
=================
|
||||
DEBUGGING SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
|
||||
<j2seproject1:nbjpdastart name="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile" name="-debug-start-debuggee">
|
||||
<j2seproject3:debug>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
|
||||
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
|
||||
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
|
||||
<j2seproject3:debug classname="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
|
||||
<target depends="init" name="-pre-debug-fix">
|
||||
<fail unless="fix.includes">Must set fix.includes</fail>
|
||||
<property name="javac.includes" value="${fix.includes}.java"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
|
||||
<j2seproject1:nbjpdareload/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
|
||||
<!--
|
||||
===============
|
||||
JAVADOC SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="-javadoc-build">
|
||||
<mkdir dir="${dist.javadoc.dir}"/>
|
||||
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
|
||||
<classpath>
|
||||
<path path="${javac.classpath}"/>
|
||||
</classpath>
|
||||
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
|
||||
<filename name="**/*.java"/>
|
||||
</fileset>
|
||||
</javadoc>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
|
||||
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
|
||||
<!--
|
||||
=========================
|
||||
JUNIT COMPILATION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
|
||||
<mkdir dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-test-depend">
|
||||
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
|
||||
<target name="-pre-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT EXECUTION SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init" if="have.tests" name="-pre-test-run">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
|
||||
<j2seproject3:junit testincludes="**/*Test.java"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init" if="have.tests" name="test-report"/>
|
||||
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
|
||||
<target depends="init" if="have.tests" name="-pre-test-run-single">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
|
||||
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
|
||||
<j2seproject3:junit excludes="" includes="${test.includes}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT DEBUGGING SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
|
||||
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
|
||||
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
|
||||
<delete file="${test.report.file}"/>
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
|
||||
<customize>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<arg value="${test.class}"/>
|
||||
<arg value="showoutput=true"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
|
||||
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
|
||||
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
|
||||
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
|
||||
<!--
|
||||
=========================
|
||||
APPLET EXECUTION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" name="run-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject1:java classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<!--
|
||||
=========================
|
||||
APPLET DEBUGGING SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject3:debug classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
|
||||
<!--
|
||||
===============
|
||||
CLEANUP SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="deps-clean" unless="no.deps"/>
|
||||
<target depends="init" name="-do-clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</target>
|
||||
<target name="-post-clean">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
build.xml.data.CRC32=8ce3cee9
|
||||
build.xml.script.CRC32=d1de2df3
|
||||
build.xml.stylesheet.CRC32=be360661
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=8ce3cee9
|
||||
nbproject/build-impl.xml.script.CRC32=22d1fbbb
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=487672f9
|
@ -0,0 +1,2 @@
|
||||
jaxws.endorsed.dir=/usr/local/netbeans-6.1/java2/modules/ext/jaxws21/api
|
||||
user.properties.file=/root/.netbeans/6.1/build.properties
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
|
||||
<file>file:/root/NetBeansProjects/BOB/Demos/echo/echoclient/src/net/i2p/BOB/Demos/echo/echoclient/Main.java</file>
|
||||
</open-files>
|
||||
</project-private>
|
60
apps/BOB/Demos/echo/echoclient/nbproject/project.properties
Normal file
60
apps/BOB/Demos/echo/echoclient/nbproject/project.properties
Normal file
@ -0,0 +1,60 @@
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/echoclient.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
excludes=
|
||||
file.reference.BOB.jar=../../../dist/BOB.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.source=1.5
|
||||
javac.target=1.5
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}:\
|
||||
${libs.junit_4.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
main.class=net.i2p.BOB.Demos.echo.echoclient.Main
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
16
apps/BOB/Demos/echo/echoclient/nbproject/project.xml
Normal file
16
apps/BOB/Demos/echo/echoclient/nbproject/project.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>echoclient</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
@ -0,0 +1,201 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB.Demos.echo.echoclient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static String Lread(InputStream in) throws IOException {
|
||||
String S;
|
||||
int b;
|
||||
char c;
|
||||
|
||||
S = new String();
|
||||
|
||||
while(true) {
|
||||
b = in.read();
|
||||
if(b == 13) {
|
||||
//skip CR
|
||||
continue;
|
||||
}
|
||||
if(b < 20 || b > 126) {
|
||||
// exit on anything not legal
|
||||
break;
|
||||
}
|
||||
c = (char)(b & 0x7f); // We only really give a fuck about ASCII
|
||||
S = new String(S + c);
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for "ERROR" and if so, throw RuntimeException
|
||||
* @param line
|
||||
* @throws java.lang.RuntimeException
|
||||
*/
|
||||
static void checkline(String line) throws RuntimeException {
|
||||
System.out.println(line); // print status
|
||||
if(line.startsWith("ERROR")) {
|
||||
throw new RuntimeException(line);
|
||||
}
|
||||
}
|
||||
|
||||
static void wrtxt(OutputStream CMDout, String s) throws IOException {
|
||||
CMDout.write(s.getBytes());
|
||||
CMDout.write('\n');
|
||||
CMDout.flush();
|
||||
}
|
||||
|
||||
static void setupconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
|
||||
String line;
|
||||
Socket CMDsock = new Socket("localhost", 0xB0B);
|
||||
InputStream CMDin = CMDsock.getInputStream();
|
||||
OutputStream CMDout = CMDsock.getOutputStream();
|
||||
// setup the tunnel.
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print the banner
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print initial status, should always be "OK"
|
||||
try {
|
||||
wrtxt(CMDout, "status " + args[2]);
|
||||
line = Lread(CMDin); // get the status of this nickname, if it's an error, create it
|
||||
checkline(line);
|
||||
} catch(RuntimeException rte) {
|
||||
wrtxt(CMDout, "setnick " + args[2]);
|
||||
line = Lread(CMDin); // create a new nickname
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "newkeys");
|
||||
line = Lread(CMDin); // set up new keys
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "inport " + args[1]);
|
||||
line = Lread(CMDin); // set the port we connect in on
|
||||
checkline(line);
|
||||
}
|
||||
wrtxt(CMDout, "getnick " + args[2]);
|
||||
line = Lread(CMDin); // Set to our nick
|
||||
try {
|
||||
checkline(line);
|
||||
} catch(RuntimeException rte) {
|
||||
System.out.println("Continuing on existing tunnel..");
|
||||
return;
|
||||
}
|
||||
wrtxt(CMDout, "start");
|
||||
line = Lread(CMDin); // an error here is OK
|
||||
System.out.println(line); // print status
|
||||
CMDsock.close(); // we no longer need this particular socket
|
||||
|
||||
}
|
||||
|
||||
static void deleteconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
|
||||
String line;
|
||||
// Wait for things to flush
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch(InterruptedException ex) {
|
||||
// nop
|
||||
}
|
||||
Socket CMDsock = new Socket("localhost", 0xB0B);
|
||||
InputStream CMDin = CMDsock.getInputStream();
|
||||
OutputStream CMDout = CMDsock.getOutputStream();
|
||||
// delete the tunnel.
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print the banner
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print initial status, should always be "OK"
|
||||
wrtxt(CMDout, "getnick " + args[2]); // Set to our nick
|
||||
line = Lread(CMDin);
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "stop");
|
||||
line = Lread(CMDin);
|
||||
checkline(line);
|
||||
try {
|
||||
Thread.sleep(2000); //sleep for 2000 ms (Two seconds)
|
||||
} catch(Exception e) {
|
||||
// nop
|
||||
}
|
||||
|
||||
wrtxt(CMDout, "clear");
|
||||
line = Lread(CMDin);
|
||||
while(line.startsWith("ERROR")) {
|
||||
wrtxt(CMDout, "clear");
|
||||
line = Lread(CMDin);
|
||||
}
|
||||
System.out.println(line); // print status
|
||||
CMDsock.close(); // we no longer need this particular socket
|
||||
|
||||
}
|
||||
|
||||
static void chatter(String[] args) throws UnknownHostException, IOException, RuntimeException {
|
||||
String line;
|
||||
Socket sock = new Socket("localhost", Integer.parseInt(args[1]));
|
||||
InputStream in = sock.getInputStream();
|
||||
OutputStreamWriter out = new OutputStreamWriter(sock.getOutputStream());
|
||||
out.write(args[3] + "\n"); // send out the i2p address to connect to
|
||||
out.flush();
|
||||
System.out.println("Connecting to " + args[3]);
|
||||
line = Lread(in); // get server greeting
|
||||
System.out.println("Got " + line); // show user
|
||||
out.write("Test complete.\n"); // send something back
|
||||
out.flush(); // make sure it's sent.
|
||||
sock.close(); // done.
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param args tunnelport tunnelnickname I2Pdestkey
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// I'm lazy, and want to exit on any failures.
|
||||
try {
|
||||
setupconn(args); // talk to BOB, set up an outbound port
|
||||
chatter(args); // talk over the connection
|
||||
|
||||
} catch(UnknownHostException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch(IOException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
try {
|
||||
deleteconn(args);
|
||||
} catch(UnknownHostException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch(IOException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch(RuntimeException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
69
apps/BOB/Demos/echo/echoserver/build.xml
Normal file
69
apps/BOB/Demos/echo/echoserver/build.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<project name="echoserver" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project echoserver.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="echoserver-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
3
apps/BOB/Demos/echo/echoserver/manifest.mf
Normal file
3
apps/BOB/Demos/echo/echoserver/manifest.mf
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
629
apps/BOB/Demos/echo/echoserver/nbproject/build-impl.xml
Normal file
629
apps/BOB/Demos/echo/echoserver/nbproject/build-impl.xml
Normal file
@ -0,0 +1,629 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
*** GENERATED FROM project.xml - DO NOT EDIT ***
|
||||
*** EDIT ../build.xml INSTEAD ***
|
||||
|
||||
For the purpose of easier reading the script
|
||||
is divided into following sections:
|
||||
|
||||
- initialization
|
||||
- compilation
|
||||
- jar
|
||||
- execution
|
||||
- debugging
|
||||
- javadoc
|
||||
- junit compilation
|
||||
- junit execution
|
||||
- junit debugging
|
||||
- applet
|
||||
- cleanup
|
||||
|
||||
-->
|
||||
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="echoserver-impl">
|
||||
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
|
||||
<!--
|
||||
======================
|
||||
INITIALIZATION SECTION
|
||||
======================
|
||||
-->
|
||||
<target name="-pre-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init" name="-init-private">
|
||||
<property file="nbproject/private/config.properties"/>
|
||||
<property file="nbproject/private/configs/${config}.properties"/>
|
||||
<property file="nbproject/private/private.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private" name="-init-user">
|
||||
<property file="${user.properties.file}"/>
|
||||
<!-- The two properties below are usually overridden -->
|
||||
<!-- by the active platform. Just a fallback. -->
|
||||
<property name="default.javac.source" value="1.4"/>
|
||||
<property name="default.javac.target" value="1.4"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
|
||||
<property file="nbproject/configs/${config}.properties"/>
|
||||
<property file="nbproject/project.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
|
||||
<available file="${manifest.file}" property="manifest.available"/>
|
||||
<condition property="manifest.available+main.class">
|
||||
<and>
|
||||
<isset property="manifest.available"/>
|
||||
<isset property="main.class"/>
|
||||
<not>
|
||||
<equals arg1="${main.class}" arg2="" trim="true"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="manifest.available+main.class+mkdist.available">
|
||||
<and>
|
||||
<istrue value="${manifest.available+main.class}"/>
|
||||
<isset property="libs.CopyLibs.classpath"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="have.tests">
|
||||
<or>
|
||||
<available file="${test.src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="have.sources">
|
||||
<or>
|
||||
<available file="${src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="netbeans.home+have.tests">
|
||||
<and>
|
||||
<isset property="netbeans.home"/>
|
||||
<isset property="have.tests"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="no.javadoc.preview">
|
||||
<and>
|
||||
<isset property="javadoc.preview"/>
|
||||
<isfalse value="${javadoc.preview}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="run.jvmargs" value=""/>
|
||||
<property name="javac.compilerargs" value=""/>
|
||||
<property name="work.dir" value="${basedir}"/>
|
||||
<condition property="no.deps">
|
||||
<and>
|
||||
<istrue value="${no.dependencies}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javac.debug" value="true"/>
|
||||
<property name="javadoc.preview" value="true"/>
|
||||
<property name="application.args" value=""/>
|
||||
<property name="source.encoding" value="${file.encoding}"/>
|
||||
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
|
||||
<and>
|
||||
<isset property="javadoc.encoding"/>
|
||||
<not>
|
||||
<equals arg1="${javadoc.encoding}" arg2=""/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javadoc.encoding.used" value="${source.encoding}"/>
|
||||
<property name="includes" value="**"/>
|
||||
<property name="excludes" value=""/>
|
||||
<property name="do.depend" value="false"/>
|
||||
<condition property="do.depend.true">
|
||||
<istrue value="${do.depend}"/>
|
||||
</condition>
|
||||
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
|
||||
<and>
|
||||
<isset property="jaxws.endorsed.dir"/>
|
||||
<available file="nbproject/jaxws-build.xml"/>
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
<target name="-post-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
|
||||
<fail unless="src.dir">Must set src.dir</fail>
|
||||
<fail unless="test.src.dir">Must set test.src.dir</fail>
|
||||
<fail unless="build.dir">Must set build.dir</fail>
|
||||
<fail unless="dist.dir">Must set dist.dir</fail>
|
||||
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
|
||||
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
|
||||
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
|
||||
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
|
||||
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
|
||||
<fail unless="dist.jar">Must set dist.jar</fail>
|
||||
</target>
|
||||
<target name="-init-macrodef-property">
|
||||
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute name="name"/>
|
||||
<attribute name="value"/>
|
||||
<sequential>
|
||||
<property name="@{name}" value="${@{value}}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-javac">
|
||||
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="${javac.debug}" name="debug"/>
|
||||
<attribute default="" name="sourcepath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
|
||||
<customize/>
|
||||
</javac>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<sequential>
|
||||
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</depend>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<sequential>
|
||||
<fail unless="javac.includes">Must set javac.includes</fail>
|
||||
<pathconvert pathsep="," property="javac.includes.binary">
|
||||
<path>
|
||||
<filelist dir="@{destdir}" files="${javac.includes}"/>
|
||||
</path>
|
||||
<globmapper from="*.java" to="*.class"/>
|
||||
</pathconvert>
|
||||
<delete>
|
||||
<files includes="${javac.includes.binary}"/>
|
||||
</delete>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-junit">
|
||||
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="**" name="testincludes"/>
|
||||
<sequential>
|
||||
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
|
||||
<batchtest todir="${build.test.results.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
|
||||
<filename name="@{testincludes}"/>
|
||||
</fileset>
|
||||
</batchtest>
|
||||
<classpath>
|
||||
<path path="${run.test.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<formatter type="brief" usefile="false"/>
|
||||
<formatter type="xml"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
</junit>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-nbjpda">
|
||||
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="name"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<attribute default="" name="stopclassname"/>
|
||||
<sequential>
|
||||
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="dt_socket">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</nbjpdastart>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${build.classes.dir}" name="dir"/>
|
||||
<sequential>
|
||||
<nbjpdareload>
|
||||
<fileset dir="@{dir}" includes="${fix.classes}">
|
||||
<include name="${fix.includes}*.class"/>
|
||||
</fileset>
|
||||
</nbjpdareload>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-debug-args">
|
||||
<property name="version-output" value="java version "${ant.java.version}"/>
|
||||
<condition property="have-jdk-older-than-1.4">
|
||||
<or>
|
||||
<contains string="${version-output}" substring="java version "1.0"/>
|
||||
<contains string="${version-output}" substring="java version "1.1"/>
|
||||
<contains string="${version-output}" substring="java version "1.2"/>
|
||||
<contains string="${version-output}" substring="java version "1.3"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
|
||||
<istrue value="${have-jdk-older-than-1.4}"/>
|
||||
</condition>
|
||||
</target>
|
||||
<target depends="-init-debug-args" name="-init-macrodef-debug">
|
||||
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${debug-args-line}"/>
|
||||
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-java">
|
||||
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="${run.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-presetdef-jar">
|
||||
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<jar compress="${jar.compress}" jarfile="${dist.jar}">
|
||||
<j2seproject1:fileset dir="${build.classes.dir}"/>
|
||||
</jar>
|
||||
</presetdef>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
|
||||
<!--
|
||||
===================
|
||||
COMPILATION SECTION
|
||||
===================
|
||||
-->
|
||||
<target depends="init" name="deps-jar" unless="no.deps"/>
|
||||
<target depends="init,deps-jar" name="-pre-pre-compile">
|
||||
<mkdir dir="${build.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-depend">
|
||||
<j2seproject3:depend/>
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
|
||||
<j2seproject3:javac/>
|
||||
<copy todir="${build.classes.dir}">
|
||||
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
|
||||
<target name="-pre-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile/>
|
||||
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
|
||||
</target>
|
||||
<target name="-post-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
|
||||
<!--
|
||||
====================
|
||||
JAR BUILDING SECTION
|
||||
====================
|
||||
-->
|
||||
<target depends="init" name="-pre-pre-jar">
|
||||
<dirname file="${dist.jar}" property="dist.jar.dir"/>
|
||||
<mkdir dir="${dist.jar.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
|
||||
<j2seproject1:jar/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
|
||||
<j2seproject1:jar manifest="${manifest.file}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
|
||||
<j2seproject1:jar manifest="${manifest.file}">
|
||||
<j2seproject1:manifest>
|
||||
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
|
||||
</j2seproject1:manifest>
|
||||
</j2seproject1:jar>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<pathconvert property="run.classpath.with.dist.jar">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
|
||||
</pathconvert>
|
||||
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<pathconvert property="run.classpath.without.build.classes.dir">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to=""/>
|
||||
</pathconvert>
|
||||
<pathconvert pathsep=" " property="jar.classpath">
|
||||
<path path="${run.classpath.without.build.classes.dir}"/>
|
||||
<chainedmapper>
|
||||
<flattenmapper/>
|
||||
<globmapper from="*" to="lib/*"/>
|
||||
</chainedmapper>
|
||||
</pathconvert>
|
||||
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
|
||||
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main.class}"/>
|
||||
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||
</manifest>
|
||||
</copylibs>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<echo>java -jar "${dist.jar.resolved}"</echo>
|
||||
</target>
|
||||
<target name="-post-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
|
||||
<!--
|
||||
=================
|
||||
EXECUTION SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init,compile" description="Run a main class." name="run">
|
||||
<j2seproject1:java>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<target name="-do-not-recompile">
|
||||
<property name="javac.includes.binary" value=""/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single" name="run-single">
|
||||
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
|
||||
<j2seproject1:java classname="${run.class}"/>
|
||||
</target>
|
||||
<!--
|
||||
=================
|
||||
DEBUGGING SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
|
||||
<j2seproject1:nbjpdastart name="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile" name="-debug-start-debuggee">
|
||||
<j2seproject3:debug>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
|
||||
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
|
||||
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
|
||||
<j2seproject3:debug classname="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
|
||||
<target depends="init" name="-pre-debug-fix">
|
||||
<fail unless="fix.includes">Must set fix.includes</fail>
|
||||
<property name="javac.includes" value="${fix.includes}.java"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
|
||||
<j2seproject1:nbjpdareload/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
|
||||
<!--
|
||||
===============
|
||||
JAVADOC SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="-javadoc-build">
|
||||
<mkdir dir="${dist.javadoc.dir}"/>
|
||||
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
|
||||
<classpath>
|
||||
<path path="${javac.classpath}"/>
|
||||
</classpath>
|
||||
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
|
||||
<filename name="**/*.java"/>
|
||||
</fileset>
|
||||
</javadoc>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
|
||||
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
|
||||
<!--
|
||||
=========================
|
||||
JUNIT COMPILATION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
|
||||
<mkdir dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-test-depend">
|
||||
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
|
||||
<target name="-pre-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT EXECUTION SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init" if="have.tests" name="-pre-test-run">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
|
||||
<j2seproject3:junit testincludes="**/*Test.java"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init" if="have.tests" name="test-report"/>
|
||||
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
|
||||
<target depends="init" if="have.tests" name="-pre-test-run-single">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
|
||||
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
|
||||
<j2seproject3:junit excludes="" includes="${test.includes}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT DEBUGGING SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
|
||||
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
|
||||
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
|
||||
<delete file="${test.report.file}"/>
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
|
||||
<customize>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<arg value="${test.class}"/>
|
||||
<arg value="showoutput=true"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
|
||||
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
|
||||
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
|
||||
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
|
||||
<!--
|
||||
=========================
|
||||
APPLET EXECUTION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" name="run-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject1:java classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<!--
|
||||
=========================
|
||||
APPLET DEBUGGING SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject3:debug classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
|
||||
<!--
|
||||
===============
|
||||
CLEANUP SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="deps-clean" unless="no.deps"/>
|
||||
<target depends="init" name="-do-clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</target>
|
||||
<target name="-post-clean">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
build.xml.data.CRC32=4ce39738
|
||||
build.xml.script.CRC32=c1deb82c
|
||||
build.xml.stylesheet.CRC32=be360661
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=4ce39738
|
||||
nbproject/build-impl.xml.script.CRC32=555cdd2d
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=487672f9
|
@ -0,0 +1,2 @@
|
||||
jaxws.endorsed.dir=/usr/local/netbeans-6.1/java2/modules/ext/jaxws21/api
|
||||
user.properties.file=/root/.netbeans/6.1/build.properties
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
|
||||
<file>file:/root/NetBeansProjects/BOB/Demos/echo/echoserver/src/net/i2p/BOB/Demos/echo/echoserver/Main.java</file>
|
||||
</open-files>
|
||||
</project-private>
|
60
apps/BOB/Demos/echo/echoserver/nbproject/project.properties
Normal file
60
apps/BOB/Demos/echo/echoserver/nbproject/project.properties
Normal file
@ -0,0 +1,60 @@
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/echoserver.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
excludes=
|
||||
file.reference.BOB.jar=../../../dist/BOB.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.source=1.5
|
||||
javac.target=1.5
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}:\
|
||||
${libs.junit_4.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
main.class=net.i2p.BOB.Demos.echo.echoserver.Main
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
16
apps/BOB/Demos/echo/echoserver/nbproject/project.xml
Normal file
16
apps/BOB/Demos/echo/echoserver/nbproject/project.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>echoserver</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
4
apps/BOB/Demos/echo/echoserver/server.sh
Executable file
4
apps/BOB/Demos/echo/echoserver/server.sh
Executable file
@ -0,0 +1,4 @@
|
||||
(
|
||||
cd dist
|
||||
java -jar echoserver.jar main 37337 testserver
|
||||
)
|
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB.Demos.echo.echoserver;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class Main {
|
||||
public static String Lread(InputStream in) throws IOException {
|
||||
String S;
|
||||
int b;
|
||||
char c;
|
||||
|
||||
S = new String();
|
||||
|
||||
while(true) {
|
||||
b = in.read();
|
||||
if(b < 20) {
|
||||
break;
|
||||
}
|
||||
c = (char)(b & 0x7f); // We only really give a fuck about ASCII
|
||||
S = new String(S + c);
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for "ERROR" and if so, throw RuntimeException
|
||||
* @param line
|
||||
* @throws java.lang.RuntimeException
|
||||
*/
|
||||
static void checkline(String line) throws RuntimeException {
|
||||
System.out.println(line); // print status
|
||||
if(line.startsWith("ERROR")) {
|
||||
throw new RuntimeException(line);
|
||||
}
|
||||
}
|
||||
|
||||
static void wrtxt(OutputStream CMDout, String s) throws IOException {
|
||||
CMDout.write(s.getBytes());
|
||||
CMDout.write('\n');
|
||||
CMDout.flush();
|
||||
}
|
||||
|
||||
static void setupconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
|
||||
String line;
|
||||
Socket CMDsock = new Socket("localhost", 0xB0B);
|
||||
InputStream CMDin = CMDsock.getInputStream();
|
||||
OutputStream CMDout = CMDsock.getOutputStream();
|
||||
// setup the tunnel.
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print the banner
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print initial status, should always be "OK"
|
||||
try {
|
||||
wrtxt(CMDout, "status " + args[2]);
|
||||
line =Lread(CMDin); // get the status of this nickname, if it's an error, create it
|
||||
checkline(line);
|
||||
} catch(RuntimeException rte) {
|
||||
wrtxt(CMDout, "setnick " + args[2]);
|
||||
line =Lread(CMDin); // create a new nickname
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "newkeys ");
|
||||
line =Lread(CMDin); // set up new keys
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "outport " + args[1]);
|
||||
line = Lread(CMDin); // set the port we connect out on
|
||||
checkline(line);
|
||||
}
|
||||
wrtxt(CMDout, "getnick " + args[2]);
|
||||
line = Lread(CMDin); // Set to our nick
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "start ");
|
||||
line = Lread(CMDin); // an error here is OK
|
||||
System.out.println(line); // print status
|
||||
CMDsock.close(); // we no longer need this particular socket
|
||||
|
||||
}
|
||||
|
||||
static void deleteconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
|
||||
String line;
|
||||
Socket CMDsock = new Socket("localhost", 0xB0B);
|
||||
InputStream CMDin = CMDsock.getInputStream();
|
||||
OutputStream CMDout = CMDsock.getOutputStream();
|
||||
// delete the tunnel.
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print the banner
|
||||
line = Lread(CMDin);
|
||||
System.out.println(line); // print initial status, should always be "OK"
|
||||
wrtxt(CMDout, "getnick " + args[2]); // Set to our nick
|
||||
line = Lread(CMDin);
|
||||
checkline(line);
|
||||
wrtxt(CMDout, "stop");
|
||||
line = Lread(CMDin);
|
||||
checkline(line);
|
||||
try {
|
||||
Thread.sleep(2000); //sleep for 2000 ms (Two seconds)
|
||||
} catch(Exception e) {
|
||||
// nop
|
||||
}
|
||||
|
||||
wrtxt(CMDout, "clear");
|
||||
line = Lread(CMDin);
|
||||
while(line.startsWith("ERROR")) {
|
||||
wrtxt(CMDout, "clear");
|
||||
line = Lread(CMDin);
|
||||
}
|
||||
System.out.println(line); // print status
|
||||
CMDsock.close(); // we no longer need this particular socket
|
||||
|
||||
}
|
||||
|
||||
static void chatter(Socket sock) throws UnknownHostException, IOException, RuntimeException {
|
||||
String line;
|
||||
InputStream in = sock.getInputStream();
|
||||
OutputStreamWriter out = new OutputStreamWriter(new BufferedOutputStream(sock.getOutputStream()));
|
||||
|
||||
line = Lread(in); // get remote I2P address
|
||||
System.out.println("Connect from: " + line); // show user
|
||||
|
||||
out.write("Hello, You are connecting from " + line + "\n"); // send greeting
|
||||
out.flush(); // make sure it's sent.
|
||||
line = Lread(in); // get test text from client
|
||||
System.out.println("Got "+line); // show user
|
||||
sock.close(); // done.
|
||||
}
|
||||
|
||||
private static void serverlistener(String[] args) throws UnknownHostException, IOException, RuntimeException {
|
||||
ServerSocket listener = new ServerSocket(Integer.parseInt(args[1]), 10, InetAddress.getByName("localhost"));
|
||||
Socket server;
|
||||
|
||||
while(true) {
|
||||
server = listener.accept();
|
||||
chatter(server);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param args tunnelport tunnelnickname
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// I'm lazy, and want to exit on any failures.
|
||||
try {
|
||||
setupconn(args); // talk to BOB, set up an inbound port
|
||||
serverlistener(args); // talk over the connection
|
||||
|
||||
} catch(UnknownHostException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch(IOException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
try {
|
||||
deleteconn(args);
|
||||
} catch(UnknownHostException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch(IOException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch(RuntimeException ex) {
|
||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
14
apps/BOB/bob.config
Normal file
14
apps/BOB/bob.config
Normal file
@ -0,0 +1,14 @@
|
||||
#bob.config
|
||||
#Tue Dec 30 00:00:00 UTC 2008
|
||||
# Please leave this file here for testing.
|
||||
# Thank you,
|
||||
# Sponge
|
||||
i2cp.tcp.port=7654
|
||||
BOB.host=localhost
|
||||
inbound.lengthVariance=0
|
||||
i2cp.messageReliability=BestEffort
|
||||
BOB.port=45067
|
||||
outbound.length=1
|
||||
inbound.length=1
|
||||
outbound.lengthVariance=0
|
||||
i2cp.tcp.host=localhost
|
74
apps/BOB/build.xml
Normal file
74
apps/BOB/build.xml
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="BOB" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project BOB.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="BOB-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
3
apps/BOB/manifest.mf
Normal file
3
apps/BOB/manifest.mf
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
642
apps/BOB/nbproject/build-impl.xml
Normal file
642
apps/BOB/nbproject/build-impl.xml
Normal file
@ -0,0 +1,642 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
*** GENERATED FROM project.xml - DO NOT EDIT ***
|
||||
*** EDIT ../build.xml INSTEAD ***
|
||||
|
||||
For the purpose of easier reading the script
|
||||
is divided into following sections:
|
||||
|
||||
- initialization
|
||||
- compilation
|
||||
- jar
|
||||
- execution
|
||||
- debugging
|
||||
- javadoc
|
||||
- junit compilation
|
||||
- junit execution
|
||||
- junit debugging
|
||||
- applet
|
||||
- cleanup
|
||||
|
||||
-->
|
||||
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="BOB-impl">
|
||||
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
|
||||
<!--
|
||||
======================
|
||||
INITIALIZATION SECTION
|
||||
======================
|
||||
-->
|
||||
<target name="-pre-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init" name="-init-private">
|
||||
<property file="nbproject/private/config.properties"/>
|
||||
<property file="nbproject/private/configs/${config}.properties"/>
|
||||
<property file="nbproject/private/private.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private" name="-init-user">
|
||||
<property file="${user.properties.file}"/>
|
||||
<!-- The two properties below are usually overridden -->
|
||||
<!-- by the active platform. Just a fallback. -->
|
||||
<property name="default.javac.source" value="1.4"/>
|
||||
<property name="default.javac.target" value="1.4"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
|
||||
<property file="nbproject/configs/${config}.properties"/>
|
||||
<property file="nbproject/project.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
|
||||
<available file="${manifest.file}" property="manifest.available"/>
|
||||
<condition property="manifest.available+main.class">
|
||||
<and>
|
||||
<isset property="manifest.available"/>
|
||||
<isset property="main.class"/>
|
||||
<not>
|
||||
<equals arg1="${main.class}" arg2="" trim="true"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="manifest.available+main.class+mkdist.available">
|
||||
<and>
|
||||
<istrue value="${manifest.available+main.class}"/>
|
||||
<isset property="libs.CopyLibs.classpath"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="have.tests">
|
||||
<or>
|
||||
<available file="${test.src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="have.sources">
|
||||
<or>
|
||||
<available file="${src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="netbeans.home+have.tests">
|
||||
<and>
|
||||
<isset property="netbeans.home"/>
|
||||
<isset property="have.tests"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="no.javadoc.preview">
|
||||
<and>
|
||||
<isset property="javadoc.preview"/>
|
||||
<isfalse value="${javadoc.preview}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="run.jvmargs" value=""/>
|
||||
<property name="javac.compilerargs" value=""/>
|
||||
<property name="work.dir" value="${basedir}"/>
|
||||
<condition property="no.deps">
|
||||
<and>
|
||||
<istrue value="${no.dependencies}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javac.debug" value="true"/>
|
||||
<property name="javadoc.preview" value="true"/>
|
||||
<property name="application.args" value=""/>
|
||||
<property name="source.encoding" value="${file.encoding}"/>
|
||||
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
|
||||
<and>
|
||||
<isset property="javadoc.encoding"/>
|
||||
<not>
|
||||
<equals arg1="${javadoc.encoding}" arg2=""/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javadoc.encoding.used" value="${source.encoding}"/>
|
||||
<property name="includes" value="**"/>
|
||||
<property name="excludes" value=""/>
|
||||
<property name="do.depend" value="false"/>
|
||||
<condition property="do.depend.true">
|
||||
<istrue value="${do.depend}"/>
|
||||
</condition>
|
||||
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
|
||||
<and>
|
||||
<isset property="jaxws.endorsed.dir"/>
|
||||
<available file="nbproject/jaxws-build.xml"/>
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
<target name="-post-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
|
||||
<fail unless="src.dir">Must set src.dir</fail>
|
||||
<fail unless="test.src.dir">Must set test.src.dir</fail>
|
||||
<fail unless="build.dir">Must set build.dir</fail>
|
||||
<fail unless="dist.dir">Must set dist.dir</fail>
|
||||
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
|
||||
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
|
||||
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
|
||||
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
|
||||
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
|
||||
<fail unless="dist.jar">Must set dist.jar</fail>
|
||||
</target>
|
||||
<target name="-init-macrodef-property">
|
||||
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute name="name"/>
|
||||
<attribute name="value"/>
|
||||
<sequential>
|
||||
<property name="@{name}" value="${@{value}}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-javac">
|
||||
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="${javac.debug}" name="debug"/>
|
||||
<attribute default="" name="sourcepath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
|
||||
<customize/>
|
||||
</javac>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<sequential>
|
||||
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</depend>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<sequential>
|
||||
<fail unless="javac.includes">Must set javac.includes</fail>
|
||||
<pathconvert pathsep="," property="javac.includes.binary">
|
||||
<path>
|
||||
<filelist dir="@{destdir}" files="${javac.includes}"/>
|
||||
</path>
|
||||
<globmapper from="*.java" to="*.class"/>
|
||||
</pathconvert>
|
||||
<delete>
|
||||
<files includes="${javac.includes.binary}"/>
|
||||
</delete>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-junit">
|
||||
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="**" name="testincludes"/>
|
||||
<sequential>
|
||||
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
|
||||
<batchtest todir="${build.test.results.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
|
||||
<filename name="@{testincludes}"/>
|
||||
</fileset>
|
||||
</batchtest>
|
||||
<classpath>
|
||||
<path path="${run.test.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<formatter type="brief" usefile="false"/>
|
||||
<formatter type="xml"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
</junit>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target depends="-init-debug-args" name="-init-macrodef-nbjpda">
|
||||
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="name"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<attribute default="" name="stopclassname"/>
|
||||
<sequential>
|
||||
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</nbjpdastart>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${build.classes.dir}" name="dir"/>
|
||||
<sequential>
|
||||
<nbjpdareload>
|
||||
<fileset dir="@{dir}" includes="${fix.classes}">
|
||||
<include name="${fix.includes}*.class"/>
|
||||
</fileset>
|
||||
</nbjpdareload>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-debug-args">
|
||||
<property name="version-output" value="java version "${ant.java.version}"/>
|
||||
<condition property="have-jdk-older-than-1.4">
|
||||
<or>
|
||||
<contains string="${version-output}" substring="java version "1.0"/>
|
||||
<contains string="${version-output}" substring="java version "1.1"/>
|
||||
<contains string="${version-output}" substring="java version "1.2"/>
|
||||
<contains string="${version-output}" substring="java version "1.3"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
|
||||
<istrue value="${have-jdk-older-than-1.4}"/>
|
||||
</condition>
|
||||
<condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
<condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
|
||||
<isset property="debug.transport"/>
|
||||
</condition>
|
||||
</target>
|
||||
<target depends="-init-debug-args" name="-init-macrodef-debug">
|
||||
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${debug-args-line}"/>
|
||||
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-java">
|
||||
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="${run.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-presetdef-jar">
|
||||
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<jar compress="${jar.compress}" jarfile="${dist.jar}">
|
||||
<j2seproject1:fileset dir="${build.classes.dir}"/>
|
||||
</jar>
|
||||
</presetdef>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
|
||||
<!--
|
||||
===================
|
||||
COMPILATION SECTION
|
||||
===================
|
||||
-->
|
||||
<target depends="init" name="deps-jar" unless="no.deps"/>
|
||||
<target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
|
||||
<target depends="init" name="-check-automatic-build">
|
||||
<available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
|
||||
</target>
|
||||
<target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
|
||||
<antcall target="clean"/>
|
||||
</target>
|
||||
<target depends="init,deps-jar" name="-pre-pre-compile">
|
||||
<mkdir dir="${build.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-depend">
|
||||
<j2seproject3:depend/>
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
|
||||
<j2seproject3:javac/>
|
||||
<copy todir="${build.classes.dir}">
|
||||
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
|
||||
<target name="-pre-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile/>
|
||||
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
|
||||
</target>
|
||||
<target name="-post-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
|
||||
<!--
|
||||
====================
|
||||
JAR BUILDING SECTION
|
||||
====================
|
||||
-->
|
||||
<target depends="init" name="-pre-pre-jar">
|
||||
<dirname file="${dist.jar}" property="dist.jar.dir"/>
|
||||
<mkdir dir="${dist.jar.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
|
||||
<j2seproject1:jar/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
|
||||
<j2seproject1:jar manifest="${manifest.file}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
|
||||
<j2seproject1:jar manifest="${manifest.file}">
|
||||
<j2seproject1:manifest>
|
||||
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
|
||||
</j2seproject1:manifest>
|
||||
</j2seproject1:jar>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<pathconvert property="run.classpath.with.dist.jar">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
|
||||
</pathconvert>
|
||||
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<pathconvert property="run.classpath.without.build.classes.dir">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to=""/>
|
||||
</pathconvert>
|
||||
<pathconvert pathsep=" " property="jar.classpath">
|
||||
<path path="${run.classpath.without.build.classes.dir}"/>
|
||||
<chainedmapper>
|
||||
<flattenmapper/>
|
||||
<globmapper from="*" to="lib/*"/>
|
||||
</chainedmapper>
|
||||
</pathconvert>
|
||||
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
|
||||
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main.class}"/>
|
||||
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||
</manifest>
|
||||
</copylibs>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<echo>java -jar "${dist.jar.resolved}"</echo>
|
||||
</target>
|
||||
<target name="-post-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
|
||||
<!--
|
||||
=================
|
||||
EXECUTION SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init,compile" description="Run a main class." name="run">
|
||||
<j2seproject1:java>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<target name="-do-not-recompile">
|
||||
<property name="javac.includes.binary" value=""/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single" name="run-single">
|
||||
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
|
||||
<j2seproject1:java classname="${run.class}"/>
|
||||
</target>
|
||||
<!--
|
||||
=================
|
||||
DEBUGGING SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
|
||||
<j2seproject1:nbjpdastart name="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile" name="-debug-start-debuggee">
|
||||
<j2seproject3:debug>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
|
||||
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
|
||||
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
|
||||
<j2seproject3:debug classname="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
|
||||
<target depends="init" name="-pre-debug-fix">
|
||||
<fail unless="fix.includes">Must set fix.includes</fail>
|
||||
<property name="javac.includes" value="${fix.includes}.java"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
|
||||
<j2seproject1:nbjpdareload/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
|
||||
<!--
|
||||
===============
|
||||
JAVADOC SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="-javadoc-build">
|
||||
<mkdir dir="${dist.javadoc.dir}"/>
|
||||
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
|
||||
<classpath>
|
||||
<path path="${javac.classpath}"/>
|
||||
</classpath>
|
||||
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
|
||||
<filename name="**/*.java"/>
|
||||
</fileset>
|
||||
</javadoc>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
|
||||
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
|
||||
<!--
|
||||
=========================
|
||||
JUNIT COMPILATION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
|
||||
<mkdir dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-test-depend">
|
||||
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
|
||||
<target name="-pre-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT EXECUTION SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init" if="have.tests" name="-pre-test-run">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
|
||||
<j2seproject3:junit testincludes="**/*Test.java"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init" if="have.tests" name="test-report"/>
|
||||
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
|
||||
<target depends="init" if="have.tests" name="-pre-test-run-single">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
|
||||
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
|
||||
<j2seproject3:junit excludes="" includes="${test.includes}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT DEBUGGING SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
|
||||
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
|
||||
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
|
||||
<delete file="${test.report.file}"/>
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
|
||||
<customize>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<arg value="${test.class}"/>
|
||||
<arg value="showoutput=true"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
|
||||
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
|
||||
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
|
||||
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
|
||||
<!--
|
||||
=========================
|
||||
APPLET EXECUTION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" name="run-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject1:java classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<!--
|
||||
=========================
|
||||
APPLET DEBUGGING SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject3:debug classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
|
||||
<!--
|
||||
===============
|
||||
CLEANUP SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="deps-clean" unless="no.deps"/>
|
||||
<target depends="init" name="-do-clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</target>
|
||||
<target name="-post-clean">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
|
||||
</project>
|
8
apps/BOB/nbproject/genfiles.properties
Normal file
8
apps/BOB/nbproject/genfiles.properties
Normal file
@ -0,0 +1,8 @@
|
||||
build.xml.data.CRC32=209349b6
|
||||
build.xml.script.CRC32=403e69e6
|
||||
build.xml.stylesheet.CRC32=958a1d3e
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=209349b6
|
||||
nbproject/build-impl.xml.script.CRC32=75fac64c
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
|
7
apps/BOB/nbproject/private/private.properties
Normal file
7
apps/BOB/nbproject/private/private.properties
Normal file
@ -0,0 +1,7 @@
|
||||
compile.on.save=false
|
||||
do.depend=false
|
||||
do.jar=true
|
||||
javac.debug=true
|
||||
javadoc.preview=true
|
||||
jaxws.endorsed.dir=/usr/local/netbeans-6.5/java2/modules/ext/jaxws21/api:/usr/local/netbeans-6.5/ide10/modules/ext/jaxb/api
|
||||
user.properties.file=/root/.netbeans/6.5/build.properties
|
4
apps/BOB/nbproject/private/private.xml
Normal file
4
apps/BOB/nbproject/private/private.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
|
||||
</project-private>
|
107
apps/BOB/nbproject/project.properties
Normal file
107
apps/BOB/nbproject/project.properties
Normal file
@ -0,0 +1,107 @@
|
||||
application.title=BOB
|
||||
application.vendor=root
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=8
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/BOB.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
excludes=
|
||||
file.reference.core.jar=../i2p.i2p/core/dist/core.jar
|
||||
file.reference.i2p.jar=../../bob/i2p/i2p.i2p/build/i2p.jar
|
||||
file.reference.i2p.jar-1=../../core/java/build/i2p.jar
|
||||
file.reference.i2p.jar-2=../i2p.i2p/core/java/build/i2p.jar
|
||||
file.reference.i2ptunnel.jar=../i2ptunnel/java/build/i2ptunnel.jar
|
||||
file.reference.java-src=../i2p.i2p/core/java/src/
|
||||
file.reference.jbigi.jar=../../bob/i2p/i2p.i2p/build/jbigi.jar
|
||||
file.reference.mstreaming.jar=../../bob/i2p/i2p.i2p/build/mstreaming.jar
|
||||
file.reference.mstreaming.jar-1=../ministreaming/java/build/mstreaming.jar
|
||||
file.reference.NetBeansProjects-i2p.i2p=../i2p.i2p/
|
||||
file.reference.streaming.jar=../../bob/i2p/i2p.i2p/build/streaming.jar
|
||||
file.reference.streaming.jar-1=../streaming/java/build/streaming.jar
|
||||
file.reference.wrapper-freebsd=../../installer/lib/wrapper/freebsd/
|
||||
file.reference.wrapper-linux=../../installer/lib/wrapper/linux/
|
||||
file.reference.wrapper-linux64=../../installer/lib/wrapper/linux64/
|
||||
file.reference.wrapper-macosx=../../installer/lib/wrapper/macosx/
|
||||
file.reference.wrapper-solaris=../../installer/lib/wrapper/solaris/
|
||||
file.reference.wrapper-win32=../../installer/lib/wrapper/win32/
|
||||
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
|
||||
file.reference.wrapper.jar-1=../../installer/lib/wrapper/freebsd/wrapper.jar
|
||||
file.reference.wrapper.jar-2=../../installer/lib/wrapper/linux64/wrapper.jar
|
||||
file.reference.wrapper.jar-3=../../installer/lib/wrapper/macosx/wrapper.jar
|
||||
file.reference.wrapper.jar-4=../../installer/lib/wrapper/solaris/wrapper.jar
|
||||
file.reference.wrapper.jar-5=../../installer/lib/wrapper/win32/wrapper.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${file.reference.i2p.jar-1}:\
|
||||
${file.reference.i2ptunnel.jar}:\
|
||||
${file.reference.mstreaming.jar-1}:\
|
||||
${file.reference.streaming.jar-1}:\
|
||||
${file.reference.wrapper.jar-1}:\
|
||||
${file.reference.wrapper.jar}:\
|
||||
${file.reference.wrapper.jar-2}:\
|
||||
${file.reference.wrapper.jar-3}:\
|
||||
${file.reference.wrapper.jar-4}:\
|
||||
${file.reference.wrapper.jar-5}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.source=1.5
|
||||
javac.target=1.5
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}:\
|
||||
${libs.junit_4.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
jnlp.codebase.type=local
|
||||
jnlp.codebase.url=file:/root/NetBeansProjects/i2p.i2p/apps/BOB/dist/
|
||||
jnlp.descriptor=application
|
||||
jnlp.enabled=false
|
||||
jnlp.offline-allowed=false
|
||||
jnlp.signed=false
|
||||
main.class=net.i2p.BOB.Main
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
16
apps/BOB/nbproject/project.xml
Normal file
16
apps/BOB/nbproject/project.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>BOB</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
238
apps/BOB/src/net/i2p/BOB/BOB.java
Normal file
238
apps/BOB/src/net/i2p/BOB/BOB.java
Normal file
@ -0,0 +1,238 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Properties;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.streaming.RetransmissionTimer;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
/**
|
||||
* <span style="font-size:8px;font-family:courier;color:#EEEEEE;background-color:#000000">
|
||||
* ################################################################################<br>
|
||||
* ############################.#..........#..#..........##########################<br>
|
||||
* #######################......................................###################<br>
|
||||
* ####################...........................#.......#........################<br>
|
||||
* #################..................##...................#.........##############<br>
|
||||
* ###############................###...####.....#..###.....#.........#############<br>
|
||||
* #############...........###..#..###...#####...###.##........#.......############<br>
|
||||
* ###########................#......##...#####...##..##.......#..#........########<br>
|
||||
* ##########.........................#....##.##..#...##.....................######<br>
|
||||
* #########...................................#....#.........................#####<br>
|
||||
* ########.........................................#...............#..........####<br>
|
||||
* ########.........................................#..........#######..........###<br>
|
||||
* #######.................................................############..........##<br>
|
||||
* #######..........................................####################.........##<br>
|
||||
* #######............####################......########################.........##<br>
|
||||
* ######.............###############################################.##.........##<br>
|
||||
* ######............################################################..##........##<br>
|
||||
* ######............################################################..##........##<br>
|
||||
* ######.............##############################################..##.........##<br>
|
||||
* ######............##############################################...##..........#<br>
|
||||
* ######............#..###########################################...##..........#<br>
|
||||
* ######.............#############################################....#..........#<br>
|
||||
* #######...........###############################################..##.........##<br>
|
||||
* #######...........#####.#.#.#.########################.....#.####...##........##<br>
|
||||
* ######............#..............##################.................##.........#<br>
|
||||
* ######................####.........###############........#####......##........#<br>
|
||||
* ######..............####..#.........############.......##.#.######...##.......##<br>
|
||||
* ######.................#.####.........########...........##....###...##.......##<br>
|
||||
* #######....#....###...................#######...............#...###..##.......##<br>
|
||||
* #######.........###..###.....###.......######.##.#####.........####..##.......##<br>
|
||||
* #######.....#...##############.........############......###########.###......##<br>
|
||||
* #######....##...##########.......##...##############......#.############.....###<br>
|
||||
* ########....#..########......######...##################################....####<br>
|
||||
* ########....##.####################...##################################....####<br>
|
||||
* ########..#.##..###################..##################################..#..####<br>
|
||||
* ##########..###..#################...##################################...#.####<br>
|
||||
* #########....##...##############....########..#####.################.##..#.#####<br>
|
||||
* ############.##....##########.......#########.###.......###########..#.#########<br>
|
||||
* ###############.....#######...#.......########.....##.....######.....###########<br>
|
||||
* ###############......###....##..........##.......######....#.........#.#########<br>
|
||||
* ##############............##..................##########..............##########<br>
|
||||
* ##############..............................##########..#.............##########<br>
|
||||
* ###############.......##..................#####..............####....###########<br>
|
||||
* ###############.......#####.......#.............####.....#######.....###########<br>
|
||||
* ################...#...####......##################.....########....############<br>
|
||||
* ################...##..#####.........####.##.....#....##########....############<br>
|
||||
* ##################..##..####...........#####.#....############.....#############<br>
|
||||
* ##################......#####.................################....##############<br>
|
||||
* ###################.....####..........##########..###########....###############<br>
|
||||
* ####################..#..#..........................########.....###############<br>
|
||||
* #####################.##.......###.................########....#################<br>
|
||||
* ######################.........#.......#.##.###############....#################<br>
|
||||
* #############.#######...............#####################....###################<br>
|
||||
* ###..#.....##...####..........#.....####################....####################<br>
|
||||
* ####......##........................##################....######################<br>
|
||||
* #.##...###..............###.........###############......#######################<br>
|
||||
* #...###..##............######...........................########################<br>
|
||||
* ##.......###..........##########....#...#...........############################<br>
|
||||
* ##.........##.......############################################################<br>
|
||||
* ###........##.....##############################################################<br>
|
||||
* ####.............###############################################################<br>
|
||||
* ######.........#################################################################<br>
|
||||
* #########....###################################################################<br>
|
||||
* ################################################################################<br>
|
||||
* </span>
|
||||
* BOB, main command socket listener, launches the command parser engine.
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class BOB {
|
||||
|
||||
private final static Log _log = new Log(BOB.class);
|
||||
public final static String PROP_CONFIG_LOCATION = "BOB.config";
|
||||
public final static String PROP_BOB_PORT = "BOB.port";
|
||||
public final static String PROP_BOB_HOST = "BOB.host";
|
||||
private static int maxConnections = 0;
|
||||
private static NamedDB database;
|
||||
private static Properties props = new Properties();
|
||||
|
||||
|
||||
/**
|
||||
* Log a warning
|
||||
*
|
||||
* @param arg
|
||||
*/
|
||||
public static void info(String arg) {
|
||||
System.out.println("INFO:" + arg);
|
||||
_log.info(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a warning
|
||||
*
|
||||
* @param arg
|
||||
*/
|
||||
public static void warn(String arg) {
|
||||
System.out.println("WARNING:" + arg);
|
||||
_log.warn(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an error
|
||||
*
|
||||
* @param arg
|
||||
*/
|
||||
public static void error(String arg) {
|
||||
System.out.println("ERROR: " + arg);
|
||||
_log.error(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for incoming connections and handle them
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
database = new NamedDB();
|
||||
int i = 0;
|
||||
boolean save = false;
|
||||
// Set up all defaults to be passed forward to other threads.
|
||||
// Re-reading the config file in each thread is pretty damn stupid.
|
||||
// I2PClient client = I2PClientFactory.createClient();
|
||||
String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config");
|
||||
|
||||
// This is here just to ensure there is no interference with our threadgroups.
|
||||
SimpleTimer Y = RetransmissionTimer.getInstance();
|
||||
i = Y.hashCode();
|
||||
{
|
||||
try {
|
||||
FileInputStream fi = new FileInputStream(configLocation);
|
||||
props.load(fi);
|
||||
fi.close();
|
||||
} catch(FileNotFoundException fnfe) {
|
||||
warn("Unable to load up the BOB config file " + configLocation + ", Using defaults.");
|
||||
warn(fnfe.toString());
|
||||
save = true;
|
||||
} catch(IOException ioe) {
|
||||
warn("IOException on BOB config file " + configLocation + ", using defaults.");
|
||||
warn(ioe.toString());
|
||||
}
|
||||
}
|
||||
// Global router and client API configurations that are missing are set to defaults here.
|
||||
if(!props.containsKey(I2PClient.PROP_TCP_HOST)) {
|
||||
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
|
||||
}
|
||||
if(!props.containsKey(I2PClient.PROP_TCP_PORT)) {
|
||||
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
|
||||
}
|
||||
if(!props.containsKey(I2PClient.PROP_RELIABILITY)) {
|
||||
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
|
||||
}
|
||||
if(!props.containsKey(PROP_BOB_PORT)) {
|
||||
props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
|
||||
}
|
||||
if(!props.containsKey("inbound.length")) {
|
||||
props.setProperty("inbound.length", "1");
|
||||
}
|
||||
if(!props.containsKey("outbound.length")) {
|
||||
props.setProperty("outbound.length", "1");
|
||||
}
|
||||
if(!props.containsKey("inbound.lengthVariance")) {
|
||||
props.setProperty("inbound.lengthVariance", "0");
|
||||
}
|
||||
if(!props.containsKey("outbound.lengthVariance")) {
|
||||
props.setProperty("outbound.lengthVariance", "0");
|
||||
}
|
||||
if(!props.containsKey(PROP_BOB_HOST)) {
|
||||
props.setProperty(PROP_BOB_HOST, "localhost");
|
||||
}
|
||||
if(save) {
|
||||
try {
|
||||
warn("Writing new defaults file " + configLocation);
|
||||
FileOutputStream fo = new FileOutputStream(configLocation);
|
||||
props.store(fo, configLocation);
|
||||
fo.close();
|
||||
} catch(IOException ioe) {
|
||||
error("IOException on BOB config file " + configLocation + ", " + ioe);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
info("BOB is now running.");
|
||||
ServerSocket listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
|
||||
Socket server;
|
||||
|
||||
while((i++ < maxConnections) || (maxConnections == 0)) {
|
||||
//DoCMDS connection;
|
||||
|
||||
server = listener.accept();
|
||||
DoCMDS conn_c = new DoCMDS(server, props, database, _log);
|
||||
Thread t = new Thread(conn_c);
|
||||
t.start();
|
||||
}
|
||||
} catch(IOException ioe) {
|
||||
error("IOException on socket listen: " + ioe);
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
21
apps/BOB/src/net/i2p/BOB/COPYING
Normal file
21
apps/BOB/src/net/i2p/BOB/COPYING
Normal file
@ -0,0 +1,21 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) sponge
|
||||
Planet Earth
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
See...
|
||||
|
||||
http://sam.zoy.org/wtfpl/
|
||||
and
|
||||
http://en.wikipedia.org/wiki/WTFPL
|
||||
|
||||
...for any additional details and license questions.
|
1427
apps/BOB/src/net/i2p/BOB/DoCMDS.java
Normal file
1427
apps/BOB/src/net/i2p/BOB/DoCMDS.java
Normal file
File diff suppressed because it is too large
Load Diff
137
apps/BOB/src/net/i2p/BOB/I2Plistener.java
Normal file
137
apps/BOB/src/net/i2p/BOB/I2Plistener.java
Normal file
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Listen on I2P and connect to TCP
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class I2Plistener implements Runnable {
|
||||
|
||||
private NamedDB info, database;
|
||||
private Log _log;
|
||||
private int tgwatch;
|
||||
public I2PSocketManager socketManager;
|
||||
public I2PServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param S
|
||||
* @param info
|
||||
* @param database
|
||||
* @param _log
|
||||
*/
|
||||
I2Plistener(I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
|
||||
this.database = database;
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
this.socketManager = S;
|
||||
serverSocket = this.socketManager.getServerSocket();
|
||||
tgwatch = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listen on I2P port, and thread connections
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
boolean g = false;
|
||||
I2PSocket sessSocket = null;
|
||||
|
||||
serverSocket.setSoTimeout(100);
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
if(info.exists("INPORT")) {
|
||||
tgwatch = 2;
|
||||
}
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
boolean spin = true;
|
||||
while(spin) {
|
||||
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
try {
|
||||
try {
|
||||
sessSocket = serverSocket.accept();
|
||||
g = true;
|
||||
} catch(ConnectException ce) {
|
||||
g = false;
|
||||
} catch(SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if(g) {
|
||||
g = false;
|
||||
// toss the connection to a new thread.
|
||||
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database);
|
||||
Thread t = new Thread(conn_c, "BOBI2PtoTCP");
|
||||
t.start();
|
||||
}
|
||||
|
||||
} catch(I2PException e) {
|
||||
// System.out.println("Exception " + e);
|
||||
}
|
||||
}
|
||||
// System.out.println("I2Plistener: Close");
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch(I2PException e) {
|
||||
// nop
|
||||
}
|
||||
// need to kill off the socket manager too.
|
||||
I2PSession session = socketManager.getSession();
|
||||
if(session != null) {
|
||||
// System.out.println("I2Plistener: destroySession");
|
||||
try {
|
||||
session.destroySession();
|
||||
} catch(I2PSessionException ex) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
// System.out.println("I2Plistener: Waiting for children");
|
||||
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
|
||||
try {
|
||||
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
||||
} catch(Exception e) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
|
||||
// System.out.println("I2Plistener: Done.");
|
||||
}
|
||||
}
|
144
apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
Normal file
144
apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
|
||||
/**
|
||||
* Process I2P->TCP
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class I2PtoTCP implements Runnable {
|
||||
|
||||
private I2PSocket I2P;
|
||||
private NamedDB info, database;
|
||||
private Socket sock;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param I2Psock
|
||||
* @param info
|
||||
* @param database
|
||||
*/
|
||||
I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database) {
|
||||
this.I2P = I2Psock;
|
||||
this.info = info;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
private void rlock() throws Exception {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() throws Exception {
|
||||
database.releaseReadLock();
|
||||
info.releaseReadLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* I2P stream to TCP stream thread starter
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
String host;
|
||||
int port;
|
||||
boolean tell;
|
||||
die: {
|
||||
try {
|
||||
try {
|
||||
rlock();
|
||||
} catch(Exception e) {
|
||||
break die;
|
||||
}
|
||||
try {
|
||||
host = info.get("OUTHOST").toString();
|
||||
port = Integer.parseInt(info.get("OUTPORT").toString());
|
||||
tell = info.get("QUIET").equals(Boolean.FALSE);
|
||||
} catch(Exception e) {
|
||||
runlock();
|
||||
break die;
|
||||
}
|
||||
try {
|
||||
runlock();
|
||||
} catch(Exception e) {
|
||||
break die;
|
||||
}
|
||||
sock = new Socket(host, port);
|
||||
// make readers/writers
|
||||
InputStream in = sock.getInputStream();
|
||||
OutputStream out = sock.getOutputStream();
|
||||
InputStream Iin = I2P.getInputStream();
|
||||
OutputStream Iout = I2P.getOutputStream();
|
||||
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
|
||||
|
||||
if(tell) {
|
||||
// tell who is connecting
|
||||
out.write(I2P.getPeerDestination().toBase64().getBytes());
|
||||
out.write(10); // nl
|
||||
out.flush(); // not really needed, but...
|
||||
}
|
||||
// setup to cross the streams
|
||||
TCPio conn_c = new TCPio(in, Iout, info, database); // app -> I2P
|
||||
TCPio conn_a = new TCPio(Iin, out, info, database); // I2P -> app
|
||||
Thread t = new Thread(conn_c, "TCPioA");
|
||||
Thread q = new Thread(conn_a, "TCPioB");
|
||||
// Fire!
|
||||
t.start();
|
||||
q.start();
|
||||
while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
|
||||
try {
|
||||
Thread.sleep(10); //sleep for 10 ms
|
||||
} catch(InterruptedException e) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
// System.out.println("I2PtoTCP: Going away...");
|
||||
} catch(Exception e) {
|
||||
// System.out.println("I2PtoTCP: Owch! damn!");
|
||||
break die;
|
||||
}
|
||||
} // die
|
||||
try {
|
||||
// System.out.println("I2PtoTCP: Close I2P");
|
||||
I2P.close();
|
||||
} catch(Exception e) {
|
||||
tell = false;
|
||||
}
|
||||
//System.out.println("I2PtoTCP: Closed I2P");
|
||||
try {
|
||||
// System.out.println("I2PtoTCP: Close sock");
|
||||
sock.close();
|
||||
} catch(Exception e) {
|
||||
tell = false;
|
||||
}
|
||||
// System.out.println("I2PtoTCP: Done");
|
||||
|
||||
}
|
||||
}
|
56
apps/BOB/src/net/i2p/BOB/Lifted.java
Normal file
56
apps/BOB/src/net/i2p/BOB/Lifted.java
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Sets of "friendly" utilities to make life easier.
|
||||
* Any "Lifted" code will apear here, and credits given.
|
||||
* It's better to "Lift" a small chunk of "free" code than add in piles of
|
||||
* code we don't need, and don't want.
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class Lifted {
|
||||
|
||||
/**
|
||||
* Copy a set of properties from one Property to another.
|
||||
* Lifted from Apache Derby code svn repository.
|
||||
* Liscenced as follows:
|
||||
* http://svn.apache.org/repos/asf/db/derby/code/trunk/LICENSE
|
||||
*
|
||||
* @param src_prop Source set of properties to copy from.
|
||||
* @param dest_prop Dest Properties to copy into.
|
||||
*
|
||||
**/
|
||||
public static void copyProperties(Properties src_prop, Properties dest_prop) {
|
||||
for (Enumeration propertyNames = src_prop.propertyNames();
|
||||
propertyNames.hasMoreElements();) {
|
||||
Object key = propertyNames.nextElement();
|
||||
dest_prop.put(key, src_prop.get(key));
|
||||
}
|
||||
}
|
||||
}
|
276
apps/BOB/src/net/i2p/BOB/MUXlisten.java
Normal file
276
apps/BOB/src/net/i2p/BOB/MUXlisten.java
Normal file
@ -0,0 +1,276 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Properties;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
||||
import net.i2p.util.Log;
|
||||
import org.tanukisoftware.wrapper.WrapperManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* Multiplex listeners for TCP and I2P
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class MUXlisten implements Runnable {
|
||||
|
||||
private NamedDB database, info;
|
||||
private Log _log;
|
||||
private I2PSocketManager socketManager;
|
||||
private ByteArrayInputStream prikey;
|
||||
private ThreadGroup tg;
|
||||
private String N;
|
||||
private ServerSocket listener;
|
||||
private int backlog = 50; // should this be more? less?
|
||||
boolean go_out;
|
||||
boolean come_in;
|
||||
|
||||
/**
|
||||
* Constructor Will fail if INPORT is occupied.
|
||||
*
|
||||
* @param info
|
||||
* @param database
|
||||
* @param _log
|
||||
* @throws net.i2p.I2PException
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
MUXlisten(NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
|
||||
int port = 0;
|
||||
InetAddress host = null;
|
||||
this.tg = null;
|
||||
this.database = database;
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
|
||||
this.database.getReadLock();
|
||||
this.info.getReadLock();
|
||||
N = this.info.get("NICKNAME").toString();
|
||||
prikey = new ByteArrayInputStream((byte[])info.get("KEYS"));
|
||||
// Make a new copy so that anything else won't muck with our database.
|
||||
Properties R = (Properties)info.get("PROPERTIES");
|
||||
Properties Q = new Properties();
|
||||
Lifted.copyProperties(R, Q);
|
||||
this.database.releaseReadLock();
|
||||
this.info.releaseReadLock();
|
||||
|
||||
this.database.getReadLock();
|
||||
this.info.getReadLock();
|
||||
this.go_out = info.exists("OUTPORT");
|
||||
this.come_in = info.exists("INPORT");
|
||||
if(this.come_in) {
|
||||
port = Integer.parseInt(info.get("INPORT").toString());
|
||||
host = InetAddress.getByName(info.get("INHOST").toString());
|
||||
}
|
||||
this.database.releaseReadLock();
|
||||
this.info.releaseReadLock();
|
||||
|
||||
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
|
||||
if(this.come_in) {
|
||||
this.listener = new ServerSocket(port, backlog, host);
|
||||
}
|
||||
|
||||
// Everything is OK as far as we can tell.
|
||||
this.database.getWriteLock();
|
||||
this.info.getWriteLock();
|
||||
this.info.add("STARTING", Boolean.TRUE);
|
||||
this.info.releaseWriteLock();
|
||||
this.database.releaseWriteLock();
|
||||
}
|
||||
|
||||
private void rlock() throws Exception {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() throws Exception {
|
||||
database.releaseReadLock();
|
||||
info.releaseReadLock();
|
||||
}
|
||||
|
||||
private void wlock() throws Exception {
|
||||
database.getWriteLock();
|
||||
info.getWriteLock();
|
||||
}
|
||||
|
||||
private void wunlock() throws Exception {
|
||||
info.releaseWriteLock();
|
||||
database.releaseWriteLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* MUX sockets, fire off a thread to connect, get destination info, and do I/O
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
info.add("RUNNING", Boolean.TRUE);
|
||||
info.add("STARTING", Boolean.FALSE);
|
||||
} catch(Exception e) {
|
||||
wunlock();
|
||||
return;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
wunlock();
|
||||
} catch(Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
quit: {
|
||||
try {
|
||||
tg = new ThreadGroup(N);
|
||||
die: {
|
||||
// toss the connections to a new threads.
|
||||
// will wrap with TCP and UDP when UDP works
|
||||
|
||||
if(go_out) {
|
||||
// I2P -> TCP
|
||||
I2Plistener conn = new I2Plistener(socketManager, info, database, _log);
|
||||
Thread t = new Thread(tg, conn, "BOBI2Plistener " + N);
|
||||
t.start();
|
||||
}
|
||||
|
||||
if(come_in) {
|
||||
// TCP -> I2P
|
||||
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log);
|
||||
Thread q = new Thread(tg, conn, "BOBTCPlistener" + N);
|
||||
q.start();
|
||||
}
|
||||
|
||||
boolean spin = true;
|
||||
while(spin) {
|
||||
try {
|
||||
Thread.sleep(1000); //sleep for 1000 ms (One second)
|
||||
} catch(InterruptedException e) {
|
||||
// nop
|
||||
}
|
||||
try {
|
||||
rlock();
|
||||
try {
|
||||
spin = info.get("STOPPING").equals(Boolean.FALSE);
|
||||
} catch(Exception e) {
|
||||
runlock();
|
||||
break die;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
break die;
|
||||
}
|
||||
try {
|
||||
runlock();
|
||||
} catch(Exception e) {
|
||||
break die;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
info.add("RUNNING", Boolean.FALSE);
|
||||
} catch(Exception e) {
|
||||
wunlock();
|
||||
break die;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
break die;
|
||||
}
|
||||
try {
|
||||
wunlock();
|
||||
} catch(Exception e) {
|
||||
break die;
|
||||
}
|
||||
} // die
|
||||
|
||||
// wait for child threads and thread groups to die
|
||||
// System.out.println("MUXlisten: waiting for children");
|
||||
while(tg.activeCount() + tg.activeGroupCount() != 0) {
|
||||
tg.interrupt(); // unwedge any blocking threads.
|
||||
try {
|
||||
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
||||
} catch(InterruptedException ex) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
tg.destroy();
|
||||
// Zap reference to the ThreadGroup so the JVM can GC it.
|
||||
tg = null;
|
||||
} catch(Exception e) {
|
||||
// System.out.println("MUXlisten: Caught an exception" + e);
|
||||
break quit;
|
||||
}
|
||||
} // quit
|
||||
// This is here to catch when something fucks up REALLY bad.
|
||||
if(tg != null) {
|
||||
System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
|
||||
System.out.println("BOB: MUXlisten: Please email the following dump to sponge@mail.i2p");
|
||||
WrapperManager.requestThreadDump();
|
||||
System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
|
||||
System.out.println("BOB: MUXlisten: Please email the above dump to sponge@mail.i2p");
|
||||
}
|
||||
// zero out everything, just incase.
|
||||
try {
|
||||
socketManager.destroySocketManager();
|
||||
} catch(Exception e) {
|
||||
// nop
|
||||
}
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
info.add("STARTING", Boolean.FALSE);
|
||||
info.add("STOPPING", Boolean.FALSE);
|
||||
info.add("RUNNING", Boolean.FALSE);
|
||||
} catch(Exception e) {
|
||||
wunlock();
|
||||
return;
|
||||
}
|
||||
wunlock();
|
||||
} catch(Exception e) {
|
||||
}
|
||||
// This is here to catch when something fucks up REALLY bad.
|
||||
if(tg != null) {
|
||||
while(tg.activeCount() + tg.activeGroupCount() != 0) {
|
||||
tg.interrupt(); // unwedge any blocking threads.
|
||||
try {
|
||||
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
||||
} catch(InterruptedException ex) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
tg.destroy();
|
||||
// Zap reference to the ThreadGroup so the JVM can GC it.
|
||||
tg = null;
|
||||
}
|
||||
}
|
||||
}
|
46
apps/BOB/src/net/i2p/BOB/Main.java
Normal file
46
apps/BOB/src/net/i2p/BOB/Main.java
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import net.i2p.client.streaming.RetransmissionTimer;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
|
||||
/**
|
||||
* Start from command line
|
||||
*
|
||||
* @author sponge
|
||||
*
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments, these are not used yet
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// THINK THINK THINK THINK THINK THINK
|
||||
SimpleTimer Y = RetransmissionTimer.getInstance();
|
||||
BOB.main(args);
|
||||
Y.removeSimpleTimer();
|
||||
}
|
||||
}
|
195
apps/BOB/src/net/i2p/BOB/NamedDB.java
Normal file
195
apps/BOB/src/net/i2p/BOB/NamedDB.java
Normal file
@ -0,0 +1,195 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
/**
|
||||
* Internal database to relate nicknames to options to values
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class NamedDB {
|
||||
|
||||
private volatile Object[][] data;
|
||||
private volatile int index, writersWaiting, readers;
|
||||
|
||||
/**
|
||||
* make initial NULL object
|
||||
*
|
||||
*/
|
||||
public NamedDB() {
|
||||
this.data = new Object[1][2];
|
||||
this.index = this.writersWaiting = this.readers = 0;
|
||||
}
|
||||
|
||||
synchronized public void getReadLock() {
|
||||
while((writersWaiting != 0)) {
|
||||
try {
|
||||
wait();
|
||||
} catch(InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
readers++;
|
||||
}
|
||||
|
||||
synchronized public void releaseReadLock() {
|
||||
readers--;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized public void getWriteLock() {
|
||||
writersWaiting++;
|
||||
while(readers != 0 && writersWaiting != 1 ) {
|
||||
try {
|
||||
wait();
|
||||
} catch(InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public void releaseWriteLock() {
|
||||
writersWaiting--;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find objects in the array, returns it's index or throws exception
|
||||
* @param key
|
||||
* @return an objects index
|
||||
* @throws ArrayIndexOutOfBoundsException when key does not exist
|
||||
*/
|
||||
public int idx(Object key) throws ArrayIndexOutOfBoundsException {
|
||||
for(int i = 0; i < index; i++) {
|
||||
if(key.equals(data[i][0])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new ArrayIndexOutOfBoundsException("Can't locate key for index");
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an object from array if it exists
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void kill(Object key) {
|
||||
|
||||
int i, j, k, l;
|
||||
Object[][] olddata;
|
||||
int didsomething = 0;
|
||||
|
||||
try {
|
||||
k = idx(key);
|
||||
} catch(ArrayIndexOutOfBoundsException b) {
|
||||
return;
|
||||
}
|
||||
olddata = new Object[index + 2][2];
|
||||
// copy to olddata, skipping 'k'
|
||||
for(i = 0 , l = 0; l < index; i++, l++) {
|
||||
if(i == k) {
|
||||
l++;
|
||||
didsomething++;
|
||||
}
|
||||
for(j = 0; j < 2; j++) {
|
||||
olddata[i][j] = data[l][j];
|
||||
}
|
||||
}
|
||||
index -= didsomething;
|
||||
data = olddata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add object to the array, deletes the old one if it exists
|
||||
*
|
||||
* @param key
|
||||
* @param val
|
||||
*/
|
||||
public void add(Object key, Object val) {
|
||||
Object[][] olddata;
|
||||
int i, j;
|
||||
i = 0;
|
||||
kill(key);
|
||||
|
||||
olddata = new Object[index + 2][2];
|
||||
// copy to olddata
|
||||
for(i = 0; i < index; i++) {
|
||||
for(j = 0; j < 2; j++) {
|
||||
olddata[i][j] = data[i][j];
|
||||
}
|
||||
}
|
||||
data = olddata;
|
||||
data[index++] = new Object[] {key, val};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object, and return it, throws RuntimeException
|
||||
*
|
||||
* @param key
|
||||
* @return Object
|
||||
* @throws java.lang.RuntimeException
|
||||
*/
|
||||
public Object get(Object key) throws RuntimeException {
|
||||
for(int i = 0; i < index; i++) {
|
||||
if(key.equals(data[i][0])) {
|
||||
return data[i][1];
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Key not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if an object exists, else returns false
|
||||
*
|
||||
* @param key
|
||||
* @return true if an object exists, else returns false
|
||||
*/
|
||||
public boolean exists(Object key) {
|
||||
for(int i = 0; i < index; i++) {
|
||||
if(key.equals(data[i][0])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i index
|
||||
* @return an indexed Object
|
||||
* @throws java.lang.RuntimeException
|
||||
*/
|
||||
public Object getnext(int i) throws RuntimeException {
|
||||
if(i < index && i > -1) {
|
||||
return data[i][1];
|
||||
}
|
||||
throw new RuntimeException("No more data");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the count of how many objects
|
||||
*/
|
||||
public int getcount() {
|
||||
return index;
|
||||
}
|
||||
}
|
105
apps/BOB/src/net/i2p/BOB/TCPio.java
Normal file
105
apps/BOB/src/net/i2p/BOB/TCPio.java
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Shove data from one stream to the other.
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class TCPio implements Runnable {
|
||||
|
||||
private InputStream Ain;
|
||||
private OutputStream Aout;
|
||||
private NamedDB info, database;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Ain
|
||||
* @param Aout
|
||||
* @param info
|
||||
* @param database
|
||||
*/
|
||||
TCPio(InputStream Ain, OutputStream Aout, NamedDB info, NamedDB database) {
|
||||
this.Ain = Ain;
|
||||
this.Aout = Aout;
|
||||
this.info = info;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy from source to destination...
|
||||
* and yes, we are totally OK to block here on writes,
|
||||
* The OS has buffers, and I intend to use them.
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
int b;
|
||||
byte a[] = new byte[1];
|
||||
boolean spin = true;
|
||||
try {
|
||||
while(spin) {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
b = Ain.read(a, 0, 1);
|
||||
// System.out.println(info.get("NICKNAME").toString() + " " + b);
|
||||
if(b > 0) {
|
||||
Aout.write(a, 0, b);
|
||||
} else if(b == 0) {
|
||||
Thread.yield(); // this should act like a mini sleep.
|
||||
if(Ain.available() == 0) {
|
||||
try {
|
||||
// Thread.yield();
|
||||
Thread.sleep(10);
|
||||
} catch(InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* according to the specs:
|
||||
*
|
||||
* The total number of bytes read into the buffer,
|
||||
* or -1 if there is no more data because the end of
|
||||
* the stream has been reached.
|
||||
*
|
||||
*/
|
||||
// System.out.println("TCPio: End Of Stream");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// System.out.println("TCPio: RUNNING = false");
|
||||
} catch(Exception e) {
|
||||
// Eject!!! Eject!!!
|
||||
// System.out.println("TCPio: Caught an exception " + e);
|
||||
return;
|
||||
}
|
||||
// System.out.println("TCPio: Leaving.");
|
||||
}
|
||||
}
|
147
apps/BOB/src/net/i2p/BOB/TCPlistener.java
Normal file
147
apps/BOB/src/net/i2p/BOB/TCPlistener.java
Normal file
@ -0,0 +1,147 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Listen on TCP port and connect to I2P
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class TCPlistener implements Runnable {
|
||||
|
||||
private NamedDB info, database;
|
||||
private Log _log;
|
||||
private int tgwatch;
|
||||
public I2PSocketManager socketManager;
|
||||
public I2PServerSocket serverSocket;
|
||||
private ServerSocket listener;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param S
|
||||
* @param info
|
||||
* @param database
|
||||
* @param _log
|
||||
*/
|
||||
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
|
||||
this.database = database;
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
this.socketManager = S;
|
||||
this.listener = listener;
|
||||
tgwatch = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listen on TCP port, and thread connections
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
boolean g = false;
|
||||
boolean spin = true;
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
if(info.exists("OUTPORT")) {
|
||||
tgwatch = 2;
|
||||
}
|
||||
try {
|
||||
Socket server = new Socket();
|
||||
listener.setSoTimeout(1000);
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
while(spin) {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
try {
|
||||
server = listener.accept();
|
||||
g = true;
|
||||
} catch(SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if(g) {
|
||||
// toss the connection to a new thread.
|
||||
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database);
|
||||
Thread t = new Thread(conn_c, "BOBTCPtoI2P");
|
||||
t.start();
|
||||
g = false;
|
||||
}
|
||||
}
|
||||
//System.out.println("TCPlistener: destroySession");
|
||||
listener.close();
|
||||
} catch(IOException ioe) {
|
||||
try {
|
||||
listener.close();
|
||||
} catch(IOException e) {
|
||||
}
|
||||
// Fatal failure, cause a stop event
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
if(spin) {
|
||||
database.getWriteLock();
|
||||
info.getWriteLock();
|
||||
info.add("STOPPING", new Boolean(true));
|
||||
info.add("RUNNING", new Boolean(false));
|
||||
info.releaseWriteLock();
|
||||
database.releaseWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
// need to kill off the socket manager too.
|
||||
I2PSession session = socketManager.getSession();
|
||||
if(session != null) {
|
||||
try {
|
||||
session.destroySession();
|
||||
} catch(I2PSessionException ex) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
//System.out.println("TCPlistener: Waiting for children");
|
||||
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
|
||||
try {
|
||||
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
||||
} catch(Exception e) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
//System.out.println("TCPlistener: Done.");
|
||||
}
|
||||
}
|
||||
|
||||
|
186
apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
Normal file
186
apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
Normal file
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.Socket;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
|
||||
/**
|
||||
*
|
||||
* Process TCP->I2P
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class TCPtoI2P implements Runnable {
|
||||
|
||||
private I2PSocket I2P;
|
||||
private NamedDB info, database;
|
||||
private Socket sock;
|
||||
private I2PSocketManager socketManager;
|
||||
|
||||
/**
|
||||
* This is a more forgiving readline,
|
||||
* it works on unbuffered streams
|
||||
*
|
||||
* @param in
|
||||
* @return line of text as a String
|
||||
* @throws Exception
|
||||
*/
|
||||
private static String lnRead(InputStream in) throws Exception {
|
||||
String S;
|
||||
int b;
|
||||
char c;
|
||||
|
||||
S = new String();
|
||||
|
||||
while(true) {
|
||||
b = in.read();
|
||||
if(b == 13) {
|
||||
//skip CR
|
||||
continue;
|
||||
}
|
||||
if(b < 20 || b > 126) {
|
||||
// exit on anything not legal
|
||||
break;
|
||||
}
|
||||
c = (char)(b & 0x7f); // We only really give a fuck about ASCII
|
||||
S = new String(S + c);
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param i2p
|
||||
* @param socket
|
||||
* @param info
|
||||
* @param database
|
||||
*/
|
||||
TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database) {
|
||||
this.sock = socket;
|
||||
this.info = info;
|
||||
this.database = database;
|
||||
this.socketManager = i2p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message to out
|
||||
*
|
||||
* @param e
|
||||
* @param out
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
private void Emsg(String e, OutputStream out) throws IOException {
|
||||
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
|
||||
out.write("ERROR".concat(e).getBytes());
|
||||
out.write(13); // cr
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* TCP stream to I2P stream thread starter
|
||||
*/
|
||||
public void run() {
|
||||
String line, input;
|
||||
|
||||
try {
|
||||
|
||||
InputStream in = sock.getInputStream();
|
||||
OutputStream out = sock.getOutputStream();
|
||||
try {
|
||||
line = lnRead(in);
|
||||
input = line.toLowerCase();
|
||||
Destination dest = null;
|
||||
|
||||
if(input.endsWith(".i2p")) {
|
||||
dest = I2PTunnel.destFromName(input);
|
||||
line = dest.toBase64();
|
||||
}
|
||||
dest = new Destination();
|
||||
dest.fromBase64(line);
|
||||
|
||||
try {
|
||||
// get a client socket
|
||||
I2P = socketManager.connect(dest);
|
||||
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
|
||||
// make readers/writers
|
||||
InputStream Iin = I2P.getInputStream();
|
||||
OutputStream Iout = I2P.getOutputStream();
|
||||
// setup to cross the streams
|
||||
TCPio conn_c = new TCPio(in, Iout, info, database); // app -> I2P
|
||||
TCPio conn_a = new TCPio(Iin, out, info, database); // I2P -> app
|
||||
Thread t = new Thread(conn_c, "TCPioA");
|
||||
Thread q = new Thread(conn_a, "TCPioB");
|
||||
// Fire!
|
||||
t.start();
|
||||
q.start();
|
||||
while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
|
||||
try {
|
||||
Thread.sleep(10); //sleep for 10 ms
|
||||
} catch(InterruptedException e) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
// System.out.println("TCPtoI2P: Going away...");
|
||||
|
||||
} catch(I2PException e) {
|
||||
Emsg("ERROR " + e.toString(), out);
|
||||
} catch(ConnectException e) {
|
||||
Emsg("ERROR " + e.toString(), out);
|
||||
} catch(NoRouteToHostException e) {
|
||||
Emsg("ERROR " + e.toString(), out);
|
||||
} catch(InterruptedIOException e) {
|
||||
Emsg("ERROR " + e.toString(), out);
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
Emsg("ERROR " + e.toString(), out);
|
||||
}
|
||||
} catch(IOException ioe) {
|
||||
}
|
||||
try {
|
||||
// System.out.println("TCPtoI2P: Close I2P");
|
||||
I2P.close();
|
||||
} catch(Exception e) {
|
||||
}
|
||||
|
||||
try {
|
||||
// System.out.println("TCPtoI2P: Close sock");
|
||||
sock.close();
|
||||
} catch(Exception e) {
|
||||
}
|
||||
// System.out.println("TCPtoI2P: Done.");
|
||||
|
||||
}
|
||||
}
|
144
apps/BOB/src/net/i2p/BOB/UDPIOthread.java
Normal file
144
apps/BOB/src/net/i2p/BOB/UDPIOthread.java
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
* Everyone is permitted to copy and distribute verbatim or modified
|
||||
* copies of this license document, and changing it is allowed as long
|
||||
* as the name is changed.
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
*
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and liscense questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.I2PSessionListener;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* UDP IO on I2P
|
||||
*
|
||||
* FIX ME: Untested, and incomplete!
|
||||
* I have no personal need to UDP yet,
|
||||
* however alot of p2p apps pretty much demand it.
|
||||
* The skeletal frame is here, just needs to be finished.
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class UDPIOthread implements I2PSessionListener, Runnable {
|
||||
|
||||
private NamedDB info;
|
||||
private Log _log;
|
||||
private Socket socket;
|
||||
private DataInputStream in;
|
||||
private DataOutputStream out;
|
||||
private I2PSession _session;
|
||||
private Destination _peerDestination;
|
||||
private boolean up;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param info
|
||||
* @param _log
|
||||
* @param socket
|
||||
* @param _session
|
||||
*/
|
||||
UDPIOthread(NamedDB info, Log _log, Socket socket, I2PSession _session) {
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
this.socket = socket;
|
||||
this._session = _session;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
byte data[] = new byte[1024];
|
||||
up = true;
|
||||
try {
|
||||
in = new DataInputStream(socket.getInputStream());
|
||||
out = new DataOutputStream(socket.getOutputStream());
|
||||
while(up) {
|
||||
int c = in.read(data);
|
||||
// Note: could do a loopback test here with a wrapper.
|
||||
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
|
||||
|
||||
if(!ok) {
|
||||
up = false; // Is this the right thing to do??
|
||||
}
|
||||
}
|
||||
} catch(IOException ioe) {
|
||||
_log.error("Error running", ioe);
|
||||
} catch(I2PSessionException ise) {
|
||||
_log.error("Error communicating", ise);
|
||||
// } catch(DataFormatException dfe) {
|
||||
// _log.error("Peer destination file is not valid", dfe);
|
||||
} finally {
|
||||
if(_session != null) {
|
||||
try {
|
||||
_session.destroySession();
|
||||
} catch(I2PSessionException ise) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param session
|
||||
* @param msgId
|
||||
* @param size
|
||||
*/
|
||||
public void messageAvailable(I2PSession session, int msgId, long size) {
|
||||
// _log.debug("Message available: id = " + msgId + " size = " + size);
|
||||
try {
|
||||
byte msg[] = session.receiveMessage(msgId);
|
||||
out.write(msg);
|
||||
out.flush();
|
||||
} catch(I2PSessionException ise) {
|
||||
up = false;
|
||||
} catch(IOException ioe) {
|
||||
up = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Great, can these be used to kill ourselves.
|
||||
/** required by {@link I2PSessionListener I2PSessionListener} to notify of disconnect */
|
||||
public void disconnected(I2PSession session) {
|
||||
_log.debug("Disconnected");
|
||||
// up = false;
|
||||
}
|
||||
|
||||
/** required by {@link I2PSessionListener I2PSessionListener} to notify of error */
|
||||
public void errorOccurred(I2PSession session, String message, Throwable error) {
|
||||
_log.debug("Error occurred: " + message, error);
|
||||
// up = false;
|
||||
}
|
||||
|
||||
/** required by {@link I2PSessionListener I2PSessionListener} to notify of abuse */
|
||||
public void reportAbuse(I2PSession session, int severity) {
|
||||
_log.debug("Abuse reported of severity " + severity);
|
||||
// up = false;
|
||||
}
|
||||
}
|
5
apps/BOB/src/net/i2p/BOB/package.html
Normal file
5
apps/BOB/src/net/i2p/BOB/package.html
Normal file
@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<project name="addressbook" default="war" basedir=".">
|
||||
|
||||
<property name="src" value="java/src/addressbook"/>
|
||||
<property name="src" value="java/src"/>
|
||||
<property name="build" value="build"/>
|
||||
<property name="dist" location="dist"/>
|
||||
<property name="jar" value="addressbook.jar"/>
|
||||
@ -19,8 +19,24 @@
|
||||
|
||||
<target name="distclean" depends="clean" />
|
||||
|
||||
<target name="compile" depends="init">
|
||||
<javac debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
<condition property="depend.available">
|
||||
<typefound name="depend" />
|
||||
</condition>
|
||||
<target name="depend" if="depend.available">
|
||||
<depend
|
||||
cache="../../build"
|
||||
srcdir="${src}"
|
||||
destdir="${build}" >
|
||||
<!-- Depend on classes instead of jars where available -->
|
||||
<classpath>
|
||||
<pathelement location="../../core/java/build/obj" />
|
||||
<pathelement location="../jetty/jettylib/javax.servlet.jar" />
|
||||
</classpath>
|
||||
</depend>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init, depend">
|
||||
<javac debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
srcdir="${src}" destdir="${build}">
|
||||
<classpath>
|
||||
<pathelement location="../../core/java/build/i2p.jar" />
|
||||
@ -37,7 +53,7 @@
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="war" depends="compile">
|
||||
<target name="war" depends="compile" unless="war.uptodate">
|
||||
<mkdir dir="${dist}/tmp"/>
|
||||
<mkdir dir="${dist}/tmp/WEB-INF"/>
|
||||
<mkdir dir="${dist}/tmp/WEB-INF/classes"/>
|
||||
@ -48,4 +64,8 @@
|
||||
<delete dir="${dist}/tmp"/>
|
||||
</target>
|
||||
|
||||
<uptodate property="war.uptodate" targetfile="${dist}/${war}">
|
||||
<srcfiles dir= "." includes="${build}/**/*.class, web.xml"/>
|
||||
</uptodate>
|
||||
|
||||
</project>
|
||||
|
@ -57,7 +57,7 @@ public class AddressBook {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Construct an AddressBook from the contents of the file at url. If the
|
||||
* remote file cannot be read, construct an empty AddressBook
|
||||
*
|
||||
@ -81,6 +81,7 @@ public class AddressBook {
|
||||
new File("addressbook.tmp").delete();
|
||||
}
|
||||
*/
|
||||
static final long MAX_SUB_SIZE = 3 * 1024 * 1024l; //about 5,000 hosts
|
||||
/**
|
||||
* Construct an AddressBook from the Subscription subscription. If the
|
||||
* address book at subscription has not changed since the last time it was
|
||||
@ -89,8 +90,9 @@ public class AddressBook {
|
||||
*
|
||||
* @param subscription
|
||||
* A Subscription instance pointing at a remote address book.
|
||||
* @param proxyHost hostname of proxy
|
||||
* @param proxyPort port number of proxy
|
||||
*/
|
||||
static final long MAX_SUB_SIZE = 3 * 1024 * 1024l; //about 5,000 hosts
|
||||
public AddressBook(Subscription subscription, String proxyHost, int proxyPort) {
|
||||
this.location = subscription.getLocation();
|
||||
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
|
||||
@ -152,10 +154,14 @@ public class AddressBook {
|
||||
*
|
||||
* @return A String representing the contents of the AddressBook.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.addresses.toString();
|
||||
}
|
||||
|
||||
private static final int MIN_DEST_LENGTH = 516;
|
||||
private static final int MAX_DEST_LENGTH = MIN_DEST_LENGTH + 100; // longer than any known cert type for now
|
||||
|
||||
/**
|
||||
* Do basic validation of the hostname and dest
|
||||
* hostname was already converted to lower case by ConfigParser.parse()
|
||||
@ -173,6 +179,11 @@ public class AddressBook {
|
||||
// IDN - basic check, not complete validation
|
||||
(host.indexOf("--") < 0 || host.startsWith("xn--") || host.indexOf(".xn--") > 0) &&
|
||||
host.replaceAll("[a-z0-9.-]", "").length() == 0 &&
|
||||
// Base32 spoofing (52chars.i2p)
|
||||
(! (host.length() == 56 && host.substring(0,52).replaceAll("[a-z2-7]", "").length() == 0)) &&
|
||||
// ... or maybe we do Base32 this way ...
|
||||
(! host.equals("b32.i2p")) &&
|
||||
(! host.endsWith(".b32.i2p")) &&
|
||||
// some reserved names that may be used for local configuration someday
|
||||
(! host.equals("proxy.i2p")) &&
|
||||
(! host.equals("router.i2p")) &&
|
||||
@ -181,8 +192,8 @@ public class AddressBook {
|
||||
(! host.endsWith(".router.i2p")) &&
|
||||
(! host.endsWith(".console.i2p")) &&
|
||||
|
||||
dest.length() == 516 &&
|
||||
dest.endsWith("AAAA") &&
|
||||
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AAAA")) ||
|
||||
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
|
||||
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
|
||||
;
|
||||
}
|
||||
@ -195,6 +206,7 @@ public class AddressBook {
|
||||
*
|
||||
* @param other
|
||||
* An AddressBook to merge with.
|
||||
* @param overwrite True to overwrite
|
||||
* @param log
|
||||
* The log to write messages about new addresses or conflicts to.
|
||||
*/
|
||||
|
@ -107,7 +107,11 @@ public class ConfigParser {
|
||||
FileInputStream fileStream = new FileInputStream(file);
|
||||
BufferedReader input = new BufferedReader(new InputStreamReader(
|
||||
fileStream));
|
||||
return ConfigParser.parse(input);
|
||||
Map rv = ConfigParser.parse(input);
|
||||
try {
|
||||
fileStream.close();
|
||||
} catch (IOException ioe) {}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,7 +142,7 @@ public class ConfigParser {
|
||||
* cannot be read, map.
|
||||
*/
|
||||
public static Map parse(File file, Map map) {
|
||||
Map result = new HashMap();
|
||||
Map result;
|
||||
try {
|
||||
result = ConfigParser.parse(file);
|
||||
} catch (IOException exp) {
|
||||
@ -188,7 +192,11 @@ public class ConfigParser {
|
||||
FileInputStream fileStream = new FileInputStream(file);
|
||||
BufferedReader input = new BufferedReader(new InputStreamReader(
|
||||
fileStream));
|
||||
return ConfigParser.parseSubscriptions(input);
|
||||
List rv = ConfigParser.parseSubscriptions(input);
|
||||
try {
|
||||
fileStream.close();
|
||||
} catch (IOException ioe) {}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,13 +221,12 @@ public class ConfigParser {
|
||||
*
|
||||
* @param file
|
||||
* A File to attempt to parse.
|
||||
* @param string
|
||||
* A List to use as the default, if file fails.
|
||||
* @param list list of files to parse
|
||||
* @return A List consisting of one element for each line in file, or if
|
||||
* file cannot be read, list.
|
||||
*/
|
||||
public static List parseSubscriptions(File file, List list) {
|
||||
List result = new LinkedList();
|
||||
List result;
|
||||
try {
|
||||
result = ConfigParser.parseSubscriptions(file);
|
||||
} catch (IOException exp) {
|
||||
|
@ -125,7 +125,6 @@ public class Daemon {
|
||||
|
||||
public void run(String[] args) {
|
||||
String settingsLocation = "config.txt";
|
||||
Map settings = new HashMap();
|
||||
String home;
|
||||
if (args.length > 0) {
|
||||
home = args[0];
|
||||
@ -157,10 +156,11 @@ public class Daemon {
|
||||
|
||||
File settingsFile = new File(homeFile, settingsLocation);
|
||||
|
||||
settings = ConfigParser.parse(settingsFile, defaultSettings);
|
||||
Map settings = ConfigParser.parse(settingsFile, defaultSettings);
|
||||
// wait
|
||||
try {
|
||||
Thread.currentThread().sleep(5*60*1000);
|
||||
Thread.sleep(5*60*1000);
|
||||
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
|
||||
} catch (InterruptedException ie) {}
|
||||
|
||||
while (true) {
|
||||
|
@ -43,6 +43,7 @@ public class DaemonThread extends Thread {
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
//try {
|
||||
// Thread.sleep(5 * 60 * 1000);
|
||||
|
@ -54,14 +54,17 @@ public class Log {
|
||||
* A String containing a message to append to the log.
|
||||
*/
|
||||
public void append(String entry) {
|
||||
BufferedWriter bw = null;
|
||||
try {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(this.file,
|
||||
bw = new BufferedWriter(new FileWriter(this.file,
|
||||
true));
|
||||
String timestamp = new Date().toString();
|
||||
bw.write(timestamp + " -- " + entry);
|
||||
bw.newLine();
|
||||
bw.close();
|
||||
} catch (IOException exp) {
|
||||
} finally {
|
||||
if (bw != null)
|
||||
try { bw.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,4 +76,4 @@ public class Log {
|
||||
public File getFile() {
|
||||
return this.file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ public class Servlet extends GenericServlet {
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
|
||||
*/
|
||||
@Override
|
||||
public void init(ServletConfig config) {
|
||||
try {
|
||||
super.init(config);
|
||||
|
@ -41,6 +41,8 @@ public class SubscriptionIterator implements Iterator {
|
||||
*
|
||||
* @param subscriptions
|
||||
* List of Subscription objects that represent address books.
|
||||
* @param proxyHost proxy hostname
|
||||
* @param proxyPort proxt port number
|
||||
*/
|
||||
public SubscriptionIterator(List subscriptions, String proxyHost, int proxyPort) {
|
||||
this.subIterator = subscriptions.iterator();
|
||||
|
@ -60,6 +60,9 @@ public class SubscriptionList {
|
||||
* @param lastModifiedFile
|
||||
* A file containg the last-modified headers used for conditional
|
||||
* GET. The file is in the format "url=leastmodified".
|
||||
* @param defaultSubs default subscription file
|
||||
* @param proxyHost proxy hostname
|
||||
* @param proxyPort proxy port number
|
||||
*/
|
||||
public SubscriptionList(File locationsFile, File etagsFile,
|
||||
File lastModifiedFile, List defaultSubs, String proxyHost,
|
||||
|
@ -41,24 +41,34 @@ import net.i2p.util.Log;
|
||||
public class ATalk implements I2PSessionListener, Runnable {
|
||||
/** logging hook - status messages are piped to this */
|
||||
private final static Log _log = new Log(ATalk.class);
|
||||
|
||||
/** platform independent newline */
|
||||
private final static String NL = System.getProperty("line.separator");
|
||||
|
||||
/** the current session */
|
||||
private I2PSession _session;
|
||||
|
||||
/** who am i */
|
||||
private Destination _myDestination;
|
||||
|
||||
/** who are you? */
|
||||
private Destination _peerDestination;
|
||||
|
||||
/** location of my secret key file */
|
||||
private String _myKeyFile;
|
||||
|
||||
/** location of their public key */
|
||||
private String _theirDestinationFile;
|
||||
|
||||
/** where the application reads input from. currently set to standard input */
|
||||
private BufferedReader _in;
|
||||
|
||||
/** where the application sends output to. currently set to standard output */
|
||||
private BufferedWriter _out;
|
||||
|
||||
/** string that messages must begin with to be treated as files */
|
||||
private final static String FILE_COMMAND = ".file: ";
|
||||
|
||||
/** the, erm, manual */
|
||||
private final static String MANUAL = "ATalk: Anonymous Talk, a demo program for the Invisible Internet Project SDK"
|
||||
+ NL
|
||||
@ -84,7 +94,9 @@ public class ATalk implements I2PSessionListener, Runnable {
|
||||
+ NL
|
||||
+ "To end the talk session, enter a period on a line by itself and hit return"
|
||||
+ NL;
|
||||
|
||||
public final static String PROP_CONFIG_LOCATION = "configFile";
|
||||
|
||||
private static final SimpleDateFormat _fmt = new SimpleDateFormat("hh:mm:ss.SSS");
|
||||
|
||||
/** Construct the talk engine, but don't connect yet */
|
||||
@ -111,11 +123,12 @@ public class ATalk implements I2PSessionListener, Runnable {
|
||||
_log.warn("Unable to load up the ATalk config file " + configLocation);
|
||||
}
|
||||
// Provide any router or client API configuration here.
|
||||
if (!props.containsKey(I2PClient.PROP_TCP_HOST)) props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
|
||||
if (!props.containsKey(I2PClient.PROP_TCP_PORT)) props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
|
||||
if (!props.containsKey(I2PClient.PROP_TCP_HOST))
|
||||
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
|
||||
if (!props.containsKey(I2PClient.PROP_TCP_PORT))
|
||||
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
|
||||
if (!props.containsKey(I2PClient.PROP_RELIABILITY))
|
||||
props.setProperty(I2PClient.PROP_RELIABILITY,
|
||||
I2PClient.PROP_RELIABILITY_BEST_EFFORT);
|
||||
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
|
||||
_session = client.createSession(new FileInputStream(myFile), props);
|
||||
_session.setSessionListener(this);
|
||||
_session.connect();
|
||||
@ -364,4 +377,5 @@ public class ATalk implements I2PSessionListener, Runnable {
|
||||
public void reportAbuse(I2PSession session, int severity) {
|
||||
_log.debug("Abuse reported of severity " + severity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,347 +0,0 @@
|
||||
/*
|
||||
* bogobot - A simple join/part stats logger bot for I2P IRC.
|
||||
*
|
||||
* Bogobot.java
|
||||
* 2004 The I2P Project
|
||||
* http://www.i2p.net
|
||||
* This code is public domain.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.apache.log4j.DailyRollingFileAppender;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.PatternLayout;
|
||||
import org.jibble.pircbot.IrcException;
|
||||
import org.jibble.pircbot.NickAlreadyInUseException;
|
||||
import org.jibble.pircbot.PircBot;
|
||||
import org.jibble.pircbot.User;
|
||||
|
||||
/**
|
||||
* TODO 0.5 Add multi-server capability.
|
||||
*
|
||||
* @author hypercubus, oOo
|
||||
* @version 0.4
|
||||
*/
|
||||
public class Bogobot extends PircBot {
|
||||
|
||||
private static final String INTERVAL_DAILY = "daily";
|
||||
private static final String INTERVAL_MONTHLY = "monthly";
|
||||
private static final String INTERVAL_WEEKLY = "weekly";
|
||||
|
||||
private boolean _isIntentionalDisconnect = false;
|
||||
private long _lastUserlistCommandTimestamp = 0;
|
||||
private Logger _logger = Logger.getLogger(Bogobot.class);
|
||||
|
||||
private int _currentAutoRoundTripTag = 0;
|
||||
private long _lastAutoRoundTripSentTime = 0;
|
||||
private Timer _tickTimer;
|
||||
|
||||
private String _configFile;
|
||||
|
||||
private String _botPrimaryNick;
|
||||
private String _botSecondaryNick;
|
||||
private String _botNickservPassword;
|
||||
private String _botUsername;
|
||||
private String _ownerPrimaryNick;
|
||||
private String _ownerSecondaryNick;
|
||||
private String _botShutdownPassword;
|
||||
private String _ircChannel;
|
||||
private String _ircServer;
|
||||
private int _ircServerPort;
|
||||
private boolean _isLoggerEnabled;
|
||||
private String _loggedHostnamePattern;
|
||||
private boolean _isUserlistCommandEnabled;
|
||||
private String _logFilePrefix;
|
||||
private String _logFileRotationInterval;
|
||||
private long _commandAntiFloodInterval;
|
||||
private String _userlistCommandTrigger;
|
||||
private boolean _isRoundTripDelayEnabled;
|
||||
private int _roundTripDelayPeriod;
|
||||
|
||||
class BogobotTickTask extends TimerTask {
|
||||
private Bogobot _caller;
|
||||
|
||||
public BogobotTickTask(Bogobot caller) {
|
||||
_caller = caller;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
_caller.onTick();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadConfigFile(String configFileName) {
|
||||
|
||||
_configFile = configFileName;
|
||||
|
||||
Properties config = new Properties();
|
||||
FileInputStream fis = null;
|
||||
|
||||
try {
|
||||
fis = new FileInputStream(configFileName);
|
||||
config.load(fis);
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Error loading configuration file");
|
||||
System.exit(2);
|
||||
|
||||
} finally {
|
||||
if (fis != null) try {
|
||||
fis.close();
|
||||
} catch (IOException ioe) { // nop
|
||||
}
|
||||
}
|
||||
|
||||
_botPrimaryNick = config.getProperty("botPrimaryNick", "somebot");
|
||||
_botSecondaryNick = config.getProperty("botSecondaryNick", "somebot_");
|
||||
_botNickservPassword = config.getProperty("botNickservPassword", "");
|
||||
_botUsername = config.getProperty("botUsername", "somebot");
|
||||
|
||||
_ownerPrimaryNick = config.getProperty("ownerPrimaryNick", "somenick");
|
||||
_ownerSecondaryNick = config.getProperty("ownerSecondaryNick", "somenick_");
|
||||
|
||||
_botShutdownPassword = config.getProperty("botShutdownPassword", "take off eh");
|
||||
|
||||
_ircChannel = config.getProperty("ircChannel", "#i2p-chat");
|
||||
_ircServer = config.getProperty("ircServer", "irc.postman.i2p");
|
||||
_ircServerPort = Integer.parseInt(config.getProperty("ircServerPort", "6668"));
|
||||
|
||||
_isLoggerEnabled = Boolean.valueOf(config.getProperty("isLoggerEnabled", "true")).booleanValue();
|
||||
_loggedHostnamePattern = config.getProperty("loggedHostnamePattern", "");
|
||||
_logFilePrefix = config.getProperty("logFilePrefix", "irc.postman.i2p.i2p-chat");
|
||||
_logFileRotationInterval = config.getProperty("logFileRotationInterval", INTERVAL_DAILY);
|
||||
|
||||
_isRoundTripDelayEnabled = Boolean.valueOf(config.getProperty("isRoundTripDelayEnabled", "false")).booleanValue();
|
||||
_roundTripDelayPeriod = Integer.parseInt(config.getProperty("roundTripDelayPeriod", "300"));
|
||||
|
||||
_isUserlistCommandEnabled = Boolean.valueOf(config.getProperty("isUserlistCommandEnabled", "true")).booleanValue();
|
||||
_userlistCommandTrigger = config.getProperty("userlistCommandTrigger", "!who");
|
||||
_commandAntiFloodInterval = Long.parseLong(config.getProperty("commandAntiFloodInterval", "60"));
|
||||
}
|
||||
|
||||
public Bogobot(String configFileName) {
|
||||
|
||||
loadConfigFile(configFileName);
|
||||
|
||||
this.setName(_botPrimaryNick);
|
||||
this.setLogin(_botUsername);
|
||||
_tickTimer = new Timer();
|
||||
_tickTimer.scheduleAtFixedRate(new BogobotTickTask(this), 1000, 10 * 1000);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Bogobot bogobot;
|
||||
|
||||
if (args.length > 1) {
|
||||
System.err.println("Too many arguments, the only allowed parameter is configuration file name");
|
||||
System.exit(3);
|
||||
}
|
||||
if (args.length == 1) {
|
||||
bogobot = new Bogobot(args[0]);
|
||||
} else {
|
||||
bogobot = new Bogobot("bogobot.config");
|
||||
}
|
||||
|
||||
bogobot.setVerbose(true);
|
||||
|
||||
if (bogobot._isLoggerEnabled)
|
||||
bogobot.initLogger();
|
||||
|
||||
bogobot.connectToServer();
|
||||
}
|
||||
|
||||
protected void onTick() {
|
||||
// Tick about once every ten seconds
|
||||
|
||||
if (this.isConnected() && _isRoundTripDelayEnabled) {
|
||||
if( ( (System.currentTimeMillis() - _lastAutoRoundTripSentTime) >= (_roundTripDelayPeriod * 1000) ) && (this.getOutgoingQueueSize() == 0) ) {
|
||||
// Connected, sending queue is empty and last RoundTrip is more then 5 minutes old -> Send a new one
|
||||
_currentAutoRoundTripTag ++;
|
||||
_lastAutoRoundTripSentTime = System.currentTimeMillis();
|
||||
sendNotice(this.getNick(),"ROUNDTRIP " + _currentAutoRoundTripTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onDisconnect() {
|
||||
|
||||
if (_isIntentionalDisconnect)
|
||||
System.exit(0);
|
||||
|
||||
if (_isLoggerEnabled)
|
||||
_logger.info(System.currentTimeMillis() + " quits *** " + this.getName() + " *** (Lost connection)");
|
||||
|
||||
try {
|
||||
Thread.sleep(60000);
|
||||
} catch (InterruptedException e) {
|
||||
// No worries.
|
||||
}
|
||||
connectToServer();
|
||||
}
|
||||
|
||||
protected void onJoin(String channel, String sender, String login, String hostname) {
|
||||
|
||||
if (_isLoggerEnabled) {
|
||||
if (sender.equals(this.getName())) {
|
||||
|
||||
_logger.info(System.currentTimeMillis() + " joins *** " + _botPrimaryNick + " ***");
|
||||
|
||||
} else {
|
||||
|
||||
String prependedHostname = "@" + hostname;
|
||||
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
|
||||
_logger.info(System.currentTimeMillis() + " joins " + sender);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onMessage(String channel, String sender, String login, String hostname, String message) {
|
||||
message = message.replaceFirst("<.+?> ", "");
|
||||
if (_isUserlistCommandEnabled && message.equals(_userlistCommandTrigger)) {
|
||||
|
||||
if (System.currentTimeMillis() - _lastUserlistCommandTimestamp < _commandAntiFloodInterval * 1000)
|
||||
return;
|
||||
|
||||
Object[] users = getUsers(_ircChannel);
|
||||
String output = "Userlist for " + _ircChannel + ": ";
|
||||
|
||||
for (int i = 0; i < users.length; i++)
|
||||
output += "[" + ((User) users[i]).getNick() + "] ";
|
||||
|
||||
sendMessage(_ircChannel, output);
|
||||
_lastUserlistCommandTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onPart(String channel, String sender, String login, String hostname) {
|
||||
|
||||
if (_isLoggerEnabled) {
|
||||
if (sender.equals(this.getName())) {
|
||||
_logger.info(System.currentTimeMillis() + " parts *** " + _botPrimaryNick + " ***");
|
||||
} else {
|
||||
String prependedHostname = "@" + hostname;
|
||||
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
|
||||
_logger.info(System.currentTimeMillis() + " parts " + sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void onPrivateMessage(String sender, String login, String hostname, String message) {
|
||||
/*
|
||||
* Nobody else except the bot's owner can shut it down, unless of
|
||||
* course the owner's nick isn't registered and someone's spoofing it.
|
||||
*/
|
||||
if ((sender.equals(_ownerPrimaryNick) || sender.equals(_ownerSecondaryNick)) && message.equals(_botShutdownPassword)) {
|
||||
|
||||
if (_isLoggerEnabled)
|
||||
_logger.info(System.currentTimeMillis() + " quits *** " + this.getName() + " ***");
|
||||
|
||||
_isIntentionalDisconnect = true;
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) {
|
||||
String prependedHostname = "@" + sourceHostname;
|
||||
|
||||
if (sourceNick.equals(_botPrimaryNick))
|
||||
changeNick(_botPrimaryNick);
|
||||
|
||||
if (_isLoggerEnabled) {
|
||||
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
|
||||
_logger.info(System.currentTimeMillis() + " quits " + sourceNick + " " + reason);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void connectToServer() {
|
||||
|
||||
int loginAttempts = 0;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
connect(_ircServer, _ircServerPort);
|
||||
break;
|
||||
} catch (NickAlreadyInUseException e) {
|
||||
if (loginAttempts == 1) {
|
||||
System.out.println("Sorry, the primary and secondary bot nicks are already taken. Exiting.");
|
||||
System.exit(1);
|
||||
}
|
||||
loginAttempts++;
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e1) {
|
||||
// Hmph.
|
||||
}
|
||||
|
||||
if (getName().equals(_botPrimaryNick))
|
||||
setName(_botSecondaryNick);
|
||||
else
|
||||
setName(_botPrimaryNick);
|
||||
|
||||
continue;
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error during login: ");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
} catch (IrcException e) {
|
||||
System.out.println("Error during login: ");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
joinChannel(_ircChannel);
|
||||
}
|
||||
|
||||
protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) {
|
||||
|
||||
if (sourceNick.equals("NickServ") && (notice.indexOf("/msg NickServ IDENTIFY") >= 0) && (_botNickservPassword != "")) {
|
||||
sendRawLineViaQueue("NICKSERV IDENTIFY " + _botNickservPassword);
|
||||
}
|
||||
|
||||
if (sourceNick.equals(getNick()) && notice.equals( "ROUNDTRIP " + _currentAutoRoundTripTag)) {
|
||||
int delay = (int)((System.currentTimeMillis() - _lastAutoRoundTripSentTime) / 100);
|
||||
// sendMessage(_ircChannel, "Round-trip delay = " + (delay / 10.0f) + " seconds");
|
||||
if (_isLoggerEnabled)
|
||||
_logger.info(System.currentTimeMillis() + " roundtrip " + delay);
|
||||
}
|
||||
}
|
||||
|
||||
private void initLogger() {
|
||||
|
||||
String logFilePath = "logs" + File.separator + _logFilePrefix;
|
||||
DailyRollingFileAppender rollingFileAppender = null;
|
||||
|
||||
if (!(new File("logs").exists()))
|
||||
(new File("logs")).mkdirs();
|
||||
|
||||
try {
|
||||
|
||||
if (_logFileRotationInterval.equals("monthly"))
|
||||
rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-MM'.log'");
|
||||
else if (_logFileRotationInterval.equals("weekly"))
|
||||
rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-ww'.log'");
|
||||
else
|
||||
rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-MM-dd'.log'");
|
||||
|
||||
rollingFileAppender.setThreshold(Level.INFO);
|
||||
_logger.addAppender(rollingFileAppender);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error: Couldn't create or open an existing log file. Exiting.");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,353 +0,0 @@
|
||||
/*
|
||||
* bogoparser - A simple logfile analyzer for bogobot.
|
||||
*
|
||||
* Bogoparser.java
|
||||
* 2004 The I2P Project
|
||||
* http://www.i2p.net
|
||||
* This code is public domain.
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author hypercubus
|
||||
* @version 0.4
|
||||
*/
|
||||
public class Bogoparser {
|
||||
|
||||
private static void displayUsageAndExit() {
|
||||
System.out.println("\r\nUsage:\r\n\r\n java Bogoparser [--by-duration] <logfile>\r\n");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Bogoparser bogoparser;
|
||||
|
||||
if (args.length < 1 || args.length > 2)
|
||||
displayUsageAndExit();
|
||||
|
||||
if (args.length == 2) {
|
||||
if (!args[0].equals("--by-duration"))
|
||||
displayUsageAndExit();
|
||||
bogoparser = new Bogoparser(args[1], true);
|
||||
}
|
||||
|
||||
if (args.length == 1)
|
||||
bogoparser = new Bogoparser(args[0], false);
|
||||
}
|
||||
|
||||
private Bogoparser(String logfile, boolean sortByDuration) {
|
||||
|
||||
ArrayList sortedSessions;
|
||||
|
||||
if (sortByDuration) {
|
||||
sortedSessions = sortSessionsByDuration(calculateSessionDurations(sortSessionsByTime(readLogfile(logfile))));
|
||||
formatAndOutputByDuration(sortedSessions);
|
||||
} else {
|
||||
sortedSessions = calculateSessionDurations(sortSessionsByQuitReason(sortSessionsByNick(sortSessionsByTime(readLogfile(logfile)))));
|
||||
formatAndOutput(sortedSessions);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList calculateSessionDurations(ArrayList sortedSessionsByQuitReasonOrDuration) {
|
||||
|
||||
ArrayList calculatedSessionDurations = new ArrayList();
|
||||
|
||||
for (int i = 0; i+1 < sortedSessionsByQuitReasonOrDuration.size(); i += 2) {
|
||||
|
||||
String joinsEntry = (String) sortedSessionsByQuitReasonOrDuration.get(i);
|
||||
String[] joinsEntryFields = joinsEntry.split(" ");
|
||||
|
||||
String quitsEntry = (String) sortedSessionsByQuitReasonOrDuration.get(i+1);
|
||||
Pattern p = Pattern.compile("^([^ ]+) [^ ]+ ([^ ]+) (.*)$");
|
||||
Matcher m = p.matcher(quitsEntry);
|
||||
|
||||
if (m.matches()) {
|
||||
|
||||
String currentJoinTime = joinsEntryFields[0];
|
||||
String currentNick = m.group(2);
|
||||
String currentQuitReason = m.group(3);
|
||||
String currentQuitTime = m.group(1);
|
||||
long joinsTimeInMilliseconds;
|
||||
long quitsTimeInMilliseconds;
|
||||
long sessionLengthInMilliseconds;
|
||||
|
||||
joinsTimeInMilliseconds = Long.parseLong(currentJoinTime);
|
||||
quitsTimeInMilliseconds = Long.parseLong(currentQuitTime);
|
||||
sessionLengthInMilliseconds = quitsTimeInMilliseconds - joinsTimeInMilliseconds;
|
||||
|
||||
String hours = "" + sessionLengthInMilliseconds/1000/60/60;
|
||||
String minutes = "" + (sessionLengthInMilliseconds/1000/60)%60;
|
||||
|
||||
if (hours.length() < 2)
|
||||
hours = "0" + hours;
|
||||
|
||||
if (hours.length() < 3)
|
||||
hours = "0" + hours;
|
||||
|
||||
if (minutes.length() < 2)
|
||||
minutes = "0" + minutes;
|
||||
|
||||
int columnPadding = 19-currentNick.length();
|
||||
String columnPaddingString = " ";
|
||||
|
||||
for (int j = 0; j < columnPadding; j++)
|
||||
columnPaddingString = columnPaddingString + " ";
|
||||
|
||||
calculatedSessionDurations.add(sessionLengthInMilliseconds + " " + currentNick + columnPaddingString + " online " + hours + " hours " + minutes + " minutes " + currentQuitReason);
|
||||
} else {
|
||||
System.out.println("\r\nError: Unexpected entry in logfile: " + quitsEntry);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
return calculatedSessionDurations;
|
||||
}
|
||||
|
||||
private void formatAndOutput(ArrayList sortedSessions) {
|
||||
|
||||
String quitReason = null;
|
||||
|
||||
for (int i = 0; i < sortedSessions.size(); i++) {
|
||||
|
||||
String entry = (String) sortedSessions.get(i);
|
||||
Pattern p = Pattern.compile("^[\\d]+ ([^ ]+ +online [\\d]+ hours [\\d]+ minutes) (.*)$");
|
||||
Matcher m = p.matcher(entry);
|
||||
|
||||
if (m.matches()) {
|
||||
|
||||
if (quitReason == null) {
|
||||
quitReason = m.group(2);
|
||||
System.out.println("\r\nQUIT: " + ((m.group(2).equals("")) ? "No Reason Given" : quitReason) + "\r\n");
|
||||
}
|
||||
|
||||
String tempQuitReason = m.group(2);
|
||||
String tempSession = m.group(1);
|
||||
|
||||
if (tempQuitReason.equals(quitReason)) {
|
||||
System.out.println(" " + tempSession);
|
||||
} else {
|
||||
quitReason = null;
|
||||
i -= 1;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
System.out.println("\r\nError: Unexpected entry in logfile: " + entry);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
System.out.println("\r\n");
|
||||
}
|
||||
|
||||
private void formatAndOutputByDuration(ArrayList sortedSessions) {
|
||||
System.out.println("\r\n");
|
||||
|
||||
for (int i = 0; i < sortedSessions.size(); i++) {
|
||||
String[] columns = ((String) sortedSessions.get(i)).split(" ", 2);
|
||||
System.out.println(columns[1]);
|
||||
}
|
||||
|
||||
System.out.println("\r\n");
|
||||
}
|
||||
|
||||
private ArrayList readLogfile(String logfile) {
|
||||
|
||||
ArrayList log = new ArrayList();
|
||||
|
||||
try {
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(logfile)));
|
||||
|
||||
for (String line; (line = in.readLine()) != null; )
|
||||
log.add(line);
|
||||
|
||||
in.close();
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("\r\nError: Can't find logfile '" + logfile + "'.\r\n");
|
||||
System.exit(1);
|
||||
|
||||
} catch (IOException e) {
|
||||
System.out.println("\r\nError: Can't read logfile '" + logfile + "'.\r\n");
|
||||
System.exit(1);
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs an odd-even transposition sort.
|
||||
*/
|
||||
private ArrayList sortSessionsByDuration(ArrayList calculatedSessionDurations) {
|
||||
|
||||
for (int i = 0; i < calculatedSessionDurations.size()/2; i++) {
|
||||
for (int j = 0; j+1 < calculatedSessionDurations.size(); j += 2) {
|
||||
|
||||
String[] currentDurationString = ((String) calculatedSessionDurations.get(j)).split(" ", 2);
|
||||
long currentDuration = Long.parseLong(currentDurationString[0]);
|
||||
String[] nextDurationString = ((String) calculatedSessionDurations.get(j+1)).split(" ", 2);
|
||||
long nextDuration = Long.parseLong(nextDurationString[0]);
|
||||
|
||||
if (currentDuration > nextDuration) {
|
||||
calculatedSessionDurations.add(j, calculatedSessionDurations.get(j+1));
|
||||
calculatedSessionDurations.remove(j+2);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 1; j+1 < calculatedSessionDurations.size(); j += 2) {
|
||||
|
||||
String[] currentDurationString = ((String) calculatedSessionDurations.get(j)).split(" ", 2);
|
||||
long currentDuration = Long.parseLong(currentDurationString[0]);
|
||||
String[] nextDurationString = ((String) calculatedSessionDurations.get(j+1)).split(" ", 2);
|
||||
long nextDuration = Long.parseLong(nextDurationString[0]);
|
||||
|
||||
if (currentDuration > nextDuration) {
|
||||
calculatedSessionDurations.add(j, calculatedSessionDurations.get(j+1));
|
||||
calculatedSessionDurations.remove(j+2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return calculatedSessionDurations;
|
||||
}
|
||||
|
||||
private ArrayList sortSessionsByNick(ArrayList sortedSessionsByTime) {
|
||||
|
||||
ArrayList sortedSessionsByNick = new ArrayList();
|
||||
|
||||
while (sortedSessionsByTime.size() != 0) {
|
||||
|
||||
String entry = (String) sortedSessionsByTime.get(0);
|
||||
String[] entryFields = entry.split(" ");
|
||||
String currentNick = entryFields[2];
|
||||
|
||||
sortedSessionsByNick.add(entry);
|
||||
sortedSessionsByNick.add(sortedSessionsByTime.get(1));
|
||||
sortedSessionsByTime.remove(0);
|
||||
sortedSessionsByTime.remove(0);
|
||||
for (int i = 0; i+1 < sortedSessionsByTime.size(); i += 2) {
|
||||
|
||||
String nextEntry = (String) sortedSessionsByTime.get(i);
|
||||
String[] nextEntryFields = nextEntry.split(" ");
|
||||
|
||||
if (nextEntryFields[2].equals(currentNick)) {
|
||||
sortedSessionsByNick.add(nextEntry);
|
||||
sortedSessionsByNick.add(sortedSessionsByTime.get(i+1));
|
||||
sortedSessionsByTime.remove(i);
|
||||
sortedSessionsByTime.remove(i);
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sortedSessionsByNick;
|
||||
}
|
||||
|
||||
private ArrayList sortSessionsByQuitReason(ArrayList sortedSessionsByNick) {
|
||||
|
||||
ArrayList sortedSessionsByQuitReason = new ArrayList();
|
||||
|
||||
while (sortedSessionsByNick.size() != 0) {
|
||||
|
||||
String entry = (String) sortedSessionsByNick.get(1);
|
||||
Pattern p = Pattern.compile("^[^ ]+ [^ ]+ [^ ]+ (.*)$");
|
||||
Matcher m = p.matcher(entry);
|
||||
|
||||
if (m.matches()) {
|
||||
|
||||
String currentQuitReason = m.group(1);
|
||||
|
||||
sortedSessionsByQuitReason.add(sortedSessionsByNick.get(0));
|
||||
sortedSessionsByQuitReason.add(entry);
|
||||
sortedSessionsByNick.remove(0);
|
||||
sortedSessionsByNick.remove(0);
|
||||
for (int i = 0; i+1 < sortedSessionsByNick.size(); i += 2) {
|
||||
|
||||
String nextEntry = (String) sortedSessionsByNick.get(i+1);
|
||||
Pattern p2 = Pattern.compile("^[^ ]+ [^ ]+ [^ ]+ (.*)$");
|
||||
Matcher m2 = p2.matcher(nextEntry);
|
||||
|
||||
if (m2.matches()) {
|
||||
|
||||
String nextQuitReason = m2.group(1);
|
||||
|
||||
if (nextQuitReason.equals(currentQuitReason)) {
|
||||
sortedSessionsByQuitReason.add(sortedSessionsByNick.get(i));
|
||||
sortedSessionsByQuitReason.add(nextEntry);
|
||||
sortedSessionsByNick.remove(i);
|
||||
sortedSessionsByNick.remove(i);
|
||||
i -= 2;
|
||||
}
|
||||
} else {
|
||||
System.out.println("\r\nError: Unexpected entry in logfile: " + nextEntry);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("\r\nError: Unexpected entry in logfile: " + entry);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
return sortedSessionsByQuitReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sessions terminated with "parts" messages instead of "quits" are filtered
|
||||
* out.
|
||||
*/
|
||||
private ArrayList sortSessionsByTime(ArrayList log) {
|
||||
|
||||
ArrayList sortedSessionsByTime = new ArrayList();
|
||||
|
||||
mainLoop:
|
||||
while (log.size() > 0) {
|
||||
|
||||
String entry = (String) log.get(0);
|
||||
String[] entryFields = entry.split(" ");
|
||||
|
||||
if (entryFields[1].equals("quits") && !entryFields[1].equals("joins")) {
|
||||
/*
|
||||
* Discard entry. The specified log either doesn't contain
|
||||
* the corresponding "joins" time for this quit entry or the
|
||||
* entry is a "parts" or unknown message, and in both cases
|
||||
* the entry's data is useless.
|
||||
*/
|
||||
log.remove(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 1; i < log.size(); i++) { // Find corresponding "quits" entry.
|
||||
|
||||
String tempEntry = (String) log.get(i);
|
||||
String[] tempEntryFields = tempEntry.split(" ");
|
||||
|
||||
if (tempEntryFields[2].equals(entryFields[2])) { // Check if the nick fields for the two entries match.
|
||||
if (!tempEntryFields[1].equals("quits")) {
|
||||
if (tempEntryFields[1].equals("joins")) { // Don't discard a subsequent "joins" entry.
|
||||
log.remove(0);
|
||||
continue mainLoop;
|
||||
}
|
||||
log.remove(i);
|
||||
continue;
|
||||
}
|
||||
sortedSessionsByTime.add(entry);
|
||||
sortedSessionsByTime.add(tempEntry);
|
||||
log.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Discard "joins" entry. The specified log doesn't contain the
|
||||
* corresponding "quits" time for this entry so the entry's
|
||||
* data is useless.
|
||||
*/
|
||||
|
||||
log.remove(0);
|
||||
}
|
||||
|
||||
return sortedSessionsByTime;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* ============================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
* ============================================================================
|
||||
*
|
||||
* Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution, if any, must
|
||||
* include the following acknowledgment: "This product includes software
|
||||
* developed by the Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself, if
|
||||
* and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "log4j" and "Apache Software Foundation" must not be used to
|
||||
* endorse or promote products derived from this software without prior
|
||||
* written permission. For written permission, please contact
|
||||
* apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache", nor may
|
||||
* "Apache" appear in their name, without prior written permission of the
|
||||
* Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
|
||||
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* on behalf of the Apache Software Foundation. For more information on the
|
||||
* Apache Software Foundation, please see <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@ -1 +0,0 @@
|
||||
java -cp .;log4j-1.2.8.jar;pircbot.jar Bogobot
|
@ -1,101 +0,0 @@
|
||||
#####
|
||||
# Bogobot user configuration
|
||||
#####
|
||||
|
||||
###
|
||||
# The bot's nick and backup nick. You will probably want to register these with
|
||||
# the IRC server's NickServ.(a NickServ interface is forthcoming).
|
||||
#
|
||||
botPrimaryNick=somebot
|
||||
botSecondaryNick=somebot_
|
||||
|
||||
###
|
||||
# The bot's password required by Nickserv service's identify command.
|
||||
# You have to register the nickname yourself first, the bot will not.
|
||||
#
|
||||
botNickservPassword=
|
||||
|
||||
###
|
||||
# The bot's username. Appears in the whois replies
|
||||
#
|
||||
botUsername=somebot
|
||||
|
||||
#####
|
||||
# The bot owner's nick and backup nick. One of these must match the owner's
|
||||
# currently-used nick or else remote shutdown will not be possible. You will
|
||||
# probably want to register these with the IRC server's NickServ.
|
||||
#
|
||||
ownerPrimaryNick=somenick
|
||||
ownerSecondaryNick=somenick_
|
||||
|
||||
###
|
||||
# The bot will disconnect and shut down when sent this password via private
|
||||
# message (aka query) from either of the owner nicks specified above. DO NOT USE
|
||||
# THIS DEFAULT VALUE!
|
||||
#
|
||||
botShutdownPassword=take off eh
|
||||
|
||||
###
|
||||
# The server, channel, and port the bot will connect to.
|
||||
#
|
||||
ircChannel=#i2p-chat
|
||||
ircServer=irc.duck.i2p
|
||||
ircServerPort=6668
|
||||
|
||||
###
|
||||
# Set to "true" to enable logging, else "false" (but don't use quotation marks).
|
||||
#
|
||||
isLoggerEnabled=true
|
||||
|
||||
###
|
||||
# Restrict logging of joins and parts on the user hostname.
|
||||
# Leave empty to log all of them
|
||||
# Prepend with a @ for a perfect match
|
||||
# Otherwise, specify the required end of the user hostname
|
||||
#
|
||||
loggedHostnamePattern=@free.duck.i2p
|
||||
|
||||
###
|
||||
# The prefix to be used for the filenames of logs.
|
||||
#
|
||||
logFilePrefix=irc.duck.i2p.i2p-chat
|
||||
|
||||
###
|
||||
# How often the logs should be rotated. Either "daily", "weekly", or "monthly"
|
||||
# (but don't use quotation marks).
|
||||
#
|
||||
logFileRotationInterval=daily
|
||||
|
||||
###
|
||||
# Set to "true" to enable the regular round-trip delay computation,
|
||||
# else "false" (but don't use quotation marks).
|
||||
#
|
||||
isRoundTripDelayEnabled=false
|
||||
|
||||
###
|
||||
# How often should the round-trip delay be recorded.
|
||||
# (in seconds)
|
||||
#
|
||||
roundTripDelayPeriod=300
|
||||
|
||||
###
|
||||
# Set to "true" to enable the userlist command, else "false" (but don't use
|
||||
# quotation marks).
|
||||
#
|
||||
isUserlistCommandEnabled=true
|
||||
|
||||
###
|
||||
# The userlist trigger command to listen for. It is a good idea to prefix
|
||||
# triggers with some non-alphanumeric character in order to avoid accidental
|
||||
# trigger use during normal channel conversation. In most cases you will
|
||||
# probably want to choose a unique trigger here that no other bots in the
|
||||
# channel will respond to.
|
||||
#
|
||||
userlistCommandTrigger=!who
|
||||
|
||||
###
|
||||
# The number of seconds to rest after replying to a userlist command issued by
|
||||
# a user in the channel. The bot will ignore subsequent userlist commands during
|
||||
# this period. This helps prevent flooding.
|
||||
#
|
||||
commandAntiFloodInterval=60
|
@ -1,2 +0,0 @@
|
||||
#!/bin/sh
|
||||
java -cp .:log4j-1.2.8.jar:pircbot.jar Bogobot
|
@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- ********************************************************** -->
|
||||
<!-- bogobot - A simple join/part stats logger bot for I2P IRC. -->
|
||||
<!-- -->
|
||||
<!-- build-eclipse.xml -->
|
||||
<!-- 2004 The I2P Project -->
|
||||
<!-- http://www.i2p.net -->
|
||||
<!-- This code is public domain. -->
|
||||
<!-- -->
|
||||
<!-- authors: hypercubus, oOo -->
|
||||
<!-- version 0.4 -->
|
||||
<!-- ********************************************************** -->
|
||||
|
||||
<project basedir="." default="dist" name="Bogobot">
|
||||
|
||||
<!-- init:
|
||||
Create distribution directory if missing and initialize time stamp for
|
||||
archive naming -->
|
||||
<target name="init">
|
||||
<mkdir dir="dist" />
|
||||
<tstamp>
|
||||
<format pattern="yyyy-MM-dd" property="DSTAMP" />
|
||||
</tstamp>
|
||||
</target>
|
||||
|
||||
<!-- dist.bin:
|
||||
Create the binary distribution archive -->
|
||||
<target depends="init" description="Create the binary distribution archive" name="dist.bin">
|
||||
<zip destfile="dist/Bogobot_${DSTAMP}.zip">
|
||||
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<!-- dist.source:
|
||||
Create the source distribution archive -->
|
||||
<target depends="init" description="Create the source distribution archive" name="dist.source">
|
||||
<zip destfile="dist/Bogobot_source_${DSTAMP}.zip">
|
||||
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<!-- dist:
|
||||
Create both the binary and source distribution archives -->
|
||||
<target depends="dist.bin,dist.source" description="Create both the binary and source distribution archives" name="dist">
|
||||
<echo message="Successfully created binary and source distribution archives in directory 'dist'." />
|
||||
</target>
|
||||
|
||||
<!-- clean:
|
||||
Delete all class files and temporary directories -->
|
||||
<target description="Delete all class files and temporary directories" name="clean">
|
||||
<delete>
|
||||
<fileset dir="${basedir}" includes="**/*.class" />
|
||||
</delete>
|
||||
<echo message="Clean successful." />
|
||||
</target>
|
||||
|
||||
</project>
|
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- ********************************************************** -->
|
||||
<!-- bogobot - A simple join/part stats logger bot for I2P IRC. -->
|
||||
<!-- -->
|
||||
<!-- build.xml -->
|
||||
<!-- 2004 The I2P Project -->
|
||||
<!-- http://www.i2p.net -->
|
||||
<!-- This code is public domain. -->
|
||||
<!-- -->
|
||||
<!-- authors: hypercubus, oOo -->
|
||||
<!-- version 0.4 -->
|
||||
<!-- ********************************************************** -->
|
||||
|
||||
<project basedir="." default="compile" name="Bogobot">
|
||||
|
||||
<!-- init:
|
||||
Create distribution directory if missing and initialize time stamp for
|
||||
archive naming -->
|
||||
<target name="init">
|
||||
<mkdir dir="dist" />
|
||||
<tstamp>
|
||||
<format pattern="yyyy-MM-dd" property="DSTAMP" />
|
||||
</tstamp>
|
||||
</target>
|
||||
|
||||
<!-- compile:
|
||||
Compile source code -->
|
||||
<target depends="init" description="Compile source code" name="compile">
|
||||
<javac classpath="${basedir};log4j-1.2.8.jar;pircbot.jar" source="1.4" srcdir="." />
|
||||
</target>
|
||||
|
||||
<!-- dist.bin:
|
||||
Create the binary distribution archive -->
|
||||
<target depends="init,compile" description="Create the binary distribution archive" name="dist.bin">
|
||||
<zip destfile="dist/Bogobot_${DSTAMP}.zip">
|
||||
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.class Bogobot$BogobotTickTask.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<!-- dist.source:
|
||||
Create the source distribution archive -->
|
||||
<target depends="init" description="Create the source distribution archive" name="dist.source">
|
||||
<zip destfile="dist/Bogobot_source_${DSTAMP}.zip">
|
||||
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<!-- dist:
|
||||
Create both the binary and source distribution archives -->
|
||||
<target depends="dist.bin,dist.source" description="Create both the binary and source distribution archives" name="dist">
|
||||
<echo message="Successfully created binary and source distribution archives in directory 'dist'." />
|
||||
</target>
|
||||
|
||||
<!-- clean:
|
||||
Delete all class files and temporary directories -->
|
||||
<target description="Delete all class files and temporary directories" name="clean">
|
||||
<delete>
|
||||
<fileset dir="${basedir}" includes="**/*.class" />
|
||||
</delete>
|
||||
<echo message="Clean successful." />
|
||||
</target>
|
||||
|
||||
</project>
|
Binary file not shown.
Binary file not shown.
1
apps/i2psnark/i2psnark.config
Normal file
1
apps/i2psnark/i2psnark.config
Normal file
@ -0,0 +1 @@
|
||||
i2psnark.dir=i2psnark
|
@ -7,12 +7,30 @@
|
||||
<ant dir="../../streaming/java/" target="build" />
|
||||
<!-- streaming will build ministreaming and core -->
|
||||
</target>
|
||||
<target name="compile">
|
||||
<condition property="depend.available">
|
||||
<typefound name="depend" />
|
||||
</condition>
|
||||
<target name="depend" if="depend.available">
|
||||
<depend
|
||||
cache="../../../build"
|
||||
srcdir="./src"
|
||||
destdir="./build/obj" >
|
||||
<!-- Depend on classes instead of jars where available -->
|
||||
<classpath>
|
||||
<pathelement location="../../../core/java/build/obj" />
|
||||
<pathelement location="../../../router/java/build/obj" />
|
||||
<pathelement location="../../ministreaming/java/build/obj" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
</classpath>
|
||||
</depend>
|
||||
</target>
|
||||
<target name="compile" depends="depend">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
destdir="./build/obj"
|
||||
classpath="../../../core/java/build/i2p.jar:../../../router/java/build/router.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../ministreaming/java/build/mstreaming.jar" />
|
||||
</target>
|
||||
@ -36,7 +54,7 @@
|
||||
</zip>
|
||||
</target>
|
||||
<target name="standalone_prep" depends="war">
|
||||
<javac debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
<javac debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
destdir="./build" srcdir="src/" includes="org/klomp/snark/web/RunStandalone.java" >
|
||||
<classpath>
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
|
@ -28,7 +28,7 @@ import java.io.OutputStream;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -36,17 +36,16 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class ConnectionAcceptor implements Runnable
|
||||
{
|
||||
private static final ConnectionAcceptor _instance = new ConnectionAcceptor();
|
||||
public static final ConnectionAcceptor instance() { return _instance; }
|
||||
private Log _log = new Log(ConnectionAcceptor.class);
|
||||
private I2PServerSocket serverSocket;
|
||||
private PeerAcceptor peeracceptor;
|
||||
private Thread thread;
|
||||
private I2PSnarkUtil _util;
|
||||
|
||||
private boolean stop;
|
||||
private boolean socketChanged;
|
||||
|
||||
private ConnectionAcceptor() {}
|
||||
public ConnectionAcceptor(I2PSnarkUtil util) { _util = util; }
|
||||
|
||||
public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) {
|
||||
if (serverSocket != socket) {
|
||||
@ -56,29 +55,30 @@ public class ConnectionAcceptor implements Runnable
|
||||
stop = false;
|
||||
socketChanged = true;
|
||||
if (thread == null) {
|
||||
thread = new I2PThread(this, "I2PSnark acceptor");
|
||||
thread = new I2PAppThread(this, "I2PSnark acceptor");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConnectionAcceptor(I2PServerSocket serverSocket,
|
||||
public ConnectionAcceptor(I2PSnarkUtil util, I2PServerSocket serverSocket,
|
||||
PeerAcceptor peeracceptor)
|
||||
{
|
||||
this.serverSocket = serverSocket;
|
||||
this.peeracceptor = peeracceptor;
|
||||
_util = util;
|
||||
|
||||
socketChanged = false;
|
||||
stop = false;
|
||||
thread = new I2PThread(this, "I2PSnark acceptor");
|
||||
thread = new I2PAppThread(this, "I2PSnark acceptor");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void halt()
|
||||
{
|
||||
if (true) throw new RuntimeException("wtf");
|
||||
if (stop) return;
|
||||
stop = true;
|
||||
|
||||
I2PServerSocket ss = serverSocket;
|
||||
@ -95,7 +95,7 @@ public class ConnectionAcceptor implements Runnable
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
serverSocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
serverSocket = _util.getServerSocket();
|
||||
socketChanged = true;
|
||||
Thread t = thread;
|
||||
if (t != null)
|
||||
@ -116,10 +116,12 @@ public class ConnectionAcceptor implements Runnable
|
||||
socketChanged = false;
|
||||
}
|
||||
while ( (serverSocket == null) && (!stop)) {
|
||||
serverSocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
serverSocket = _util.getServerSocket();
|
||||
if (serverSocket == null)
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
if(stop)
|
||||
break;
|
||||
try
|
||||
{
|
||||
I2PSocket socket = serverSocket.accept();
|
||||
@ -127,27 +129,27 @@ public class ConnectionAcceptor implements Runnable
|
||||
if (socketChanged) {
|
||||
continue;
|
||||
} else {
|
||||
I2PServerSocket ss = I2PSnarkUtil.instance().getServerSocket();
|
||||
I2PServerSocket ss = _util.getServerSocket();
|
||||
if (ss != serverSocket) {
|
||||
serverSocket = ss;
|
||||
socketChanged = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Thread t = new I2PThread(new Handler(socket), "Connection-" + socket);
|
||||
Thread t = new I2PAppThread(new Handler(socket), "Connection-" + socket);
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
catch (I2PException ioe)
|
||||
{
|
||||
if (!socketChanged) {
|
||||
Snark.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Snark.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
@ -159,7 +161,6 @@ public class ConnectionAcceptor implements Runnable
|
||||
}
|
||||
catch (I2PException ignored) { }
|
||||
|
||||
throw new RuntimeException("wtf");
|
||||
}
|
||||
|
||||
private class Handler implements Runnable {
|
||||
|
@ -30,4 +30,8 @@ public interface CoordinatorListener
|
||||
* Called when the PeerCoordinator notices a change in the state of a peer.
|
||||
*/
|
||||
void peerChange(PeerCoordinator coordinator, Peer peer);
|
||||
|
||||
public boolean overUploadLimit(int uploaders);
|
||||
public boolean overUpBWLimit();
|
||||
public boolean overUpBWLimit(long total);
|
||||
}
|
||||
|
@ -2,12 +2,15 @@ package org.klomp.snark;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
@ -25,12 +28,13 @@ import net.i2p.util.SimpleTimer;
|
||||
|
||||
/**
|
||||
* I2P specific helpers for I2PSnark
|
||||
* We use this class as a sort of context for i2psnark
|
||||
* so we can run multiple instances of single Snarks
|
||||
* (but not multiple SnarkManagers, it is still static)
|
||||
*/
|
||||
public class I2PSnarkUtil {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private static I2PSnarkUtil _instance = new I2PSnarkUtil();
|
||||
public static I2PSnarkUtil instance() { return _instance; }
|
||||
|
||||
private boolean _shouldProxy;
|
||||
private String _proxyHost;
|
||||
@ -43,9 +47,17 @@ public class I2PSnarkUtil {
|
||||
private Set _shitlist;
|
||||
private int _maxUploaders;
|
||||
private int _maxUpBW;
|
||||
private int _maxConnections;
|
||||
|
||||
private I2PSnarkUtil() {
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
||||
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
||||
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
||||
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
||||
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
|
||||
public static final int MAX_CONNECTIONS = 16; // per torrent
|
||||
|
||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
_log = _context.logManager().getLog(Snark.class);
|
||||
_opts = new HashMap();
|
||||
setProxy("127.0.0.1", 4444);
|
||||
@ -53,6 +65,8 @@ public class I2PSnarkUtil {
|
||||
_shitlist = new HashSet(64);
|
||||
_configured = false;
|
||||
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
||||
_maxUpBW = DEFAULT_MAX_UP_BW;
|
||||
_maxConnections = MAX_CONNECTIONS;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,8 +90,10 @@ public class I2PSnarkUtil {
|
||||
public boolean configured() { return _configured; }
|
||||
|
||||
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
|
||||
_i2cpHost = i2cpHost;
|
||||
_i2cpPort = i2cpPort;
|
||||
if (i2cpHost != null)
|
||||
_i2cpHost = i2cpHost;
|
||||
if (i2cpPort > 0)
|
||||
_i2cpPort = i2cpPort;
|
||||
if (opts != null)
|
||||
_opts.putAll(opts);
|
||||
_configured = true;
|
||||
@ -93,6 +109,11 @@ public class I2PSnarkUtil {
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
public void setMaxConnections(int limit) {
|
||||
_maxConnections = limit;
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
public String getI2CPHost() { return _i2cpHost; }
|
||||
public int getI2CPPort() { return _i2cpPort; }
|
||||
public Map getI2CPOptions() { return _opts; }
|
||||
@ -101,6 +122,7 @@ public class I2PSnarkUtil {
|
||||
public boolean getEepProxySet() { return _shouldProxy; }
|
||||
public int getMaxUploaders() { return _maxUploaders; }
|
||||
public int getMaxUpBW() { return _maxUpBW; }
|
||||
public int getMaxConnections() { return _maxConnections; }
|
||||
|
||||
/**
|
||||
* Connect to the router, if we aren't already
|
||||
@ -185,9 +207,11 @@ public class I2PSnarkUtil {
|
||||
out = File.createTempFile("i2psnark", "url", new File("."));
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
out.delete();
|
||||
if (out != null)
|
||||
out.delete();
|
||||
return null;
|
||||
}
|
||||
out.deleteOnExit();
|
||||
String fetchURL = url;
|
||||
if (rewrite)
|
||||
fetchURL = rewriteAnnounce(url);
|
||||
@ -222,6 +246,28 @@ public class I2PSnarkUtil {
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/** Base64 only - static (no naming service) */
|
||||
static Destination getDestinationFromBase64(String ip) {
|
||||
if (ip == null) return null;
|
||||
if (ip.endsWith(".i2p")) {
|
||||
if (ip.length() < 520)
|
||||
return null;
|
||||
try {
|
||||
return new Destination(ip.substring(0, ip.length()-4)); // sans .i2p
|
||||
} catch (DataFormatException dfe) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return new Destination(ip);
|
||||
} catch (DataFormatException dfe) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Base64 Hash or Hash.i2p or name.i2p using naming service */
|
||||
Destination getDestination(String ip) {
|
||||
if (ip == null) return null;
|
||||
if (ip.endsWith(".i2p")) {
|
||||
@ -266,7 +312,40 @@ public class I2PSnarkUtil {
|
||||
return rv;
|
||||
}
|
||||
|
||||
public String getOpenTrackerString() {
|
||||
String rv = (String) _opts.get(PROP_OPENTRACKERS);
|
||||
if (rv == null)
|
||||
return DEFAULT_OPENTRACKERS;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** comma delimited list open trackers to use as backups */
|
||||
/** sorted map of name to announceURL=baseURL */
|
||||
public List getOpenTrackers() {
|
||||
if (!shouldUseOpenTrackers())
|
||||
return null;
|
||||
List rv = new ArrayList(1);
|
||||
String trackers = getOpenTrackerString();
|
||||
StringTokenizer tok = new StringTokenizer(trackers, ", ");
|
||||
while (tok.hasMoreTokens())
|
||||
rv.add(tok.nextToken());
|
||||
|
||||
if (rv.size() <= 0)
|
||||
return null;
|
||||
return rv;
|
||||
}
|
||||
|
||||
public boolean shouldUseOpenTrackers() {
|
||||
String rv = (String) _opts.get(PROP_USE_OPENTRACKERS);
|
||||
if (rv == null)
|
||||
return DEFAULT_USE_OPENTRACKERS;
|
||||
return Boolean.valueOf(rv).booleanValue();
|
||||
}
|
||||
|
||||
/** hook between snark's logger and an i2p log */
|
||||
void debug(String msg, int snarkDebugLevel) {
|
||||
debug(msg, snarkDebugLevel, null);
|
||||
}
|
||||
void debug(String msg, int snarkDebugLevel, Throwable t) {
|
||||
if (t instanceof OutOfMemoryError) {
|
||||
try { Thread.sleep(100); } catch (InterruptedException ie) {}
|
||||
|
@ -408,7 +408,7 @@ public class MetaInfo
|
||||
info.put("name", name);
|
||||
if (name_utf8 != null)
|
||||
info.put("name.utf-8", name_utf8);
|
||||
info.put("piece length", new Integer(piece_length));
|
||||
info.put("piece length", Integer.valueOf(piece_length));
|
||||
info.put("pieces", piece_hashes);
|
||||
if (files == null)
|
||||
info.put("length", new Long(length));
|
||||
@ -434,9 +434,10 @@ public class MetaInfo
|
||||
Map info = createInfoMap();
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append("info: ");
|
||||
for (Iterator iter = info.keySet().iterator(); iter.hasNext(); ) {
|
||||
String key = (String)iter.next();
|
||||
Object val = info.get(key);
|
||||
for (Iterator iter = info.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String key = (String)entry.getKey();
|
||||
Object val = entry.getValue();
|
||||
buf.append(key).append('=');
|
||||
if (val instanceof byte[])
|
||||
buf.append(Base64.encode((byte[])val, true));
|
||||
|
@ -173,7 +173,7 @@ public class Peer implements Comparable
|
||||
* If the given BitField is non-null it is send to the peer as first
|
||||
* message.
|
||||
*/
|
||||
public void runConnection(PeerListener listener, BitField bitfield)
|
||||
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield)
|
||||
{
|
||||
if (state != null)
|
||||
throw new IllegalStateException("Peer already started");
|
||||
@ -184,7 +184,7 @@ public class Peer implements Comparable
|
||||
// Do we need to handshake?
|
||||
if (din == null)
|
||||
{
|
||||
sock = I2PSnarkUtil.instance().connect(peerID);
|
||||
sock = util.connect(peerID);
|
||||
_log.debug("Connected to " + peerID + ": " + sock);
|
||||
if ((sock == null) || (sock.isClosed())) {
|
||||
throw new IOException("Unable to reach " + peerID);
|
||||
|
@ -32,12 +32,14 @@ import java.util.TimerTask;
|
||||
*/
|
||||
class PeerCheckerTask extends TimerTask
|
||||
{
|
||||
private final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
|
||||
private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
|
||||
|
||||
private final PeerCoordinator coordinator;
|
||||
public I2PSnarkUtil _util;
|
||||
|
||||
PeerCheckerTask(PeerCoordinator coordinator)
|
||||
PeerCheckerTask(I2PSnarkUtil util, PeerCoordinator coordinator)
|
||||
{
|
||||
_util = util;
|
||||
this.coordinator = coordinator;
|
||||
}
|
||||
|
||||
@ -102,8 +104,8 @@ class PeerCheckerTask extends TimerTask
|
||||
peer.setRateHistory(upload, download);
|
||||
peer.resetCounters();
|
||||
|
||||
Snark.debug(peer + ":", Snark.DEBUG);
|
||||
Snark.debug(" ul: " + upload/KILOPERSECOND
|
||||
_util.debug(peer + ":", Snark.DEBUG);
|
||||
_util.debug(" ul: " + upload/KILOPERSECOND
|
||||
+ " dl: " + download/KILOPERSECOND
|
||||
+ " i: " + peer.isInterested()
|
||||
+ " I: " + peer.isInteresting()
|
||||
@ -129,7 +131,7 @@ class PeerCheckerTask extends TimerTask
|
||||
// Check if it still wants pieces from us.
|
||||
if (!peer.isInterested())
|
||||
{
|
||||
Snark.debug("Choke uninterested peer: " + peer,
|
||||
_util.debug("Choke uninterested peer: " + peer,
|
||||
Snark.INFO);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
@ -141,7 +143,7 @@ class PeerCheckerTask extends TimerTask
|
||||
}
|
||||
else if (overBWLimitChoke)
|
||||
{
|
||||
Snark.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
|
||||
_util.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
|
||||
Snark.INFO);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
@ -155,7 +157,7 @@ class PeerCheckerTask extends TimerTask
|
||||
else if (peer.isInteresting() && peer.isChoked())
|
||||
{
|
||||
// If they are choking us make someone else a downloader
|
||||
Snark.debug("Choke choking peer: " + peer, Snark.DEBUG);
|
||||
_util.debug("Choke choking peer: " + peer, Snark.DEBUG);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
coordinator.uploaders--;
|
||||
@ -168,7 +170,7 @@ class PeerCheckerTask extends TimerTask
|
||||
else if (!peer.isInteresting() && !coordinator.completed())
|
||||
{
|
||||
// If they aren't interesting make someone else a downloader
|
||||
Snark.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
|
||||
_util.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
coordinator.uploaders--;
|
||||
@ -183,7 +185,7 @@ class PeerCheckerTask extends TimerTask
|
||||
&& download == 0)
|
||||
{
|
||||
// We are downloading but didn't receive anything...
|
||||
Snark.debug("Choke downloader that doesn't deliver:"
|
||||
_util.debug("Choke downloader that doesn't deliver:"
|
||||
+ peer, Snark.DEBUG);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
@ -222,7 +224,7 @@ class PeerCheckerTask extends TimerTask
|
||||
|| uploaders > uploadLimit)
|
||||
&& worstDownloader != null)
|
||||
{
|
||||
Snark.debug("Choke worst downloader: " + worstDownloader,
|
||||
_util.debug("Choke worst downloader: " + worstDownloader,
|
||||
Snark.DEBUG);
|
||||
|
||||
worstDownloader.setChoking(true);
|
||||
@ -247,6 +249,10 @@ class PeerCheckerTask extends TimerTask
|
||||
// store the rates
|
||||
coordinator.setRateHistory(uploaded, downloaded);
|
||||
|
||||
// close out unused files, but we don't need to do it every time
|
||||
if (random.nextInt(4) == 0)
|
||||
coordinator.getStorage().cleanRAFs();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
|
||||
@ -58,7 +58,7 @@ class PeerConnectionOut implements Runnable
|
||||
}
|
||||
|
||||
public void startup() {
|
||||
thread = new I2PThread(this, "Snark sender " + _id + ": " + peer);
|
||||
thread = new I2PAppThread(this, "Snark sender " + _id + ": " + peer);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Timer;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -44,7 +44,6 @@ public class PeerCoordinator implements PeerListener
|
||||
|
||||
// package local for access by CheckDownLoadersTask
|
||||
final static long CHECK_PERIOD = 40*1000; // 40 seconds
|
||||
final static int MAX_CONNECTIONS = 16;
|
||||
final static int MAX_UPLOADERS = 6;
|
||||
|
||||
// Approximation of the number of current uploaders.
|
||||
@ -77,13 +76,15 @@ public class PeerCoordinator implements PeerListener
|
||||
private boolean halted = false;
|
||||
|
||||
private final CoordinatorListener listener;
|
||||
public I2PSnarkUtil _util;
|
||||
|
||||
public String trackerProblems = null;
|
||||
public int trackerSeenPeers = 0;
|
||||
|
||||
public PeerCoordinator(byte[] id, MetaInfo metainfo, Storage storage,
|
||||
public PeerCoordinator(I2PSnarkUtil util, byte[] id, MetaInfo metainfo, Storage storage,
|
||||
CoordinatorListener listener, Snark torrent)
|
||||
{
|
||||
_util = util;
|
||||
this.id = id;
|
||||
this.metainfo = metainfo;
|
||||
this.storage = storage;
|
||||
@ -96,7 +97,7 @@ public class PeerCoordinator implements PeerListener
|
||||
// Randomize the first start time so multiple tasks are spread out,
|
||||
// this will help the behavior with global limits
|
||||
Random r = new Random();
|
||||
timer.schedule(new PeerCheckerTask(this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
|
||||
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
|
||||
}
|
||||
|
||||
// only called externally from Storage after the double-check fails
|
||||
@ -235,7 +236,7 @@ public class PeerCoordinator implements PeerListener
|
||||
{
|
||||
synchronized(peers)
|
||||
{
|
||||
return !halted && peers.size() < MAX_CONNECTIONS;
|
||||
return !halted && peers.size() < _util.getMaxConnections();
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,7 +294,7 @@ public class PeerCoordinator implements PeerListener
|
||||
peer.disconnect(false); // Don't deregister this connection/peer.
|
||||
}
|
||||
// This is already checked in addPeer() but we could have gone over the limit since then
|
||||
else if (peers.size() >= MAX_CONNECTIONS)
|
||||
else if (peers.size() >= _util.getMaxConnections())
|
||||
{
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
|
||||
@ -349,7 +350,7 @@ public class PeerCoordinator implements PeerListener
|
||||
peersize = peers.size();
|
||||
// This isn't a strict limit, as we may have several pending connections;
|
||||
// thus there is an additional check in connected()
|
||||
need_more = (!peer.isConnected()) && peersize < MAX_CONNECTIONS;
|
||||
need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
|
||||
// Check if we already have this peer before we build the connection
|
||||
Peer old = peerIDInList(peer.getPeerID(), peers);
|
||||
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
|
||||
@ -366,18 +367,18 @@ public class PeerCoordinator implements PeerListener
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
peer.runConnection(listener, bitfield);
|
||||
peer.runConnection(_util, listener, bitfield);
|
||||
}
|
||||
};
|
||||
String threadName = peer.toString();
|
||||
new I2PThread(r, threadName).start();
|
||||
new I2PAppThread(r, threadName).start();
|
||||
return true;
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
if (peer.isConnected())
|
||||
_log.info("Add peer already connected: " + peer);
|
||||
else
|
||||
_log.info("Connections: " + peersize + "/" + MAX_CONNECTIONS
|
||||
_log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
|
||||
+ " not accepting extra peer: " + peer);
|
||||
}
|
||||
return false;
|
||||
@ -846,7 +847,7 @@ public class PeerCoordinator implements PeerListener
|
||||
*/
|
||||
public int allowedUploaders()
|
||||
{
|
||||
if (Snark.overUploadLimit(uploaders)) {
|
||||
if (listener != null && listener.overUploadLimit(uploaders)) {
|
||||
// if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Over limit, uploaders was: " + uploaders);
|
||||
return uploaders - 1;
|
||||
@ -858,12 +859,16 @@ public class PeerCoordinator implements PeerListener
|
||||
|
||||
public boolean overUpBWLimit()
|
||||
{
|
||||
return Snark.overUpBWLimit();
|
||||
if (listener != null)
|
||||
return listener.overUpBWLimit();
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean overUpBWLimit(long total)
|
||||
{
|
||||
return Snark.overUpBWLimit(total * 1000 / CHECK_PERIOD);
|
||||
if (listener != null)
|
||||
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,9 @@ import java.util.Set;
|
||||
* from it there too)
|
||||
*/
|
||||
public class PeerCoordinatorSet {
|
||||
private static final PeerCoordinatorSet _instance = new PeerCoordinatorSet();
|
||||
public static final PeerCoordinatorSet instance() { return _instance; }
|
||||
private Set _coordinators;
|
||||
|
||||
private PeerCoordinatorSet() {
|
||||
public PeerCoordinatorSet() {
|
||||
_coordinators = new HashSet();
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class PeerID implements Comparable
|
||||
bevalue = (BEValue)m.get("ip");
|
||||
if (bevalue == null)
|
||||
throw new InvalidBEncodingException("ip missing");
|
||||
address = I2PSnarkUtil.instance().getDestination(bevalue.getString());
|
||||
address = I2PSnarkUtil.getDestinationFromBase64(bevalue.getString());
|
||||
if (address == null)
|
||||
throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]");
|
||||
|
||||
|
@ -30,7 +30,7 @@ import java.util.TimerTask;
|
||||
class PeerMonitorTask extends TimerTask
|
||||
{
|
||||
final static long MONITOR_PERIOD = 10 * 1000; // Ten seconds.
|
||||
private final long KILOPERSECOND = 1024 * (MONITOR_PERIOD / 1000);
|
||||
private static final long KILOPERSECOND = 1024 * (MONITOR_PERIOD / 1000);
|
||||
|
||||
private final PeerCoordinator coordinator;
|
||||
|
||||
|
@ -28,12 +28,15 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.router.client.ClientManagerFacadeImpl;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.I2PThread;
|
||||
@ -102,7 +105,7 @@ public class Snark
|
||||
public void outOfMemory(OutOfMemoryError err) {
|
||||
try {
|
||||
err.printStackTrace();
|
||||
I2PSnarkUtil.instance().debug("OOM in the snark", Snark.ERROR, err);
|
||||
System.out.println("OOM in the snark" + err);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("OOM in the OOM");
|
||||
}
|
||||
@ -225,7 +228,7 @@ public class Snark
|
||||
}
|
||||
catch(IOException ioe)
|
||||
{
|
||||
debug("ERROR while reading stdin: " + ioe, ERROR);
|
||||
System.out.println("ERROR while reading stdin: " + ioe);
|
||||
}
|
||||
|
||||
// Explicit shutdown.
|
||||
@ -234,6 +237,7 @@ public class Snark
|
||||
}
|
||||
}
|
||||
|
||||
public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections";
|
||||
public String torrent;
|
||||
public MetaInfo meta;
|
||||
public Storage storage;
|
||||
@ -244,19 +248,59 @@ public class Snark
|
||||
public CompleteListener completeListener;
|
||||
public boolean stopped;
|
||||
byte[] id;
|
||||
public I2PSnarkUtil _util;
|
||||
private PeerCoordinatorSet _peerCoordinatorSet;
|
||||
|
||||
Snark(String torrent, String ip, int user_port,
|
||||
/** from main() via parseArguments() single torrent */
|
||||
Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
|
||||
StorageListener slistener, CoordinatorListener clistener) {
|
||||
this(torrent, ip, user_port, slistener, clistener, true, ".");
|
||||
this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
|
||||
}
|
||||
Snark(String torrent, String ip, int user_port,
|
||||
StorageListener slistener, CoordinatorListener clistener, boolean start, String rootDir)
|
||||
|
||||
/** single torrent - via router */
|
||||
public Snark(I2PAppContext ctx, Properties opts, String torrent,
|
||||
StorageListener slistener, boolean start, String rootDir) {
|
||||
this(new I2PSnarkUtil(ctx), torrent, null, -1, slistener, null, null, null, null, false, rootDir);
|
||||
String host = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_HOST);
|
||||
int port = 0;
|
||||
String s = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT);
|
||||
if (s != null) {
|
||||
try {
|
||||
port = Integer.parseInt(s);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
_util.setI2CPConfig(host, port, opts);
|
||||
s = opts.getProperty(SnarkManager.PROP_UPBW_MAX);
|
||||
if (s != null) {
|
||||
try {
|
||||
int v = Integer.parseInt(s);
|
||||
_util.setMaxUpBW(v);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
s = opts.getProperty(PROP_MAX_CONNECTIONS);
|
||||
if (s != null) {
|
||||
try {
|
||||
int v = Integer.parseInt(s);
|
||||
_util.setMaxConnections(v);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
if (start)
|
||||
this.startTorrent();
|
||||
}
|
||||
|
||||
/** multitorrent */
|
||||
public Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
|
||||
StorageListener slistener, CoordinatorListener clistener,
|
||||
CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet,
|
||||
ConnectionAcceptor connectionAcceptor, boolean start, String rootDir)
|
||||
{
|
||||
if (slistener == null)
|
||||
slistener = this;
|
||||
|
||||
if (clistener == null)
|
||||
clistener = this;
|
||||
completeListener = complistener;
|
||||
_util = util;
|
||||
_peerCoordinatorSet = peerCoordinatorSet;
|
||||
acceptor = connectionAcceptor;
|
||||
|
||||
this.torrent = torrent;
|
||||
this.rootDataDir = rootDir;
|
||||
@ -289,7 +333,7 @@ public class Snark
|
||||
while (i < 20)
|
||||
id[i++] = (byte)random.nextInt(256);
|
||||
|
||||
Snark.debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
|
||||
debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
|
||||
|
||||
int port;
|
||||
IOException lastException = null;
|
||||
@ -298,9 +342,9 @@ public class Snark
|
||||
* If we are starting,
|
||||
* startTorrent() will force a connect.
|
||||
*
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
boolean ok = util.connect();
|
||||
if (!ok) fatal("Unable to connect to I2P");
|
||||
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
I2PServerSocket serversocket = util.getServerSocket();
|
||||
if (serversocket == null)
|
||||
fatal("Unable to listen for I2P connections");
|
||||
else {
|
||||
@ -312,16 +356,16 @@ public class Snark
|
||||
// Figure out what the torrent argument represents.
|
||||
meta = null;
|
||||
File f = null;
|
||||
InputStream in = null;
|
||||
try
|
||||
{
|
||||
InputStream in = null;
|
||||
f = new File(torrent);
|
||||
if (f.exists())
|
||||
in = new FileInputStream(f);
|
||||
else
|
||||
{
|
||||
activity = "Getting torrent";
|
||||
File torrentFile = I2PSnarkUtil.instance().get(torrent, 3);
|
||||
File torrentFile = _util.get(torrent, 3);
|
||||
if (torrentFile == null) {
|
||||
fatal("Unable to fetch " + torrent);
|
||||
if (false) return; // never reached - fatal(..) throws
|
||||
@ -345,7 +389,7 @@ public class Snark
|
||||
/*
|
||||
{
|
||||
// Try to create a new metainfo file
|
||||
Snark.debug
|
||||
debug
|
||||
("Trying to create metainfo torrent for '" + torrent + "'",
|
||||
NOTICE);
|
||||
try
|
||||
@ -364,8 +408,11 @@ public class Snark
|
||||
*/
|
||||
else
|
||||
fatal("Cannot open '" + torrent + "'", ioe);
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (in != null)
|
||||
try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
|
||||
debug(meta.toString(), INFO);
|
||||
|
||||
// When the metainfo torrent was created from an existing file/dir
|
||||
@ -375,8 +422,14 @@ public class Snark
|
||||
try
|
||||
{
|
||||
activity = "Checking storage";
|
||||
storage = new Storage(meta, slistener);
|
||||
storage.check(rootDataDir);
|
||||
storage = new Storage(_util, meta, slistener);
|
||||
if (completeListener != null) {
|
||||
storage.check(rootDataDir,
|
||||
completeListener.getSavedTorrentTime(this),
|
||||
completeListener.getSavedTorrentBitField(this));
|
||||
} else {
|
||||
storage.check(rootDataDir);
|
||||
}
|
||||
// have to figure out when to reopen
|
||||
// if (!start)
|
||||
// storage.close();
|
||||
@ -410,10 +463,10 @@ public class Snark
|
||||
* Start up contacting peers and querying the tracker
|
||||
*/
|
||||
public void startTorrent() {
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) fatal("Unable to connect to I2P");
|
||||
if (coordinator == null) {
|
||||
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
I2PServerSocket serversocket = _util.getServerSocket();
|
||||
if (serversocket == null)
|
||||
fatal("Unable to listen for I2P connections");
|
||||
else {
|
||||
@ -422,12 +475,20 @@ public class Snark
|
||||
}
|
||||
debug("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient", NOTICE);
|
||||
activity = "Collecting pieces";
|
||||
coordinator = new PeerCoordinator(id, meta, storage, this, this);
|
||||
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
|
||||
set.add(coordinator);
|
||||
ConnectionAcceptor acceptor = ConnectionAcceptor.instance();
|
||||
acceptor.startAccepting(set, serversocket);
|
||||
trackerclient = new TrackerClient(meta, coordinator);
|
||||
coordinator = new PeerCoordinator(_util, id, meta, storage, this, this);
|
||||
if (_peerCoordinatorSet != null) {
|
||||
// multitorrent
|
||||
_peerCoordinatorSet.add(coordinator);
|
||||
if (acceptor != null) {
|
||||
acceptor.startAccepting(_peerCoordinatorSet, serversocket);
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
} else {
|
||||
// single torrent
|
||||
acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator));
|
||||
}
|
||||
trackerclient = new TrackerClient(_util, meta, coordinator);
|
||||
}
|
||||
|
||||
stopped = false;
|
||||
@ -435,11 +496,12 @@ public class Snark
|
||||
if (coordinator.halted()) {
|
||||
// ok, we have already started and stopped, but the coordinator seems a bit annoying to
|
||||
// restart safely, so lets build a new one to replace the old
|
||||
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
|
||||
set.remove(coordinator);
|
||||
PeerCoordinator newCoord = new PeerCoordinator(coordinator.getID(), coordinator.getMetaInfo(),
|
||||
if (_peerCoordinatorSet != null)
|
||||
_peerCoordinatorSet.remove(coordinator);
|
||||
PeerCoordinator newCoord = new PeerCoordinator(_util, coordinator.getID(), coordinator.getMetaInfo(),
|
||||
coordinator.getStorage(), coordinator.getListener(), this);
|
||||
set.add(newCoord);
|
||||
if (_peerCoordinatorSet != null)
|
||||
_peerCoordinatorSet.add(newCoord);
|
||||
coordinator = newCoord;
|
||||
coordinatorChanged = true;
|
||||
}
|
||||
@ -457,7 +519,7 @@ public class Snark
|
||||
}
|
||||
fatal("Could not reopen storage", ioe);
|
||||
}
|
||||
TrackerClient newClient = new TrackerClient(coordinator.getMetaInfo(), coordinator);
|
||||
TrackerClient newClient = new TrackerClient(_util, coordinator.getMetaInfo(), coordinator);
|
||||
if (!trackerclient.halted())
|
||||
trackerclient.halt();
|
||||
trackerclient = newClient;
|
||||
@ -477,17 +539,20 @@ public class Snark
|
||||
pc.halt();
|
||||
Storage st = storage;
|
||||
if (st != null) {
|
||||
if (storage.changed)
|
||||
SnarkManager.instance().saveTorrentStatus(storage.getMetaInfo(), storage.getBitField());
|
||||
boolean changed = storage.changed;
|
||||
try {
|
||||
storage.close();
|
||||
} catch (IOException ioe) {
|
||||
System.out.println("Error closing " + torrent);
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
if (changed && completeListener != null)
|
||||
completeListener.updateStatus(this);
|
||||
}
|
||||
if (pc != null)
|
||||
PeerCoordinatorSet.instance().remove(pc);
|
||||
if (pc != null && _peerCoordinatorSet != null)
|
||||
_peerCoordinatorSet.remove(pc);
|
||||
if (_peerCoordinatorSet == null)
|
||||
_util.disconnect();
|
||||
}
|
||||
|
||||
static Snark parseArguments(String[] args)
|
||||
@ -509,7 +574,8 @@ public class Snark
|
||||
String ip = null;
|
||||
String torrent = null;
|
||||
|
||||
boolean configured = I2PSnarkUtil.instance().configured();
|
||||
I2PSnarkUtil util = new I2PSnarkUtil(I2PAppContext.getGlobalContext());
|
||||
boolean configured = util.configured();
|
||||
|
||||
int i = 0;
|
||||
while (i < args.length)
|
||||
@ -559,7 +625,7 @@ public class Snark
|
||||
String proxyHost = args[i+1];
|
||||
String proxyPort = args[i+2];
|
||||
if (!configured)
|
||||
I2PSnarkUtil.instance().setProxy(proxyHost, Integer.parseInt(proxyPort));
|
||||
util.setProxy(proxyHost, Integer.parseInt(proxyPort));
|
||||
i += 3;
|
||||
}
|
||||
else if (args[i].equals("--i2cp"))
|
||||
@ -581,7 +647,7 @@ public class Snark
|
||||
}
|
||||
}
|
||||
if (!configured)
|
||||
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
|
||||
util.setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
|
||||
i += 3 + (opts != null ? 1 : 0);
|
||||
}
|
||||
else
|
||||
@ -598,7 +664,7 @@ public class Snark
|
||||
else
|
||||
usage("Need exactly one <url>, <file> or <dir>.");
|
||||
|
||||
return new Snark(torrent, ip, user_port, slistener, clistener);
|
||||
return new Snark(util, torrent, ip, user_port, slistener, clistener);
|
||||
}
|
||||
|
||||
private static void usage(String s)
|
||||
@ -665,7 +731,7 @@ public class Snark
|
||||
*/
|
||||
public void fatal(String s, Throwable t)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug(s, ERROR, t);
|
||||
_util.debug(s, ERROR, t);
|
||||
//System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
|
||||
//if (debug >= INFO && t != null)
|
||||
// t.printStackTrace();
|
||||
@ -676,13 +742,12 @@ public class Snark
|
||||
/**
|
||||
* Show debug info if debug is true.
|
||||
*/
|
||||
public static void debug(String s, int level)
|
||||
private void debug(String s, int level)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug(s, level, null);
|
||||
//if (debug >= level)
|
||||
// System.out.println(s);
|
||||
_util.debug(s, level, null);
|
||||
}
|
||||
|
||||
/** coordinatorListener */
|
||||
public void peerChange(PeerCoordinator coordinator, Peer peer)
|
||||
{
|
||||
// System.out.println(peer.toString());
|
||||
@ -721,7 +786,7 @@ public class Snark
|
||||
{
|
||||
// Use the MetaInfo from the storage since our own might not
|
||||
// yet be setup correctly.
|
||||
MetaInfo meta = storage.getMetaInfo();
|
||||
//MetaInfo meta = storage.getMetaInfo();
|
||||
//if (meta != null)
|
||||
// System.out.print("Checking existing "
|
||||
// + meta.getPieces()
|
||||
@ -729,7 +794,7 @@ public class Snark
|
||||
checking = true;
|
||||
}
|
||||
if (!checking)
|
||||
Snark.debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
|
||||
debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
|
||||
Snark.INFO);
|
||||
}
|
||||
|
||||
@ -740,11 +805,13 @@ public class Snark
|
||||
|
||||
allChecked = true;
|
||||
checking = false;
|
||||
if (storage.changed && completeListener != null)
|
||||
completeListener.updateStatus(this);
|
||||
}
|
||||
|
||||
public void storageCompleted(Storage storage)
|
||||
{
|
||||
Snark.debug("Completely received " + torrent, Snark.INFO);
|
||||
debug("Completely received " + torrent, Snark.INFO);
|
||||
//storage.close();
|
||||
//System.out.println("Completely received: " + torrent);
|
||||
if (completeListener != null)
|
||||
@ -765,44 +832,47 @@ public class Snark
|
||||
|
||||
public interface CompleteListener {
|
||||
public void torrentComplete(Snark snark);
|
||||
public void updateStatus(Snark snark);
|
||||
// not really listeners but the easiest way to get back to an optional SnarkManager
|
||||
public long getSavedTorrentTime(Snark snark);
|
||||
public BitField getSavedTorrentBitField(Snark snark);
|
||||
}
|
||||
|
||||
/** Maintain a configurable total uploader cap
|
||||
* coordinatorListener
|
||||
*/
|
||||
final static int MIN_TOTAL_UPLOADERS = 4;
|
||||
final static int MAX_TOTAL_UPLOADERS = 10;
|
||||
public static boolean overUploadLimit(int uploaders) {
|
||||
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
|
||||
if (coordinators == null || uploaders <= 0)
|
||||
public boolean overUploadLimit(int uploaders) {
|
||||
if (_peerCoordinatorSet == null || uploaders <= 0)
|
||||
return false;
|
||||
int totalUploaders = 0;
|
||||
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
|
||||
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
|
||||
PeerCoordinator c = (PeerCoordinator)iter.next();
|
||||
if (!c.halted())
|
||||
totalUploaders += c.uploaders;
|
||||
}
|
||||
int limit = I2PSnarkUtil.instance().getMaxUploaders();
|
||||
// Snark.debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
|
||||
int limit = _util.getMaxUploaders();
|
||||
// debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
|
||||
return totalUploaders > limit;
|
||||
}
|
||||
|
||||
public static boolean overUpBWLimit() {
|
||||
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
|
||||
if (coordinators == null)
|
||||
public boolean overUpBWLimit() {
|
||||
if (_peerCoordinatorSet == null)
|
||||
return false;
|
||||
long total = 0;
|
||||
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
|
||||
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
|
||||
PeerCoordinator c = (PeerCoordinator)iter.next();
|
||||
if (!c.halted())
|
||||
total += c.getCurrentUploadRate();
|
||||
}
|
||||
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW();
|
||||
Snark.debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
|
||||
long limit = 1024l * _util.getMaxUpBW();
|
||||
debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
|
||||
return total > limit;
|
||||
}
|
||||
|
||||
public static boolean overUpBWLimit(long total) {
|
||||
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW();
|
||||
public boolean overUpBWLimit(long total) {
|
||||
long limit = 1024l * _util.getMaxUpBW();
|
||||
return total > limit;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -32,11 +32,14 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
/** map of (canonical) filename to Snark instance (unsynchronized) */
|
||||
private Map _snarks;
|
||||
private Object _addSnarkLock;
|
||||
private String _configFile;
|
||||
private String _configFile = "i2psnark.config";
|
||||
private Properties _config;
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private List _messages;
|
||||
private I2PSnarkUtil _util;
|
||||
private PeerCoordinatorSet _peerCoordinatorSet;
|
||||
private ConnectionAcceptor _connectionAcceptor;
|
||||
|
||||
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
|
||||
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
|
||||
@ -51,10 +54,6 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
|
||||
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
|
||||
public static final String DEFAULT_AUTO_START = "false";
|
||||
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
||||
public static final String DEFAULT_USE_OPENTRACKERS = "true";
|
||||
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
||||
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
||||
public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
|
||||
public static final String DEFAULT_LINK_PREFIX = "file:///";
|
||||
|
||||
@ -67,16 +66,28 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
_log = _context.logManager().getLog(SnarkManager.class);
|
||||
_messages = new ArrayList(16);
|
||||
loadConfig("i2psnark.config");
|
||||
_util = new I2PSnarkUtil(_context);
|
||||
loadConfig(null);
|
||||
}
|
||||
|
||||
/** Caller _must_ call loadConfig(file) before this if setting new values
|
||||
* for i2cp host/port or i2psnark.dir
|
||||
*/
|
||||
public void start() {
|
||||
_peerCoordinatorSet = new PeerCoordinatorSet();
|
||||
_connectionAcceptor = new ConnectionAcceptor(_util);
|
||||
int minutes = getStartupDelayMinutes();
|
||||
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
|
||||
I2PThread monitor = new I2PThread(new DirMonitor(), "Snark DirMonitor");
|
||||
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
|
||||
monitor.setDaemon(true);
|
||||
monitor.start();
|
||||
if (_context instanceof RouterContext)
|
||||
((RouterContext)_context).router().addShutdownTask(new SnarkManagerShutdown());
|
||||
}
|
||||
|
||||
/** hook to I2PSnarkUtil for the servlet */
|
||||
public I2PSnarkUtil util() { return _util; }
|
||||
|
||||
private static final int MAX_MESSAGES = 5;
|
||||
public void addMessage(String message) {
|
||||
synchronized (_messages) {
|
||||
@ -98,9 +109,6 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
public boolean shouldAutoStart() {
|
||||
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START+"")).booleanValue();
|
||||
}
|
||||
public boolean shouldUseOpenTrackers() {
|
||||
return Boolean.valueOf(_config.getProperty(PROP_USE_OPENTRACKERS, DEFAULT_USE_OPENTRACKERS)).booleanValue();
|
||||
}
|
||||
public String linkPrefix() {
|
||||
return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar);
|
||||
}
|
||||
@ -112,17 +120,20 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
return new File(dir);
|
||||
}
|
||||
|
||||
/** null to set initial defaults */
|
||||
public void loadConfig(String filename) {
|
||||
_configFile = filename;
|
||||
if (_config == null)
|
||||
_config = new Properties();
|
||||
File cfg = new File(filename);
|
||||
if (cfg.exists()) {
|
||||
try {
|
||||
DataHelper.loadProps(_config, cfg);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error loading I2PSnark config '" + filename + "'", ioe);
|
||||
}
|
||||
if (filename != null) {
|
||||
_configFile = filename;
|
||||
File cfg = new File(filename);
|
||||
if (cfg.exists()) {
|
||||
try {
|
||||
DataHelper.loadProps(_config, cfg);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error loading I2PSnark config '" + filename + "'", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
// now add sane defaults
|
||||
if (!_config.containsKey(PROP_I2CP_HOST))
|
||||
@ -130,7 +141,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
if (!_config.containsKey(PROP_I2CP_PORT))
|
||||
_config.setProperty(PROP_I2CP_PORT, "7654");
|
||||
if (!_config.containsKey(PROP_I2CP_OPTS))
|
||||
_config.setProperty(PROP_I2CP_OPTS, "inbound.length=1 inbound.lengthVariance=1 outbound.length=1 outbound.lengthVariance=1");
|
||||
_config.setProperty(PROP_I2CP_OPTS, "inbound.length=2 inbound.lengthVariance=0 outbound.length=2 outbound.lengthVariance=0");
|
||||
if (!_config.containsKey(PROP_EEP_HOST))
|
||||
_config.setProperty(PROP_EEP_HOST, "localhost");
|
||||
if (!_config.containsKey(PROP_EEP_PORT))
|
||||
@ -169,16 +180,16 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (i2cpHost != null) {
|
||||
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
|
||||
_util.setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
|
||||
_log.debug("Configuring with I2CP options " + i2cpOpts);
|
||||
}
|
||||
//I2PSnarkUtil.instance().setI2CPConfig("66.111.51.110", 7654, new Properties());
|
||||
String eepHost = _config.getProperty(PROP_EEP_HOST);
|
||||
int eepPort = getInt(PROP_EEP_PORT, 4444);
|
||||
if (eepHost != null)
|
||||
I2PSnarkUtil.instance().setProxy(eepHost, eepPort);
|
||||
I2PSnarkUtil.instance().setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
|
||||
I2PSnarkUtil.instance().setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||
_util.setProxy(eepHost, eepPort);
|
||||
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
|
||||
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||
getDataDir().mkdirs();
|
||||
}
|
||||
|
||||
@ -198,12 +209,12 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) {
|
||||
boolean changed = false;
|
||||
if (eepHost != null) {
|
||||
int port = I2PSnarkUtil.instance().getEepProxyPort();
|
||||
int port = _util.getEepProxyPort();
|
||||
try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
|
||||
String host = I2PSnarkUtil.instance().getEepProxyHost();
|
||||
String host = _util.getEepProxyHost();
|
||||
if ( (eepHost.trim().length() > 0) && (port > 0) &&
|
||||
((!host.equals(eepHost) || (port != I2PSnarkUtil.instance().getEepProxyPort()) )) ) {
|
||||
I2PSnarkUtil.instance().setProxy(eepHost, port);
|
||||
((!host.equals(eepHost) || (port != _util.getEepProxyPort()) )) ) {
|
||||
_util.setProxy(eepHost, port);
|
||||
changed = true;
|
||||
_config.setProperty(PROP_EEP_HOST, eepHost);
|
||||
_config.setProperty(PROP_EEP_PORT, eepPort+"");
|
||||
@ -211,11 +222,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (upLimit != null) {
|
||||
int limit = I2PSnarkUtil.instance().getMaxUploaders();
|
||||
int limit = _util.getMaxUploaders();
|
||||
try { limit = Integer.parseInt(upLimit); } catch (NumberFormatException nfe) {}
|
||||
if ( limit != I2PSnarkUtil.instance().getMaxUploaders()) {
|
||||
if ( limit != _util.getMaxUploaders()) {
|
||||
if ( limit >= Snark.MIN_TOTAL_UPLOADERS ) {
|
||||
I2PSnarkUtil.instance().setMaxUploaders(limit);
|
||||
_util.setMaxUploaders(limit);
|
||||
changed = true;
|
||||
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit);
|
||||
addMessage("Total uploaders limit changed to " + limit);
|
||||
@ -225,11 +236,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (upBW != null) {
|
||||
int limit = I2PSnarkUtil.instance().getMaxUpBW();
|
||||
int limit = _util.getMaxUpBW();
|
||||
try { limit = Integer.parseInt(upBW); } catch (NumberFormatException nfe) {}
|
||||
if ( limit != I2PSnarkUtil.instance().getMaxUpBW()) {
|
||||
if ( limit != _util.getMaxUpBW()) {
|
||||
if ( limit >= MIN_UP_BW ) {
|
||||
I2PSnarkUtil.instance().setMaxUpBW(limit);
|
||||
_util.setMaxUpBW(limit);
|
||||
changed = true;
|
||||
_config.setProperty(PROP_UPBW_MAX, "" + limit);
|
||||
addMessage("Up BW limit changed to " + limit + "KBps");
|
||||
@ -239,8 +250,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (i2cpHost != null) {
|
||||
int oldI2CPPort = I2PSnarkUtil.instance().getI2CPPort();
|
||||
String oldI2CPHost = I2PSnarkUtil.instance().getI2CPHost();
|
||||
int oldI2CPPort = _util.getI2CPPort();
|
||||
String oldI2CPHost = _util.getI2CPHost();
|
||||
int port = oldI2CPPort;
|
||||
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
|
||||
String host = oldI2CPHost;
|
||||
@ -266,7 +277,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
|
||||
if ( (i2cpHost.trim().length() > 0) && (port > 0) &&
|
||||
((!host.equals(i2cpHost) ||
|
||||
(port != I2PSnarkUtil.instance().getI2CPPort()) ||
|
||||
(port != _util.getI2CPPort()) ||
|
||||
(!oldOpts.equals(opts)))) ) {
|
||||
boolean snarksActive = false;
|
||||
Set names = listTorrentFiles();
|
||||
@ -282,19 +293,19 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
|
||||
+ "] oldOpts [" + oldOpts + "]");
|
||||
} else {
|
||||
if (I2PSnarkUtil.instance().connected()) {
|
||||
I2PSnarkUtil.instance().disconnect();
|
||||
if (_util.connected()) {
|
||||
_util.disconnect();
|
||||
addMessage("Disconnecting old I2CP destination");
|
||||
}
|
||||
Properties p = new Properties();
|
||||
p.putAll(opts);
|
||||
addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")");
|
||||
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, port, p);
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
_util.setI2CPConfig(i2cpHost, port, p);
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) {
|
||||
addMessage("Unable to connect with the new settings, reverting to the old I2CP settings");
|
||||
I2PSnarkUtil.instance().setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
|
||||
ok = I2PSnarkUtil.instance().connect();
|
||||
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
|
||||
ok = _util.connect();
|
||||
if (!ok)
|
||||
addMessage("Unable to reconnect with the old settings!");
|
||||
} else {
|
||||
@ -322,14 +333,14 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
addMessage("Adjusted autostart to " + autoStart);
|
||||
changed = true;
|
||||
}
|
||||
if (shouldUseOpenTrackers() != useOpenTrackers) {
|
||||
_config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + "");
|
||||
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
|
||||
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
|
||||
addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect");
|
||||
changed = true;
|
||||
}
|
||||
if (openTrackers != null) {
|
||||
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(getOpenTrackerString())) {
|
||||
_config.setProperty(PROP_OPENTRACKERS, openTrackers.trim());
|
||||
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
|
||||
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
|
||||
addMessage("Open Tracker list changed - torrent restart required to take effect");
|
||||
changed = true;
|
||||
}
|
||||
@ -354,7 +365,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
public Properties getConfig() { return _config; }
|
||||
|
||||
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
|
||||
private static final int MAX_FILES_PER_TORRENT = 128;
|
||||
private static final int MAX_FILES_PER_TORRENT = 256;
|
||||
|
||||
/** set of filenames that we are dealing with */
|
||||
public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
|
||||
@ -364,9 +375,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
|
||||
public void addTorrent(String filename) { addTorrent(filename, false); }
|
||||
public void addTorrent(String filename, boolean dontAutoStart) {
|
||||
if ((!dontAutoStart) && !I2PSnarkUtil.instance().connected()) {
|
||||
if ((!dontAutoStart) && !_util.connected()) {
|
||||
addMessage("Connecting to I2P");
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) {
|
||||
addMessage("Error connecting to I2P - check your I2CP settings");
|
||||
return;
|
||||
@ -407,7 +418,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
addMessage(rejectMessage);
|
||||
return;
|
||||
} else {
|
||||
torrent = new Snark(filename, null, -1, null, null, false, dataDir.getPath());
|
||||
torrent = new Snark(_util, filename, null, -1, null, null, this,
|
||||
_peerCoordinatorSet, _connectionAcceptor,
|
||||
false, dataDir.getPath());
|
||||
torrent.completeListener = this;
|
||||
synchronized (_snarks) {
|
||||
_snarks.put(filename, torrent);
|
||||
@ -438,7 +451,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
/**
|
||||
* Get the timestamp for a torrent from the config file
|
||||
*/
|
||||
public long getSavedTorrentTime(MetaInfo metainfo) {
|
||||
public long getSavedTorrentTime(Snark snark) {
|
||||
MetaInfo metainfo = snark.meta;
|
||||
byte[] ih = metainfo.getInfoHash();
|
||||
String infohash = Base64.encode(ih);
|
||||
infohash = infohash.replace('=', '$');
|
||||
@ -457,7 +471,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
* Get the saved bitfield for a torrent from the config file.
|
||||
* Convert "." to a full bitfield.
|
||||
*/
|
||||
public BitField getSavedTorrentBitField(MetaInfo metainfo) {
|
||||
public BitField getSavedTorrentBitField(Snark snark) {
|
||||
MetaInfo metainfo = snark.meta;
|
||||
byte[] ih = metainfo.getInfoHash();
|
||||
String infohash = Base64.encode(ih);
|
||||
infohash = infohash.replace('=', '$');
|
||||
@ -574,7 +589,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
if (remaining == 0) {
|
||||
// should we disconnect/reconnect here (taking care to deal with the other thread's
|
||||
// I2PServerSocket.accept() call properly?)
|
||||
////I2PSnarkUtil.instance().
|
||||
////_util.
|
||||
}
|
||||
if (!wasStopped)
|
||||
addMessage("Torrent stopped: '" + sfile.getName() + "'");
|
||||
@ -618,11 +633,17 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
|
||||
/** two listeners */
|
||||
public void torrentComplete(Snark snark) {
|
||||
File f = new File(snark.torrent);
|
||||
long len = snark.meta.getTotalLength();
|
||||
addMessage("Download complete of " + f.getName()
|
||||
+ (len < 5*1024*1024 ? " (size: " + (len/1024) + "KB)" : " (size: " + (len/(1024*1024l)) + "MB)"));
|
||||
updateStatus(snark);
|
||||
}
|
||||
|
||||
public void updateStatus(Snark snark) {
|
||||
saveTorrentStatus(snark.meta, snark.storage.getBitField());
|
||||
}
|
||||
|
||||
private void monitorTorrents(File dir) {
|
||||
@ -644,7 +665,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
if (existingNames.contains(foundNames.get(i))) {
|
||||
// already known. noop
|
||||
} else {
|
||||
if (shouldAutoStart() && !I2PSnarkUtil.instance().connect())
|
||||
if (shouldAutoStart() && !_util.connect())
|
||||
addMessage("Unable to connect to I2P");
|
||||
addTorrent((String)foundNames.get(i), !shouldAutoStart());
|
||||
}
|
||||
@ -672,6 +693,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
, "welterde", "http://BGKmlDOoH3RzFbPRfRpZV2FjpVj8~3moFftw5-dZfDf2070TOe8Tf2~DAVeaM6ZRLdmFEt~9wyFL8YMLMoLoiwGEH6IGW6rc45tstN68KsBDWZqkTohV1q9XFgK9JnCwE~Oi89xLBHsLMTHOabowWM6dkC8nI6QqJC2JODqLPIRfOVrDdkjLwtCrsckzLybNdFmgfoqF05UITDyczPsFVaHtpF1sRggOVmdvCM66otyonlzNcJbn59PA-R808vUrCPMGU~O9Wys0i-NoqtIbtWfOKnjCRFMNw5ex4n9m5Sxm9e20UkpKG6qzEuvKZWi8vTLe1NW~CBrj~vG7I3Ok4wybUFflBFOaBabxYJLlx4xTE1zJIVxlsekmAjckB4v-cQwulFeikR4LxPQ6mCQknW2HZ4JQIq6hL9AMabxjOlYnzh7kjOfRGkck8YgeozcyTvcDUcUsOuSTk06L4kdrv8h2Cozjbloi5zl6KTbj5ZTciKCxi73Pn9grICn-HQqEAAAA.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
|
||||
// , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
|
||||
// , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
|
||||
, "crstrack", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
|
||||
};
|
||||
|
||||
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
|
||||
@ -706,26 +728,6 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
return trackerMap;
|
||||
}
|
||||
|
||||
public String getOpenTrackerString() {
|
||||
return _config.getProperty(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS);
|
||||
}
|
||||
|
||||
/** comma delimited list open trackers to use as backups */
|
||||
/** sorted map of name to announceURL=baseURL */
|
||||
public List getOpenTrackers() {
|
||||
if (!shouldUseOpenTrackers())
|
||||
return null;
|
||||
List rv = new ArrayList(1);
|
||||
String trackers = getOpenTrackerString();
|
||||
StringTokenizer tok = new StringTokenizer(trackers, ", ");
|
||||
while (tok.hasMoreTokens())
|
||||
rv.add(tok.nextToken());
|
||||
|
||||
if (rv.size() <= 0)
|
||||
return null;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private static class TorrentFilenameFilter implements FilenameFilter {
|
||||
private static final TorrentFilenameFilter _filter = new TorrentFilenameFilter();
|
||||
public static TorrentFilenameFilter instance() { return _filter; }
|
||||
@ -734,7 +736,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
|
||||
public class SnarkManagerShutdown extends I2PThread {
|
||||
public class SnarkManagerShutdown extends I2PAppThread {
|
||||
public void run() {
|
||||
Set names = listTorrentFiles();
|
||||
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
|
||||
|
@ -22,12 +22,12 @@ package org.klomp.snark;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
* Makes sure everything ends correctly when shutting down.
|
||||
*/
|
||||
public class SnarkShutdown extends I2PThread
|
||||
public class SnarkShutdown extends I2PAppThread
|
||||
{
|
||||
private final Storage storage;
|
||||
private final PeerCoordinator coordinator;
|
||||
@ -51,21 +51,21 @@ public class SnarkShutdown extends I2PThread
|
||||
|
||||
public void run()
|
||||
{
|
||||
Snark.debug("Shutting down...", Snark.NOTICE);
|
||||
//Snark.debug("Shutting down...", Snark.NOTICE);
|
||||
|
||||
Snark.debug("Halting ConnectionAcceptor...", Snark.INFO);
|
||||
//Snark.debug("Halting ConnectionAcceptor...", Snark.INFO);
|
||||
if (acceptor != null)
|
||||
acceptor.halt();
|
||||
|
||||
Snark.debug("Halting TrackerClient...", Snark.INFO);
|
||||
//Snark.debug("Halting TrackerClient...", Snark.INFO);
|
||||
if (trackerclient != null)
|
||||
trackerclient.halt();
|
||||
|
||||
Snark.debug("Halting PeerCoordinator...", Snark.INFO);
|
||||
//Snark.debug("Halting PeerCoordinator...", Snark.INFO);
|
||||
if (coordinator != null)
|
||||
coordinator.halt();
|
||||
|
||||
Snark.debug("Closing Storage...", Snark.INFO);
|
||||
//Snark.debug("Closing Storage...", Snark.INFO);
|
||||
if (storage != null)
|
||||
{
|
||||
try
|
||||
@ -74,7 +74,7 @@ public class SnarkShutdown extends I2PThread
|
||||
}
|
||||
catch(IOException ioe)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
|
||||
//I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
|
||||
throw new RuntimeException("b0rking");
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ public class SnarkShutdown extends I2PThread
|
||||
// XXX - Should actually wait till done...
|
||||
try
|
||||
{
|
||||
Snark.debug("Waiting 5 seconds...", Snark.INFO);
|
||||
//Snark.debug("Waiting 5 seconds...", Snark.INFO);
|
||||
Thread.sleep(5*1000);
|
||||
}
|
||||
catch (InterruptedException ie) { /* ignored */ }
|
||||
|
@ -39,11 +39,16 @@ public class Storage
|
||||
private long[] lengths;
|
||||
private RandomAccessFile[] rafs;
|
||||
private String[] names;
|
||||
private Object[] RAFlock; // lock on RAF access
|
||||
private long[] RAFtime; // when was RAF last accessed, or 0 if closed
|
||||
private File[] RAFfile; // File to make it easier to reopen
|
||||
|
||||
private final StorageListener listener;
|
||||
private I2PSnarkUtil _util;
|
||||
|
||||
private BitField bitfield; // BitField to represent the pieces
|
||||
private int needed; // Number of pieces needed
|
||||
private boolean _probablyComplete; // use this to decide whether to open files RO
|
||||
|
||||
// XXX - Not always set correctly
|
||||
int piece_size;
|
||||
@ -62,12 +67,14 @@ public class Storage
|
||||
*
|
||||
* @exception IOException when creating and/or checking files fails.
|
||||
*/
|
||||
public Storage(MetaInfo metainfo, StorageListener listener)
|
||||
public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
_util = util;
|
||||
this.metainfo = metainfo;
|
||||
this.listener = listener;
|
||||
needed = metainfo.getPieces();
|
||||
_probablyComplete = false;
|
||||
bitfield = new BitField(needed);
|
||||
}
|
||||
|
||||
@ -76,9 +83,10 @@ public class Storage
|
||||
* with an appropriate MetaInfo file as can be announced on the
|
||||
* given announce String location.
|
||||
*/
|
||||
public Storage(File baseFile, String announce, StorageListener listener)
|
||||
public Storage(I2PSnarkUtil util, File baseFile, String announce, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
_util = util;
|
||||
this.listener = listener;
|
||||
// Create names, rafs and lengths arrays.
|
||||
getFiles(baseFile);
|
||||
@ -119,7 +127,6 @@ public class Storage
|
||||
files.add(file);
|
||||
}
|
||||
|
||||
String name = baseFile.getName();
|
||||
if (files.size() == 1) // FIXME: ...and if base file not a directory or should this be the only check?
|
||||
// this makes a bad metainfo if the directory has only one file in it
|
||||
{
|
||||
@ -133,7 +140,8 @@ public class Storage
|
||||
|
||||
}
|
||||
|
||||
// Creates piece hases for a new storage.
|
||||
// Creates piece hashes for a new storage.
|
||||
// This does NOT create the files, just the hashes
|
||||
public void create() throws IOException
|
||||
{
|
||||
// if (true) {
|
||||
@ -197,14 +205,8 @@ public class Storage
|
||||
piece_hashes[20 * i + j] = hash[j];
|
||||
|
||||
bitfield.set(i);
|
||||
|
||||
if (listener != null)
|
||||
listener.storageChecked(this, i, true);
|
||||
}
|
||||
|
||||
if (listener != null)
|
||||
listener.storageAllChecked(this);
|
||||
|
||||
// Reannounce to force recalculating the info_hash.
|
||||
metainfo = metainfo.reannounce(metainfo.getAnnounce());
|
||||
}
|
||||
@ -218,6 +220,9 @@ public class Storage
|
||||
names = new String[size];
|
||||
lengths = new long[size];
|
||||
rafs = new RandomAccessFile[size];
|
||||
RAFlock = new Object[size];
|
||||
RAFtime = new long[size];
|
||||
RAFfile = new File[size];
|
||||
|
||||
int i = 0;
|
||||
Iterator it = files.iterator();
|
||||
@ -228,12 +233,13 @@ public class Storage
|
||||
if (base.isDirectory() && names[i].startsWith(base.getPath()))
|
||||
names[i] = names[i].substring(base.getPath().length() + 1);
|
||||
lengths[i] = f.length();
|
||||
rafs[i] = new RandomAccessFile(f, "r");
|
||||
RAFlock[i] = new Object();
|
||||
RAFfile[i] = f;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addFiles(List l, File f)
|
||||
private void addFiles(List l, File f)
|
||||
{
|
||||
if (!f.isDirectory())
|
||||
l.add(f);
|
||||
@ -242,7 +248,7 @@ public class Storage
|
||||
File[] files = f.listFiles();
|
||||
if (files == null)
|
||||
{
|
||||
Snark.debug("WARNING: Skipping '" + f
|
||||
_util.debug("WARNING: Skipping '" + f
|
||||
+ "' not a normal file.", Snark.WARNING);
|
||||
return;
|
||||
}
|
||||
@ -288,40 +294,44 @@ public class Storage
|
||||
* Creates (and/or checks) all files from the metainfo file list.
|
||||
*/
|
||||
public void check(String rootDir) throws IOException
|
||||
{
|
||||
check(rootDir, 0, null);
|
||||
}
|
||||
|
||||
/** use a saved bitfield and timestamp from a config file */
|
||||
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
|
||||
{
|
||||
File base = new File(rootDir, filterName(metainfo.getName()));
|
||||
// look for saved bitfield and timestamp in the config file
|
||||
long savedTime = SnarkManager.instance().getSavedTorrentTime(metainfo);
|
||||
BitField savedBitField = SnarkManager.instance().getSavedTorrentBitField(metainfo);
|
||||
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
|
||||
|
||||
List files = metainfo.getFiles();
|
||||
if (files == null)
|
||||
{
|
||||
// Create base as file.
|
||||
Snark.debug("Creating/Checking file: " + base, Snark.NOTICE);
|
||||
_util.debug("Creating/Checking file: " + base, Snark.NOTICE);
|
||||
if (!base.createNewFile() && !base.exists())
|
||||
throw new IOException("Could not create file " + base);
|
||||
|
||||
lengths = new long[1];
|
||||
rafs = new RandomAccessFile[1];
|
||||
names = new String[1];
|
||||
RAFlock = new Object[1];
|
||||
RAFtime = new long[1];
|
||||
RAFfile = new File[1];
|
||||
lengths[0] = metainfo.getTotalLength();
|
||||
RAFlock[0] = new Object();
|
||||
RAFfile[0] = base;
|
||||
if (useSavedBitField) {
|
||||
long lm = base.lastModified();
|
||||
if (lm <= 0 || lm > savedTime)
|
||||
useSavedBitField = false;
|
||||
}
|
||||
if (base.exists() && ((useSavedBitField && savedBitField.complete()) || !base.canWrite()))
|
||||
rafs[0] = new RandomAccessFile(base, "r");
|
||||
else
|
||||
rafs[0] = new RandomAccessFile(base, "rw");
|
||||
names[0] = base.getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create base as dir.
|
||||
Snark.debug("Creating/Checking directory: " + base, Snark.NOTICE);
|
||||
_util.debug("Creating/Checking directory: " + base, Snark.NOTICE);
|
||||
if (!base.mkdir() && !base.isDirectory())
|
||||
throw new IOException("Could not create directory " + base);
|
||||
|
||||
@ -331,20 +341,21 @@ public class Storage
|
||||
lengths = new long[size];
|
||||
rafs = new RandomAccessFile[size];
|
||||
names = new String[size];
|
||||
RAFlock = new Object[size];
|
||||
RAFtime = new long[size];
|
||||
RAFfile = new File[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
File f = createFileFromNames(base, (List)files.get(i));
|
||||
lengths[i] = ((Long)ls.get(i)).longValue();
|
||||
RAFlock[i] = new Object();
|
||||
RAFfile[i] = f;
|
||||
total += lengths[i];
|
||||
if (useSavedBitField) {
|
||||
long lm = base.lastModified();
|
||||
if (lm <= 0 || lm > savedTime)
|
||||
useSavedBitField = false;
|
||||
}
|
||||
if (f.exists() && ((useSavedBitField && savedBitField.complete()) || !f.canWrite()))
|
||||
rafs[i] = new RandomAccessFile(f, "r");
|
||||
else
|
||||
rafs[i] = new RandomAccessFile(f, "rw");
|
||||
names[i] = f.getName();
|
||||
}
|
||||
|
||||
@ -357,11 +368,17 @@ public class Storage
|
||||
if (useSavedBitField) {
|
||||
bitfield = savedBitField;
|
||||
needed = metainfo.getPieces() - bitfield.count();
|
||||
Snark.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
|
||||
_probablyComplete = complete();
|
||||
_util.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
|
||||
} else {
|
||||
// the following sets the needed variable
|
||||
changed = true;
|
||||
checkCreateFiles();
|
||||
SnarkManager.instance().saveTorrentStatus(metainfo, bitfield);
|
||||
}
|
||||
if (complete())
|
||||
_util.debug("Torrent is complete", Snark.NOTICE);
|
||||
else
|
||||
_util.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -376,19 +393,14 @@ public class Storage
|
||||
if (files == null)
|
||||
{
|
||||
// Reopen base as file.
|
||||
Snark.debug("Reopening file: " + base, Snark.NOTICE);
|
||||
_util.debug("Reopening file: " + base, Snark.NOTICE);
|
||||
if (!base.exists())
|
||||
throw new IOException("Could not reopen file " + base);
|
||||
|
||||
if (complete() || !base.canWrite()) // hope we can get away with this, if we are only seeding...
|
||||
rafs[0] = new RandomAccessFile(base, "r");
|
||||
else
|
||||
rafs[0] = new RandomAccessFile(base, "rw");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reopen base as dir.
|
||||
Snark.debug("Reopening directory: " + base, Snark.NOTICE);
|
||||
_util.debug("Reopening directory: " + base, Snark.NOTICE);
|
||||
if (!base.isDirectory())
|
||||
throw new IOException("Could not reopen directory " + base);
|
||||
|
||||
@ -398,10 +410,6 @@ public class Storage
|
||||
File f = getFileFromNames(base, (List)files.get(i));
|
||||
if (!f.exists())
|
||||
throw new IOException("Could not reopen file " + f);
|
||||
if (complete() || !f.canWrite()) // see above re: only seeding
|
||||
rafs[i] = new RandomAccessFile(f, "r");
|
||||
else
|
||||
rafs[i] = new RandomAccessFile(f, "rw");
|
||||
}
|
||||
|
||||
}
|
||||
@ -453,27 +461,43 @@ public class Storage
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called at the beginning, and at presumed completion,
|
||||
* so we have to be careful about locking.
|
||||
*/
|
||||
private void checkCreateFiles() throws IOException
|
||||
{
|
||||
// Whether we are resuming or not,
|
||||
// if any of the files already exists we assume we are resuming.
|
||||
boolean resume = false;
|
||||
|
||||
_probablyComplete = true;
|
||||
needed = metainfo.getPieces();
|
||||
|
||||
// Make sure all files are available and of correct length
|
||||
for (int i = 0; i < rafs.length; i++)
|
||||
{
|
||||
long length = rafs[i].length();
|
||||
if(length == lengths[i])
|
||||
long length = RAFfile[i].length();
|
||||
if(RAFfile[i].exists() && length == lengths[i])
|
||||
{
|
||||
if (listener != null)
|
||||
listener.storageAllocated(this, length);
|
||||
resume = true; // XXX Could dynamicly check
|
||||
}
|
||||
else if (length == 0)
|
||||
allocateFile(i);
|
||||
else {
|
||||
Snark.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
|
||||
rafs[i].setLength(lengths[i]);
|
||||
else if (length == 0) {
|
||||
changed = true;
|
||||
synchronized(RAFlock[i]) {
|
||||
allocateFile(i);
|
||||
}
|
||||
} else {
|
||||
_util.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
|
||||
changed = true;
|
||||
_probablyComplete = false; // to force RW
|
||||
synchronized(RAFlock[i]) {
|
||||
checkRAF(i);
|
||||
rafs[i].setLength(lengths[i]);
|
||||
}
|
||||
// will be closed below
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,6 +521,17 @@ public class Storage
|
||||
}
|
||||
}
|
||||
|
||||
_probablyComplete = complete();
|
||||
// close all the files so we don't end up with a zillion open ones;
|
||||
// we will reopen as needed
|
||||
for (int i = 0; i < rafs.length; i++) {
|
||||
synchronized(RAFlock[i]) {
|
||||
try {
|
||||
closeRAF(i);
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.storageAllChecked(this);
|
||||
if (needed <= 0)
|
||||
@ -506,6 +541,8 @@ public class Storage
|
||||
|
||||
private void allocateFile(int nr) throws IOException
|
||||
{
|
||||
// caller synchronized
|
||||
openRAF(nr, false); // RW
|
||||
// XXX - Is this the best way to make sure we have enough space for
|
||||
// the whole file?
|
||||
listener.storageCreateFile(this, names[nr], lengths[nr]);
|
||||
@ -520,6 +557,7 @@ public class Storage
|
||||
}
|
||||
int size = (int)(lengths[nr] - i*ZEROBLOCKSIZE);
|
||||
rafs[nr].write(zeros, 0, size);
|
||||
// caller will close rafs[nr]
|
||||
if (listener != null)
|
||||
listener.storageAllocated(this, size);
|
||||
}
|
||||
@ -535,12 +573,11 @@ public class Storage
|
||||
for (int i = 0; i < rafs.length; i++)
|
||||
{
|
||||
try {
|
||||
synchronized(rafs[i])
|
||||
{
|
||||
rafs[i].close();
|
||||
}
|
||||
synchronized(RAFlock[i]) {
|
||||
closeRAF(i);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
I2PSnarkUtil.instance().debug("Error closing " + rafs[i], Snark.ERROR, ioe);
|
||||
_util.debug("Error closing " + RAFfile[i], Snark.ERROR, ioe);
|
||||
// gobble gobble
|
||||
}
|
||||
}
|
||||
@ -561,7 +598,7 @@ public class Storage
|
||||
try {
|
||||
bs = new byte[len];
|
||||
} catch (OutOfMemoryError oom) {
|
||||
I2PSnarkUtil.instance().debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
|
||||
_util.debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
|
||||
return null;
|
||||
}
|
||||
getUncheckedPiece(piece, bs, off, len);
|
||||
@ -587,18 +624,10 @@ public class Storage
|
||||
if (!correctHash)
|
||||
return false;
|
||||
|
||||
boolean complete;
|
||||
synchronized(bitfield)
|
||||
{
|
||||
if (bitfield.get(piece))
|
||||
return true; // No need to store twice.
|
||||
else
|
||||
{
|
||||
bitfield.set(piece);
|
||||
needed--;
|
||||
complete = needed == 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Early typecast, avoid possibly overflowing a temp integer
|
||||
@ -618,8 +647,9 @@ public class Storage
|
||||
{
|
||||
int need = length - written;
|
||||
int len = (start + need < raflen) ? need : (int)(raflen - start);
|
||||
synchronized(rafs[i])
|
||||
synchronized(RAFlock[i])
|
||||
{
|
||||
checkRAF(i);
|
||||
rafs[i].seek(start);
|
||||
rafs[i].write(bs, off + written, len);
|
||||
}
|
||||
@ -633,8 +663,21 @@ public class Storage
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
// do this after the write, so we know it succeeded, and we don't set the
|
||||
// needed count to zero, which would cause checkRAF() to open the file readonly.
|
||||
boolean complete = false;
|
||||
synchronized(bitfield)
|
||||
{
|
||||
if (!bitfield.get(piece))
|
||||
{
|
||||
bitfield.set(piece);
|
||||
needed--;
|
||||
complete = needed == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (complete) {
|
||||
// listener.storageCompleted(this);
|
||||
// do we also need to close all of the files and reopen
|
||||
// them readonly?
|
||||
|
||||
@ -649,11 +692,10 @@ public class Storage
|
||||
bitfield = new BitField(needed);
|
||||
checkCreateFiles();
|
||||
if (needed > 0) {
|
||||
listener.setWantedPieces(this);
|
||||
Snark.debug("WARNING: Not really done, missing " + needed
|
||||
if (listener != null)
|
||||
listener.setWantedPieces(this);
|
||||
_util.debug("WARNING: Not really done, missing " + needed
|
||||
+ " pieces", Snark.WARNING);
|
||||
} else {
|
||||
SnarkManager.instance().saveTorrentStatus(metainfo, bitfield);
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,8 +730,9 @@ public class Storage
|
||||
{
|
||||
int need = length - read;
|
||||
int len = (start + need < raflen) ? need : (int)(raflen - start);
|
||||
synchronized(rafs[i])
|
||||
synchronized(RAFlock[i])
|
||||
{
|
||||
checkRAF(i);
|
||||
rafs[i].seek(start);
|
||||
rafs[i].readFully(bs, read, len);
|
||||
}
|
||||
@ -704,4 +747,59 @@ public class Storage
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close unused RAFs - call periodically
|
||||
*/
|
||||
private static final long RAFCloseDelay = 7*60*1000;
|
||||
public void cleanRAFs() {
|
||||
long cutoff = System.currentTimeMillis() - RAFCloseDelay;
|
||||
for (int i = 0; i < RAFlock.length; i++) {
|
||||
synchronized(RAFlock[i]) {
|
||||
if (RAFtime[i] > 0 && RAFtime[i] < cutoff) {
|
||||
try {
|
||||
closeRAF(i);
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For each of the following,
|
||||
* caller must synchronize on RAFlock[i]
|
||||
* ... except at the beginning if you're careful
|
||||
*/
|
||||
|
||||
/**
|
||||
* This must be called before using the RAF to ensure it is open
|
||||
*/
|
||||
private void checkRAF(int i) throws IOException {
|
||||
if (RAFtime[i] > 0) {
|
||||
RAFtime[i] = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
openRAF(i);
|
||||
}
|
||||
|
||||
private void openRAF(int i) throws IOException {
|
||||
openRAF(i, _probablyComplete);
|
||||
}
|
||||
|
||||
private void openRAF(int i, boolean readonly) throws IOException {
|
||||
rafs[i] = new RandomAccessFile(RAFfile[i], (readonly || !RAFfile[i].canWrite()) ? "r" : "rw");
|
||||
RAFtime[i] = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be called even if not open
|
||||
*/
|
||||
private void closeRAF(int i) throws IOException {
|
||||
RAFtime[i] = 0;
|
||||
if (rafs[i] == null)
|
||||
return;
|
||||
rafs[i].close();
|
||||
rafs[i] = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -59,7 +59,6 @@ public interface StorageListener
|
||||
/** Reset the peer's wanted pieces table
|
||||
* Call after the storage double-check fails
|
||||
*
|
||||
* @param peer the peer
|
||||
*/
|
||||
void setWantedPieces(Storage storage);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -40,7 +40,7 @@ import net.i2p.util.Log;
|
||||
*
|
||||
* @author Mark Wielaard (mark@klomp.org)
|
||||
*/
|
||||
public class TrackerClient extends I2PThread
|
||||
public class TrackerClient extends I2PAppThread
|
||||
{
|
||||
private static final Log _log = new Log(TrackerClient.class);
|
||||
private static final String NO_EVENT = "";
|
||||
@ -57,6 +57,7 @@ public class TrackerClient extends I2PThread
|
||||
private final static int MAX_CONSEC_FAILS = 5; // slow down after this
|
||||
private final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails
|
||||
|
||||
private I2PSnarkUtil _util;
|
||||
private final MetaInfo meta;
|
||||
private final PeerCoordinator coordinator;
|
||||
private final int port;
|
||||
@ -66,10 +67,11 @@ public class TrackerClient extends I2PThread
|
||||
|
||||
private List trackers;
|
||||
|
||||
public TrackerClient(MetaInfo meta, PeerCoordinator coordinator)
|
||||
public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator)
|
||||
{
|
||||
// Set unique name.
|
||||
super("TrackerClient-" + urlencode(coordinator.getID()));
|
||||
_util = util;
|
||||
this.meta = meta;
|
||||
this.coordinator = coordinator;
|
||||
|
||||
@ -98,13 +100,13 @@ public class TrackerClient extends I2PThread
|
||||
}
|
||||
|
||||
private boolean verifyConnected() {
|
||||
while (!stop && !I2PSnarkUtil.instance().connected()) {
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
while (!stop && !_util.connected()) {
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) {
|
||||
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
return !stop && I2PSnarkUtil.instance().connected();
|
||||
return !stop && _util.connected();
|
||||
}
|
||||
|
||||
public void run()
|
||||
@ -121,7 +123,7 @@ public class TrackerClient extends I2PThread
|
||||
// the primary tracker, that we don't add it twice.
|
||||
trackers = new ArrayList(2);
|
||||
trackers.add(new Tracker(meta.getAnnounce(), true));
|
||||
List tlist = SnarkManager.instance().getOpenTrackers();
|
||||
List tlist = _util.getOpenTrackers();
|
||||
if (tlist != null) {
|
||||
for (int i = 0; i < tlist.size(); i++) {
|
||||
String url = (String)tlist.get(i);
|
||||
@ -136,7 +138,7 @@ public class TrackerClient extends I2PThread
|
||||
}
|
||||
if (meta.getAnnounce().startsWith(url.substring(0, slash)))
|
||||
continue;
|
||||
String dest = I2PSnarkUtil.instance().lookup(url.substring(7, slash));
|
||||
String dest = _util.lookup(url.substring(7, slash));
|
||||
if (dest == null) {
|
||||
_log.error("Announce host unknown: [" + url + "]");
|
||||
continue;
|
||||
@ -264,7 +266,7 @@ public class TrackerClient extends I2PThread
|
||||
catch (IOException ioe)
|
||||
{
|
||||
// Probably not fatal (if it doesn't last to long...)
|
||||
Snark.debug
|
||||
_util.debug
|
||||
("WARNING: Could not contact tracker at '"
|
||||
+ tr.announce + "': " + ioe, Snark.WARNING);
|
||||
tr.trackerProblems = ioe.getMessage();
|
||||
@ -295,12 +297,12 @@ public class TrackerClient extends I2PThread
|
||||
// we could try and total the unique peers but that's too hard for now
|
||||
coordinator.trackerSeenPeers = maxSeenPeers;
|
||||
if (!started)
|
||||
Snark.debug(" Retrying in one minute...", Snark.DEBUG);
|
||||
_util.debug(" Retrying in one minute...", Snark.DEBUG);
|
||||
} // *** end of while loop
|
||||
} // try
|
||||
catch (Throwable t)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug("TrackerClient: " + t, Snark.ERROR, t);
|
||||
_util.debug("TrackerClient: " + t, Snark.ERROR, t);
|
||||
if (t instanceof OutOfMemoryError)
|
||||
throw (OutOfMemoryError)t;
|
||||
}
|
||||
@ -332,19 +334,18 @@ public class TrackerClient extends I2PThread
|
||||
+ "?info_hash=" + infoHash
|
||||
+ "&peer_id=" + peerID
|
||||
+ "&port=" + port
|
||||
+ "&ip=" + I2PSnarkUtil.instance().getOurIPString() + ".i2p"
|
||||
+ "&ip=" + _util.getOurIPString() + ".i2p"
|
||||
+ "&uploaded=" + uploaded
|
||||
+ "&downloaded=" + downloaded
|
||||
+ "&left=" + left
|
||||
+ ((event != NO_EVENT) ? ("&event=" + event) : "");
|
||||
Snark.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
|
||||
tr.lastRequestTime = System.currentTimeMillis();
|
||||
File fetched = I2PSnarkUtil.instance().get(s);
|
||||
File fetched = _util.get(s);
|
||||
if (fetched == null) {
|
||||
throw new IOException("Error fetching " + s);
|
||||
}
|
||||
fetched.deleteOnExit();
|
||||
|
||||
InputStream in = null;
|
||||
try {
|
||||
@ -352,7 +353,7 @@ public class TrackerClient extends I2PThread
|
||||
|
||||
TrackerInfo info = new TrackerInfo(in, coordinator.getID(),
|
||||
coordinator.getMetaInfo());
|
||||
Snark.debug("TrackerClient response: " + info, Snark.INFO);
|
||||
_util.debug("TrackerClient response: " + info, Snark.INFO);
|
||||
|
||||
String failure = info.getFailureReason();
|
||||
if (failure != null)
|
||||
|
@ -101,7 +101,7 @@ public class TrackerInfo
|
||||
peerID = new PeerID(((BEValue)it.next()).getMap());
|
||||
} catch (InvalidBEncodingException ibe) {
|
||||
// don't let one bad entry spoil the whole list
|
||||
Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
|
||||
//Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
|
||||
continue;
|
||||
}
|
||||
peers.add(new Peer(peerID, my_id, metainfo));
|
||||
|
@ -5,6 +5,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -23,7 +24,7 @@ import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import org.klomp.snark.I2PSnarkUtil;
|
||||
@ -55,6 +56,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if ( (configFile == null) || (configFile.trim().length() <= 0) )
|
||||
configFile = "i2psnark.config";
|
||||
_manager.loadConfig(configFile);
|
||||
_manager.start();
|
||||
}
|
||||
|
||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
@ -87,12 +89,12 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<table border=\"0\" width=\"100%\">\n");
|
||||
out.write("<tr><td><a href=\"" + req.getRequestURI() + peerString + "\" class=\"snarkRefresh\">Refresh</a>\n");
|
||||
out.write("<td><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\">Forum</a>\n");
|
||||
out.write("<tr><td><a href=\"http://codevoid.i2p/forums/5\" class=\"snarkRefresh\">Wishlist</a>\n");
|
||||
int count = 1;
|
||||
int count = 0;
|
||||
Map trackers = _manager.getTrackers();
|
||||
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String baseURL = (String)trackers.get(name);
|
||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String name = (String)entry.getKey();
|
||||
String baseURL = (String)entry.getValue();
|
||||
int e = baseURL.indexOf('=');
|
||||
if (e < 0)
|
||||
continue;
|
||||
@ -115,7 +117,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
List snarks = getSortedSnarks(req);
|
||||
String uri = req.getRequestURI();
|
||||
out.write(TABLE_HEADER);
|
||||
if (I2PSnarkUtil.instance().connected() && snarks.size() > 0) {
|
||||
if (_manager.util().connected() && snarks.size() > 0) {
|
||||
if (peerParam != null)
|
||||
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n");
|
||||
else
|
||||
@ -123,7 +125,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
}
|
||||
out.write(TABLE_HEADER2);
|
||||
out.write("<th align=\"left\" valign=\"top\">");
|
||||
if (I2PSnarkUtil.instance().connected())
|
||||
if (_manager.util().connected())
|
||||
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
|
||||
"\" title=\"Stop all torrents and the i2p tunnel\">Stop All</a>");
|
||||
else if (snarks.size() > 0)
|
||||
@ -200,7 +202,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
}
|
||||
} else if ( (newURL != null) && (newURL.trim().length() > "http://.i2p/".length()) ) {
|
||||
_manager.addMessage("Fetching " + newURL);
|
||||
I2PThread fetch = new I2PThread(new FetchAndAdd(_manager, newURL), "Fetch and add");
|
||||
I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add");
|
||||
fetch.start();
|
||||
} else {
|
||||
// no file or URL specified
|
||||
@ -329,7 +331,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
_manager.addMessage("Error creating torrent - you must select a tracker");
|
||||
else if (baseFile.exists()) {
|
||||
try {
|
||||
Storage s = new Storage(baseFile, announceURL, null);
|
||||
Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
|
||||
s.create();
|
||||
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
|
||||
MetaInfo info = s.getMetaInfo();
|
||||
@ -360,8 +362,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (!snark.stopped)
|
||||
_manager.stopTorrent(snark.torrent, false);
|
||||
}
|
||||
if (I2PSnarkUtil.instance().connected()) {
|
||||
I2PSnarkUtil.instance().disconnect();
|
||||
if (_manager.util().connected()) {
|
||||
_manager.util().disconnect();
|
||||
_manager.addMessage("I2P tunnel closed");
|
||||
}
|
||||
} else if ("StartAll".equals(action)) {
|
||||
@ -377,7 +379,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
|
||||
private List getSortedSnarks(HttpServletRequest req) {
|
||||
Set files = _manager.listTorrentFiles();
|
||||
TreeSet fileNames = new TreeSet(files); // sorts it alphabetically
|
||||
TreeSet fileNames = new TreeSet(Collator.getInstance()); // sorts it alphabetically
|
||||
fileNames.addAll(files);
|
||||
ArrayList rv = new ArrayList(fileNames.size());
|
||||
for (Iterator iter = fileNames.iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
@ -496,9 +499,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
String announce = snark.meta.getAnnounce();
|
||||
if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr")) {
|
||||
Map trackers = _manager.getTrackers();
|
||||
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String baseURL = (String)trackers.get(name);
|
||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String name = (String)entry.getKey();
|
||||
String baseURL = (String)entry.getValue();
|
||||
if (!baseURL.startsWith(announce))
|
||||
continue;
|
||||
int e = baseURL.indexOf('=');
|
||||
@ -571,6 +575,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
client = "I2P-BT";
|
||||
else if ("LUFa".equals(ch))
|
||||
client = "Azureus";
|
||||
else if ("CwsL".equals(ch))
|
||||
client = "I2PSnarkXL";
|
||||
else if ("AUZV".equals(ch) || "AkZV".equals(ch) || "A0ZV".equals(ch))
|
||||
client = "Robert";
|
||||
else
|
||||
client = "Unknown";
|
||||
out.write("<font size=-1>" + client + "</font> <tt>" + peer.toString().substring(5, 9) + "</tt>");
|
||||
@ -668,9 +676,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
+ "\" title=\"File to seed (must be within the specified path)\" /><br />\n");
|
||||
out.write("Tracker: <select name=\"announceURL\"><option value=\"\">Select a tracker</option>\n");
|
||||
Map trackers = _manager.getTrackers();
|
||||
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String announceURL = (String)trackers.get(name);
|
||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String name = (String)entry.getKey();
|
||||
String announceURL = (String)entry.getValue();
|
||||
int e = announceURL.indexOf('=');
|
||||
if (e > 0)
|
||||
announceURL = announceURL.substring(0, e);
|
||||
@ -687,8 +696,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
String uri = req.getRequestURI();
|
||||
String dataDir = _manager.getDataDir().getAbsolutePath();
|
||||
boolean autoStart = _manager.shouldAutoStart();
|
||||
boolean useOpenTrackers = _manager.shouldUseOpenTrackers();
|
||||
String openTrackers = _manager.getOpenTrackerString();
|
||||
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
|
||||
String openTrackers = _manager.util().getOpenTrackerString();
|
||||
//int seedPct = 0;
|
||||
|
||||
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
|
||||
@ -720,9 +729,9 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("</select><br />\n");
|
||||
*/
|
||||
out.write("Total uploader limit: <input type=\"text\" name=\"upLimit\" value=\""
|
||||
+ I2PSnarkUtil.instance().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
|
||||
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
|
||||
out.write("Up bandwidth limit: <input type=\"text\" name=\"upBW\" value=\""
|
||||
+ I2PSnarkUtil.instance().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Router Up BW / 2 recommended)</i><br />\n");
|
||||
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Router Up BW / 2 recommended)</i><br />\n");
|
||||
|
||||
out.write("Use open trackers also: <input type=\"checkbox\" name=\"useOpenTrackers\" value=\"true\" "
|
||||
+ (useOpenTrackers ? "checked " : "")
|
||||
@ -732,18 +741,19 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
|
||||
//out.write("<hr />\n");
|
||||
out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\""
|
||||
+ I2PSnarkUtil.instance().getEepProxyHost() + "\" size=\"15\" /> ");
|
||||
+ _manager.util().getEepProxyHost() + "\" size=\"15\" /> ");
|
||||
out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
|
||||
+ I2PSnarkUtil.instance().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
|
||||
+ _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
|
||||
out.write("I2CP host: <input type=\"text\" name=\"i2cpHost\" value=\""
|
||||
+ I2PSnarkUtil.instance().getI2CPHost() + "\" size=\"15\" /> ");
|
||||
+ _manager.util().getI2CPHost() + "\" size=\"15\" /> ");
|
||||
out.write("port: <input type=\"text\" name=\"i2cpPort\" value=\"" +
|
||||
+ I2PSnarkUtil.instance().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
|
||||
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
|
||||
StringBuffer opts = new StringBuffer(64);
|
||||
Map options = new TreeMap(I2PSnarkUtil.instance().getI2CPOptions());
|
||||
for (Iterator iter = options.keySet().iterator(); iter.hasNext(); ) {
|
||||
String key = (String)iter.next();
|
||||
String val = (String)options.get(key);
|
||||
Map options = new TreeMap(_manager.util().getI2CPOptions());
|
||||
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String key = (String)entry.getKey();
|
||||
String val = (String)entry.getValue();
|
||||
opts.append(key).append('=').append(val).append(' ');
|
||||
}
|
||||
out.write("I2CP opts: <input type=\"text\" name=\"i2cpOpts\" size=\"80\" value=\""
|
||||
@ -873,7 +883,7 @@ class FetchAndAdd implements Runnable {
|
||||
public void run() {
|
||||
_url = _url.trim();
|
||||
// 3 retries
|
||||
File file = I2PSnarkUtil.instance().get(_url, false, 3);
|
||||
File file = _manager.util().get(_url, false, 3);
|
||||
try {
|
||||
if ( (file != null) && (file.exists()) && (file.length() > 0) ) {
|
||||
_manager.addMessage("Torrent fetched from " + _url);
|
||||
|
@ -7,12 +7,27 @@
|
||||
<ant dir="../../jetty/" target="build" />
|
||||
<!-- ministreaming will build core -->
|
||||
</target>
|
||||
<target name="compile">
|
||||
<condition property="depend.available">
|
||||
<typefound name="depend" />
|
||||
</condition>
|
||||
<target name="depend" if="depend.available">
|
||||
<depend
|
||||
cache="../../../build"
|
||||
srcdir="./src"
|
||||
destdir="./build/obj" >
|
||||
<!-- Depend on classes instead of jars where available -->
|
||||
<classpath>
|
||||
<pathelement location="../../../core/java/build/obj" />
|
||||
<pathelement location="../../ministreaming/java/build/obj" />
|
||||
</classpath>
|
||||
</depend>
|
||||
</target>
|
||||
<target name="compile" depends="depend">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
destdir="./build/obj"
|
||||
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
|
||||
</target>
|
||||
@ -30,7 +45,7 @@
|
||||
basedir="../jsp/" excludes="web.xml, *.java, *.jsp">
|
||||
</war>
|
||||
</target>
|
||||
<target name="precompilejsp">
|
||||
<target name="precompilejsp" unless="precompilejsp.uptodate">
|
||||
<delete dir="../jsp/WEB-INF/" />
|
||||
<delete file="../jsp/web-fragment.xml" />
|
||||
<delete file="../jsp/web-out.xml" />
|
||||
@ -56,7 +71,7 @@
|
||||
<arg value="-webapp" />
|
||||
<arg value="../jsp/" />
|
||||
</java>
|
||||
<javac debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
<javac debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
destdir="../jsp/WEB-INF/classes/" srcdir="../jsp/WEB-INF/classes" includes="**/*.java">
|
||||
<classpath>
|
||||
<pathelement location="../../jetty/jettylib/jasper-runtime.jar" />
|
||||
@ -72,6 +87,11 @@
|
||||
<replacefilter token="<!-- precompiled servlets -->" value="${jspc.web.fragment}" />
|
||||
</replace>
|
||||
</target>
|
||||
|
||||
<uptodate property="precompilejsp.uptodate" targetfile="../jsp/web-out.xml">
|
||||
<srcfiles dir= "../jsp" includes="*.jsp, *.html, web.xml"/>
|
||||
</uptodate>
|
||||
|
||||
<target name="javadoc">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/javadoc" />
|
||||
@ -84,6 +104,9 @@
|
||||
</target>
|
||||
<target name="clean">
|
||||
<delete dir="./build" />
|
||||
<delete dir="../jsp/WEB-INF/" />
|
||||
<delete file="../jsp/web-fragment.xml" />
|
||||
<delete file="../jsp/web-out.xml" />
|
||||
</target>
|
||||
<target name="cleandep" depends="clean">
|
||||
<!-- ministreaming will clean core -->
|
||||
|
@ -47,9 +47,9 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
public HTTPResponseOutputStream(OutputStream raw) {
|
||||
super(raw);
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
_context.statManager().createRateStat("i2ptunnel.httpCompressionRatio", "ratio of compressed size to decompressed size after transfer", "i2ptunnel", new long[] { 60*1000, 30*60*1000 });
|
||||
_context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "i2ptunnel", new long[] { 60*1000, 30*60*1000 });
|
||||
_context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "i2ptunnel", new long[] { 60*1000, 30*60*1000 });
|
||||
_context.statManager().createRateStat("i2ptunnel.httpCompressionRatio", "ratio of compressed size to decompressed size after transfer", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
|
||||
_context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
|
||||
_context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
|
||||
_log = _context.logManager().getLog(getClass());
|
||||
_cache = ByteCache.getInstance(8, CACHE_SIZE);
|
||||
_headerBuffer = _cache.acquire();
|
||||
@ -395,4 +395,4 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
System.out.println("Properly fails with " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -284,6 +284,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
l.log("Command list:");
|
||||
l.log("config <i2phost> <i2pport>");
|
||||
l.log("listen_on <ip>");
|
||||
l.log("clientoptions[ key=value]*");
|
||||
l.log("read_timeout <msecs>");
|
||||
l.log("owndest yes|no");
|
||||
l.log("ping <args>");
|
||||
@ -346,7 +347,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (UnknownHostException uhe) {
|
||||
l.log("unknown host");
|
||||
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -355,7 +356,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -363,19 +364,19 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
notifyEvent("serverTaskId", new Integer(serv.getId()));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
|
||||
return;
|
||||
} else {
|
||||
l.log("server <host> <port> <privkeyfile>");
|
||||
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,7 +402,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (UnknownHostException uhe) {
|
||||
l.log("unknown host");
|
||||
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -410,7 +411,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -420,21 +421,21 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
I2PTunnelHTTPServer serv = new I2PTunnelHTTPServer(serverHost, portNum, privKeyFile, args[3], spoofedHost, l, (EventDispatcher) this, this);
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
notifyEvent("serverTaskId", new Integer(serv.getId()));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
|
||||
return;
|
||||
} else {
|
||||
l.log("httpserver <host> <port> <spoofedhost> <privkeyfile>");
|
||||
l.log(" creates an HTTP server that sends all incoming data\n"
|
||||
+ " of its destination to host:port., filtering the HTTP\n"
|
||||
+ " headers so it looks like the request is to the spoofed host.");
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,7 +459,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (UnknownHostException uhe) {
|
||||
l.log("unknown host");
|
||||
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -467,7 +468,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -475,11 +476,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
notifyEvent("serverTaskId", new Integer(serv.getId()));
|
||||
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
|
||||
} else {
|
||||
l.log("textserver <host> <port> <privkey>");
|
||||
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
|
||||
notifyEvent("textserverTaskId", new Integer(-1));
|
||||
notifyEvent("textserverTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,7 +508,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("clientTaskId", new Integer(-1));
|
||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
I2PTunnelTask task;
|
||||
@ -515,11 +516,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
try {
|
||||
task = new I2PTunnelClient(portNum, args[1], l, ownDest, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("clientTaskId", new Integer(task.getId()));
|
||||
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create a client [" + host + ":"+ port + "]", iae);
|
||||
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
|
||||
notifyEvent("clientTaskId", new Integer(-1));
|
||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
} else {
|
||||
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>]");
|
||||
@ -528,7 +529,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
+ " a comma delimited list of pubkeys, it will rotate among them\n"
|
||||
+ " randomlyl. sharedClient indicates if this client shares \n"
|
||||
+ " with other clients (true of false)");
|
||||
notifyEvent("clientTaskId", new Integer(-1));
|
||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,7 +551,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("httpclientTaskId", new Integer(-1));
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -582,11 +583,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
try {
|
||||
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("httpclientTaskId", new Integer(task.getId()));
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ port + "]", iae);
|
||||
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
|
||||
notifyEvent("httpclientTaskId", new Integer(-1));
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
} else {
|
||||
l.log("httpclient <port> [<sharedClient>] [<proxy>]");
|
||||
@ -595,7 +596,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
l.log(" <proxy> (optional) indicates a proxy server to be used");
|
||||
l.log(" when trying to access an address out of the .i2p domain");
|
||||
l.log(" (the default proxy is squid.i2p).");
|
||||
notifyEvent("httpclientTaskId", new Integer(-1));
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -617,7 +618,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("ircclientTaskId", new Integer(-1));
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -639,17 +640,17 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
try {
|
||||
task = new I2PTunnelIRCClient(port, args[1],l, ownDest, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("ircclientTaskId", new Integer(task.getId()));
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ port + "]", iae);
|
||||
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
|
||||
notifyEvent("ircclientTaskId", new Integer(-1));
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
} else {
|
||||
l.log("ircclient <port> [<sharedClient>]");
|
||||
l.log(" creates a client that filter IRC protocol.");
|
||||
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
|
||||
notifyEvent("ircclientTaskId", new Integer(-1));
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -672,18 +673,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("sockstunnelTaskId", new Integer(-1));
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
I2PTunnelTask task;
|
||||
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", new Integer(task.getId()));
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} else {
|
||||
l.log("sockstunnel <port>");
|
||||
l.log(" creates a tunnel that distributes SOCKS requests.");
|
||||
notifyEvent("sockstunnelTaskId", new Integer(-1));
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,7 +968,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
l.log(" try to resolve the name into a destination key");
|
||||
notifyEvent("lookupResult", "invalidUsage");
|
||||
} else {
|
||||
String target = args[0];
|
||||
try {
|
||||
Destination dest = destFromName(args[0]);
|
||||
if (dest == null) {
|
||||
@ -998,13 +998,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
// pings always use the main destination
|
||||
task = new I2Ping(allargs, l, false, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("pingTaskId", new Integer(task.getId()));
|
||||
notifyEvent("pingTaskId", Integer.valueOf(task.getId()));
|
||||
} else {
|
||||
l.log("ping <opts> <dest>");
|
||||
l.log("ping <opts> -h");
|
||||
l.log("ping <opts> -l <destlistfile>");
|
||||
l.log(" Tests communication with peers.\n" + " opts can be -ns (nosync) or not.");
|
||||
notifyEvent("pingTaskId", new Integer(-1));
|
||||
l.log("ping <opts> -h (pings all hosts in hosts.txt)");
|
||||
l.log("ping <opts> -l <destlistfile> (pings a list of hosts in a file)");
|
||||
l.log(" Options:\n" +
|
||||
" -c (require 5 consecutive pings to report success)\n" +
|
||||
" -m maxSimultaneousPings (default 10)\n" +
|
||||
" -n numberOfPings (default 3)\n" +
|
||||
" -t timeout (ms, default 5000)\n");
|
||||
l.log(" Tests communication with peers.\n");
|
||||
notifyEvent("pingTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1083,7 +1088,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
public static void makeKey(OutputStream writeTo, OutputStream pubDest, Logging l) {
|
||||
try {
|
||||
l.log("Generating new keys...");
|
||||
ByteArrayOutputStream priv = new ByteArrayOutputStream(), pub = new ByteArrayOutputStream();
|
||||
I2PClient client = I2PClientFactory.createClient();
|
||||
Destination d = client.createDestination(writeTo);
|
||||
l.log("Secret key saved.");
|
||||
@ -1107,7 +1111,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
*/
|
||||
public static void showKey(InputStream readFrom, OutputStream pubDest, Logging l) {
|
||||
try {
|
||||
I2PClient client = I2PClientFactory.createClient();
|
||||
Destination d = new Destination();
|
||||
d.readBytes(readFrom);
|
||||
l.log("Public key: " + d.toBase64());
|
||||
|
@ -217,10 +217,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
||||
Properties props = new Properties();
|
||||
if (tunnel == null)
|
||||
props.putAll(System.getProperties());
|
||||
else
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
int portNum = 7654;
|
||||
if (tunnel.port != null) {
|
||||
try {
|
||||
|
@ -225,6 +225,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
}
|
||||
|
||||
private static final boolean DEFAULT_GZIP = true;
|
||||
// all default to false
|
||||
public static final String PROP_REFERER = "i2ptunnel.httpclient.sendReferer";
|
||||
public static final String PROP_USER_AGENT = "i2ptunnel.httpclient.sendUserAgent";
|
||||
public static final String PROP_VIA = "i2ptunnel.httpclient.sendVia";
|
||||
|
||||
private static long __requestId = 0;
|
||||
protected void clientConnectionRun(Socket s) {
|
||||
@ -465,8 +469,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
line = "Host: " + host;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(getPrefix(requestId) + "Setting host = " + host);
|
||||
} else if (lowercaseLine.startsWith("user-agent: ")) {
|
||||
// always stripped, added back at the end
|
||||
} else if (lowercaseLine.startsWith("user-agent: ") &&
|
||||
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
|
||||
line = null;
|
||||
continue;
|
||||
} else if (lowercaseLine.startsWith("accept")) {
|
||||
@ -474,12 +478,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
// browser to browser
|
||||
line = null;
|
||||
continue;
|
||||
} else if (lowercaseLine.startsWith("referer: ")) {
|
||||
} else if (lowercaseLine.startsWith("referer: ") &&
|
||||
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_REFERER)).booleanValue()) {
|
||||
// Shouldn't we be more specific, like accepting in-site referers ?
|
||||
//line = "Referer: i2p";
|
||||
line = null;
|
||||
continue; // completely strip the line
|
||||
} else if (lowercaseLine.startsWith("via: ")) {
|
||||
} else if (lowercaseLine.startsWith("via: ") &&
|
||||
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_VIA)).booleanValue()) {
|
||||
//line = "Via: i2p";
|
||||
line = null;
|
||||
continue; // completely strip the line
|
||||
@ -492,7 +498,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
|
||||
if (line.length() == 0) {
|
||||
|
||||
String ok = getTunnel().getContext().getProperty("i2ptunnel.gzip");
|
||||
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
|
||||
boolean gzip = DEFAULT_GZIP;
|
||||
if (ok != null)
|
||||
gzip = Boolean.valueOf(ok).booleanValue();
|
||||
@ -503,7 +509,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
newRequest.append("Accept-Encoding: \r\n");
|
||||
newRequest.append("X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n");
|
||||
}
|
||||
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
|
||||
if (!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue())
|
||||
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
|
||||
newRequest.append("Connection: close\r\n\r\n");
|
||||
break;
|
||||
} else {
|
||||
|
@ -32,12 +32,13 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
private final static Log _log = new Log(I2PTunnelHTTPServer.class);
|
||||
/** what Host: should we seem to be to the webserver? */
|
||||
private String _spoofHost;
|
||||
private static final String HASH_HEADER = "X-I2P-DestHash";
|
||||
|
||||
public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host, port, privData, l, notifyThis, tunnel);
|
||||
_spoofHost = spoofHost;
|
||||
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
|
||||
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 });
|
||||
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
|
||||
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel", new long[] { 60*1000, 10*60*1000 });
|
||||
}
|
||||
|
||||
public I2PTunnelHTTPServer(InetAddress host, int port, File privkey, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
@ -71,6 +72,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
|
||||
StringBuffer command = new StringBuffer(128);
|
||||
Properties headers = readHeaders(in, command);
|
||||
headers.setProperty(HASH_HEADER, socket.getPeerDestination().calculateHash().toBase64());
|
||||
if ( (_spoofHost != null) && (_spoofHost.trim().length() > 0) )
|
||||
headers.setProperty("Host", _spoofHost);
|
||||
headers.setProperty("Connection", "close");
|
||||
@ -327,6 +329,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
name = "Accept-encoding";
|
||||
else if ("X-Accept-encoding".equalsIgnoreCase(name))
|
||||
name = "X-Accept-encoding";
|
||||
else if (HASH_HEADER.equalsIgnoreCase(name))
|
||||
continue; // Prevent spoofing
|
||||
headers.setProperty(name, value);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Read the header [" + name + "] = [" + value + "]");
|
||||
|
@ -216,9 +216,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
|
||||
private void removeRef() {
|
||||
if (sockList != null) {
|
||||
synchronized (slock) {
|
||||
boolean removed = sockList.remove(i2ps);
|
||||
//System.out.println("Removal of i2psocket " + i2ps + " successful? "
|
||||
// + removed + " remaining: " + sockList.size());
|
||||
sockList.remove(i2ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
@ -69,11 +70,16 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
_usePool = "true".equalsIgnoreCase(usePool);
|
||||
else
|
||||
_usePool = DEFAULT_USE_POOL;
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
init(host, port, new FileInputStream(privkey), privkeyname, l);
|
||||
fis = new FileInputStream(privkey);
|
||||
init(host, port, fis, privkeyname, l);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error starting server", ioe);
|
||||
notifyEvent("openServerResult", "error");
|
||||
} finally {
|
||||
if (fis != null)
|
||||
try { fis.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +97,6 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
this.l = l;
|
||||
this.remoteHost = host;
|
||||
this.remotePort = port;
|
||||
I2PClient client = I2PClientFactory.createClient();
|
||||
Properties props = new Properties();
|
||||
props.putAll(getTunnel().getClientOptions());
|
||||
int portNum = 7654;
|
||||
@ -219,6 +224,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Error accepting", ce);
|
||||
// not killing the server..
|
||||
} catch(SocketTimeoutException ste) {
|
||||
// ignored, we never set the timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import net.i2p.util.Log;
|
||||
public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
private final static Log _log = new Log(I2Ping.class);
|
||||
|
||||
private static final int PING_COUNT = 3;
|
||||
private int PING_COUNT = 3;
|
||||
private static final int CPING_COUNT = 5;
|
||||
private static final int PING_TIMEOUT = 5000;
|
||||
|
||||
@ -29,6 +29,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
private int MAX_SIMUL_PINGS = 10; // not really final...
|
||||
|
||||
private boolean countPing = false;
|
||||
private boolean reportTimes = true;
|
||||
|
||||
private I2PSocketManager sockMgr;
|
||||
private Logging l;
|
||||
@ -82,6 +83,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
|
||||
public void runCommand(String cmd) throws InterruptedException, IOException {
|
||||
while (true) {
|
||||
if (cmd.startsWith("-t ")) { // timeout
|
||||
cmd = cmd.substring(3);
|
||||
int pos = cmd.indexOf(" ");
|
||||
@ -92,8 +94,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
timeout = Long.parseLong(cmd.substring(0, pos));
|
||||
cmd = cmd.substring(pos + 1);
|
||||
}
|
||||
}
|
||||
if (cmd.startsWith("-m ")) { // max simultaneous pings
|
||||
} else if (cmd.startsWith("-m ")) { // max simultaneous pings
|
||||
cmd = cmd.substring(3);
|
||||
int pos = cmd.indexOf(" ");
|
||||
if (pos == -1) {
|
||||
@ -103,18 +104,26 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
MAX_SIMUL_PINGS = Integer.parseInt(cmd.substring(0, pos));
|
||||
cmd = cmd.substring(pos + 1);
|
||||
}
|
||||
}
|
||||
if (cmd.startsWith("-c ")) { // "count" ping
|
||||
} else if (cmd.startsWith("-n ")) { // number of pings
|
||||
cmd = cmd.substring(3);
|
||||
int pos = cmd.indexOf(" ");
|
||||
if (pos == -1) {
|
||||
l.log("Syntax error");
|
||||
return;
|
||||
} else {
|
||||
PING_COUNT = Integer.parseInt(cmd.substring(0, pos));
|
||||
cmd = cmd.substring(pos + 1);
|
||||
}
|
||||
} else if (cmd.startsWith("-c ")) { // "count" ping
|
||||
countPing = true;
|
||||
cmd = cmd.substring(3);
|
||||
}
|
||||
if (cmd.equals("-h")) { // ping all hosts
|
||||
} else if (cmd.equals("-h")) { // ping all hosts
|
||||
cmd = "-l hosts.txt";
|
||||
}
|
||||
if (cmd.startsWith("-l ")) { // ping a list of hosts
|
||||
} else if (cmd.startsWith("-l ")) { // ping a list of hosts
|
||||
BufferedReader br = new BufferedReader(new FileReader(cmd.substring(3)));
|
||||
String line;
|
||||
List pingHandlers = new ArrayList();
|
||||
int i = 0;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (line.startsWith("#")) continue; // comments
|
||||
if (line.startsWith(";")) continue;
|
||||
@ -123,17 +132,21 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
line = line.substring(0, line.indexOf("="));
|
||||
}
|
||||
pingHandlers.add(new PingHandler(line));
|
||||
if (++i > 1)
|
||||
reportTimes = false;
|
||||
}
|
||||
br.close();
|
||||
for (Iterator it = pingHandlers.iterator(); it.hasNext();) {
|
||||
Thread t = (Thread) it.next();
|
||||
t.join();
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
Thread t = new PingHandler(cmd);
|
||||
t.join();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean close(boolean forced) {
|
||||
@ -163,7 +176,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
lastPingTime = System.currentTimeMillis();
|
||||
}
|
||||
boolean sent = sockMgr.ping(dest, PING_TIMEOUT);
|
||||
boolean sent = sockMgr.ping(dest, timeout);
|
||||
synchronized (simulLock) {
|
||||
simulPings--;
|
||||
simulLock.notifyAll();
|
||||
@ -193,6 +206,9 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
return;
|
||||
}
|
||||
int pass = 0;
|
||||
int fail = 0;
|
||||
long totalTime = 0;
|
||||
int cnt = countPing ? CPING_COUNT : PING_COUNT;
|
||||
StringBuffer pingResults = new StringBuffer(2 * cnt + destination.length() + 3);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
@ -206,10 +222,28 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
pingResults.append("+ ");
|
||||
}
|
||||
} else {
|
||||
pingResults.append(sent ? "+ " : "- ");
|
||||
if (reportTimes) {
|
||||
if (sent) {
|
||||
pass++;
|
||||
long rtt = System.currentTimeMillis() - lastPingTime;
|
||||
totalTime += rtt;
|
||||
l.log((i+1) + ": + " + rtt + " ms");
|
||||
} else {
|
||||
fail++;
|
||||
l.log((i+1) + ": -");
|
||||
}
|
||||
} else {
|
||||
pingResults.append(sent ? "+ " : "- ");
|
||||
}
|
||||
}
|
||||
// System.out.println(sent+" -> "+destination);
|
||||
}
|
||||
if (reportTimes) {
|
||||
pingResults.append(" ").append(pass).append(" received ");
|
||||
if (pass > 0)
|
||||
pingResults.append("(average time ").append(totalTime/pass).append(" ms) ");
|
||||
pingResults.append("and ").append(fail).append(" lost for destination: ");
|
||||
}
|
||||
pingResults.append(" ").append(destination);
|
||||
synchronized (lock) { // Logger is not thread safe
|
||||
l.log(pingResults.toString());
|
||||
@ -219,4 +253,4 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.data.Base32;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
@ -361,6 +362,19 @@ public class TunnelController implements Logging {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMyDestHashBase32() {
|
||||
if (_tunnel != null) {
|
||||
List sessions = _tunnel.getSessions();
|
||||
for (int i = 0; i < sessions.size(); i++) {
|
||||
I2PSession session = (I2PSession)sessions.get(i);
|
||||
Destination dest = session.getMyDestination();
|
||||
if (dest != null)
|
||||
return Base32.encode(dest.calculateHash().getData());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean getIsRunning() { return _running; }
|
||||
public boolean getIsStarting() { return _starting; }
|
||||
|
||||
|
@ -41,11 +41,11 @@ public class EditBean extends IndexBean {
|
||||
if (tun != null)
|
||||
return tun.getTargetHost();
|
||||
else
|
||||
return "";
|
||||
return "127.0.0.1";
|
||||
}
|
||||
public String getTargetPort(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null)
|
||||
if (tun != null && tun.getTargetPort() != null)
|
||||
return tun.getTargetPort();
|
||||
else
|
||||
return "";
|
||||
@ -59,7 +59,7 @@ public class EditBean extends IndexBean {
|
||||
}
|
||||
public String getPrivateKeyFile(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null)
|
||||
if (tun != null && tun.getPrivKeyFile() != null)
|
||||
return tun.getPrivKeyFile();
|
||||
else
|
||||
return "";
|
||||
@ -266,4 +266,4 @@ public class EditBean extends IndexBean {
|
||||
}
|
||||
return props;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ public class IndexBean {
|
||||
_curNonce = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPassphrase(String phrase) {
|
||||
_passphrase = phrase;
|
||||
}
|
||||
@ -332,15 +333,15 @@ public class IndexBean {
|
||||
|
||||
public String getTunnelName(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null)
|
||||
if (tun != null && tun.getName() != null)
|
||||
return tun.getName();
|
||||
else
|
||||
return "";
|
||||
return "New Tunnel";
|
||||
}
|
||||
|
||||
public String getClientPort(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null)
|
||||
if (tun != null && tun.getListenPort() != null)
|
||||
return tun.getListenPort();
|
||||
else
|
||||
return "";
|
||||
@ -389,7 +390,7 @@ public class IndexBean {
|
||||
|
||||
public String getTunnelDescription(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null)
|
||||
if (tun != null && tun.getDescription() != null)
|
||||
return tun.getDescription();
|
||||
else
|
||||
return "";
|
||||
@ -406,7 +407,12 @@ public class IndexBean {
|
||||
public String getClientDestination(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun == null) return "";
|
||||
if ("client".equals(tun.getType())||"ircclient".equals(tun.getType())) return tun.getTargetDestination();
|
||||
if ("client".equals(tun.getType())||"ircclient".equals(tun.getType())) {
|
||||
if (tun.getTargetDestination() != null)
|
||||
return tun.getTargetDestination();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
else return tun.getProxyList();
|
||||
}
|
||||
|
||||
@ -431,6 +437,19 @@ public class IndexBean {
|
||||
}
|
||||
}
|
||||
|
||||
public String getDestHashBase32(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null) {
|
||||
String rv = tun.getMyDestHashBase32();
|
||||
if (rv != null)
|
||||
return rv;
|
||||
else
|
||||
return "";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// bean props for form submission
|
||||
///
|
||||
@ -707,7 +726,11 @@ public class IndexBean {
|
||||
}
|
||||
}
|
||||
if ("interactive".equals(_profile))
|
||||
config.setProperty("option.i2p.streaming.maxWindowSize", "1");
|
||||
// This was 1 which doesn't make much sense
|
||||
// The real way to make it interactive is to make the streaming lib
|
||||
// MessageInputStream flush faster but there's no option for that yet,
|
||||
// Setting it to 16 instead of the default but not sure what good that is either.
|
||||
config.setProperty("option.i2p.streaming.maxWindowSize", "16");
|
||||
else
|
||||
config.remove("option.i2p.streaming.maxWindowSize");
|
||||
}
|
||||
@ -737,4 +760,4 @@ public class IndexBean {
|
||||
buf.append((String)msgs.get(i)).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,10 @@
|
||||
<div id="portField" class="rowItem">
|
||||
<label for="port" accesskey="P">
|
||||
<span class="accessKey">P</span>ort:
|
||||
<% String value = editBean.getClientPort(curTunnel);
|
||||
if (value == null || "".equals(value.trim()))
|
||||
out.write(" <font color=\"red\">(required)</font>");
|
||||
%>
|
||||
</label>
|
||||
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
|
||||
</div>
|
||||
@ -123,6 +127,10 @@
|
||||
%><div id="destinationField" class="rowItem">
|
||||
<label for="targetDestination" accesskey="T">
|
||||
<span class="accessKey">T</span>unnel Destination:
|
||||
<% String value2 = editBean.getClientDestination(curTunnel);
|
||||
if (value2 == null || "".equals(value2.trim()))
|
||||
out.write(" <font color=\"red\">(required)</font>");
|
||||
%>
|
||||
</label>
|
||||
<input type="text" size="30" id="targetDestination" name="targetDestination" title="Destination of the Tunnel" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext" />
|
||||
<span class="comment">(name or destination)</span>
|
||||
|
@ -93,6 +93,10 @@
|
||||
<div id="portField" class="rowItem">
|
||||
<label for="targetPort" accesskey="P">
|
||||
<span class="accessKey">P</span>ort:
|
||||
<% String value = editBean.getTargetPort(curTunnel);
|
||||
if (value == null || "".equals(value.trim()))
|
||||
out.write(" <font color=\"red\">(required)</font>");
|
||||
%>
|
||||
</label>
|
||||
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="Target Port Number" value="<%=editBean.getTargetPort(curTunnel)%>" class="freetext" />
|
||||
</div>
|
||||
@ -112,6 +116,10 @@
|
||||
%><div id="privKeyField" class="rowItem">
|
||||
<label for="privKeyFile" accesskey="k">
|
||||
Private <span class="accessKey">k</span>ey file:
|
||||
<% String value2 = editBean.getPrivateKeyFile(curTunnel);
|
||||
if (value2 == null || "".equals(value2.trim()))
|
||||
out.write(" <font color=\"red\">(required)</font>");
|
||||
%>
|
||||
</label>
|
||||
<input type="text" size="30" id="privKeyFile" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
|
||||
</div>
|
||||
@ -129,7 +137,7 @@
|
||||
<label for="localDestination" accesskey="L">
|
||||
<span class="accessKey">L</span>ocal destination:
|
||||
</label>
|
||||
<input type="text" size="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" value="<%=editBean.getDestinationBase64(curTunnel)%>" class="freetext" />
|
||||
<textarea rows="1" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off"><%=editBean.getDestinationBase64(curTunnel)%></textarea>
|
||||
<span class="comment">(if known)</span>
|
||||
</div>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user