Compare commits

...

652 Commits

Author SHA1 Message Date
zzz
8cc561775b 0.8 2010-07-12 14:25:21 +00:00
c08f79f71e Unfuzzy susidns translation, typo fixes for eepsite help. (thx _4get) 2010-07-10 11:49:40 +00:00
7532276a00 Dutch eepsite help page 2010-07-10 11:04:30 +00:00
ee29074a30 Dutch proxy translations, we missed a couple. 2010-07-10 09:06:26 +00:00
zzz
870ace55e2 version bump just to add -rc 2010-07-09 17:46:38 +00:00
ad7447f8ae merge of '6471243b39d38669b029124571adc47ad6417db4'
and 'a24bf3a898b6310d05bf2ee9ce99b3a52f067205'
2010-07-09 14:04:25 +00:00
4f827a5b1d Dutch help page 2010-07-09 14:02:55 +00:00
zzz
be75455b84 More i2ptunnel error propagation fixes - key file - thx echelon 2010-07-08 18:45:30 +00:00
96d3f67436 Dutch translation for RouterConsole sidebar labels 2010-07-08 14:41:56 +00:00
906bce637a new strings, corrections in german translation 2010-07-08 08:25:17 +00:00
3c0d0dfeee Russian translation updated (help & faq link, local identity link) 2010-07-07 20:30:05 +00:00
2ca5802e4d Include logo in updater now that it is themeable. (thanks RN!) 2010-07-07 19:49:07 +00:00
f4b06e586e RouterConsole: Add Help & FAQ link, minor label improvements. 2010-07-07 19:04:30 +00:00
zzz
525806d776 merge of '798de678af324027c003163c81c1b6169a487992'
and 'a75a75901ecc2b8caa1b97cd0693f491063826ba'
2010-07-07 13:36:52 +00:00
zzz
ed04747517 snark css fix for Opera 10.60 thx i2pn00b http://forum.i2p/viewtopic.php?t=4712 2010-07-07 13:28:27 +00:00
e13d336f2f Dutch translation of proxy error pages 2010-07-07 13:21:50 +00:00
zzz
5accdd24fc RIP p2i.mine.nu 2010-07-06 23:05:24 +00:00
5c61c28772 Dutch news 2010-07-06 20:09:26 +00:00
zzz
3a767d84df concurrentify with LBQ 2010-07-06 17:14:57 +00:00
zzz
d04ce7a2b7 launch browser sooner 2010-07-06 17:14:41 +00:00
b312fdeac1 susidns: Dutch translation (thanks do monkeybrains) 2010-07-05 23:07:19 +00:00
30c8cf7b96 merge of 'c6af0acc022d4fc8e24488a86ab869d7cb561f57'
and 'fafee42899e7efa42942bc451a888bf77be69ac9'
2010-07-05 16:39:47 +00:00
c43ca7de87 - removed one useless line of code 2010-07-05 15:34:39 +00:00
826951536b - anged user agent for outproxy from Wget/1.11.4 to Firefox 3.6.6 on WinXP to avoid getting blocked as a crawler 2010-07-05 14:35:22 +00:00
zzz
5f52edf831 * I2PTunnelIRCClient: Filter PART messages like we do for QUIT 2010-07-05 14:21:38 +00:00
zzz
29bc53d618 * i2psnark: Fix transition to end game 2010-07-05 14:20:34 +00:00
zzz
378c855902 cleanup 2010-07-05 14:20:02 +00:00
546a588aa5 I2PTunnel & I2PSnark: Dutch translation (thanks to monkeybrains) 2010-07-05 13:37:36 +00:00
6e517c4a19 RouterConsole: Fix typos in Dutch translation 2010-07-04 23:03:02 +00:00
30d3f52f30 RouterConsole: Dutch translation (thanks to monkeybrains) 2010-07-04 13:13:45 +00:00
zzz
5dee6cb3d5 * I2PTunnel: More error propagation fixes 2010-07-03 13:59:46 +00:00
zzz
2a96c9a145 static 2010-07-03 13:58:59 +00:00
zzz
6435514e0d * I2PTunnelHTTPClient: Don't use BufferedReader 2010-07-03 13:41:24 +00:00
zzz
cd7a41924d cleanup 2010-07-03 13:40:27 +00:00
zzz
b9452546c5 fix ant distclean poupdate 2010-07-03 13:39:25 +00:00
zzz
4fa89d5e86 javadoc 2010-07-03 13:38:13 +00:00
zzz
63ece7e1aa cleanup 2010-07-03 13:37:52 +00:00
4808055054 merge of '02b40376f4c34b45e4f77deb70bd24bdef34f867'
and '2365aee6776961ebaa1ca862ffa21e0457ece0a6'
2010-07-02 05:45:46 +00:00
zzz
115016e75e add trac.i2p2.i2p (linked from logs.jsp) 2010-07-01 12:36:09 +00:00
ee09bfac66 translation fix 2010-07-01 11:09:15 +00:00
zzz
530a3fcd10 * I2PTunnel: Don't start a tunnel if no valid destinations;
cleanups, logging, and error propagation fixes
2010-06-30 23:37:25 +00:00
zzz
0010229363 unused icon 2010-06-30 23:30:50 +00:00
zzz
d241afcbd8 * EventDispatcher: Minor cleanups and comments 2010-06-30 23:29:31 +00:00
zzz
615257831c * Transport: Fix NTCP address generation when host is specified but port is auto 2010-06-30 23:28:44 +00:00
36a032d249 25%-50% cpu savings in BOB. The remainder of the fix is in streaming lib,
which aparently keeps running and does not sleep according to profiling.
2010-06-29 19:06:39 +00:00
zzz
726079e0bb CapacityCalculator cleanup and comments - no changes to formula 2010-06-29 13:40:26 +00:00
zzz
66421858e7 formatSize cleanups 2010-06-29 02:32:08 +00:00
zzz
df7b3dd861 * Scale prng.buffers based on max memory, reduce default from 16 to 9 2010-06-29 02:30:40 +00:00
zzz
22ea79a4ff * Jetty: Disable TRACE and OPTIONS in console and eepsite 2010-06-29 02:29:42 +00:00
zzz
2025fe7c20 * SOCKS: Better HTTP error message 2010-06-29 02:27:10 +00:00
zzz
a11c529557 * I2PTunnel: Add default HTTPS outproxy 2010-06-29 02:25:29 +00:00
zzz
edaa2fba16 * RouterInfo: Add main() to dump RI files 2010-06-29 02:23:57 +00:00
110f01a55b I2P logo in routerconsole sidebar is now themed. 2010-06-27 17:04:51 +00:00
ada39a970e Russian translation updated (i2psnark startup delay option) 2010-06-26 21:20:04 +00:00
zzz
8c2641703c - Move connection profile and delay connect to advanced config section
- Add persistent client key support to SOCKS IRC
2010-06-26 04:11:02 +00:00
zzz
9fcb07250d explicitly set shared client for POP (defaults true anyway) 2010-06-26 04:06:32 +00:00
zzz
47f39d0766 stripHTML on form params 2010-06-26 04:05:30 +00:00
zzz
bcba5af8a9 static 2010-06-26 04:04:01 +00:00
zzz
aec1b3aeef * jbigi, jcpuid: Suppress log messages when not in router context 2010-06-26 04:03:33 +00:00
zzz
a979ed770d * logs.jsp: Add more JVM version info so we can distinguish OpenJDK from Sun 2010-06-26 04:01:58 +00:00
zzz
5485568764 * jetty.xml: Add info on how to configure for following symlinks 2010-06-26 04:01:13 +00:00
zzz
6f3597cc83 fix display of interactive setting 2010-06-26 04:00:18 +00:00
zzz
1202d09966 * FileUtil: Try to handle lack of unpack200 support more gracefully
* Update: Select old update URL if no unpack200 available
2010-06-16 13:29:41 +00:00
zzz
266eb8307c sort countries using collator for locale for current language 2010-06-16 13:23:21 +00:00
zzz
8843cc2948 cleanups 2010-06-16 13:22:35 +00:00
2c4acce0f3 finally i2ptunnel messages_de 2010-06-15 12:13:49 +00:00
87beb2ea1a updated susidns messages_de, fix kbit/kbyte in i2psnark messages_de 2010-06-15 09:27:59 +00:00
9c5b7760ba mentioned path of jetty to be put in 2010-06-14 17:29:23 +00:00
6964786552 plural fixes. hope thats all 2010-06-14 10:06:28 +00:00
d755756ee5 routerconsole messages_de.po updated 2010-06-14 09:52:27 +00:00
fbc970e4a7 updates i2psnark messages_de 2010-06-14 07:38:58 +00:00
zzz
364b905790 UDP fix and comments 2010-06-13 16:42:24 +00:00
zzz
34a1085604 use a different user agent for outproxy traffic 2010-06-13 16:04:28 +00:00
zzz
c460ac8ade * Console: Add some divs for languages to news and readmes 2010-06-13 16:02:33 +00:00
zzz
49a09f61a2 * i2psnark:
- Move config to separate page
      - Icon tweaks
2010-06-13 16:01:11 +00:00
zzz
08b4563f49 zh fix 2010-06-13 15:54:01 +00:00
026f62f183 i2ptunnel .de 2010-06-13 12:44:17 +00:00
2307ac5a22 SusiDNS .de and i2psnark .de translations 2010-06-13 12:41:15 +00:00
2b186421a7 change more 2010-06-13 11:51:22 +00:00
1dc471e07e router console messages_de.po 100 percent done 2010-06-13 11:48:59 +00:00
dev
db1fb7ccf7 minor style change 2010-06-12 11:06:24 +00:00
dev
e5071a3b7c update history 2010-06-12 11:03:56 +00:00
dev
e6bfe0c10b fixed possible race-condition and improved code style 2010-06-12 11:02:39 +00:00
dev
919a97d4c8 really fixed #49 now.. use Context->routerHash instead of calculating it everyt time 2010-06-09 12:43:48 +00:00
dev
61216b638d fixed #49: missing calculateHash() 2010-06-09 12:37:11 +00:00
dev
e065d2b01e merge of '8c5085970b330a592129aa2da5a473d318426bbb'
and 'f11c600b339d0742fb91a87df7322ec4b84eee4d'
2010-06-08 15:37:25 +00:00
zzz
746bad3c30 remove jetty fixes from release target 2010-06-07 12:57:10 +00:00
zzz
5bbd61b75c 0.7.14 2010-06-07 12:18:43 +00:00
zzz
27eb7e46d0 tweak 2 2010-06-06 20:38:19 +00:00
zzz
c20bef3731 tweaks after review 2010-06-06 20:36:54 +00:00
dev
d5aaff7f06 merge of '9ec612b8794a44b9337b7743afef8ccbb2fc904e'
and 'ec741e25082ea0a9d1fd530f613b2282edefc1d9'
2010-06-06 15:51:25 +00:00
dev
fc60768a66 prevent an NPE in case the connection is gone already(but that should not happen?) 2010-06-06 15:49:29 +00:00
zzz
2024fb1b65 * Netdb:
- Use new receivedAsReply flag in LeaseSet to mark
        those received as response to a query
      - Mark which methods in FloodfillPeerSelector may return
        our own hash
      - Redefine selectNearest() so it may return our own hash,
        so it can be used for closeness measurement
      - Redefine findNearestRouters() to return Hashes
        instead of RouterInfos
      - Fix LeaseSet response decisions for floodfills, based
        on partial keyspace and closeness measurements
      - List only count of published leasesets in netdb
2010-06-05 01:10:56 +00:00
zzz
617ca79b8f conn throttler fix when only total configured 2010-06-05 01:07:29 +00:00
5081755d0b - integration of dynamicly configurable startup delay of i2psnark
- i2psnark webfrontent configuration of startup delay
- default startup delay 3 minutes
- new config variable in i2psnark.config: i2psnark.startupDelay
2010-06-04 23:50:13 +00:00
zzz
7bfb5b1bf4 readme cleanup 2010-06-04 12:18:57 +00:00
8d73529fa4 po revise 2010-06-04 03:46:52 +00:00
dev
a19d04d3ba merge of '4002ce96746459cd6ab6f91f16795bdbe3165644'
and 'db4aaff4718328041f29e6166333139f845406cd'
2010-06-03 23:13:35 +00:00
dev
a9c7748a52 minor code style updates to ntcp EventPumper 2010-06-03 23:13:13 +00:00
zzz
41e4e952b7 * Update: Fix multiple updates after manually
starting update - caused by refreshing summary bar
      (thx 'backup'!)
2010-06-03 16:53:55 +00:00
zzz
c0b0b5e4c5 Add min delay after startup before fetching news 2010-06-03 16:51:37 +00:00
e424479e7e peers.jsp:
Show definitions panel if any transport is enabled (was: only for UDP). 
  Use div.wideload for the whole page (was: only for transports and broken if only one of them enabled).
2010-06-03 08:35:14 +00:00
a8804f3093 merge of 'bdef8183da2c97dd55e2c2fad915537640e0f404'
and 'f908793c77bb4bd3d5fa3dd71bed704f32404fd0'
2010-06-03 07:21:52 +00:00
6479a24bb7 merge of '0bd9edccbe59dc0c8dddee2b45cde1af0f8551f2'
and '779311c9e2df158049abc2e0f56e4e9fcb071142'
2010-06-03 06:27:12 +00:00
8b372ad306 Fixed build.sh
jbigi's build.sh had a number of failed assumptions as per where I2P and JAVA_HOME were which needed to be removed and a warning put in their place. A better solution would be to have some way to search for JAVA_HOME and I2P in common locations, but at least this solution works if you do it manually:

I2P=~i2p JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.20 sh build.sh dynamic

thank zzz for prodding me to do this
2010-06-03 03:35:46 +00:00
86791a2f1b Russian translation updated (descriptions for the stats that are graphed by default) 2010-06-03 03:22:35 +00:00
zzz
7cf0aad388 * UDP: Fix a bug from a blank i2np.udp.host config
causing frequent RouterInfo updates and incorrect
      addition of introducers, caused by config.jsp handling
2010-06-02 18:20:13 +00:00
zzz
c5ea51beec * graphs.jsp: Tag some more 2010-06-02 18:16:43 +00:00
zzz
7cc8e51d73 * Update: Change default update URLs to .su2 for pack200 2010-06-02 18:13:45 +00:00
zzz
75ba58d68c * Translation: Set xgettext add-comments option 2010-06-02 18:12:46 +00:00
zzz
cd35b219db * i2psnark:
- More listing fixes (more thanks to 'backup')
      - Start end game a little sooner
2010-06-01 22:19:10 +00:00
zzz
4a863f8ce7 comment 2010-06-01 14:02:21 +00:00
zzz
24264548a6 * Installer: Disable pack200 in updater again, doesn't work
on Java 1.5
    * Remove jetty from updater - it's been in for a few
      releases, and i2psnark now has its own listHTML method
2010-06-01 14:01:21 +00:00
zzz
f9e4b1a56b snark css tweak 2010-06-01 13:57:39 +00:00
zzz
13b54b864e * i2psnark:
- More listing fixes
      - Revert choker change
      thx 'backup' !
2010-06-01 13:56:53 +00:00
05d45fe945 po update 2010-05-29 07:18:56 +00:00
2781f6035a Russian translation updated for ngettext (plural forms) strings 2010-05-27 17:59:57 +00:00
zzz
dc3378d084 * Translate: Add GNU ngettext (plurals) support 2010-05-27 00:38:32 +00:00
zzz
9132e94143 * i2psnark: Listing fixes and cleanups; icons on front page; tweak bw choker again 2010-05-26 14:28:46 +00:00
b61e2aa73c Russian translation updated 2010-05-26 04:37:28 +00:00
7fdbae3b0f Tagged "bytes remaining" 2010-05-26 04:37:03 +00:00
dev
4dc6fc3b5d merge of '20f5a25a77de641ddf49c4d47d4ede923b59bfa3'
and '7dfc6bc466e7b6ee3212af949a08c51d4e3dd3db'
2010-05-25 19:08:31 +00:00
dev
618275b1f9 merge of '13c351b9c26b147632b40df8c0e8d9ca7d2d4485'
and 'b281a23e2f1719a388abed362ec3653f63e6769b'
2010-05-25 19:07:13 +00:00
dev
7a1111d845 updated history 2010-05-25 19:06:15 +00:00
zzz
3af356840e -11 2010-05-25 18:31:09 +00:00
zzz
911a278926 snark listing icons and cleanups 2010-05-25 13:08:34 +00:00
dev
014063700f merge of '82b66240733c560b038d4874d1630bf59f5fbe1a'
and 'd6f8e674646687b5efb03d09b6cdca57c6bd8f50'
2010-05-23 19:52:49 +00:00
dev
f7c0db0454 -10 2010-05-23 19:52:06 +00:00
zzz
a534d25d82 -10 2010-05-23 19:18:50 +00:00
zzz
bcf3e4a2d3 merge of '200dbdfc1dba31eb7abc6bb3403ac77cc9072c94'
and '56425d32b819bb74fe3abb999e7e3763814533ac'
2010-05-23 19:17:50 +00:00
dev
0cdfbd9803 merge of '01deefdd2f5a2b8f21fd3e97d1a6bd0dd66fecab'
and '1a75d8e703883bde472616a9def0b27bb64b7815'
2010-05-23 18:08:26 +00:00
dev
a3e5654d86 merge of '03e8a3d066ce112bb4ddaa98c0387dfefde94a0e'
and '751ff97c62634ee13a8f8baf3d7947e373d5368a'
2010-05-23 17:05:15 +00:00
dev
2f9364db2b fixed a major bug in the datagram dissector, improved performance a little bit and added a utility method to get the already calculated hash of the payload 2010-05-23 17:04:37 +00:00
zzz
5d7c9ebf82 * i2psnark:
- Choke slower when at bandwidth limit
      - Fix completion % for small files
      - Use Random from context
2010-05-23 16:18:10 +00:00
zzz
48da98d0e4 * NewsFetcher:
- Add backup URL
      - Change to 0 retries (was 2)
2010-05-23 16:15:37 +00:00
dev
55e994ac3c merge of '751ff97c62634ee13a8f8baf3d7947e373d5368a'
and 'ddc06f282f1b88e164c208509d818e3ed701143e'
2010-05-23 16:06:20 +00:00
dev
6d46a21f9f implemented WEBIRC support in the I2PTunnel IRC server 2010-05-23 16:04:22 +00:00
fdc83484fd NTCP bind interface
Adding support for binding to a specific IP in the NTCP configuration. Uses new config option i2np.ntcp.bindAddress.
2010-05-22 16:50:39 +00:00
zzz
6786817fff -9 2010-05-21 17:34:30 +00:00
zzz
b77cd0db15 show completion status in listing 2010-05-21 15:07:34 +00:00
zzz
20bef76878 * i2psnark:
- Spiff up dir listings
      - Urlify some messages
      - Only go into end game at the end
      - Bye Bart Bye
2010-05-21 04:38:49 +00:00
zzz
7a30490482 more validation 2010-05-19 18:55:53 +00:00
zzz
3bc2e469cc remove unnecessaary initializers from constructors 2010-05-16 18:08:24 +00:00
zzz
d770d3c6da border-radius thx dr. 2010-05-16 17:11:40 +00:00
zzz
339a001592 never used 2010-05-16 13:16:05 +00:00
zzz
ace57a96a9 translate log priorities 2010-05-15 15:42:20 +00:00
zzz
2c26b8d422 * Hash: Move caching XOR methods only used by KBucket into netdb 2010-05-15 14:21:31 +00:00
zzz
e1eafa2394 * Eepsite: Set no-cache in redirecting page 2010-05-15 14:19:41 +00:00
zzz
39cb51c9eb snark css tweaks 2010-05-15 14:18:54 +00:00
zzz
fa5016ab04 javadoc fix 2010-05-15 14:17:54 +00:00
zzz
b134ef1a74 * Console:
- Tag text in graphs
      - Move SummaryRenderer to its own file
2010-05-15 14:17:17 +00:00
zzz
234dff888d Try to prevent ZipErrors after plugin update 2010-05-13 17:04:16 +00:00
zzz
a08c15a3ee leaseset debug tweak 2010-05-13 17:02:32 +00:00
zzz
cfa894e7b6 peer id tweak 2010-05-13 17:01:30 +00:00
zzz
d6c8e64575 throttle fix 2010-05-10 16:21:20 +00:00
zzz
dc91580e30 fixes from DataHelper.eq() deprecation 2010-05-10 15:58:53 +00:00
zzz
7ec1dd7a98 netdb.jsp leaseset debug 2010-05-10 15:22:10 +00:00
zzz
82f3f7506c * NetDB:
- Handle old and duplicate stores more efficiently
      - Have DataStore put() return success
2010-05-10 15:00:13 +00:00
zzz
e26df1c26b * LeaseSet: Add receivedAsReply() methods in preparation for
some netdb changes
2010-05-10 14:52:53 +00:00
zzz
aea77cf225 * NetDB: Move getDistance() to its own class 2010-05-10 14:50:55 +00:00
zzz
a1e3ef9c5c cleanup fail output on peers.jsp 2010-05-10 14:26:19 +00:00
zzz
7aece71342 cleanup 2010-05-10 14:24:47 +00:00
zzz
bdbde54f04 * Router: Add router.forceBandwidthClass advanced config for testing 2010-05-10 14:23:25 +00:00
zzz
157e035710 summary bar tweaks 2010-05-10 14:22:37 +00:00
zzz
97d9a3a4e5 show monthly bw estimate 2010-05-10 14:21:48 +00:00
zzz
cb7f111ade * UDP: To help limit connections, don't offer to introduce
when floodfill
2010-05-10 14:20:27 +00:00
zzz
35f670706a * TunnelPoolManager: Concurrent 2010-05-10 14:18:15 +00:00
zzz
3fac888fe5 * DataHelper: Deprecate inefficient eq() methods 2010-05-10 14:17:05 +00:00
zzz
d843646b4f * Streaming: Add support for connection throttling 2010-05-10 14:15:31 +00:00
zzz
c2b73d9fb5 * i2psnark:
- Add tunnel config dropdowns
      - Comment out old proxy stuff
2010-05-10 14:13:55 +00:00
9da95b8165 PluginStarter: If there is some delay, there may be a really good reason for it.
Loading a class would be one of them!
    So we do a quick check first, If it bombs out, we delay and try again.
    If it bombs after that, then we throw the ClassNotFoundException.
2010-05-10 07:27:34 +00:00
zzz
5bcd8efe14 2 transport test classes out 2010-05-06 13:21:30 +00:00
027a1d748d merge of '19b2cad8459bddf9473031504b0f30aa3aad97e3'
and '5fc11615066ab7c27262a8670b7713405d25424c'
2010-05-06 04:15:34 +00:00
6d6e012c19 adapt to the change in build.xml 2010-05-06 03:59:23 +00:00
zzz
a8db6b007f * Plugins:
- Set classpath for specific client only, not for the whole JVM
      - Use ConfigDir() not AppDir()
2010-05-05 19:34:03 +00:00
zzz
f3576e54c6 throw IllegalStateException rather than NPE if no context 2010-05-05 18:44:12 +00:00
zzz
0325f6c4d2 more isEmpty and a static 2010-05-05 18:43:33 +00:00
zzz
8225ce063a * Console: Print stack trace if exception on startup 2010-05-05 17:50:28 +00:00
zzz
c2c379c994 * i2psnark: Skip 'the' when sorting snarks 2010-05-05 17:45:52 +00:00
zzz
7344c2af47 * I2PTunnelHTTPClient: Reject 192.168.* 2010-05-05 17:34:24 +00:00
zzz
f484ea8c64 * EepGet: Limit max times to fail completely even if numRetries is higher 2010-05-05 17:27:20 +00:00
zzz
ac790492eb * build.xml: Create packed sud in release 2010-05-05 16:55:00 +00:00
zzz
9ac5fb4890 * RouterInfo: Clean up use of sortStructures() 2010-05-05 16:54:28 +00:00
zzz
2baee7413c * Replace size() <= 0 with isEmpty() everywhere, ditto > 0 -> !isEmpty() 2010-05-05 16:51:54 +00:00
16bec08f09 merge of '03068a89c26b0986a8bf2b6f36cb478f565664eb'
and 'c3c31953c884c3aafb142e05c2dbef2809516d9c'
2010-05-03 16:44:06 +00:00
afb3c76922 - rewrite portable targets
pkg-portable-clean
	preppkg-portable-win32-jbigi
	preppkg-portable-linux-jbigi
	preppkg-portable-basic
	preppkg-portable-win32
	pkg-portable-win32
- add windoz support to target pack200
2010-05-03 16:42:45 +00:00
z3d
2f526b35e8 merge of '77299d7d613df0c3d1308d1056facc243ef693bb'
and 'a088711b406a5c062940ebbdd1709aa891283d74'
2010-05-02 16:43:46 +00:00
2dc32aa310 fix name "preppkg-linux-only" 2010-05-02 13:04:40 +00:00
zzz
10e669165a Fix plugin version check bug 2010-05-02 12:19:17 +00:00
zzz
b6cb90d731 * ByteCache:
- Add a per-cache stat
      - Limit each cache based on max memory
      - Disable in UDP MessageReceiver
      - Add clearAll() method to be called when under
        severe memory pressure; call from Router
2010-05-02 12:14:14 +00:00
zzz
949a8901fb comment out mains 2010-05-02 12:11:20 +00:00
d608f450af return what is taken a way ;) 2010-05-02 11:30:31 +00:00
z3d
e0a1341901 Adjust dimensions of installer splash graphic: was 171x275, now 171x270. 2010-04-30 10:26:54 +00:00
z3d
2cfb03f17d New installer splash graphic. 2010-04-30 09:30:01 +00:00
z3d
4dd0f51da4 merge of '6b54027d89ac66a5b395118365de13f5ab61bcaf'
and 'b915692e91863a7122937dbd0bad366bf38a7dfc'
2010-04-30 09:26:43 +00:00
dev
d65a3e54a2 update checklist 2010-04-28 17:53:18 +00:00
c212eacf19 - add new target: pkg-portable-win32 (must run buildSmall first)
- add configs/win batchfiles to installer/resources/portable

* currently only pkg-portable-win32 on win32 available
need linuxers to write target preppkg-portable-nix/pkg-portable-linux
and enable pkg-portable-win32 on linux (i doubt anyone need it ?)
shell scripts should goto installer/resources/portable/configs/linux/
2010-04-27 15:01:03 +00:00
zzz
46f341d782 peers.jsp: cleanup and tag 2010-04-27 12:55:37 +00:00
zzz
ab4ff5548d fix reseed tips links 2010-04-27 12:54:07 +00:00
zzz
d4713e1e6c every body needs some <body> 2010-04-27 12:53:16 +00:00
zzz
8a3a1466c9 * i2psnark: Serve downloaded files from the servlet rather
than with a file: link
2010-04-27 12:52:17 +00:00
zzz
a5af9dc973 * Jetty: Backport directory listing bugfix from jetty 6 2010-04-27 12:51:14 +00:00
zzz
049a083e42 0.7.13 2010-04-27 01:43:35 +00:00
zzz
9683a110d6 plugin cleanups 2010-04-23 16:28:14 +00:00
zzz
c44698f61a comments 2010-04-23 16:27:56 +00:00
zzz
106bccda0e log compress errors 2010-04-21 17:41:14 +00:00
zzz
b1aafa5aaf increase buf size for extraction 2010-04-21 17:06:54 +00:00
zzz
e2e43cd534 * EepGet: Don't convert a MalformedURLException into
an IOE so we recognize it when it's throuwn
2010-04-21 17:05:39 +00:00
zzz
43b4fe8300 * ReusableGZIPStreams:
- Concurrent
      - Workaround for Apache Harmony 5.0M13 Deflater bug
2010-04-21 17:04:53 +00:00
zzz
7c3e4fd947 reduce floodfill max conns slightly; fix clients start button 2010-04-18 23:06:04 +00:00
zzz
9916ef4d3d IRC links on readmes and initialNews 2010-04-18 19:57:42 +00:00
zzz
ad4da54bc4 I2PTunnelServer: Log incoming connections with net.i2p.i2ptunnel.I2PTunnelServer=INFO 2010-04-18 15:22:33 +00:00
2415c5a38b * BOB early session destroy to speed up tunnel tare-down. 2010-04-16 19:38:40 +00:00
ecbc0a2a2d Show the start button when a plugin is not running, and the stop button when a plugin is running. 2010-04-16 03:58:48 +00:00
zzz
10d37a9be5 log tweaks 2010-04-15 18:16:00 +00:00
zzz
590d2e4639 Floodfills: Increase max to 100 (was 60) and min to 60 (was 45) 2010-04-15 18:14:21 +00:00
zzz
806a07acc5 Limit max length in readline() 2010-04-15 18:13:51 +00:00
zzz
8258cdd6cf Limit max header lines 2010-04-15 18:13:30 +00:00
2fcee6e87a I2PTunnelHTTPClient: Test for "http://:/" and output error page.
This avoids an ArrayIndexOutOfBoundsException, which can eventually
cause the eepproxy to stop functioning.
2010-04-15 06:38:35 +00:00
zzz
27587e83c8 add test 2010-04-12 22:26:54 +00:00
zzz
a0d6741ff5 fix wrong prefix for startOnLoad in plugin webapps.config 2010-04-12 21:11:22 +00:00
zzz
63562ddd48 * i2ptunnel: Implement access lists for TCP servers.
Enter b32 or b64 hash or dest into list box, and
      check enable for whitelist. Uncheck enable and enter
      i2cp.enableBlackList=true in advanced i2cp options for
      blacklist. Todo: make black/whitelists radio buttons.
2010-04-12 19:18:21 +00:00
zzz
aac96b15b0 * configstats.jsp: Fix full stats checkbox default 2010-04-12 19:12:04 +00:00
zzz
0f502b4229 * LogManager: Concurrent 2010-04-12 19:10:11 +00:00
zzz
a916f970b1 * i2psnark: - Concurrent, limit, display, log tweaks 2010-04-12 19:07:53 +00:00
zzz
7f2d0acc3b merge of 'b12b7f42f59f400abd7032f3f2bffba289f3ec7a'
and 'b5a86744c2877d9d738a2fdd2b99970a0160e062'
2010-04-10 16:06:14 +00:00
zzz
8b6751f419 Streaming:
Fix the window size increment logic so it does it much more often.
The code increased the window size by MSS * MSS / N, like
in RFC 2581, but it did it only once every N,
so that was like MSS * MSS / N**2.
Now do it all the time, except for isolated packets like keepalives
that aren't using more than one message of the window.
Seems to speed up outbound significantly, without any
noticable increase in stream.sendsBeforeAck.
2010-04-10 15:42:08 +00:00
zzz
70e9cf5838 add comments about the null privkey bug 2010-04-10 15:41:42 +00:00
zzz
24020302fd cleanup 2010-04-10 15:29:16 +00:00
zzz
d7e2f39d25 * Startup:
- Don't die horribly if there is a router.info file
        but no router.keys file
        http://forum.i2p/viewtopic.php?t=4424
      - Log tweaks
2010-04-10 15:28:31 +00:00
zzz
89d0d7b266 Disconnect seeds that connect to a seed 2010-04-10 15:26:23 +00:00
zzz
e3c222b5c1 Lower per-torrent conn limits for large pieces 2010-04-10 15:25:57 +00:00
a199015bc9 Russian translation updated (trac.i2p2.i2p link) 2010-04-08 09:57:32 +00:00
zzz
23617f7b30 dont set stats off, defaults to off anyway 2010-04-07 23:22:48 +00:00
zzz
f5f02236df toString() for logging 2010-04-07 23:21:45 +00:00
zzz
ad76bc378c * OCMOSJ:
- Increase min timeout
      - Logging tweaks
2010-04-07 23:20:42 +00:00
zzz
570d8d15af * Key Manager: Hopefully avoid some races at startup
http://forum.i2p/viewtopic.php?t=4424
2010-04-07 23:19:24 +00:00
zzz
e254c5f31a * Streaming:
- Detect and drop dup SYNs rather than create
        a duplicate connection - will hopefully fix
        "Received a syn with the wrong IDs"
      - Send reset for a SYN ACK with the wrong IDs
      - Don't send a reset to a null dest
      - Logging tweaks
      - Cleanups
2010-04-07 23:18:58 +00:00
zzz
2a92be5946 * Console:
- More HTML transitional fixes
      - Standardize on 'save' to the right of 'cancel'
2010-04-05 13:34:45 +00:00
zzz
caab860351 - Add tooltip support for plugin links
- Make target=_blank for plugin links
2010-04-05 13:22:16 +00:00
z3d
32861b7ce9 merge of '44418e8f7048de3ac06833176b607d55afc94bdd'
and '6cd2f8bb60720e3aeeb500d67b3f162f2831c3fa'
2010-04-05 12:26:28 +00:00
z3d
a08802c4b6 Fix the errant horizontal rule in the console news section (classic/midnight). 2010-04-04 11:32:28 +00:00
z3d
6b51be6fae Fix the errant horizontal rule issue in the console news section (classic/midnight). 2010-04-04 05:46:07 +00:00
zzz
5b5c975884 turned the knob the wrong way before 2010-04-02 13:10:08 +00:00
zzz
605dfec5e7 dont call exit 2010-03-31 18:33:40 +00:00
zzz
71aa0cfba7 * FloodfillPeerSelector: Adjust rankings to try to
improve LeaseSet lookups
2010-03-31 18:33:08 +00:00
zzz
55e45c4274 * HostsTxtNamingService: Don't load the whole hosts.txt
into memory for every lookup
2010-03-31 18:32:16 +00:00
zzz
8c880b2518 prep for a windows-only pkg 2010-03-29 21:21:56 +00:00
zzz
c43b16cfbb * configclients.jsp:
- Always show start button for webapps and plugins
    * configclients.jsp, configupdate.jsp:
      - Fix submission when entering CR in a text box
    * Plugins:
      - Stop all plugins at shutdown
      - Log tweaks
    * WebApps:
      - Remove the WAC after stopping it
      - Stop a WAC before starting it to prevent dups
2010-03-29 21:20:48 +00:00
zzz
394903a8f0 - Implement destroy() in i2psnark to prevent dups 2010-03-29 21:14:35 +00:00
zzz
e31c0636ab - Implement destroy() in addressbook to prevent dups 2010-03-29 21:13:45 +00:00
zzz
e9fe80f8e5 * HTTPResponseOutputStream: More static 2010-03-29 21:12:51 +00:00
zzz
7671550a9f * EepGet: Don't retry after a MalformedURLException 2010-03-29 21:12:04 +00:00
zzz
83d24fa90d -2 2010-03-25 20:26:28 +00:00
zzz
3e2956da3f * netdb.jsp: Tag transport properties 2010-03-25 20:25:03 +00:00
zzz
cf3fd01012 * Plugins: Remove final check and install console
messages after a while
2010-03-25 20:23:32 +00:00
zzz
319071c73b Add new reseed host
thx merd@mail.i2p
2010-03-25 19:09:30 +00:00
zzz
ab8d9bb79b * PrivateKeyFile: Add b32 output 2010-03-25 19:07:35 +00:00
zzz
25eaf8cad7 fix dup anchor 2010-03-25 19:06:47 +00:00
zzz
c8f97d9c73 * i2psnark:
- Send numwant=0 if we don't need peers
      - Report returned complete and incomplete counts
        if higher than peer count
      - Allow missing peer list
      - Log tweaks
2010-03-25 19:05:45 +00:00
zzz
d3f1fe1c30 * Console: Sort plugin links in summary bar 2010-03-25 19:04:45 +00:00
zzz
5fb01a01af history for prop, -1 2010-03-18 15:55:42 +00:00
zzz
617d1cd648 propagate from branch 'i2p.i2p.zzz.test' (head c295ab421dd719cfe0e273268b5b4e48505e4f61)
to branch 'i2p.i2p' (head 995914d8e049d9bb695fd25e4cf5be860cd4e487)
2010-03-18 15:49:03 +00:00
zzz
f672193fcf enable VTBM 2010-03-18 15:48:40 +00:00
zzz
d3c490e9d7 bold the rest of the update msg 2010-03-18 12:32:28 +00:00
zzz
2e8fd23f2b concurrent 2010-03-18 12:32:01 +00:00
zzz
3eef403b04 concurrent 2010-03-18 12:31:44 +00:00
zzz
f3b78fc82f post-release cost cleanup 2010-03-17 22:05:45 +00:00
zzz
80654b2732 Discard at IBGW based on router clock not system clock 2010-03-17 17:00:35 +00:00
zzz
05597ae914 disable i2ptunnel nonce checking if console password is set 2010-03-17 16:23:20 +00:00
zzz
0f1eb464e8 add reseed host thx mathiasdm 2010-03-17 16:22:11 +00:00
zzz
8745ffd42f * config.jsp: Set burst to +10% for 20s by default,
to fix bug where the burst stays high when limits
      are reduced.
2010-03-17 16:18:25 +00:00
zzz
db99e98658 display transport cost 2010-03-17 16:15:52 +00:00
zzz
9f1a663f63 typo fix thx duck 2010-03-16 13:52:57 +00:00
zzz
db0b3da446 snark up bw tracking tweak 2010-03-16 13:32:34 +00:00
zzz
5d22d41201 pack200 for installer (-3.3MB) 2010-03-16 12:38:07 +00:00
zzz
b397de1d54 link to trac 2010-03-16 12:37:32 +00:00
dev
4bda79b263 merge of '7e9ec9156e65514e00e0d9f82be002cf9aadac5f'
and '9df57c2abc8e859828f9edf80e9d104fd6bf6729'
2010-03-15 19:01:28 +00:00
dev
697a9dbd06 merge of '59ab6afe6ba2e217124fe55e8d854d0e04b965c4'
and '6cf70779bcd05bcf782d6d7bb8d131ce8d71426f'
2010-03-15 19:01:07 +00:00
dev
accaabcfde added c.netdb.i2p2.de to the reseed sites 2010-03-15 19:01:03 +00:00
zzz
5026cbdc8d 0.7.12 2010-03-15 18:03:46 +00:00
zzz
16a14d4ebd * Clients:
- Negative delay means run immediately and inline
      - Add methods to test class and run inline,
        to propagate errors to the console
      - Add javadoc for clients.config format
      - Use new methods for plugins
2010-03-15 16:19:19 +00:00
zzz
c151352910 cleanup 2010-03-15 16:15:23 +00:00
zzz
52e2aaa20d javadoc cleanup after review 2010-03-15 14:34:25 +00:00
zzz
9df87ba167 partial fix for i2ptunnel nonce troubles 2010-03-13 20:33:48 +00:00
zzz
b80f70fc54 dont yell so loud 2010-03-13 16:04:32 +00:00
zzz
939cdb019b log tweak 2010-03-13 15:00:47 +00:00
zzz
fde36fe238 flip backwards arraycopy args 2010-03-13 14:59:54 +00:00
116be93160 Russian translation updated (snark file open error message, reseed messages, SOCKS IRC proxy) 2010-03-13 09:57:55 +00:00
zzz
40e820cabb * UDP:
- Big refactor of several classes for concurrent,
        elimination of several locks
      - Reduce max number of resent acks in a packet to
        lower overhead
      - Take incoming messages from the head of the queue,
        not sure why taking them from the tail "reduces latency"
      - Java 5 cleanup
2010-03-09 20:44:46 +00:00
zzz
d79387bd92 * TunnelGatewayPumper: Refactor for concurrent 2010-03-09 20:43:30 +00:00
zzz
05f2a62cbb * Job Queue:
- Replace some locks with concurrent
      - Change job ID to a long so it won't wrap
      - Remove some unused stats
      - Java 5 and debug cleanup
2010-03-09 17:32:29 +00:00
zzz
78a965dc90 * FIFOBandwidthRefiller:
- Replace global counters with atomics
      - Use lockless shortcut methods to grant
        requests if we can satisfy immediately
2010-03-09 17:10:18 +00:00
zzz
5b603d6627 cleanups and comments 2010-03-08 22:17:46 +00:00
zzz
e93d2046d3 Remove some unused stats 2010-03-08 22:15:42 +00:00
zzz
995871db8a more java 5 cleanups 2010-03-08 22:13:43 +00:00
zzz
501535f196 Java 5 cleanups 2010-03-08 22:07:52 +00:00
zzz
91e854e99c * Peer Manager:
- Replace some locks with concurrent
      - Switch back to fast version of getPeersByCapability()
      - Java 5 cleanup
2010-03-08 22:02:42 +00:00
zzz
9b05d8e774 * ByteCache:
- Remove some locks with concurrent
2010-03-08 21:32:14 +00:00
zzz
e70793c3bc propagate from branch 'i2p.i2p' (head b7a8a00272124eec0d149224af58bd144358c009)
to branch 'i2p.i2p.zzz.test' (head a4d67a357c36f4e94718bf237a7af96b8617a4a7)
2010-03-08 20:04:55 +00:00
zzz
abb2603bea one more unused class 2010-03-08 20:04:35 +00:00
c91218be27 Add i2pbote.net to the list of reseed hosts 2010-03-08 05:14:26 +00:00
zzz
9eab44128a * Random: Remove and deprecate some old classses 2010-03-08 00:48:56 +00:00
zzz
f98101afa6 * i2psnark: Better track outgoing bandwidth by incrementing
counter before the blocking write
2010-03-08 00:45:08 +00:00
zzz
4fae7a8cb6 * Floodfills: Increase max to 60 (was 28) and min to 45 (was 20) 2010-03-08 00:44:40 +00:00
zzz
26cf1922db * Reseeder: Reduce max response size to 1MB (was 8MB) 2010-03-08 00:44:15 +00:00
c087b0695f An update of the network configuration page in the messages_fr.po file. 2010-03-06 13:22:49 +00:00
zzz
16930d2004 merge of '18a87911d2a41f5a1fa0f5019d9bcd7249731338'
and '1d260b764d0fde4b8df67bdb23320b85e6944721'
2010-03-05 15:56:57 +00:00
zzz
33939e7cfb translate country names on flag popups 2010-03-05 15:56:17 +00:00
zzz
e759ef5865 tag console reseed messages 2010-03-05 15:36:24 +00:00
zzz
2be1b1ece4 couple of tags 2010-03-05 15:27:32 +00:00
1820a29aed translation update 2010-03-05 15:14:43 +00:00
zzz
ee9f85d53c rename getString() since it was getting tagged 2010-03-05 14:44:50 +00:00
zzz
afbb1dbe86 compile fix 2010-03-05 14:44:18 +00:00
zzz
9244bd6b0f * I2PSOCKSIRCTunnel:
- New, for filtering IRC client traffic when using SOCKS
    * I2PTunnelIRCClient:
      - Make filter classes static and public for use by SOCKS
      - Eliminate redundant case conversion
      - Pass ISON message through (jIRCii uses it for pings)
      - Switch back to StringBuffer since it's used by 2 threads
      - Set daemon on filter threads
    * SOCKS5Server:
      - Fix handling of multiple authentication methods
2010-03-05 14:04:32 +00:00
zzz
6bb4403207 updates after trying SDK 2.1 2010-03-05 13:48:26 +00:00
24ebd503d4 susidns translation 2010-03-05 13:39:37 +00:00
285a5eed35 Russian translation updated (job queue link, address helper conflict message) 2010-03-04 13:04:01 +00:00
zzz
26aebe6a0f * Console:
- Add link to jobs.jsp on configservice.jsp
      - Add plugin disableStop support
2010-03-02 22:54:32 +00:00
zzz
ca9f174171 * Context: Add boolean getProperty methods 2010-03-02 22:52:26 +00:00
zzz
ffbced22b3 * LoadClientAppsJob:
- Fix unquoted arg after quoted arg
      - Logging cleanup
2010-03-02 22:51:53 +00:00
zzz
45ca459ceb * HTTP Proxy:
- Fix address helper conflicts caused by last checkin
      - Use B32 instead of random hostname for conflict link
2010-03-02 22:50:46 +00:00
5a539f0619 merge of '98497fef229d3e37922d4c09cb52e043b01647ee'
and 'de5aa1476c5d447deb031032dbfbc921114dfbd6'
2010-02-27 18:03:05 +00:00
c6cef72cb7 Fix: webapps keep asking for the router console password even after the user entered it 2010-02-27 18:02:56 +00:00
zzz
8081d053cc Prevent UDP startup NPE http://zzz.i2p/topics/571 2010-02-27 14:38:52 +00:00
zzz
efdc8e5df0 * HTTP Proxy:
- Put B32 instead of B64 in Host: header, saves 450 bytes
      - Eliminate some redundant lookups
      - Fix http://i2p/b64/ and /eepproxy/site/ requests
      - Disallow a port specified for an i2p address
      - Cleanup and comments
2010-02-27 01:16:39 +00:00
zzz
b4911a2b2f support plugin themes 2010-02-26 16:58:01 +00:00
zzz
7b70210c9a * UDP Transport:
- Replace the unused-since-2006 TimedWeightedPriorityMessageQueue
        with DummyThrottle
      - Don't instantiate and start TWPMQ Cleaner and OutboundRefiller
        threads, part of priority queues unused since 0.6.1.11
      - Don't instantiate and start UDPFlooder, it is for testing only
2010-02-26 16:54:41 +00:00
zzz
e3353df8bb * NTCP Transport:
- Replace lists with concurrent queues in EventPumper
        and NTCPConnection to remove global locks
      - Java 5 cleanup
2010-02-26 16:52:09 +00:00
zzz
25285fc059 remove jobs link from summary bar 2010-02-26 16:47:41 +00:00
zzz
7720f71e44 * eepsite: Add some help to index.html 2010-02-26 16:46:12 +00:00
zzz
1657ac5357 * netdb: Fix NPE after OOM http://trac.i2p2.i2p/ticket/38 2010-02-26 16:45:34 +00:00
zzz
299214aa1d * i2psnark:
- Fix NPE after create file failure
      - Sanitize more characters in file names
2010-02-26 16:44:49 +00:00
5fd4488e08 Russian translation updated (delete confirmation, non-i2p trackers warning) 2010-02-23 08:49:37 +00:00
zzz
87fcaf2651 * Unzip: Any files in the zip with a .jar.pack or .war.pack extension
will be transparently unpacked with unpack200. Savings is about 60%.
      Someday we will do this for suds, but we can do it for xpi2ps now.
    * build: Add updater200 target
2010-02-23 02:44:47 +00:00
zzz
f6b9cf6f21 * configclients.jsp:
- Add js delete confirm
      - Remove delete button for webapps
    * i2psnark:
      - Ignore a non-i2p tracker in a torrent rather than deleting
        the torrent, thus "converting" a torrent to in-netowrk use
        via the open trackers
      - Add js delete confirm
2010-02-22 18:17:11 +00:00
zzz
eae18e61b7 unhide plugins, fix d/l status display 2010-02-19 14:42:43 +00:00
zzz
96735f2543 make file box bigger 2010-02-19 14:40:57 +00:00
54459d3b5c Russian translation updated (plugin support) 2010-02-18 21:16:15 +00:00
zzz
82444f9e7b move getConsoleServer() method 2010-02-18 16:33:47 +00:00
zzz
3d8365a473 * HTTP Proxy: Fix blank page instead of error page for eepsite unreachable 2010-02-18 16:32:44 +00:00
zzz
e2dc9715d2 * Transport:
- Fix recognition of IP change when not firewalled
      - Require consecutive identical results from two peers before changing IP
2010-02-18 16:31:57 +00:00
zzz
d4f1230b37 better error message when finding HTML instead of metainfo 2010-02-17 19:56:54 +00:00
zzz
7701693d37 * Plugins:
- Fix plugin start button
      - Change signer prop to match docs
      - Tweaks
2010-02-17 18:12:46 +00:00
zzz
b6704fce4e javadoc fix 2010-02-17 18:11:16 +00:00
zzz
39a68d4a2b slew tweak 2010-02-17 18:10:45 +00:00
zzz
94633899d7 CLI exit 1 on error for ease of use in scripts 2010-02-17 18:10:20 +00:00
zzz
c45bc1554f move to i2p.scripts 2010-02-17 18:08:54 +00:00
789c8edc45 Russian translation updated (plugin support) 2010-02-15 20:53:49 +00:00
zzz
e0b44f43e3 history for 3 props, -1 2010-02-15 16:37:22 +00:00
zzz
b45069e377 propagate from branch 'i2p.i2p.zzz.VTBM' (head fb6ef5bc51e18536bc1611a483e9be804084e37b)
to branch 'i2p.i2p' (head c9f5d7378a6028393fe560739ec02f5f87f50f80)
2010-02-15 16:22:20 +00:00
zzz
c3a156ce4b propagate from branch 'i2p.i2p.zzz.plugin' (head fafcd8c8c41873b4d106a9e06504dd7b48109ad8)
to branch 'i2p.i2p' (head 7eafbe18b0a1e26f09b9488d374f5fed4c278a78)
2010-02-15 16:21:15 +00:00
zzz
ee5cc099ed propagate from branch 'i2p.i2p.zzz.test' (head 0914f799641c6ec04dbe40f325f8368403167885)
to branch 'i2p.i2p' (head f3d096929c21753a2117f93d7550b751b021c2a7)
2010-02-15 16:17:40 +00:00
zzz
f189587153 log tweak 2010-02-15 16:16:03 +00:00
zzz
a1fb5ef6ed verify that signing key name matches 2010-02-15 16:12:49 +00:00
zzz
8c2550c39a * Streaming: MessageOutputStream logging tweaks 2010-02-15 16:10:41 +00:00
zzz
abd96a920f 0.7.11 2010-02-15 12:43:28 +00:00
zzz
1d3f0fe96c * Transport:
- Update addressses before publishing
      - Increment address cost if near capacity
      - Synchronize notifyReplaceAddress()
2010-02-15 04:08:02 +00:00
zzz
49a6cdbda6 - Clear the geoip negative cache periodically 2010-02-14 01:17:19 +00:00
zzz
2700028da7 * Transport: Adjust bids based on address cost
- More finals
2010-02-13 15:16:12 +00:00
51a1564566 Fix addWebApplications API goofup, Bump BOB version, which I forgot to do. 2010-02-13 13:46:10 +00:00
zzz
bd068058c3 * Floodfills: Increase max to 28 (was 15) and min to 20 (was 10) 2010-02-13 12:02:33 +00:00
4591f77928 A few minor updates 2010-02-13 10:51:00 +00:00
zzz
4f70a7d0fe * Clock:
- getFramedAveragePeerClockSkew() now returns a long (ms);
        was a Long (s)
      - Implement NTP-style clock slewing so the clock is adjusted
        gradually
      - Implement clock strata so we prefer better clocks
      - Implement a timestamper in the transport so we will periodically
        update the clock even if NTP is not working
        This allows the router to converge the clock instead of simply
        hoping the first connected peer is correct.
      - Slow down NTP attempts after several consecutive failures
2010-02-13 01:20:23 +00:00
6d67848096 org.mortbay.jetty.Server modified method to accept Attributes for batch webapp launches via addWebApplications(). 2010-02-12 22:15:59 +00:00
zzz
c145ed103a merge of '5a88275dbd49dfde016676939fb28b1387447216'
and 'b4afc02ff8ecaf95f621169763cfa99e3f309102'
2010-02-11 23:02:03 +00:00
zzz
f265db4037 fix stop button; catch and log exceptions better 2010-02-11 21:41:54 +00:00
zzz
62308f26bc * Plugins:
- Fix classpath setting for webapps
      - Implement uninstall args in clients.config
2010-02-11 19:18:26 +00:00
2b4b47eff6 Russian translation updated (readonly install directory message) 2010-02-10 20:30:51 +00:00
zzz
04ae0e2610 * I2PTunnelRunner: Flush initial data, for some reason it wasn't
getting flushed ever in some cases.
2010-02-10 20:17:31 +00:00
zzz
cada9fae44 flush requests in I2PTunelRunner 2010-02-10 20:13:07 +00:00
zzz
949aea951e * Plugins:
- Hook up update/delete/check/save buttons
      - Implement delete
      - Hide unless router.enablePlugins=true
2010-02-10 19:09:35 +00:00
zzz
cfc49ab261 * Plugins:
- Check plugin key against all installed plugins
      - Reword some error messages
    * VersionComparator: add '-' and '_' as valid separators
      to better support plugin and java version checking
2010-02-10 15:35:00 +00:00
zzz
0e853a3119 fix missing readme files in debian 2010-02-10 13:45:31 +00:00
zzz
a0cad7e8e9 -10 2010-02-10 12:58:45 +00:00
zzz
880f1866dc take version number off jrobin jar so we can overwrite if we upgrade 2010-02-10 12:06:30 +00:00
zzz
05d22344b5 * Izpack: Add 64-bit windows dll so installer doesn't die trying to add shortcuts 2010-02-10 11:49:21 +00:00
zzz
7212f855d8 Upgrade to launch4j 3.0.1 2008-07-20.
The license is BSD for launch4j and MIT for the wrapper code in head/

Changelog is in installer/lib/launch4j/web/changelog.html
Hopefully this will fix installs for 64-bit JRE on 64-bit windows.

The previous version was 2.0-RC3 2005-08-13.
The previous license was GPLv2 for launch4j and LGPLv2.1 for the wrapper code in head/

The bin/ld.exe and bin/windres.exe files were contributed by
i2p users in 2005 so the i2p installer could be built on windows.

They have not been updated for 3.0.1, so pkg builds on windows
will presumably still get 2.0-RC3.
2010-02-09 17:21:48 +00:00
zzz
54171e4be2 ... and more 2010-02-08 23:37:31 +00:00
zzz
a820c01ba5 strip HTML from fields 2010-02-08 23:28:09 +00:00
zzz
9d1ae891bb check for mismatched versions 2010-02-08 22:50:30 +00:00
zzz
2df7247e83 fix start webapp, add stop webapp 2010-02-08 22:19:59 +00:00
zzz
a109ebef28 stop button 2010-02-08 20:57:30 +00:00
zzz
c0135b592d plugin stopper 2010-02-08 20:37:49 +00:00
zzz
b7a0aeea34 plugin buttons 2010-02-08 19:04:46 +00:00
zzz
66375e25c6 start of a plugin version checker 2010-02-08 18:45:53 +00:00
zzz
85482a67f5 plugin description on configclients 2010-02-08 16:15:23 +00:00
zzz
d7e90969d0 delete jettylib on distclean to ensure we get the new jetty 2010-02-07 20:16:18 +00:00
zzz
9012baf51e plugin links 2010-02-07 19:01:06 +00:00
zzz
3c8355790f load translation bundles in plugins 2010-02-07 18:18:31 +00:00
zzz
e9f1da85e4 classpath for plugins 2010-02-07 17:13:44 +00:00
zzz
58adccfd4a start of a plugin starter 2010-02-07 13:32:49 +00:00
zzz
040f3e016e move jrobin from routerconsole.jar to its own jar 2010-02-06 20:48:14 +00:00
zzz
505d5f5cae * Plugins: New plugin downloader/installer
* configclients.jsp: Use new WebAppStarter so webapps that are
      started later also get the temp dir, password, and classpath
      configuration just like if they were started at the beginning
    * configupdate.jsp: Delay after checking for update so the
      summary bar will have buttons.
2010-02-06 20:25:13 +00:00
zzz
2a99e2a295 -9 2010-02-06 18:55:11 +00:00
zzz
49fae646e2 merge of '9e658a1b1e62b486a399a162ceb27fe3461a9eb0'
and 'fe3561146f8172bdb86292eade40a031b7dee4fb'
2010-02-06 18:53:18 +00:00
zzz
f7780b6745 * TrustedUpdate:
- Allow method to check if we know about a key
      - Add method to extract without verifying
2010-02-06 18:47:08 +00:00
zzz
7a59d15e9c - Pull jstl.jar and standard.jar out of susidns.war (-300KB someday)
- Remove duplicate classes from i2psnark.war (100KB)
2010-02-06 18:44:29 +00:00
zzz
9b141bd9dd * Webapps: Allow additions to a webapp classpath. This will let us:
- Pull jstl.jar and standard.jar out of susidns.war
      - Remove 100KB of duplicate classes from i2psnark.war
      - Add classpaths for plugins
2010-02-06 18:40:55 +00:00
d0d062b6f4 No more port 8887 in de troubleshoot 2010-02-06 16:52:16 +00:00
zzz
375118fe02 Refactor and tag update status messages 2010-02-05 21:12:10 +00:00
zzz
7b59ceb4ae Add transmission ID 2010-02-05 20:02:23 +00:00
zzz
3aebe45a7d refactor the storage of signing keys 2010-02-05 19:19:33 +00:00
zzz
7c236c0fa0 Console: Fix saving update keys, was broken in 0.7.10 2010-02-05 19:18:26 +00:00
zzz
7a7e650ca0 news.xml: Wrap i2p version tags in XML comment 2010-02-05 19:18:06 +00:00
zzz
7a32f8efd6 Try yet again to prevent two NTCP pumpers 2010-02-05 19:17:46 +00:00
zzz
2f8b55ceda propagate from branch 'i2p.i2p' (head d84bac5f340fb1f9f4826a3326847a84cf32b1a1)
to branch 'i2p.i2p.zzz.test' (head c055e344e2d86aa417bb248bb0a6c54ba3b2f52d)
2010-02-05 00:31:33 +00:00
zzz
b77be20cc1 set up transport cost constants 2010-02-05 00:31:00 +00:00
zzz
101135a99a fix sending of stopped events to the tracker 2010-02-04 14:47:15 +00:00
zzz
746c1bd628 * NetDb: Lower min RouterInfo expiration to 2.5h (was 3h)
* i2psnark debug logging tweak
2010-02-03 14:21:55 +00:00
zzz
b0502b1873 Fix several VTBM read/write bugs after testing 2010-02-03 14:16:05 +00:00
zzz
6801fc667a - Hide update buttons and update config if install dir is readonly or if configured 2010-02-02 15:25:26 +00:00
zzz
794db19b6d javadoc 2010-02-02 15:19:17 +00:00
zzz
d4637818be - Show yellow star if no outbound tunnels 2010-02-02 15:18:22 +00:00
zzz
33b7dca782 * i2psnark: Don't prefer to opportunistically unchoke unchoking peers when not interested 2010-02-02 15:14:44 +00:00
zzz
d7015cf2e6 disable sending VTBMs 2010-02-01 14:46:00 +00:00
zzz
5689fa8512 propagate from branch 'i2p.i2p' (head 2b1a99ea78270f80514ced3860a7d54cc3f2e309)
to branch 'i2p.i2p.zzz.VTBM' (head 155eea7b96fa5ce48faec385242e0b6eb232b0dd)
2010-02-01 14:39:16 +00:00
zzz
25e51a945c - Fix first hop expiration for Build Messages, was way too long
- Randomize Build Message expiration to make it harder to guess hop position
      - Save expired tunnel build configs for a while, so that we will still use the tunnel
        and update peer stats if the reply comes in late
      - Don't update our own profile for Tunnel Build Replies
2010-02-01 14:17:11 +00:00
zzz
bfd1306a56 fix for missing tgz build error 2010-01-31 20:26:57 +00:00
zzz
839986db22 * I2NP: Add UnknownI2NPMessage so we can route unknown message types 2010-01-31 16:31:36 +00:00
zzz
ed443fe0d6 jetty 5.1.15 2010-01-31 05:06:50 +00:00
390981e10c Fix NPE in TCPtoI2P when a lookup fails, report the error to the stream.
Fix setkeys bug in DoCMDS, forgot to create the object before calling t's methods, which threw an NPE.
2010-01-30 05:26:30 +00:00
zzz
56b3e6a993 * Tunnel Building:
- Add getRecordCount() to TunnelBuildMessage and TunnelBuildReplyMessage
        so they can be extended.
      - New I2NP Messages VariableTunnelBuildMessage and VariableTunnelBuildReplyMessage,
        which contain the number of request slots in them.
      - Convert all static assumptions of 8 slots to getRecordCount()
      - Use the new VTBM if all hops in the tunnel and the OBEP or IBGW of the reply tunnel
        support it, and the tunnel is 4 hops or shorter.
      - Reply to a VTBM with a VTBRM of the same size
      - Make BuildReplyHandler static
      - Convert the currentlyBuilding List to a ConcurrentHashMap to speed reply lookups
        and eliminate a global lock; don't put fallback tunnels in there
      - Add new tunnel.corruptBuildReply stat
      - Various cleanups and javadoc

    Tested as compatible with current network, new messages untested.
2010-01-29 19:22:10 +00:00
zzz
f86f2701ff - Speed up some hashcode() and equals()
- Cleanup and javadoc
2010-01-29 13:57:57 +00:00
zzz
63d3685652 * Jetty: Turn on checkAliases 2010-01-29 13:55:16 +00:00
zzz
0a93466999 - Add basic DOS prevention for lookups
- Move flood throttle check so we don't throttle ourselves
2010-01-29 13:53:14 +00:00
zzz
81664bc776 - Don't update unused lease fail stats 2010-01-29 13:47:50 +00:00
zzz
6d60a6f833 - Don't store over client tunnels to pre-0.7.10 floodfills 2010-01-29 13:42:42 +00:00
zzz
4186894a39 * build.xml: Add a debian-source target
* Startup: Disable browser launch for debian daemon
2010-01-29 13:41:40 +00:00
cfeafacd07 update the pos 2010-01-29 09:26:02 +00:00
dev
9c2edf5c6a update history 2010-01-28 20:06:16 +00:00
dev
72396f0f96 merge of '3679ca64eea825719eb0d26b285091a9e81107f3'
and '36fc8877438b0f8fa6220cd52459497af5a2eed6'
2010-01-28 20:05:12 +00:00
dev
45388b0d48 added an getTargetAddresses(transportStyle) method to the RouterInfo structure 2010-01-28 20:05:03 +00:00
zzz
a8ae36c403 fixup 2010-01-26 20:05:03 +00:00
zzz
164b39d8df * I2NP: Various cleanup and bulletproofing 2010-01-26 19:59:39 +00:00
zzz
ccc95087a1 shrink the stats.jsp dropdown 2010-01-26 19:56:36 +00:00
zzz
b97f4f8bd7 try to silence log errors at shutdown 2010-01-26 19:53:25 +00:00
zzz
76c1f47b20 * Profiles: Fix lack of profiles at router startup, especially for new routers 2010-01-26 19:52:06 +00:00
zzz
ce74e49236 * Clock: Don't refuse to update because of peer skew the first time 2010-01-26 19:49:35 +00:00
zzz
977d39aeb1 minor license updates 2010-01-26 19:49:21 +00:00
zzz
a821ea2752 take non-linux stuff out of debian jbigi.jar 2010-01-26 16:25:03 +00:00
zzz
b97197c0fa * Debian: Fixup, update, enhance dream's scripts
* build.xml: Speed up sponge's distclean additions
2010-01-26 15:21:41 +00:00
zzz
474691927a fix date 2010-01-24 15:41:33 +00:00
zzz
81dcbedd17 * Transport clock skews:
- Store and report UDP clock skews even for large values, so
        a badly skewed local clock will be reported to the console
      - Don't shitlist for NTCP clock skew if we don't know what time it is
      - If NTP hasn't worked yet, have NTCP or SSU update the clock one time
      - Include failed clock skew in NTCP skew vector if there aren't many connections
      - Don't include NTCP clock skews for non-established connections
      - Fix framed clock skew frame size
      - Report framed clock skew even if for only one peer, if NTP hasn't worked yet
      - Don't log RRD errors after clock adjustment
      - Reduce min skew for console warning to 30s (was 45s)
      - More Java 5 cleanups
2010-01-24 15:38:44 +00:00
zzz
4f5cfdee57 adjust welt reseed hostname 2010-01-24 15:35:02 +00:00
zzz
2c7725a8e4 cleanups 2010-01-24 15:34:40 +00:00
zzz
0ba6482da5 -1 2010-01-24 02:42:06 +00:00
zzz
4c1fd67925 propagate from branch 'i2p.i2p.zzz.test' (head 9b243b031d937eaefcd4c15ae61bb4fa280d78f3)
to branch 'i2p.i2p' (head 9383c447b12abf45f80bd0059f719acfce4c70a3)
2010-01-24 02:37:55 +00:00
zzz
25683cc0de merge of '338745763da1ce77c8adc9f889449dc14451f3fb'
and 'ba40565ead71f8ce02500978ca95ca90340a294d'
2010-01-24 02:37:21 +00:00
zzz
087fd5a909 * NetDb:
- Move stat initialization, reduce number of rates
      - Add basic DOS prevention by not flooding if stores are too-frequent
2010-01-24 02:36:42 +00:00
zzz
fdfbab850a minor cleanups 2010-01-24 02:16:36 +00:00
zzz
f1c50b7fc3 * Clock:
- Don't let a client update the router clock
      - Restore and enhance vanished clock error log message
2010-01-24 02:14:39 +00:00
zzz
959bf4a7f4 limit max graph size 2010-01-24 02:11:55 +00:00
zzz
5dda915467 * Startup:
- Enable multiple parallel job runners much sooner to speed startup
      - Rearrange the startup order to get the long jobs started sooner
      - Don't allow the netDb readin job to clog the job queue
2010-01-23 19:12:37 +00:00
zzz
66d8fd6c2a * ProfileOrganizer:
- Limit High Cap to 75 max
      - Reduce max lock wait time
      - More cleanup
2010-01-23 03:40:56 +00:00
06efe306c3 Deutsch eepsite help text updated to the latest version by zzz (October'2009). Fixed i2host.i2p url typo. 2010-01-22 17:04:59 +00:00
dev
15d1b005f5 merge of '120e01fdee48c2f8652e8314f3dcfb5655a3b7b1'
and 'e30d2f11dde010812b8a5607e5407e37d745700d'
2010-01-22 15:27:01 +00:00
zzz
7efab75c3c 0.7.10 2010-01-21 19:44:49 +00:00
zzz
a9e4248c93 Increase ff count; -6 2010-01-21 14:22:32 +00:00
zzz
5338dc5540 * Properties: Don't play games with \r and \n on load/save,
it was causing fatal issues on DOS if your username started
      with r or n
2010-01-21 14:19:38 +00:00
zzz
09d3dc8e90 * Logs: Don't be quite so noisy in the wrapper log if we
can't open the router log
2010-01-21 14:18:31 +00:00
zzz
3bf95e566c * I2PTunnelServer: Fix bug preventing connection retries
at startup from working
2010-01-21 14:17:37 +00:00
zzz
958a5a3c4e * eepget.bat: Add to pkg 2010-01-21 14:17:10 +00:00
7b48f6387f build.xml tweaks for batch copying the eepsite.help 2010-01-21 13:22:15 +00:00
fcd2cdb136 merge of '4755aa75bada4925580e70471d2cbe82d52f4e1e'
and 'af16732f69734b702b887071df3348e77d3c7c97'
2010-01-21 12:15:43 +00:00
6b59356bc5 disapproval of revision 'df747c3515cd167431e6e003a732943e35aef79d' 2010-01-21 12:14:11 +00:00
z3d
1c7f098d9b Add missing index_na.html to our eepsite stash. 2010-01-21 11:46:52 +00:00
103c15f000 Russian translation updated to dr|z3d's template, links to the Russian page moved to the alphabetically sorted position 2010-01-21 08:53:31 +00:00
0fd55f8b07 Added: missing non-translated welcome page from dr|z3d's template. 2010-01-21 08:50:54 +00:00
511c1e7b9d Re-added: docroot location on Windows (from October'2009 version by zzz) 2010-01-21 08:50:36 +00:00
z3d
7df3bde2ce Add Russian to the eepsite index; prettify the Russian index with the new css. Minor tweaks to the css. 2010-01-21 08:18:55 +00:00
z3d
25e6b6e6c4 Add a note to history.txt re eespite changes. 2010-01-21 08:00:37 +00:00
z3d
cb81f2c9ba Updated eepsite indexes with the new layout + pagetemplate.html 2010-01-21 07:46:03 +00:00
z3d
6c25f0fd16 Build.xml mods to accomodate new eepsite structure. 2010-01-21 07:21:01 +00:00
z3d
934f3d1814 Move robots.txt to eepsite.help dir; add redirecting index.html 2010-01-21 02:52:04 +00:00
z3d
e883fd6b1b Let's mirror the actual eepsite contents in the installer.. 2010-01-21 02:48:49 +00:00
z3d
e3b300e978 Add graphical resources to eepsite. 2010-01-21 02:08:55 +00:00
z3d
03a9f69739 Move Russian eepsite index to our new eepsite.help dir. 2010-01-21 00:49:56 +00:00
z3d
be2dca8ee7 merge of '6dbc656c7ca49810cd09d02d8ddafdc9e083d12e'
and 'efdeefc134243f15d893f98dcbe275657fcc807a'
2010-01-19 11:38:49 +00:00
5c595ef289 * Firewall fix for NTCP, where firewalls will forget a NAT relationship
on a stream... AKA setting keepalive. This should fix the stuck NTCP
      issue that has been bothing zzz for years.
    * Set keepalive on BOB connections too, since this will assist closing
      the connections in the event of a crash on a client.
2010-01-19 08:54:40 +00:00
z3d
d9534e5f23 First stage of eepsite starter page rejig. 2010-01-18 21:13:29 +00:00
00fa3806d8 Russian translation update (Share ratio, HTTP bidir, Add Client, ...) 2010-01-18 19:28:32 +00:00
6c5ef9acdc Added: Russian translation 2010-01-18 19:27:59 +00:00
zzz
2db5914ba0 Save graph settings when changed 2010-01-18 17:39:12 +00:00
zzz
35a0dafb83 * Reseed: Support SSL and proxies 2010-01-18 15:42:50 +00:00
zzz
5f12688a90 * Console: Add a tunnel share ratio estimate 2010-01-18 14:57:03 +00:00
zzz
f8d9af871a javadoc 2010-01-18 14:54:59 +00:00
zzz
08a2b4bbf0 * graphs.jsp: Remove jrobin sig, set lower limit to 0 2010-01-18 14:54:32 +00:00
zzz
27a5793fd0 * configclients.jsp: Fix add-new-client feature
* Translate: Catch empty string
2010-01-18 14:51:39 +00:00
b1151f82b5 Messages_fr.po update 2010-01-17 21:11:20 +00:00
zzz
b6332f8313 history for prop, -3 2010-01-17 13:50:16 +00:00
zzz
e036cd4332 propagate from branch 'i2p.i2p.zzz.test' (head dc29b32afe515f704985a4f92cda6e28a65ccdc5)
to branch 'i2p.i2p' (head fb38016f22528778128e22269b8f256c8c640466)
2010-01-17 13:42:33 +00:00
zzz
174fedc2e6 - Flood even if the entry was received via a garlic message
- Encrypt stores only if floodfill supports it
2010-01-17 02:45:55 +00:00
zzz
4803e60db4 Limit fast tier to 30 max 2010-01-16 23:23:58 +00:00
zzz
abb62b93e3 store to a different ff after verify fail 2010-01-16 18:59:00 +00:00
zzz
95bb322cd7 Clock: Change a CRIT to an ERROR, lower threshold for changing from 10s to 5s 2010-01-16 18:58:02 +00:00
zzz
670b4033cb Add a small number of ms (0-300) that increases as we approach the expire time.
Since the earliest date functions as a version number,
this will force the floodfill to flood each new version;
otherwise it won't if the earliest time hasn't changed.
2010-01-16 17:06:20 +00:00
zzz
715ae13997 dont log a RI DSM down a client tunnel as an error, just silently drop, as probably the result of a FVSJ 2010-01-16 17:06:01 +00:00
zzz
77b88ab59d * NetDb Stores and Verifies:
- Do LS stores and verifies through client tunnels
        to prevent correlation by the OBEP or FF
      - Encrypt LS stores to prevent snooping by the OBEP
      - Encrypt LS and RI verifies to prevent snooping by the OBEP
      - Extend verify delay and timeout
      - Reenable RI verifies
      - Disallow simultaneous verifies for the same key
      - Don't resend on verify timeout; try a different peer instead
      - Adjust ff selection criteria
2010-01-15 21:37:41 +00:00
zzz
64235bd745 * NetDb Lookups: Don't try to send a RI lookup to itself through a zero-hop tunnel 2010-01-15 15:16:58 +00:00
0a1960461a Fully clean up I2PTunnel. No more lint issues, should compile 100% clean.
Dropped unused class BufferLogger from I2PTunnel as it is not used anylonger.
2010-01-15 03:32:35 +00:00
11249657ac Clean up reverse connection ability, remove some annoyingly redundent code.
Place all settings in the console. It works!
2010-01-14 05:45:01 +00:00
zzz
188ac4f730 SSLEepGet 2010-01-13 22:33:43 +00:00
865116b3f4 merge of '1f636df6ff10db350d6b020b2e06daf842fb23e1'
and '5e5df32501efc3a7548958249e5bd99acf8edd8f'
2010-01-13 14:38:01 +00:00
zzz
9f28c06e9e 0.7.9, and:
* I2CP: Clean up resources on 5-minute leaseset timeout at startup
    * Increase max floodfills to 9 (was 6)
    * Temporarily disable routerInfo floodfill verifies
    * Fix .fr eepsite index css
    * Javdoc tweaks
2010-01-12 18:48:47 +00:00
zzz
3cd6520758 logging and javadoc tweaks 2010-01-10 22:01:00 +00:00
zzz
da1a50bfeb * VersionComparator: Move from TrustedUpdate.java to util 2010-01-10 16:42:21 +00:00
zzz
9ec79f50fa * I2CP: Clean up resources on 5-minute leaseset timeout at startup 2010-01-10 16:38:34 +00:00
b15392ea85 Insert reverse connection ability into the http server code so that
seedless can start to get worked on. It's disabled by default.
2010-01-10 11:23:20 +00:00
zzz
b8339e72b0 tweaks; include new translated eepsite pages in pkg; -18-rc 2010-01-09 14:26:01 +00:00
6eaec7fd44 Russian translation update 2010-01-09 03:01:04 +00:00
9e8f2ce771 Russian translation: Router console (969/969), router help page, eepsite help page 2010-01-09 02:58:49 +00:00
e8e6f6f531 Tagged missing strings. 2010-01-08 15:57:48 +00:00
f16ba8ee06 Tagged missing strings. Retagged (merged) couple strings to have 1 string per sentence instead of translating them chunk by chunk while their internal punctuation marks were outside of the translation scope. 2010-01-08 15:46:22 +00:00
zzz
76f11859b2 hide add button when editing 2010-01-06 21:33:53 +00:00
zzz
5be21a19db support add, delete,edit of clients 2010-01-06 21:24:08 +00:00
zzz
043359dd40 propagate from branch 'i2p.i2p' (head dbcd208a02bbecfe924e13a7d71297ece3f01ef3)
to branch 'i2p.i2p.zzz.test' (head 9eee20312852c80ca6c8e079174578a335edbe6d)
2010-01-06 17:16:18 +00:00
zzz
1b95b00b44 prevent more than one zero-hop tunnel in a leaseset 2010-01-06 17:16:00 +00:00
zzz
eaaf6af31d javadoc and logging tweaks; bring back i2ptunnel link to summary bar 2010-01-06 14:52:53 +00:00
d8d50aaf41 Snark font color fix 2010-01-03 14:12:48 +00:00
5fcddd581e Fix one last stupid mistake in build.xml, my fault. 2010-01-02 22:58:50 +00:00
f1a9613a92 merge of '4259744a4e2a56c50c62c34ecc3340120b48a427'
and 'd548b2a3c95f98dd3296cdd891e03e7c2936e61e'
2010-01-02 16:55:58 +00:00
a2ce10759c po update 2010-01-02 16:55:15 +00:00
5065aec773 Fix NB 6.8 goofyness... 'till ant 1.7.1 or > is needed, stay with NB 6.5,
as the newer ones place a check for 1.7.1. We require 1.7.0
2010-01-02 14:59:50 +00:00
25fc64933a Fix build.xml target for justBOB and fix Main build.xml so that it actually
deletes backup files and add a few extra types that should be commonly 
needed... atleast by me.
2010-01-02 14:34:20 +00:00
bbdd54efc8 Russian translation: Error pages (9/9) 2010-01-02 07:57:03 +00:00
92597baab9 Russian translation updated: I2PTunnel (138/138) 2010-01-02 07:56:35 +00:00
62786dcc09 Tagged couple of messages required for error pages (previously marked as fixme's) 2010-01-02 07:49:42 +00:00
c012e5bf17 tagging and translation 2010-01-02 05:43:50 +00:00
zzz
5ed29b6c27 laptop mode 2010-01-02 02:46:23 +00:00
zzz
2d5decd943 save refresh setting 2010-01-02 02:43:18 +00:00
zzz
9d167dc83a path fix 2010-01-02 02:40:58 +00:00
zzz
afe8394658 optimize URL encoder 2010-01-02 02:40:12 +00:00
zzz
72db6d1a08 alignment fix 2010-01-02 02:39:24 +00:00
zzz
9d0e300924 css update for readability 2010-01-02 02:38:35 +00:00
4f548b7b27 Added a target to generate a stand-alone BOB jar file. 2010-01-01 21:28:28 +00:00
cbd50372e4 Fixed: braceless if (where it proved to be harmful) 2010-01-01 17:33:55 +00:00
zzz
3caee8bc71 i2ptunnel java tagging and fixups 2010-01-01 14:58:21 +00:00
6c64faf0ba translation 2010-01-01 14:31:06 +00:00
65290f1ed7 Russian translation update/reworded 2009-12-31 21:00:17 +00:00
498af5d203 i2ptunnel\jsp tagging and translation 2009-12-31 13:10:33 +00:00
zzz
883b53de0a cleanups, javadoc 2009-12-30 22:38:37 +00:00
zzz
cefc1f130d * NetDb: Fix exploration by adding a null hash to mean
"don't give me floodfills"
    * PeerSelector: Downgrade floodfills with high fail rate
2009-12-30 22:36:53 +00:00
zzz
b2a137c5bc make BuildResponseRecord static 2009-12-30 22:33:26 +00:00
zzz
62f056f884 remove more unused logs 2009-12-30 22:28:07 +00:00
zzz
3944ea53d2 make the message box big enough that we dont need a scrollbar 2009-12-30 22:26:36 +00:00
zzz
d372ea753f fallback to external socket 2009-12-30 22:26:02 +00:00
zzz
2528cd205d javadoc 2009-12-30 22:25:34 +00:00
zzz
afd54fc212 logs.jsp tweak 2009-12-30 22:25:21 +00:00
8e7a9fc513 update translation 2009-12-27 05:43:25 +00:00
zzz
acb75f4212 oops 2009-12-26 20:37:05 +00:00
zzz
c40b56c19d -12 2009-12-26 20:28:11 +00:00
zzz
98027a06ec javadoc 2009-12-26 20:26:47 +00:00
zzz
d92dfec1bf * UDP: Bid lower than NTCP when we need introducers and don't
have enough; was preventing firewalled routers from
      being reachable
2009-12-26 20:25:32 +00:00
zzz
72a588bfbf * Tunnels
- More code to detect improper reuse of cached objects
        after release
      - Don't pass a msg with a failed IV on to
        the FragmentHandler at the OBEP
      - More cleanups and comments
2009-12-26 20:20:11 +00:00
zzz
213bc4bb71 - Prevent release of TunnelDataMessage cached ByteArray,
as it may be reused if retried in another transport;
        a nasty bug causing corrupt messages
      - Lots of code to detect improper reuse of cached objects
        after release
2009-12-26 20:12:43 +00:00
zzz
1a01aa0ae4 - Code to detect improper reuse of cached objects
after release
      - Prevent race with released resources in UDP OutboundMessageState;
        a nasty bug causing corrupt messages
      - More cleanups and comments
2009-12-26 20:05:41 +00:00
zzz
0b0e3fffe4 various cleanups, javadocs, logging 2009-12-26 20:00:47 +00:00
zzz
1fc32c5e6f more logs.jsp tagging 2009-12-26 19:54:27 +00:00
ba9f05ca06 translation update 2009-12-26 09:55:16 +00:00
zzz
629d12ade1 * Tunnels:
- Do RED dropping before the IBGW fragmenter, not after
      - Change batch time to 250ms for IBGWs (was 100ms)
      - Change batch time to 150ms for exploratory OBGWs (was 100ms)
      - Start a new message in the fragmenter if almost full
      - Fix a major, longstanding synchronization bug in the FragmentHandler
        which led to corrupt messages at the endpoints
      - More cleanups and comments
2009-12-22 15:08:10 +00:00
zzz
08929752a6 move SubmitMessageHistoryJob to test 2009-12-22 15:02:28 +00:00
zzz
aaa5b4ca86 oops 2009-12-20 15:05:58 +00:00
zzz
8d7e84494b -10 2009-12-20 15:00:19 +00:00
zzz
99df95697a merge of '5cbdacfbeb8f09f9ac497016e429eaf6fe7225c6'
and 'dae5a2b76e24fc3215d46d5b96ea0f547c83f63c'
2009-12-20 14:52:57 +00:00
zzz
a877b21839 more comments and cleanup 2009-12-20 14:50:41 +00:00
3f267693d2 Russian translation update/reworded: I2PSnark, SusiDNS 2009-12-20 07:11:39 +00:00
zzz
30b7dbf1f7 Tunnel fragmenter cleanup, prep for enhancements 2009-12-19 22:20:58 +00:00
f32d162b62 Russian translation update: SusiDNS (83/83) 2009-12-19 18:23:18 +00:00
126fa320e5 susidns UTF-8 fixes for POST requests (yep, blame tagged 'action' parameters) 2009-12-19 18:16:28 +00:00
zzz
ecae0b055d schedule the outbound rather than sleep the thread for 3 seconds 2009-12-19 18:15:21 +00:00
zzz
9bf22fb0d3 stats.jsp tagging 2009-12-19 17:41:47 +00:00
zzz
2a1d358141 * Profile, DBHistory:
- Tweak the rate periods
      - Add a global fail rate stat
      - Increase the HashMap sizes
2009-12-19 17:10:39 +00:00
zzz
579b450029 clean up context usage 2009-12-19 16:56:38 +00:00
zzz
72eafe0920 * Tunnels: Reduce the drop probability for TunnelBuildMessages at the OBEP 2009-12-19 16:54:59 +00:00
zzz
f226392c9d static access fix 2009-12-19 16:53:49 +00:00
zzz
2cd5c209f5 unused cleanup 2009-12-19 16:52:49 +00:00
zzz
f0d444b32e add to javadoc and adjust logging 2009-12-19 16:52:18 +00:00
zzz
4baff9fbab * Router: Move some more threads to I2PAppThread so an OOM won't crash the router 2009-12-19 16:49:55 +00:00
zzz
8e656427d8 * Console:
- Fix status to show a disconnected network error rather than
        clock skew or UDP error when disconnected
      - Use peer clock skew rather than clock offset for determining
        whether to display clock skew error, i.e. display what matters
    * Transport: Rework peer clock skew method to always return a value
      by falling back to router clock offset;
      Fix possible AIOOBE and divide by zero; remove logging;
      reduce min number of peers
2009-12-19 16:47:18 +00:00
zzz
aaa7302e80 clarify table headings 2009-12-19 16:40:57 +00:00
zzz
33407fd5be reduce delays (cuts 10s from router startup 2009-12-19 16:39:50 +00:00
zzz
513b93f789 no room for cows 2009-12-19 16:39:06 +00:00
zzz
08e54c515e add isRouterContext() method 2009-12-19 16:37:44 +00:00
zzz
55682810b1 doc updates 2009-12-19 16:35:15 +00:00
ec893d09d0 as promised. translation done. Snark still needs review. 2009-12-18 08:27:17 +00:00
zzz
f9b745a671 * Log:
- Close old file on rotate
      - Buffer writes
      - Write in UTF-8
2009-12-18 00:04:16 +00:00
zzz
43b71a263c * Tunnel building:
- Increase timeout to 13s (was 10s)
      - Fix tunnel.buildReplyTooSlow stat
      - Tweak logging
      - Prioritize expl. builds over client builds
      - Code cleanups
2009-12-17 23:45:20 +00:00
zzz
5c4672d1e3 drop another unused class 2009-12-17 15:49:17 +00:00
zzz
7ca8e0c3a1 fix spacing in update section 2009-12-17 14:02:02 +00:00
zzz
b530316850 * I2CP:
- Move client-side writes to their own thread
      - Reenable InternalSockets
2009-12-17 01:05:29 +00:00
zzz
fa92beae5a more cleanup and tagging; remove untranslatable button images; add button css 2009-12-16 17:29:28 +00:00
zzz
f58f703ecb add some newlines to the source 2009-12-16 17:26:49 +00:00
zzz
6b83fc6b3b InNetMessagePool cleanup 2009-12-16 17:25:09 +00:00
zzz
cdb390f7ce fix bundle script 2009-12-16 17:23:52 +00:00
zzz
7b1caac9ac cleanup and tag susidns jsps 2009-12-15 17:25:01 +00:00
zzz
cec75fa60e fix i2ptunnel bundles 2009-12-15 01:51:56 +00:00
zzz
eb23306b12 configurable jump list 2009-12-15 01:48:57 +00:00
zzz
43f6813609 snark start/stop fix, action cleanups 2009-12-15 01:47:24 +00:00
zzz
ea36b7b153 susidns UTF-8 fixes 2009-12-15 01:46:10 +00:00
zzz
448ff4d398 better error msg on sud copy fail 2009-12-15 01:45:15 +00:00
zzz
e16227211f remove unused logs 2009-12-15 01:44:20 +00:00
zzz
e07e329c26 Tunnels: static fix, synchronization fix, deprecate setPairedTunnel() 2009-12-15 01:41:43 +00:00
a3d79aaa4e Russian translation: I2PSnark (140/140), SusiDNS (1/1), I2PTunnel (3/3) 2009-12-14 20:15:16 +00:00
zzz
3fa9ae0b82 * Find ResourceBundles in wars
* Fix restart from config.jsp if no wrapper
    * i2psnark: Elaborate popups
2009-12-13 15:47:51 +00:00
dev
7feed50af4 -5 2009-12-13 09:26:10 +00:00
dev
0c0eb5765d merge of '306029c0c1bb9b7d62fcfdaeddd47bff7db82f66'
and 'c14952061dd61ddd6638f0a3655dd818f0a3db8e'
2009-12-13 09:25:09 +00:00
dev
e87ff25ef6 fix NPE 2009-12-13 09:24:25 +00:00
21e09cb0a5 no more 8887 2009-12-13 07:35:30 +00:00
04d54607ae merge of '63c4c4c5586988695f01b6e845851bad2196b89a'
and 'db28ef1a2085d0585cc3606f1e614467913f758b'
2009-12-13 06:39:08 +00:00
ad8bfbdaab merge of 'afee8fe3ed03c61266ad369b5ce5408382948977'
and 'cec49ea3b0b9120ba6e58435852fb18c06912c55'
2009-12-13 06:39:05 +00:00
aca815c4aa snark rough translation (i am not a bt guy, so need review and refine) 2009-12-13 06:38:39 +00:00
24683c19a4 Added messages_ru.po with 100% fuzzy translations. Awaiting review by native. 2009-12-12 18:18:46 +00:00
dev
6b8dffc401 -4 2009-12-12 17:51:01 +00:00
dev
c4bb84058a sort peers per country 2009-12-12 17:49:54 +00:00
zzz
c3dc76e35f disable internal sockets until I can fix the borkenness 2009-12-12 01:36:57 +00:00
zzz
993fa5c210 fix all summary bar relative links 2009-12-11 19:03:30 +00:00
zzz
1cec793217 add missing file, prop history, -2 2009-12-11 18:26:53 +00:00
zzz
6029e1a291 * Fragmenter: Pull the new comments, new stats, and
debug log fix from i2p.i2p.zzz.batch in - but not the
      batching mods, which need a fresh look.
2009-12-11 18:00:34 +00:00
zzz
7cc75c0cb9 html fix 2009-12-11 00:42:25 +00:00
zzz
e5248b09ab add 2-param method, tag the java messages, fix the buttons, clean up add and create forms 2009-12-10 18:08:50 +00:00
zzz
c39f047703 pretty much the last of the tags 2009-12-10 14:52:09 +00:00
zzz
4562254862 propagate from branch 'i2p.i2p' (head f672021bb9871a728005be3bd9581710738b9e5f)
to branch 'i2p.i2p.zzz.test' (head e115e218dbb666839e69fa1e1ba7378554b9874f)
2009-12-10 13:34:05 +00:00
zzz
8116d88aaf translation build fixups 2009-12-10 02:12:18 +00:00
zzz
14362630d7 translation support 2009-12-10 01:54:49 +00:00
zzz
9af796a10a translation support 2009-12-10 01:06:55 +00:00
zzz
eeb884e8ce more tags 2009-12-09 23:36:18 +00:00
zzz
02baf905c6 more tagging 2009-12-09 21:22:06 +00:00
zzz
df7029d2c2 translation support and initial tagging 2009-12-09 20:54:10 +00:00
zzz
c22b7568b1 * Translation: Move code from routerconsole to core,
to support translation of other webapps
2009-12-09 14:07:16 +00:00
73537d27d0 bump as requested 2009-12-08 15:27:14 +00:00
449d7ab589 typo 2009-12-08 14:53:25 +00:00
zzz
1e32170df2 move hosts.txt; do distclean in apps/jetty 2009-12-08 01:20:13 +00:00
zzz
fb21fb25ee * I2PTunnel:
- Switch all I2PThreads to I2PAppThreads
      - Run an InternalSocket as well for the HTTP Proxy
    * EepGet: Use InternalSocket
    * Console: Change "depth" to "length"
2009-12-07 21:25:27 +00:00
zzz
deae0e8856 truncate the history in the updater 2009-12-07 21:24:03 +00:00
zzz
2c456c291a remove jsps from war 2009-12-06 17:44:53 +00:00
zzz
c5b3c2f430 add restart msg as requested by dr|z3d 2009-12-06 15:17:47 +00:00
zzz
e46e747ac0 add the anchor 2009-12-06 15:16:52 +00:00
zzz
e1a88c9426 drop 6 unused classes 2009-12-06 15:07:03 +00:00
zzz
bda4eb830e prevent accept() hang on internal socket 2009-12-04 11:16:43 +00:00
zzz
7262c014c0 * I2CP: Implement an internal "socket" class that
allows clients in the same JVM to connect to the
      router without going through the kernel
2009-12-04 00:20:43 +00:00
zzz
9f7bd99051 fix popup based on torrent type 2009-12-02 16:50:42 +00:00
zzz
9e4f04cc18 fix exception text 2009-12-02 16:50:15 +00:00
zzz
412d641eb6 fix pathspec 2009-11-29 18:40:20 +00:00
zzz
d7d058e772 addressbook servlet cleanup 2009-11-29 17:58:24 +00:00
zzz
4b6989ef7b * Addressbook, susidns: Rework addressbook into a
HttpServlet, so susidns can kick it when the subscription
      list changes
2009-11-28 17:08:02 +00:00
zzz
c10ea84ade * NamingServices
- Move default reverseLookup to base class
      - Deprecate unused services
2009-11-28 14:37:07 +00:00
zzz
2db7c2bdd8 new 2009-11-28 13:38:35 +00:00
zzz
8682e7deb5 cache the hash of the Hash 2009-11-27 16:29:15 +00:00
zzz
ea0747171f * NetDb:
- Switch from ArrayList to ConcurrentHashSet in
        KBucketImpl to reduce chance of deadlock;
        remove periodic shuffling of the bucket,
        needs to be addressed elsewhere
2009-11-27 14:39:53 +00:00
zzz
13349777ad propagate from branch 'i2p.i2p' (head f42d02067d4fb58b86ffb79222a285f26c3a2628)
to branch 'i2p.i2p.zzz.test' (head 2ceb319557032e54cc8ace070515c6d540e0a7a4)
2009-11-27 13:26:52 +00:00
zzz
ab0a5a06af add basic no-webapp handler 2009-11-27 13:26:38 +00:00
795 changed files with 61861 additions and 23017 deletions

View File

@ -27,6 +27,7 @@ run I2P for the first time.
To run I2P explicitly:
(*nix): sh i2prouter start
(win*): I2P.exe
(Platforms unsupported by the wrapper - PPC, ARM, etc): sh runplain.sh
To stop the router (gracefully):
lynx http://localhost:7657/configservice.jsp ("Shutdown gracefully")

View File

@ -1,10 +1,18 @@
I2P source installation instructions
Prerequisites to build from source:
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
The SDK must have Pack200 support (java.util.jar.Pack200)
Apache Ant 1.7.0 or higher
Optional, For multilanguage support: The xgettext, msgfmt, and msgmerge tools installed
from the GNU gettext package http://www.gnu.org/software/gettext/
To build and install I2P from source, you must first build
and package up the appropriate installer by running:
ant pkg
This will produce a few key files:
* install.jar: the GUI and console installer
* i2pinstall.exe: the GUI and console installer wrapped for cross-platform execution
@ -18,9 +26,6 @@ Or run the GUI installer:
Or move the update file into an existing installation directory and restart.
You will need to have ant installed from http://ant.apache.org/
(1.7.0 or newer)
Supported JVMs:
Windows: Latest available from http://java.sun.com/ (1.5+ supported)
Linux: Latest available from http://java.sun.com/ (1.5+ supported)

View File

@ -64,6 +64,9 @@ Public domain except as listed below:
Copyright 2006 Gregory Rubin grrubin@gmail.com
See licenses/LICENSE-HashCash.txt
GettextResource from gettext v0.18:
Copyright (C) 2001, 2007 Free Software Foundation, Inc.
See licenses/LICENSE-LGPLv2.1.txt
Router:
@ -80,9 +83,10 @@ Public domain except as listed below:
Installer:
Launch4j 2.0.RC3:
Copyright (C) 2005 Grzegorz Kowal
See licenses/LICENSE-GPLv2.txt
Launch4j 3.0.1:
Copyright (c) 2004, 2008 Grzegorz Kowal
See licenses/LICENSE-Launch4j.txt (in binary packages)
See installer/lib/launch4j/LICENSE.txt (in source packages)
The following projects are used by Launch4j...
MinGW binutils (http://www.mingw.org/)
@ -138,6 +142,7 @@ Applications:
I2PSnark:
Copyright (C) 2003 Mark J. Wielaard
See licenses/LICENSE-GPLv2.txt
Silk icons: See licenses/LICENSE-SilkIcons.txt
I2PTunnel:
(c) 2003 - 2004 mihi
@ -175,6 +180,7 @@ Applications:
Router console:
Public domain.
Flag icons: public domain, courtesy mjames@gmail.com http://www.famfamfam.com/
Silk icons: See licenses/LICENSE-SilkIcons.txt
GeoIP Data:
Copyright (c) 2003 Direct Information Pvt. Ltd. All Rights Reserved.
@ -207,6 +213,9 @@ The following applications and libraries are not used or bundled in
binary packages, therefore the licenses are not included in binary
distributions. See the source package for the additional license information.
Admin Manager:
Public domain
Atalk:
Public domain

View File

@ -1,11 +1,14 @@
Prerequisites to build from source:
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
The SDK must have Pack200 support (java.util.jar.Pack200)
Apache Ant 1.7.0 or higher
Optional, For multilanguage support: The xgettext, msgfmt, and msgmerge tools installed
from the GNU gettext package http://www.gnu.org/software/gettext/
To build:
ant pkg
Run 'ant' with no arguments to see other build options.
See http://www.i2p2.de/download.html for installation instructions.
See INSTALL.txt or http://www.i2p2.de/download.html for installation instructions.
Documentation:
http://www.i2p2.de/

View File

@ -1,29 +1,38 @@
These instructions are for the 1.5 Android SDK.
These instructions are for a recent Android SDK (1.6 or later)..
Should also still work with a 1.5 SDK.
The build file is not compatible with the 1.1 SDK any more.
1.6 and 2.0 SDKs are untested.
#Download the SDK from http://developer.android.com/sdk/index.html
#Unzip the android SDK in ../../
#So then the android tools will be in ../../android-sdk-linux_x86-1.5_r2/tools/
#So then the android tools will be in ../../android-sdk-linux_86/tools/
#
# now go to the available packages tab, check the box and click refresh,
# and download an SDK Platform
# Since I2P is configured to run on 1.1 or higher
# (API 2) download that one. Otherwise you must change the
# target in default.properties from android-2 to andriod-x
# where x is the API version.
# create a file local.properties with the following line:
# sdk-location=/path/to/your/android-sdk-linux_x86-1.5_r2
# sdk-location=/path/to/your/android-sdk-linux_86
#then build the android apk file:
ant debug
# Create the android 1.5 virtual device
# Create the android 1.1 (API 2) virtual device
# (don't make a custom hardware profile)
../../android-sdk-linux_x86-1.5_r2/tools/android create avd --name i2p --target 2
# A AVD created with the 1.5 SDK will not work with the newer tools
../../android-sdk-linux_86/tools/android create avd --name i2p --target 2
#then run the emulator:
../../android-sdk-linux_x86-1.5_r2/tools/emulator -avd i2p &
../../android-sdk-linux_86/tools/emulator -avd i2p &
#then wait a couple minutes until the emulator is up
#then install the I2P app
ant install
#then run the debugger
../../android-sdk-linux_x86-1.5_r2/tools/ddms &
../../android-sdk-linux_86/tools/ddms &
#to rebuild and reinstall to emulator:
ant reinstall

View File

@ -113,6 +113,10 @@
<delete file="${external-libs-folder}/crypto.jar" />
</target>
<!-- fix for property name change sometime after SDK 1.5 -->
<property name="android-jar" value="${android.jar}" />
<property name="android-aidl" value="${android.aidl}" />
<!--
================================================================================
From here down copied from SDK platforms/android-1.1/templates/android_rules.xml

View File

@ -10,7 +10,13 @@ i2np.udp.maxConnections=30
# no I2CP
i2p.dummyClientFacade=true
# for now
i2np.ntcp.enable=false
#i2np.ntcp.enable=false
#
# UDP crashes the JVM, don't know why
#
i2np.udp.enable=false
# no COMM at all!!!
#i2p.vmCommSystem=true
# not on android
i2np.upnp.enable=false
routerconsole.geoip.enable=false

View File

@ -69,7 +69,7 @@ public class I2PAndroid extends Activity
// from routerconsole ContextHelper
List contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.size() <= 0) )
if ( (contexts == null) || (contexts.isEmpty()) )
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
RouterContext ctx = (RouterContext)contexts.get(0);

View File

@ -71,4 +71,44 @@
nbproject/build-impl.xml file.
-->
<target depends="jar" description="Build BOB into a SINGLE JAR." name="onejar">
<!-- Make needed working dirs -->
<mkdir dir="${dist.dir}/lib" />
<mkdir dir="${dist.dir}/classes" />
<!-- Copy jars -->
<copy todir="${dist.dir}/lib" flatten="true" >
<path>
<pathelement path="${javac.classpath}" />
</path>
</copy>
<copy todir="${dist.dir}/lib" file="../../installer/lib/jbigi/jbigi.jar" />
<!-- Extract the classes inside the jar files -->
<unjar dest="${dist.dir}/classes" >
<fileset dir="${dist.dir}/lib" >
<include name="**/*.jar" />
</fileset>
</unjar>
<!-- Recombine the classes into a new jar file -->
<jar jarfile="${dist.dir}/lib/all-in-one.jar" >
<fileset dir="${dist.dir}/classes" />
</jar>
<!-- Clean up work area -->
<delete dir="${dist.dir}/classes" followsymlinks="false" includeemptydirs="true"/>
<!-- Make the single jar file -->
<jar jarfile="dist/BOB-one.jar" >
<zipfileset src="${dist.jar}" excludes="META-INF/*" />
<zipfileset src="${dist.dir}/lib/all-in-one.jar" excludes="**/META-INF/*" />
<manifest>
<attribute name="Main-Class" value="net.i2p.BOB.Main" />
</manifest>
</jar>
<!-- Clean up the fake jar file -->
<delete file="${dist.dir}/lib/all-in-one.jar" />
</target>
</project>

View File

@ -1,7 +0,0 @@
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

View File

@ -1,7 +0,0 @@
<?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:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/TCPio.java</file>
</open-files>
</project-private>

View File

@ -1,5 +1,6 @@
application.homepage=http://bob.i2p/
application.title=BOB
application.vendor=root
application.vendor=Sponge
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
@ -11,6 +12,7 @@ build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
@ -23,6 +25,7 @@ debug.test.classpath=\
dist.dir=dist
dist.jar=${dist.dir}/BOB.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
file.reference.i2p.jar=../../core/java/build/i2p.jar
@ -33,7 +36,7 @@ file.reference.router.jar=../../router/java/build/router.jar
file.reference.streaming.jar=../streaming/java/build/streaming.jar
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
includes=**
jar.compress=false
jar.compress=true
javac.classpath=\
${file.reference.router.jar}:\
${file.reference.i2ptunnel.jar}:\
@ -63,8 +66,9 @@ javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
jnlp.codebase.type=local
jnlp.codebase.url=file:/root/NetBeansProjects/i2p.i2p/apps/BOB/dist/
jnlp.codebase.url=file:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/dist
jnlp.descriptor=application
jnlp.enabled=false
jnlp.offline-allowed=false

View File

@ -256,11 +256,13 @@ public class BOB {
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
Socket server = null;
listener.setSoTimeout(500); // .5 sec
while (spin.get()) {
//DoCMDS connection;
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (ConnectException ce) {
g = false;

View File

@ -50,7 +50,7 @@ public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
public static final String BMAJ = "00", BMIN = "00", BREV = "0A", BEXT = "";
public static final String BMAJ = "00", BMIN = "00", BREV = "0D", BEXT = "";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private Socket server;
private Properties props;
@ -691,6 +691,7 @@ public class DoCMDS implements Runnable {
try {
prikey = new ByteArrayOutputStream();
prikey.write(net.i2p.data.Base64.decode(Arg));
d = new Destination();
d.fromBase64(Arg);
} catch (Exception ex) {
Arg = "";

View File

@ -102,6 +102,7 @@ public class I2PtoTCP implements Runnable {
break die;
}
sock = new Socket(host, port);
sock.setKeepAlive(true);
// make readers/writers
in = sock.getInputStream();
out = sock.getOutputStream();

View File

@ -311,6 +311,19 @@ public class MUXlisten implements Runnable {
} catch (InterruptedException ex) {
}
// Hopefully nuke stuff here...
{
String boner = tg.getName();
try {
_log.warn("destroySocketManager " + boner);
socketManager.destroySocketManager();
_log.warn("destroySocketManager Successful" + boner);
} catch (Exception e) {
// nop
_log.warn("destroySocketManager Failed" + boner);
_log.warn(e.toString());
}
}
// zero out everything.
try {
wlock();

View File

@ -95,10 +95,14 @@ public class TCPio implements Runnable {
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) {
Thread.sleep(10);
// Will this die? We'll see.
while(Ain.available() == 0) {
Thread.sleep(20);
}
// Thread.yield(); // this should act like a mini sleep.
// if (Ain.available() == 0) {
// Thread.sleep(10);
// }
} else {
/* according to the specs:
*

View File

@ -78,6 +78,7 @@ public class TCPlistener implements Runnable {
while (lives.get()) {
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (SocketTimeoutException ste) {
g = false;

View File

@ -146,8 +146,14 @@ public class TCPtoI2P implements Runnable {
input = line.toLowerCase();
Destination dest = null;
if (input.endsWith(".i2p")) {
dest = I2PTunnel.destFromName(input);
line = dest.toBase64();
try {
dest = I2PTunnel.destFromName(input);
line = dest.toBase64();
} catch (NullPointerException npe) {
// Could not find the destination!?
Emsg("Can't find destination: " + input, out);
return;
}
}
dest = new Destination();
dest.fromBase64(line);

View File

@ -39,6 +39,7 @@ import net.i2p.I2PAppContext;
public class Daemon {
public static final String VERSION = "2.0.3";
private static final Daemon _instance = new Daemon();
private boolean _running;
/**
* Update the router and published address books using remote data from the
@ -126,6 +127,7 @@ public class Daemon {
}
public void run(String[] args) {
_running = true;
String settingsLocation = "config.txt";
File homeFile;
if (args.length > 0) {
@ -166,7 +168,7 @@ public class Daemon {
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
} catch (InterruptedException ie) {}
while (true) {
while (_running) {
long delay = Long.parseLong((String) settings.get("update_delay"));
if (delay < 1) {
delay = 1;
@ -179,6 +181,8 @@ public class Daemon {
}
} catch (InterruptedException exp) {
}
if (!_running)
break;
settings = ConfigParser.parse(settingsFile, defaultSettings);
}
}
@ -192,4 +196,9 @@ public class Daemon {
_instance.notifyAll();
}
}
public static void stop() {
_instance._running = false;
wakeup();
}
}

View File

@ -51,4 +51,9 @@ public class DaemonThread extends Thread {
//}
Daemon.main(this.args);
}
}
public void halt() {
Daemon.stop();
interrupt();
}
}

View File

@ -21,24 +21,48 @@
package net.i2p.addressbook;
import javax.servlet.GenericServlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* A wrapper for addressbook to allow it to be started as a web application.
*
* This was a GenericServlet, we make it an HttpServlet solely to provide a hook
* for SusiDNS to wake us up when the subscription list changes.
*
* @author Ragnarok
*
*/
public class Servlet extends GenericServlet {
public class Servlet extends HttpServlet {
private DaemonThread thread;
private String nonce;
private static final String PROP_NONCE = "addressbook.nonce";
/* (non-Javadoc)
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
/**
* Hack to allow susidns to kick the daemon when the subscription list changes.
* URL must be /addressbook/ with wakeup param set, and nonce param set from system property.
*
* (non-Javadoc)
* see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public void service(ServletRequest request, ServletResponse response) {
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
//System.err.println("Got request nonce = " + request.getParameter("nonce"));
if (this.thread != null && request.getParameter("wakeup") != null &&
this.nonce != null && this.nonce.equals(request.getParameter("nonce"))) {
//System.err.println("Sending interrupt");
this.thread.interrupt();
// no output
} else {
PrintWriter out = response.getWriter();
out.write("I2P addressbook OK");
}
}
/* (non-Javadoc)
@ -49,15 +73,24 @@ public class Servlet extends GenericServlet {
try {
super.init(config);
} catch (ServletException exp) {
System.err.println("Addressbook init exception: " + exp);
}
this.nonce = "" + Math.abs((new Random()).nextLong());
// put the nonce where susidns can get it
System.setProperty(PROP_NONCE, this.nonce);
String[] args = new String[1];
args[0] = config.getInitParameter("home");
DaemonThread thread = new DaemonThread(args);
thread.setDaemon(true);
thread.setName("Addressbook");
thread.start();
this.thread = new DaemonThread(args);
this.thread.setDaemon(true);
this.thread.setName("Addressbook");
this.thread.start();
System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
System.out.println("INFO: config root under " + args[0]);
//System.out.println("INFO: config root under " + args[0]);
}
@Override
public void destroy() {
this.thread.halt();
super.destroy();
}
}

View File

@ -13,4 +13,10 @@
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>addressbook</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

BIN
apps/i2psnark/_icons/cd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View File

@ -0,0 +1,17 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
# zzz - public domain
#
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
## need to cd into our orignal path - where we call sh.exe from.
cd $CALLFROM
## echo $PWD
## except this everything is the same with bundle-message.sh
## walking - public domain :-D
source bundle-messages.sh $PARAS

View File

@ -37,7 +37,7 @@
</javac>
</target>
<target name="jar" depends="builddep, compile">
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class">
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class **/messages_*.class">
<manifest>
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
@ -51,12 +51,45 @@
- So we must continue to duplicate everything in the war.
<classes dir="./build/obj" includes="**/I2PSnarkServlet*.class" />
-->
<target name="war" depends="jar">
<war destfile="../i2psnark.war" webxml="../web.xml">
<classes dir="./build/obj" includes="**/*.class" excludes="**/RunStandalone.class" />
<target name="war" depends="jar, bundle">
<war destfile="../i2psnark.war" webxml="../web.xml" basedir="../" includes="_icons/*" >
<!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
<classes dir="./build/obj" includes="**/web/*.class" />
</war>
</target>
<target name="bundle" depends="compile">
<!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
</exec>
</target>
<target name="poupdate" depends="builddep, compile">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
<arg value="-p" />
</exec>
</target>
<target name="standalone" depends="standalone_prep">
<zip destfile="i2psnark-standalone.zip">
<zipfileset dir="./dist/" prefix="i2psnark/" />
@ -95,9 +128,7 @@
<delete dir="./dist" />
</target>
<target name="cleandep" depends="clean">
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
<target name="distclean" depends="clean">
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
</project>

View File

@ -0,0 +1,26 @@
@echo off
set Callfrom=%cd%
set Paras=%1
rem before calling make sure you have msys and mingw 's "bin" path
rem in your current searching path
rem type "set path" to check
if not exist ..\locale\*.only goto updateALL
rem put a messages_xx.only(eg messages_zh.only) into locale folder
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
for %%i in (..\locale\*.only) do set PO=%%~ni
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
call sh --login %cd%\bmsg.sh
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
goto end
:updateALL
call sh --login %cd%\bmsg.sh
:end
echo End of Message Bundling

View File

@ -0,0 +1,85 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
#
# usage:
# bundle-messages.sh (generates the resource bundle from the .po file)
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
#
# zzz - public domain
#
CLASS=org.klomp.snark.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
if [ "$1" = "-p" ]
then
POUPDATE=1
fi
# add ../java/ so the refs will work in the po file
JPATHS="../java/src"
for i in ../locale/messages_*.po
do
# get language
LG=${i#../locale/messages_}
LG=${LG%.po}
if [ "$POUPDATE" = "1" ]
then
# make list of java files newer than the .po file
find $JPATHS -name *.java -newer $i > $TMPFILE
fi
if [ -s build/obj/org/klomp/snark/web/messages_$LG.class -a \
build/obj/org/klomp/snark/web/messages_$LG.class -nt $i -a \
! -s $TMPFILE ]
then
continue
fi
if [ "$POUPDATE" = "1" ]
then
echo "Updating the $i file from the tags..."
# extract strings from java and jsp files, and update messages.po files
# translate calls must be one of the forms:
# _("foo")
# _x("foo")
# To start a new translation, copy the header from an old translation to the new .po file,
# then ant distclean poupdate.
find $JPATHS -name *.java > $TMPFILE
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\
--keyword=_ --keyword=_x \
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
rm -f ${i}t
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
rm -f ${i}t
break
fi
rm -f ${i}t
# so we don't do this again
touch $i
fi
echo "Generating ${CLASS}_$LG ResourceBundle..."
# convert to class files in build/obj
msgfmt --java --statistics -r $CLASS -l $LG -d build/obj $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
break
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
@ -36,7 +37,7 @@ import net.i2p.util.Log;
*/
public class ConnectionAcceptor implements Runnable
{
private Log _log = new Log(ConnectionAcceptor.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ConnectionAcceptor.class);
private I2PServerSocket serverSocket;
private PeerAcceptor peeracceptor;
private Thread thread;

View File

@ -4,7 +4,6 @@ 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;
@ -23,11 +22,13 @@ import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.EepGet;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.Translate;
/**
* I2P specific helpers for I2PSnark
@ -44,33 +45,35 @@ public class I2PSnarkUtil {
private int _proxyPort;
private String _i2cpHost;
private int _i2cpPort;
private Map _opts;
private Map<String, String> _opts;
private I2PSocketManager _manager;
private boolean _configured;
private final Set _shitlist;
private final Set<Hash> _shitlist;
private int _maxUploaders;
private int _maxUpBW;
private int _maxConnections;
private File _tmpDir;
private int _startupDelay;
public static final int DEFAULT_STARTUP_DELAY = 3;
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);
//setProxy("127.0.0.1", 4444);
setI2CPConfig("127.0.0.1", 7654, null);
_shitlist = new HashSet(64);
_shitlist = new ConcurrentHashSet();
_configured = false;
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
_maxUpBW = DEFAULT_MAX_UP_BW;
_maxConnections = MAX_CONNECTIONS;
_startupDelay = DEFAULT_STARTUP_DELAY;
// This is used for both announce replies and .torrent file downloads,
// so it must be available even if not connected to I2CP.
// so much for multiple instances
@ -84,6 +87,7 @@ public class I2PSnarkUtil {
* host for no proxying)
*
*/
/*****
public void setProxy(String host, int port) {
if ( (host != null) && (port > 0) ) {
_shouldProxy = true;
@ -96,6 +100,7 @@ public class I2PSnarkUtil {
}
_configured = true;
}
******/
public boolean configured() { return _configured; }
@ -124,17 +129,23 @@ public class I2PSnarkUtil {
_maxConnections = limit;
_configured = true;
}
public void setStartupDelay(int minutes) {
_startupDelay = minutes;
_configured = true;
}
public String getI2CPHost() { return _i2cpHost; }
public int getI2CPPort() { return _i2cpPort; }
public Map getI2CPOptions() { return _opts; }
public Map<String, String> getI2CPOptions() { return _opts; }
public String getEepProxyHost() { return _proxyHost; }
public int getEepProxyPort() { return _proxyPort; }
public boolean getEepProxySet() { return _shouldProxy; }
public int getMaxUploaders() { return _maxUploaders; }
public int getMaxUpBW() { return _maxUpBW; }
public int getMaxConnections() { return _maxConnections; }
public int getStartupDelay() { return _startupDelay; }
/**
* Connect to the router, if we aren't already
*/
@ -186,18 +197,15 @@ public class I2PSnarkUtil {
/** connect to the given destination */
I2PSocket connect(PeerID peer) throws IOException {
Hash dest = peer.getAddress().calculateHash();
synchronized (_shitlist) {
if (_shitlist.contains(dest))
throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are shitlisted");
}
if (_shitlist.contains(dest))
throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are shitlisted");
try {
I2PSocket rv = _manager.connect(peer.getAddress());
if (rv != null) synchronized (_shitlist) { _shitlist.remove(dest); }
if (rv != null)
_shitlist.remove(dest);
return rv;
} catch (I2PException ie) {
synchronized (_shitlist) {
_shitlist.add(dest);
}
_shitlist.add(dest);
SimpleScheduler.getInstance().addEvent(new Unshitlist(dest), 10*60*1000);
throw new IOException("Unable to reach the peer " + peer + ": " + ie.getMessage());
}
@ -206,7 +214,7 @@ public class I2PSnarkUtil {
private class Unshitlist implements SimpleTimer.TimedEvent {
private Hash _dest;
public Unshitlist(Hash dest) { _dest = dest; }
public void timeReached() { synchronized (_shitlist) { _shitlist.remove(_dest); } }
public void timeReached() { _shitlist.remove(_dest); }
}
/**
@ -357,7 +365,7 @@ public class I2PSnarkUtil {
while (tok.hasMoreTokens())
rv.add(tok.nextToken());
if (rv.size() <= 0)
if (rv.isEmpty())
return null;
return rv;
}
@ -402,4 +410,37 @@ public class I2PSnarkUtil {
break;
}
}
private static final String BUNDLE_NAME = "org.klomp.snark.web.messages";
/** lang in routerconsole.lang property, else current locale */
public String getString(String key) {
return Translate.getString(key, _context, BUNDLE_NAME);
}
/**
* translate a string with a parameter
* This is a lot more expensive than getString(s, ctx), so use sparingly.
*
* @param s string to be translated containing {0}
* The {0} will be replaced by the parameter.
* Single quotes must be doubled, i.e. ' -> '' in the string.
* @param o parameter, not translated.
* To tranlslate parameter also, use _("foo {0} bar", _("baz"))
* Do not double the single quotes in the parameter.
* Use autoboxing to call with ints, longs, floats, etc.
*/
public String getString(String s, Object o) {
return Translate.getString(s, o, _context, BUNDLE_NAME);
}
/** {0} and {1} */
public String getString(String s, Object o, Object o2) {
return Translate.getString(s, o, o2, _context, BUNDLE_NAME);
}
/** ngettext @since 0.7.14 */
public String getString(int n, String s, String p) {
return Translate.getString(n, s, p, _context, BUNDLE_NAME);
}
}

View File

@ -30,6 +30,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.crypto.SHA1;
import net.i2p.data.Base64;
import net.i2p.util.Log;
@ -47,7 +48,7 @@ import org.klomp.snark.bencode.InvalidBEncodingException;
*/
public class MetaInfo
{
private static final Log _log = new Log(MetaInfo.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(MetaInfo.class);
private final String announce;
private final byte[] info_hash;
private final String name;

View File

@ -388,6 +388,7 @@ public class Peer implements Comparable
* Sets whether or not we are interested in pieces from this peer.
* Defaults to false. When interest is true and this peer unchokes
* us then we start downloading from it. Has no effect when not connected.
* @deprecated unused
*/
public void setInteresting(boolean interest)
{

View File

@ -28,6 +28,7 @@ import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.util.Iterator;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
@ -41,7 +42,7 @@ import net.i2p.util.Log;
*/
public class PeerAcceptor
{
private static final Log _log = new Log(PeerAcceptor.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerAcceptor.class);
private final PeerCoordinator coordinator;
final PeerCoordinatorSet coordinators;

View File

@ -26,6 +26,8 @@ import java.util.List;
import java.util.Random;
import java.util.TimerTask;
import net.i2p.I2PAppContext;
/**
* TimerTask that checks for good/bad up/downloader. Works together
* with the PeerCoordinator to select which Peers get (un)choked.
@ -43,7 +45,7 @@ class PeerCheckerTask extends TimerTask
this.coordinator = coordinator;
}
private Random random = new Random();
private static final Random random = I2PAppContext.getGlobalContext().random();
public void run()
{
@ -105,15 +107,15 @@ class PeerCheckerTask extends TimerTask
peer.resetCounters();
_util.debug(peer + ":", Snark.DEBUG);
_util.debug(" ul: " + upload/KILOPERSECOND
+ " dl: " + download/KILOPERSECOND
_util.debug(" ul: " + upload*1024/KILOPERSECOND
+ " dl: " + download*1024/KILOPERSECOND
+ " i: " + peer.isInterested()
+ " I: " + peer.isInteresting()
+ " c: " + peer.isChoking()
+ " C: " + peer.isChoked(),
Snark.DEBUG);
// Choke half of them rather than all so it isn't so drastic...
// Choke a percentage of them rather than all so it isn't so drastic...
// unless this torrent is over the limit all by itself.
boolean overBWLimitChoke = upload > 0 &&
((overBWLimit && random.nextBoolean()) ||

View File

@ -23,11 +23,12 @@ package org.klomp.snark;
import java.io.DataInputStream;
import java.io.IOException;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
class PeerConnectionIn implements Runnable
{
private Log _log = new Log(PeerConnectionIn.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerConnectionIn.class);
private final Peer peer;
private final DataInputStream din;
@ -129,7 +130,7 @@ class PeerConnectionIn implements Runnable
din.readFully(bitmap);
ps.bitfieldMessage(bitmap);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Received bitmap from " + peer + " on " + peer.metainfo.getName() + ": size=" + (i-1) + ": " + ps.bitfield);
_log.debug("Received bitmap from " + peer + " on " + peer.metainfo.getName() + ": size=" + (i-1) /* + ": " + ps.bitfield */ );
break;
case 6:
piece = din.readInt();

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
@ -33,7 +34,7 @@ import net.i2p.util.SimpleTimer;
class PeerConnectionOut implements Runnable
{
private Log _log = new Log(PeerConnectionOut.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerConnectionOut.class);
private final Peer peer;
private final DataOutputStream dout;
@ -141,7 +142,7 @@ class PeerConnectionOut implements Runnable
it.remove();
}
}
if (m == null && sendQueue.size() > 0) {
if (m == null && !sendQueue.isEmpty()) {
m = (Message)sendQueue.remove(0);
SimpleTimer.getInstance().removeEvent(m.expireEvent);
}
@ -151,7 +152,11 @@ class PeerConnectionOut implements Runnable
{
if (_log.shouldLog(Log.DEBUG))
_log.debug("Send " + peer + ": " + m + " on " + peer.metainfo.getName());
m.sendMessage(dout);
// This can block for quite a while.
// To help get slow peers going, and track the bandwidth better,
// move this _after_ state.uploaded() and see how it works.
//m.sendMessage(dout);
lastSent = System.currentTimeMillis();
// Remove all piece messages after sending a choke message.
@ -159,9 +164,22 @@ class PeerConnectionOut implements Runnable
removeMessage(Message.PIECE);
// XXX - Should also register overhead...
if (m.type == Message.PIECE)
state.uploaded(m.len);
// Don't let other clients requesting big chunks get an advantage
// when we are seeding;
// only count the rest of the upload after sendMessage().
int remainder = 0;
if (m.type == Message.PIECE) {
if (m.len <= PeerState.PARTSIZE) {
state.uploaded(m.len);
} else {
state.uploaded(PeerState.PARTSIZE);
remainder = m.len - PeerState.PARTSIZE;
}
}
m.sendMessage(dout);
if (remainder > 0)
state.uploaded(remainder);
m = null;
}
}

View File

@ -29,6 +29,7 @@ import java.util.List;
import java.util.Random;
import java.util.Timer;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
@ -37,7 +38,7 @@ import net.i2p.util.Log;
*/
public class PeerCoordinator implements PeerListener
{
private final Log _log = new Log(PeerCoordinator.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class);
final MetaInfo metainfo;
final Storage storage;
final Snark snark;
@ -61,7 +62,7 @@ public class PeerCoordinator implements PeerListener
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
// synchronize on this when changing peers or downloaders
final List peers = new ArrayList();
final List<Peer> peers = new ArrayList();
/** estimate of the peers, without requiring any synchronization */
volatile int peerCount;
@ -71,7 +72,7 @@ public class PeerCoordinator implements PeerListener
private final byte[] id;
// Some random wanted pieces
private List wantedPieces;
private List<Piece> wantedPieces;
private boolean halted = false;
@ -96,7 +97,7 @@ public class PeerCoordinator implements PeerListener
// Install a timer to check the uploaders.
// Randomize the first start time so multiple tasks are spread out,
// this will help the behavior with global limits
Random r = new Random();
Random r = I2PAppContext.getGlobalContext().random();
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
}
@ -116,7 +117,7 @@ public class PeerCoordinator implements PeerListener
public CoordinatorListener getListener() { return listener; }
// for web page detailed stats
public List peerList()
public List<Peer> peerList()
{
synchronized(peers)
{
@ -134,8 +135,10 @@ public class PeerCoordinator implements PeerListener
return storage.complete();
}
/** might be wrong */
public int getPeerCount() { return peerCount; }
/** should be right */
public int getPeers()
{
synchronized(peers)
@ -240,15 +243,18 @@ public class PeerCoordinator implements PeerListener
}
}
/** reduce max if huge pieces to keep from ooming */
/**
* Reduce max if huge pieces to keep from ooming when leeching
* @return 512K: 16; 1M: 11; 2M: 6
*/
private int getMaxConnections() {
int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
if (size <= 1024*1024)
if (size <= 512*1024 || completed())
return max;
if (size <= 2*1024*1024)
return (max + 1) / 2;
return (max + 3) / 4;
if (size <= 1024*1024)
return (max + max + 2) / 3;
return (max + 2) / 3;
}
public boolean halted() { return halted; }
@ -256,7 +262,7 @@ public class PeerCoordinator implements PeerListener
public void halt()
{
halted = true;
List removed = new ArrayList();
List<Peer> removed = new ArrayList();
synchronized(peers)
{
// Stop peer checker task.
@ -268,8 +274,8 @@ public class PeerCoordinator implements PeerListener
peerCount = 0;
}
while (removed.size() > 0) {
Peer peer = (Peer)removed.remove(0);
while (!removed.isEmpty()) {
Peer peer = removed.remove(0);
peer.disconnect();
removePeerFromPieces(peer);
}
@ -336,9 +342,9 @@ public class PeerCoordinator implements PeerListener
// caller must synchronize on peers
private static Peer peerIDInList(PeerID pid, List peers)
{
Iterator it = peers.iterator();
Iterator<Peer> it = peers.iterator();
while (it.hasNext()) {
Peer cur = (Peer)it.next();
Peer cur = it.next();
if (pid.sameID(cur.getPeerID()))
return cur;
}
@ -402,21 +408,21 @@ public class PeerCoordinator implements PeerListener
// linked list will contain all interested peers that we choke.
// At the start are the peers that have us unchoked at the end the
// other peer that are interested, but are choking us.
List interested = new LinkedList();
List<Peer> interested = new LinkedList();
synchronized (peers) {
int count = 0;
int unchokedCount = 0;
int maxUploaders = allowedUploaders();
Iterator it = peers.iterator();
Iterator<Peer> it = peers.iterator();
while (it.hasNext())
{
Peer peer = (Peer)it.next();
Peer peer = it.next();
if (peer.isChoking() && peer.isInterested())
{
count++;
if (uploaders < maxUploaders)
{
if (!peer.isChoked())
if (peer.isInteresting() && !peer.isChoked())
interested.add(unchokedCount++, peer);
else
interested.add(peer);
@ -424,9 +430,9 @@ public class PeerCoordinator implements PeerListener
}
}
while (uploaders < maxUploaders && interested.size() > 0)
while (uploaders < maxUploaders && !interested.isEmpty())
{
Peer peer = (Peer)interested.remove(0);
Peer peer = interested.remove(0);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unchoke: " + peer);
peer.setChoking(false);
@ -471,10 +477,10 @@ public class PeerCoordinator implements PeerListener
synchronized(wantedPieces)
{
Iterator it = wantedPieces.iterator();
Iterator<Piece> it = wantedPieces.iterator();
while (it.hasNext())
{
Piece p = (Piece)it.next();
Piece p = it.next();
int i = p.getId();
if (bitfield.get(i)) {
p.addPeer(peer);
@ -485,6 +491,13 @@ public class PeerCoordinator implements PeerListener
return false;
}
/**
* This should be somewhat less than the max conns per torrent,
* but not too much less, so a torrent doesn't get stuck near the end.
* @since 0.7.14
*/
private static final int END_GAME_THRESHOLD = 8;
/**
* Returns one of pieces in the given BitField that is still wanted or
* -1 if none of the given pieces are wanted.
@ -501,11 +514,11 @@ public class PeerCoordinator implements PeerListener
{
Piece piece = null;
Collections.sort(wantedPieces); // Sort in order of rarest first.
List requested = new ArrayList();
Iterator it = wantedPieces.iterator();
List<Piece> requested = new ArrayList();
Iterator<Piece> it = wantedPieces.iterator();
while (piece == null && it.hasNext())
{
Piece p = (Piece)it.next();
Piece p = it.next();
if (havePieces.get(p.getId()) && !p.isRequested())
{
piece = p;
@ -518,12 +531,17 @@ public class PeerCoordinator implements PeerListener
//Only request a piece we've requested before if there's no other choice.
if (piece == null) {
// AND if there are almost no wanted pieces left (real end game).
// If we do end game all the time, we generate lots of extra traffic
// when the seeder is super-slow and all the peers are "caught up"
if (wantedPieces.size() > END_GAME_THRESHOLD)
return -1; // nothing to request and not in end game
// let's not all get on the same piece
Collections.shuffle(requested);
Iterator it2 = requested.iterator();
Iterator<Piece> it2 = requested.iterator();
while (piece == null && it2.hasNext())
{
Piece p = (Piece)it2.next();
Piece p = it2.next();
if (havePieces.get(p.getId()))
{
piece = p;
@ -643,11 +661,11 @@ public class PeerCoordinator implements PeerListener
// Disconnect from other seeders when we get the last piece
synchronized(peers)
{
List toDisconnect = new ArrayList();
Iterator it = peers.iterator();
List<Peer> toDisconnect = new ArrayList();
Iterator<Peer> it = peers.iterator();
while (it.hasNext())
{
Peer p = (Peer)it.next();
Peer p = it.next();
if (p.isConnected())
{
if (completed() && p.isCompleted())
@ -659,7 +677,7 @@ public class PeerCoordinator implements PeerListener
it = toDisconnect.iterator();
while (it.hasNext())
{
Peer p = (Peer)it.next();
Peer p = it.next();
p.disconnect(true);
}
}
@ -725,8 +743,8 @@ public class PeerCoordinator implements PeerListener
*/
public void removePeerFromPieces(Peer peer) {
synchronized(wantedPieces) {
for(Iterator iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece piece = (Piece)iter.next();
for(Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece piece = iter.next();
piece.removePeer(peer);
}
}
@ -780,8 +798,8 @@ public class PeerCoordinator implements PeerListener
}
synchronized(wantedPieces)
{
for(Iterator iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece piece = (Piece)iter.next();
for(Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece piece = iter.next();
if (piece.getId() == savedRequest.piece) {
Request req = savedRequest;
piece.setRequested(true);
@ -806,9 +824,9 @@ public class PeerCoordinator implements PeerListener
// see if anybody else is requesting
synchronized (peers)
{
Iterator it = peers.iterator();
Iterator<Peer> it = peers.iterator();
while (it.hasNext()) {
Peer p = (Peer)it.next();
Peer p = it.next();
if (p.equals(peer))
continue;
if (p.state == null)
@ -826,9 +844,9 @@ public class PeerCoordinator implements PeerListener
// nobody is, so mark unrequested
synchronized(wantedPieces)
{
Iterator it = wantedPieces.iterator();
Iterator<Piece> it = wantedPieces.iterator();
while (it.hasNext()) {
Piece p = (Piece)it.next();
Piece p = it.next();
if (p.getId() == piece) {
p.setRequested(false);
if (_log.shouldLog(Log.DEBUG))

View File

@ -24,11 +24,12 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
class PeerState
{
private Log _log = new Log(PeerState.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
final Peer peer;
final PeerListener listener;
final MetaInfo metainfo;
@ -152,7 +153,16 @@ class PeerState
// XXX - Check for weird bitfield and disconnect?
bitfield = new BitField(bitmap, metainfo.getPieces());
}
setInteresting(listener.gotBitField(peer, bitfield));
boolean interest = listener.gotBitField(peer, bitfield);
setInteresting(interest);
if (bitfield.complete() && !interest) {
// They are seeding and we are seeding,
// why did they contact us? (robert)
// Dump them quick before we send our whole bitmap
if (_log.shouldLog(Log.WARN))
_log.warn("Disconnecting seed that connects to seeds: " + peer);
peer.disconnect(true);
}
}
void requestMessage(int piece, int begin, int length)
@ -186,6 +196,7 @@ class PeerState
// Limit total pipelined requests to MAX_PIPELINE bytes
// to conserve memory and prevent DOS
// Todo: limit number of requests also? (robert 64 x 4KB)
if (out.queuedBytes() + length > MAX_PIPELINE_BYTES)
{
if (_log.shouldLog(Log.WARN))
@ -512,8 +523,10 @@ class PeerState
_log.debug(peer + " requests " + outstandingRequests);
}
// Starts requesting first chunk of next piece. Returns true if
// something has been added to the requests, false otherwise.
/**
* Starts requesting first chunk of next piece. Returns true if
* something has been added to the requests, false otherwise.
*/
private boolean requestNextPiece()
{
// Check that we already know what the other side has.
@ -545,6 +558,15 @@ class PeerState
if (nextPiece != -1
&& (lastRequest == null || lastRequest.piece != nextPiece))
{
// Fail safe to make sure we are interested
// When we transition into the end game we may not be interested...
if (!interesting) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " transition to end game, setting interesting");
interesting = true;
out.sendInterest(true);
}
int piece_length = metainfo.getPieceLength(nextPiece);
//Catch a common place for OOMs esp. on 1MB pieces
byte[] bs;

View File

@ -321,7 +321,7 @@ public class Snark
// sixteen random bytes.
byte snark = (((3 + 7 + 10) * (1000 - 8)) / 992) - 17;
id = new byte[20];
Random random = new Random();
Random random = I2PAppContext.getGlobalContext().random();
int i;
for (i = 0; i < 9; i++)
id[i] = 0;
@ -618,14 +618,14 @@ public class Snark
command_interpreter = false;
i++;
}
else if (args[i].equals("--eepproxy"))
{
String proxyHost = args[i+1];
String proxyPort = args[i+2];
if (!configured)
util.setProxy(proxyHost, Integer.parseInt(proxyPort));
i += 3;
}
//else if (args[i].equals("--eepproxy"))
// {
// String proxyHost = args[i+1];
// String proxyPort = args[i+2];
// if (!configured)
// util.setProxy(proxyHost, Integer.parseInt(proxyPort));
// i += 3;
// }
else if (args[i].equals("--i2cp"))
{
String i2cpHost = args[i+1];
@ -734,7 +734,7 @@ public class Snark
//if (debug >= INFO && t != null)
// t.printStackTrace();
stopTorrent();
throw new RuntimeException("die bart die");
throw new RuntimeException(s + (t == null ? "" : ": " + t));
}
/**

View File

@ -29,8 +29,8 @@ public class SnarkManager implements Snark.CompleteListener {
private static SnarkManager _instance = new SnarkManager();
public static SnarkManager instance() { return _instance; }
/** map of (canonical) filename to Snark instance (unsynchronized) */
private final Map _snarks;
/** map of (canonical) filename of the .torrent file to Snark instance (unsynchronized) */
private final Map<String, Snark> _snarks;
private final Object _addSnarkLock;
private /* FIXME final FIXME */ File _configFile;
private Properties _config;
@ -40,12 +40,14 @@ public class SnarkManager implements Snark.CompleteListener {
private I2PSnarkUtil _util;
private PeerCoordinatorSet _peerCoordinatorSet;
private ConnectionAcceptor _connectionAcceptor;
private Thread _monitor;
private boolean _running;
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
public static final String PROP_I2CP_OPTS = "i2psnark.i2cpOptions";
public static final String PROP_EEP_HOST = "i2psnark.eepHost";
public static final String PROP_EEP_PORT = "i2psnark.eepPort";
//public static final String PROP_EEP_HOST = "i2psnark.eepHost";
//public static final String PROP_EEP_PORT = "i2psnark.eepPort";
public static final String PROP_UPLOADERS_TOTAL = "i2psnark.uploaders.total";
public static final String PROP_UPBW_MAX = "i2psnark.upbw.max";
public static final String PROP_DIR = "i2psnark.dir";
@ -57,10 +59,11 @@ public class SnarkManager implements Snark.CompleteListener {
public static final String DEFAULT_AUTO_START = "false";
public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
public static final String DEFAULT_LINK_PREFIX = "file:///";
public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
public static final int MIN_UP_BW = 2;
public static final int DEFAULT_MAX_UP_BW = 10;
public static final int DEFAULT_STARTUP_DELAY = 3;
private SnarkManager() {
_snarks = new HashMap();
_addSnarkLock = new Object();
@ -78,15 +81,22 @@ public class SnarkManager implements Snark.CompleteListener {
* for i2cp host/port or i2psnark.dir
*/
public void start() {
_running = true;
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util);
int minutes = getStartupDelayMinutes();
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
monitor.setDaemon(true);
monitor.start();
_messages.add(_("Adding torrents in {0} minutes", minutes));
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
_monitor.start();
_context.addShutdownTask(new SnarkManagerShutdown());
}
public void stop() {
_running = false;
_monitor.interrupt();
_connectionAcceptor.halt();
(new SnarkManagerShutdown()).run();
}
/** hook to I2PSnarkUtil for the servlet */
public I2PSnarkUtil util() { return _util; }
@ -115,7 +125,9 @@ public class SnarkManager implements Snark.CompleteListener {
public String linkPrefix() {
return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar);
}
private int getStartupDelayMinutes() { return 3; }
private int getStartupDelayMinutes() {
return Integer.valueOf(_config.getProperty(PROP_STARTUP_DELAY)).intValue();
}
public File getDataDir() {
String dir = _config.getProperty(PROP_DIR, "i2psnark");
File f = new File(dir);
@ -148,16 +160,19 @@ public class SnarkManager implements Snark.CompleteListener {
_config.setProperty(PROP_I2CP_PORT, "7654");
if (!_config.containsKey(PROP_I2CP_OPTS))
_config.setProperty(PROP_I2CP_OPTS, "inbound.length=2 inbound.lengthVariance=0 outbound.length=2 outbound.lengthVariance=0 inbound.quantity=3 outbound.quantity=3");
if (!_config.containsKey(PROP_EEP_HOST))
_config.setProperty(PROP_EEP_HOST, "127.0.0.1");
if (!_config.containsKey(PROP_EEP_PORT))
_config.setProperty(PROP_EEP_PORT, "4444");
//if (!_config.containsKey(PROP_EEP_HOST))
// _config.setProperty(PROP_EEP_HOST, "127.0.0.1");
//if (!_config.containsKey(PROP_EEP_PORT))
// _config.setProperty(PROP_EEP_PORT, "4444");
if (!_config.containsKey(PROP_UPLOADERS_TOTAL))
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + Snark.MAX_TOTAL_UPLOADERS);
if (!_config.containsKey(PROP_DIR))
_config.setProperty(PROP_DIR, "i2psnark");
if (!_config.containsKey(PROP_AUTO_START))
_config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
if (!_config.containsKey(PROP_STARTUP_DELAY))
_config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY);
updateConfig();
}
@ -189,15 +204,17 @@ public class SnarkManager implements Snark.CompleteListener {
_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)
_util.setProxy(eepHost, eepPort);
//String eepHost = _config.getProperty(PROP_EEP_HOST);
//int eepPort = getInt(PROP_EEP_PORT, 4444);
//if (eepHost != null)
// _util.setProxy(eepHost, eepPort);
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
_util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY));
String ot = _config.getProperty(I2PSnarkUtil.PROP_OPENTRACKERS);
if (ot != null)
_util.setOpenTrackerString(ot);
// FIXME set util use open trackers property somehow
getDataDir().mkdirs();
}
@ -212,23 +229,24 @@ public class SnarkManager implements Snark.CompleteListener {
return defaultVal;
}
public void updateConfig(String dataDir, boolean autoStart, String seedPct, String eepHost,
public void updateConfig(String dataDir, boolean autoStart, String startDelay, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) {
boolean changed = false;
if (eepHost != null) {
int port = _util.getEepProxyPort();
try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
String host = _util.getEepProxyHost();
if ( (eepHost.trim().length() > 0) && (port > 0) &&
((!host.equals(eepHost) || (port != _util.getEepProxyPort()) )) ) {
_util.setProxy(eepHost, port);
changed = true;
_config.setProperty(PROP_EEP_HOST, eepHost);
_config.setProperty(PROP_EEP_PORT, eepPort+"");
addMessage("EepProxy location changed to " + eepHost + ":" + port);
}
}
//if (eepHost != null) {
// // unused, we use socket eepget
// int port = _util.getEepProxyPort();
// try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
// String host = _util.getEepProxyHost();
// if ( (eepHost.trim().length() > 0) && (port > 0) &&
// ((!host.equals(eepHost) || (port != _util.getEepProxyPort()) )) ) {
// _util.setProxy(eepHost, port);
// changed = true;
// _config.setProperty(PROP_EEP_HOST, eepHost);
// _config.setProperty(PROP_EEP_PORT, eepPort+"");
// addMessage("EepProxy location changed to " + eepHost + ":" + port);
// }
//}
if (upLimit != null) {
int limit = _util.getMaxUploaders();
try { limit = Integer.parseInt(upLimit); } catch (NumberFormatException nfe) {}
@ -237,9 +255,9 @@ public class SnarkManager implements Snark.CompleteListener {
_util.setMaxUploaders(limit);
changed = true;
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit);
addMessage("Total uploaders limit changed to " + limit);
addMessage(_("Total uploaders limit changed to {0}", limit));
} else {
addMessage("Minimum total uploaders limit is " + Snark.MIN_TOTAL_UPLOADERS);
addMessage(_("Minimum total uploaders limit is {0}", Snark.MIN_TOTAL_UPLOADERS));
}
}
}
@ -251,13 +269,25 @@ public class SnarkManager implements Snark.CompleteListener {
_util.setMaxUpBW(limit);
changed = true;
_config.setProperty(PROP_UPBW_MAX, "" + limit);
addMessage("Up BW limit changed to " + limit + "KBps");
addMessage(_("Up BW limit changed to {0}KBps", limit));
} else {
addMessage("Minimum Up BW limit is " + MIN_UP_BW + "KBps");
addMessage(_("Minimum up bandwidth limit is {0}KBps", MIN_UP_BW));
}
}
}
if (i2cpHost != null) {
if (startDelay != null){
int minutes = _util.getStartupDelay();
try { minutes = Integer.parseInt(startDelay); } catch (NumberFormatException nfe) {}
if ( minutes != _util.getStartupDelay()) {
_util.setStartupDelay(minutes);
changed = true;
_config.setProperty(PROP_STARTUP_DELAY, "" + minutes);
addMessage(_("Startup delay limit changed to {0} minutes", minutes));
}
}
if (i2cpHost != null) {
int oldI2CPPort = _util.getI2CPPort();
String oldI2CPHost = _util.getI2CPHost();
int port = oldI2CPPort;
@ -297,27 +327,30 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
if (snarksActive) {
addMessage("Cannot change the I2CP settings while torrents are active");
Properties p = new Properties();
p.putAll(opts);
_util.setI2CPConfig(i2cpHost, port, p);
addMessage(_("I2CP and tunnel changes will take effect after stopping all torrents"));
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
+ "] oldOpts [" + oldOpts + "]");
} else {
if (_util.connected()) {
_util.disconnect();
addMessage("Disconnecting old I2CP destination");
addMessage(_("Disconnecting old I2CP destination"));
}
Properties p = new Properties();
p.putAll(opts);
addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")");
addMessage(_("I2CP settings changed to {0}", i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")"));
_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");
addMessage(_("Unable to connect with the new settings, reverting to the old I2CP settings"));
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
ok = _util.connect();
if (!ok)
addMessage("Unable to reconnect with the old settings!");
addMessage(_("Unable to reconnect with the old settings!"));
} else {
addMessage("Reconnected on the new I2CP destination");
addMessage(_("Reconnected on the new I2CP destination"));
_config.setProperty(PROP_I2CP_HOST, i2cpHost.trim());
_config.setProperty(PROP_I2CP_PORT, "" + port);
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
@ -328,7 +361,7 @@ public class SnarkManager implements Snark.CompleteListener {
Snark snark = getTorrent(name);
if ( (snark != null) && (snark.acceptor != null) ) {
snark.acceptor.restart();
addMessage("I2CP listener restarted for " + snark.meta.getName());
addMessage(_("I2CP listener restarted for \"{0}\"", snark.meta.getName()));
}
}
}
@ -338,26 +371,32 @@ public class SnarkManager implements Snark.CompleteListener {
}
if (shouldAutoStart() != autoStart) {
_config.setProperty(PROP_AUTO_START, autoStart + "");
addMessage("Adjusted autostart to " + autoStart);
if (autoStart)
addMessage(_("Enabled autostart"));
else
addMessage(_("Disabled autostart"));
changed = true;
}
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect.");
if (useOpenTrackers)
addMessage(_("Enabled open trackers - torrent restart required to take effect."));
else
addMessage(_("Disabled open trackers - torrent restart required to take effect."));
changed = true;
}
if (openTrackers != null) {
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
_util.setOpenTrackerString(openTrackers);
addMessage("Open Tracker list changed - torrent restart required to take effect.");
addMessage(_("Open Tracker list changed - torrent restart required to take effect."));
changed = true;
}
}
if (changed) {
saveConfig();
} else {
addMessage("Configuration unchanged.");
addMessage(_("Configuration unchanged."));
}
}
@ -367,7 +406,7 @@ public class SnarkManager implements Snark.CompleteListener {
DataHelper.storeProps(_config, _configFile);
}
} catch (IOException ioe) {
addMessage("Unable to save the config to '" + _configFile.getAbsolutePath() + "'.");
addMessage(_("Unable to save the config to {0}", _configFile.getAbsolutePath()));
}
}
@ -376,19 +415,37 @@ public class SnarkManager implements Snark.CompleteListener {
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
private static final int MAX_FILES_PER_TORRENT = 512;
/** set of filenames that we are dealing with */
public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
/** set of canonical .torrent filenames that we are dealing with */
public Set<String> listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
/**
* Grab the torrent given the (canonical) filename
* Grab the torrent given the (canonical) filename of the .torrent file
* @return Snark or null
*/
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
/**
* Grab the torrent given the base name of the storage
* @return Snark or null
* @since 0.7.14
*/
public Snark getTorrentByBaseName(String filename) {
synchronized (_snarks) {
for (Snark s : _snarks.values()) {
if (s.storage.getBaseName().equals(filename))
return s;
}
}
return null;
}
public void addTorrent(String filename) { addTorrent(filename, false); }
public void addTorrent(String filename, boolean dontAutoStart) {
if ((!dontAutoStart) && !_util.connected()) {
addMessage("Connecting to I2P");
addMessage(_("Connecting to I2P"));
boolean ok = _util.connect();
if (!ok) {
addMessage("Error connecting to I2P - check your I2CP settings!");
addMessage(_("Error connecting to I2P - check your I2CP settings!"));
return;
}
}
@ -397,7 +454,7 @@ public class SnarkManager implements Snark.CompleteListener {
filename = sfile.getCanonicalPath();
} catch (IOException ioe) {
_log.error("Unable to add the torrent " + filename, ioe);
addMessage("ERR: Could not add the torrent '" + filename + "': " + ioe.getMessage());
addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe.getMessage());
return;
}
File dataDir = getDataDir();
@ -417,10 +474,27 @@ public class SnarkManager implements Snark.CompleteListener {
FileInputStream fis = null;
try {
fis = new FileInputStream(sfile);
} catch (IOException ioe) {
// catch this here so we don't try do delete it below
addMessage(_("Cannot open \"{0}\"", sfile.getName()) + ": " + ioe.getMessage());
return;
}
try {
MetaInfo info = new MetaInfo(fis);
fis.close();
fis = null;
try {
fis.close();
fis = null;
} catch (IOException e) {}
if (!TrackerClient.isValidAnnounce(info.getAnnounce())) {
if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
addMessage(_("Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only", info.getName()));
} else {
addMessage(_("Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!", info.getName()));
dontAutoStart = true;
}
}
String rejectMessage = locked_validateTorrent(info);
if (rejectMessage != null) {
sfile.delete();
@ -436,7 +510,7 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
} catch (IOException ioe) {
addMessage("Torrent in " + sfile.getName() + " is invalid: " + ioe.getMessage());
addMessage(_("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage());
if (sfile.exists())
sfile.delete();
return;
@ -451,9 +525,9 @@ public class SnarkManager implements Snark.CompleteListener {
File f = new File(filename);
if (!dontAutoStart && shouldAutoStart()) {
torrent.startTorrent();
addMessage("Torrent added and started: '" + f.getName() + "'.");
addMessage(_("Torrent added and started: \"{0}\"", f.getName()));
} else {
addMessage("Torrent added: '" + f.getName() + "'.");
addMessage(_("Torrent added: \"{0}\"", f.getName()));
}
}
@ -544,24 +618,22 @@ public class SnarkManager implements Snark.CompleteListener {
saveConfig();
}
/**
* Warning - does not validate announce URL - use TrackerClient.isValidAnnounce()
*/
private String locked_validateTorrent(MetaInfo info) throws IOException {
String announce = info.getAnnounce();
// basic validation of url
if ((!announce.startsWith("http://")) ||
(announce.indexOf(".i2p/") < 0)) // need to do better than this
return "Non-i2p tracker in " + info.getName() + ", deleting it from our list of trackers!";
List files = info.getFiles();
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
return "Too many files in " + info.getName() + " (" + files.size() + "), deleting it!";
return _("Too many files in \"{0}\" ({1}), deleting it!", info.getName(), files.size());
} else if ( (files == null) && (info.getName().endsWith(".torrent")) ) {
return "Torrent file " + info.getName() + " cannot end in '.torrent', deleting it!";
return _("Torrent file \"{0}\" cannot end in \".torrent\", deleting it!", info.getName());
} else if (info.getPieces() <= 0) {
return "No pieces in " + info.getName() + "? deleting it!";
return _("No pieces in \"{0}\", deleting it!", info.getName());
} else if (info.getPieces() > Storage.MAX_PIECES) {
return "Too many pieces in " + info.getName() + ", limit is " + Storage.MAX_PIECES + ", deleting it!";
return _("Too many pieces in \"{0}\", limit is {1}, deleting it!", info.getName(), Storage.MAX_PIECES);
} else if (info.getPieceLength(0) > Storage.MAX_PIECE_SIZE) {
return "Pieces are too large in " + info.getName() + " (" + DataHelper.formatSize(info.getPieceLength(0)) +
"B, limit is " + DataHelper.formatSize(Storage.MAX_PIECE_SIZE) + "B), deleting it.";
return _("Pieces are too large in \"{0}\" ({1}B), deleting it.", info.getName(), DataHelper.formatSize2(info.getPieceLength(0))) + ' ' +
_("Limit is {0}B", DataHelper.formatSize2(Storage.MAX_PIECE_SIZE));
} else if (info.getTotalLength() > Storage.MAX_TOTAL_SIZE) {
System.out.println("torrent info: " + info.toString());
List lengths = info.getLengths();
@ -569,8 +641,7 @@ public class SnarkManager implements Snark.CompleteListener {
for (int i = 0; i < lengths.size(); i++)
System.out.println("File " + i + " is " + lengths.get(i) + " long.");
return "Torrents larger than " + DataHelper.formatSize(Storage.MAX_TOTAL_SIZE) +
"B are not supported yet (because we're paranoid): " + info.getName() + ", deleting it!";
return _("Torrents larger than {0}B are not supported yet, deleting \"{1}\"", Storage.MAX_TOTAL_SIZE, info.getName());
} else {
// ok
return null;
@ -586,7 +657,7 @@ public class SnarkManager implements Snark.CompleteListener {
filename = sfile.getCanonicalPath();
} catch (IOException ioe) {
_log.error("Unable to remove the torrent " + filename, ioe);
addMessage("ERR: Could not remove the torrent '" + filename + "': " + ioe.getMessage());
addMessage(_("Error: Could not remove the torrent {0}", filename) + ": " + ioe.getMessage());
return null;
}
int remaining = 0;
@ -607,7 +678,7 @@ public class SnarkManager implements Snark.CompleteListener {
////_util.
}
if (!wasStopped)
addMessage("Torrent stopped: '" + sfile.getName() + "'.");
addMessage(_("Torrent stopped: \"{0}\"", sfile.getName()));
}
return torrent;
}
@ -622,7 +693,7 @@ public class SnarkManager implements Snark.CompleteListener {
torrentFile.delete();
if (torrent.storage != null)
removeTorrentStatus(torrent.storage.getMetaInfo());
addMessage("Torrent removed: '" + torrentFile.getName() + "'.");
addMessage(_("Torrent removed: \"{0}\"", torrentFile.getName()));
}
}
@ -655,7 +726,7 @@ public class SnarkManager implements Snark.CompleteListener {
public void torrentComplete(Snark snark) {
File f = new File(snark.torrent);
long len = snark.meta.getTotalLength();
addMessage("Download finished: " + f.getName() + " (size: " + DataHelper.formatSize(len) + "B)");
addMessage(_("Download finished: \"{0}\"", f.getName()) + " (" + _("size: {0}B", DataHelper.formatSize2(len)) + ')');
updateStatus(snark);
}
@ -683,7 +754,7 @@ public class SnarkManager implements Snark.CompleteListener {
// already known. noop
} else {
if (shouldAutoStart() && !_util.connect())
addMessage("Unable to connect to I2P!");
addMessage(_("Unable to connect to I2P!"));
addTorrent((String)foundNames.get(i), !shouldAutoStart());
}
}
@ -699,6 +770,21 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
/** translate */
private String _(String s) {
return _util.getString(s);
}
/** translate */
private String _(String s, Object o) {
return _util.getString(s, o);
}
/** translate */
private String _(String s, Object o, Object o2) {
return _util.getString(s, o, o2);
}
/**
* "name", "announceURL=websiteURL" pairs
*/

View File

@ -286,6 +286,50 @@ public class Storage
return needed == 0;
}
/**
* @param file canonical path (non-directory)
* @return number of bytes remaining; -1 if unknown file
* @since 0.7.14
*/
public long remaining(String file) {
long bytes = 0;
for (int i = 0; i < rafs.length; i++) {
File f = RAFfile[i];
// use canonical in case snark dir or sub dirs are symlinked
String canonical = null;
if (f != null) {
try {
canonical = f.getCanonicalPath();
} catch (IOException ioe) {
f = null;
}
}
if (f != null && canonical.equals(file)) {
if (complete())
return 0;
int psz = metainfo.getPieceLength(0);
long start = bytes;
long end = start + lengths[i];
int pc = (int) (bytes / psz);
long rv = 0;
if (!bitfield.get(pc))
rv = Math.min(psz - (start % psz), lengths[i]);
int pieces = metainfo.getPieces();
for (int j = pc + 1; (((long)j) * psz) < end && j < pieces; j++) {
if (!bitfield.get(j)) {
if (((long)(j+1))*psz < end)
rv += psz;
else
rv += end - (((long)j) * psz);
}
}
return rv;
}
bytes += lengths[i];
}
return -1;
}
/**
* The BitField that tells which pieces this storage contains.
* Do not change this since this is the current state of the storage.
@ -295,6 +339,18 @@ public class Storage
return bitfield;
}
/**
* The base file or directory name of the data,
* as specified in the .torrent file, but filtered to remove
* illegal characters. This is where the data actually is,
* relative to the snark base dir.
*
* @since 0.7.14
*/
public String getBaseName() {
return filterName(metainfo.getName());
}
/**
* Creates (and/or checks) all files from the metainfo file list.
*/
@ -420,13 +476,29 @@ public class Storage
}
}
private static final char[] ILLEGAL = new char[] {
'<', '>', ':', '"', '/', '\\', '|', '?', '*',
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
/**
* Removes 'suspicious' characters from the give file name.
* Removes 'suspicious' characters from the given file name.
* http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
*/
private static String filterName(String name)
{
// XXX - Is this enough?
return name.replace(File.separatorChar, '_');
if (name.equals(".") || name.equals(" "))
return "_";
String rv = name;
if (rv.startsWith("."))
rv = '_' + rv.substring(1);
if (rv.endsWith(".") || rv.endsWith(" "))
rv = rv.substring(0, rv.length() - 1) + '_';
for (int i = 0; i < ILLEGAL.length; i++) {
if (rv.indexOf(ILLEGAL[i]) >= 0)
rv = rv.replace(ILLEGAL[i], '_');
}
return rv;
}
private File createFileFromNames(File base, List names) throws IOException
@ -577,6 +649,9 @@ public class Storage
if (rafs == null) return;
for (int i = 0; i < rafs.length; i++)
{
// if we had an IOE in check(), the RAFlock may be null
if (RAFlock[i] == null)
continue;
try {
synchronized(RAFlock[i]) {
closeRAF(i);

View File

@ -24,6 +24,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@ -31,6 +33,7 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
@ -42,7 +45,7 @@ import net.i2p.util.Log;
*/
public class TrackerClient extends I2PAppThread
{
private static final Log _log = new Log(TrackerClient.class);
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(TrackerClient.class);
private static final String NO_EVENT = "";
private static final String STARTED_EVENT = "started";
private static final String COMPLETED_EVENT = "completed";
@ -123,13 +126,19 @@ public class TrackerClient extends I2PAppThread
// followed by the secondary open trackers
// It's painful, but try to make sure if an open tracker is also
// the primary tracker, that we don't add it twice.
// todo: check for b32 matches as well
trackers = new ArrayList(2);
trackers.add(new Tracker(meta.getAnnounce(), true));
String primary = meta.getAnnounce();
if (isValidAnnounce(primary)) {
trackers.add(new Tracker(meta.getAnnounce(), true));
} else {
_log.warn("Skipping invalid or non-i2p announce: " + primary);
}
List tlist = _util.getOpenTrackers();
if (tlist != null) {
for (int i = 0; i < tlist.size(); i++) {
String url = (String)tlist.get(i);
if (!url.startsWith("http://")) {
if (!isValidAnnounce(url)) {
_log.error("Bad announce URL: [" + url + "]");
continue;
}
@ -138,22 +147,29 @@ public class TrackerClient extends I2PAppThread
_log.error("Bad announce URL: [" + url + "]");
continue;
}
if (meta.getAnnounce().startsWith(url.substring(0, slash)))
if (primary.startsWith(url.substring(0, slash)))
continue;
String dest = _util.lookup(url.substring(7, slash));
if (dest == null) {
_log.error("Announce host unknown: [" + url + "]");
_log.error("Announce host unknown: [" + url.substring(7, slash) + "]");
continue;
}
if (meta.getAnnounce().startsWith("http://" + dest))
if (primary.startsWith("http://" + dest))
continue;
if (meta.getAnnounce().startsWith("http://i2p/" + dest))
if (primary.startsWith("http://i2p/" + dest))
continue;
trackers.add(new Tracker(url, false));
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
}
}
if (tlist.isEmpty()) {
// FIXME really need to get this message to the gui
stop = true;
_log.error("No valid trackers for infoHash: " + infoHash);
return;
}
long uploaded = coordinator.getUploaded();
long downloaded = coordinator.getDownloaded();
long left = coordinator.getLeft();
@ -167,7 +183,7 @@ public class TrackerClient extends I2PAppThread
boolean runStarted = false;
boolean firstTime = true;
int consecutiveFails = 0;
Random r = new Random();
Random r = I2PAppContext.getGlobalContext().random();
while(!stop)
{
try
@ -243,7 +259,7 @@ public class TrackerClient extends I2PAppThread
tr.started = true;
Set peers = info.getPeers();
tr.seenPeers = peers.size();
tr.seenPeers = info.getPeerCount();
if (coordinator.trackerSeenPeers < tr.seenPeers) // update rising number quickly
coordinator.trackerSeenPeers = tr.seenPeers;
if ( (left > 0) && (!completed) ) {
@ -254,6 +270,7 @@ public class TrackerClient extends I2PAppThread
Iterator it = ordered.iterator();
while (it.hasNext()) {
Peer cur = (Peer)it.next();
// FIXME if id == us || dest == us continue;
// only delay if we actually make an attempt to add peer
if(coordinator.addPeer(cur)) {
int delay = DELAY_MUL;
@ -315,7 +332,7 @@ public class TrackerClient extends I2PAppThread
// try to contact everybody we can
// Don't try to restart I2CP connection just to say goodbye
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
if (!verifyConnected()) return;
if (!_util.connected()) return;
Tracker tr = (Tracker)iter.next();
if (tr.started && (!tr.stop) && tr.trackerProblems == null)
doRequest(tr, infoHash, peerID, uploaded,
@ -341,6 +358,10 @@ public class TrackerClient extends I2PAppThread
+ "&downloaded=" + downloaded
+ "&left=" + left
+ ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
if (left <= 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
s += "&numwant=0";
else
s += "&numwant=" + _util.getMaxConnections();
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
tr.lastRequestTime = System.currentTimeMillis();
@ -370,8 +391,13 @@ public class TrackerClient extends I2PAppThread
}
/**
* Very lazy byte[] to URL encoder. Just encodes everything, even
* "normal" chars.
* Very lazy byte[] to URL encoder. Just encodes almost everything, even
* some "normal" chars.
* By not encoding about 1/4 of the chars, we make random data like hashes about 16% smaller.
*
* RFC1738: 0-9a-zA-Z$-_.+!*'(),
* Us: 0-9a-zA-Z
*
*/
public static String urlencode(byte[] bs)
{
@ -379,16 +405,38 @@ public class TrackerClient extends I2PAppThread
for (int i = 0; i < bs.length; i++)
{
int c = bs[i] & 0xFF;
sb.append('%');
if (c < 16)
sb.append('0');
sb.append(Integer.toHexString(c));
if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z')) {
sb.append((char)c);
} else {
sb.append('%');
if (c < 16)
sb.append('0');
sb.append(Integer.toHexString(c));
}
}
return sb.toString();
}
private class Tracker
/**
* @return true for i2p hosts only
* @since 0.7.12
*/
static boolean isValidAnnounce(String ann) {
URL url;
try {
url = new URL(ann);
} catch (MalformedURLException mue) {
return false;
}
return url.getProtocol().equals("http") &&
(url.getHost().endsWith(".i2p") || url.getHost().equals("i2p")) &&
url.getPort() < 0;
}
private static class Tracker
{
String announce;
boolean isPrimary;

View File

@ -23,6 +23,7 @@ package org.klomp.snark;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -37,6 +38,8 @@ public class TrackerInfo
private final String failure_reason;
private final int interval;
private final Set peers;
private int complete;
private int incomplete;
public TrackerInfo(InputStream in, byte[] my_id, MetaInfo metainfo)
throws IOException
@ -68,11 +71,26 @@ public class TrackerInfo
throw new InvalidBEncodingException("No interval given");
else
interval = beInterval.getInt();
BEValue bePeers = (BEValue)m.get("peers");
if (bePeers == null)
throw new InvalidBEncodingException("No peer list");
peers = Collections.EMPTY_SET;
else
peers = getPeers(bePeers.getList(), my_id, metainfo);
BEValue bev = (BEValue)m.get("complete");
if (bev != null) try {
complete = bev.getInt();
if (complete < 0)
complete = 0;
} catch (InvalidBEncodingException ibe) {}
bev = (BEValue)m.get("incomplete");
if (bev != null) try {
incomplete = bev.getInt();
if (incomplete < 0)
incomplete = 0;
} catch (InvalidBEncodingException ibe) {}
}
}
@ -115,6 +133,12 @@ public class TrackerInfo
return peers;
}
public int getPeerCount()
{
int pc = peers == null ? 0 : peers.size();
return Math.max(pc, complete + incomplete - 1);
}
public String getFailureReason()
{
return failure_reason;
@ -132,6 +156,8 @@ public class TrackerInfo
return "TrackerInfo[FAILED: " + failure_reason + "]";
else
return "TrackerInfo[interval=" + interval
+ (complete > 0 ? (", complete=" + complete) : "" )
+ (incomplete > 0 ? (", incomplete=" + incomplete) : "" )
+ ", peers=" + peers + "]";
}
}

View File

@ -279,7 +279,9 @@ public class BDecoder
public BEValue bdecodeMap() throws IOException
{
int c = getNextIndicator();
if (c != 'd')
if (c == '<')
throw new InvalidBEncodingException("Expected a .torrent metainfo file but found HTML? Check URL or file!");
else if (c != 'd')
throw new InvalidBEncodingException("Expected 'd', not '"
+ (char)c + "'");
indicator = 0;

View File

@ -179,7 +179,7 @@ public class BEValue
if (value instanceof byte[])
{
byte[] bs = (byte[])value;
// XXX - Stupid heuristic...
// XXX - Stupid heuristic... and not UTF-8
if (bs.length <= 12)
valueString = new String(bs);
else

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,23 @@
<Arg>webapps/i2psnark.war</Arg>
</Call>
<!-- this is so we can find the css -->
<Call name="addContext">
<Arg>
<New class="org.mortbay.http.HttpContext">
<Set name="contextPath">/themes</Set>
<Set name="resourceBase">./docs/themes</Set>
<Call name="addHandler">
<Arg>
<New class="org.mortbay.http.handler.ResourceHandler">
<Set name="redirectWelcome">FALSE</Set>
</New>
</Arg>
</Call>
</New>
</Arg>
</Call>
<!-- =============================================================== -->
<!-- Configure the Other Server Options -->
<!-- =============================================================== -->

View File

@ -0,0 +1,783 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-07-08 08:03+0000\n"
"PO-Revision-Date: 2010-07-08 10:15+0100\n"
"Last-Translator: echelon <echelon@i2pmail.org>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: German\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:88
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Füge Torrents in {0} Minuten hinzu"
#: ../java/src/org/klomp/snark/SnarkManager.java:258
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Totale Anzahl an Uploadslots geändert auf {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:260
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "Minimale Anzahl and Uploadslots ist {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:272
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Upload Bandbreite wurde geändert auf {0}kbyte/s"
#: ../java/src/org/klomp/snark/SnarkManager.java:274
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Minimales upload Bandbreiten Limit ist {0} kbyte/s"
#: ../java/src/org/klomp/snark/SnarkManager.java:286
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "Startverzögerung geändert auf {0} Minuten"
#: ../java/src/org/klomp/snark/SnarkManager.java:333
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "Änderungen an I2CP und am Tunnel werden nach dem Stoppen aller Torrents wirksam"
#: ../java/src/org/klomp/snark/SnarkManager.java:339
msgid "Disconnecting old I2CP destination"
msgstr "Trenne das alte I2CP Ziel"
#: ../java/src/org/klomp/snark/SnarkManager.java:343
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "I2CP Einstellungen geändert auf {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:347
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Konnte nicht mit den neuen Einstellungen verbinden, benutze wieder die alten I2CP Einstellungen"
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Unable to reconnect with the old settings!"
msgstr "Konnte nicht mit den alten Einstellungen verbinden!"
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Reconnected on the new I2CP destination"
msgstr "Verbunden auf dem neuem I2CP Ziel"
#: ../java/src/org/klomp/snark/SnarkManager.java:364
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "I2CP Verbindung neu gestartet für \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:375
msgid "Enabled autostart"
msgstr "Aktiviere Autostart"
#: ../java/src/org/klomp/snark/SnarkManager.java:377
msgid "Disabled autostart"
msgstr "Deaktiviere Autostart"
#: ../java/src/org/klomp/snark/SnarkManager.java:383
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Open Tracker aktiviert - zum aktiv werden müssen die Torrents neu gestartet werden"
#: ../java/src/org/klomp/snark/SnarkManager.java:385
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Open Tracker deaktiviert - zum aktiv werden müssen die Torrents neu gestartet werden"
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Open Tracker Liste geändert - zum aktiv werden müssen die Torrents neu gestartet werden"
#: ../java/src/org/klomp/snark/SnarkManager.java:399
msgid "Configuration unchanged."
msgstr "Konfiguration nicht geändert."
#: ../java/src/org/klomp/snark/SnarkManager.java:409
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Konnte Konfiguration nicht nach {0} sichern"
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Connecting to I2P"
msgstr "Verbinde mit I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:448
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Fehler beim Verbinden mit I2P - Kontrollieren Sie die I2CP EInstellungen!"
#: ../java/src/org/klomp/snark/SnarkManager.java:457
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Fehler: Konnte den Torrent nicht hinzufügen {0}"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:479
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Kann folgendes nicht öffnen: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:492
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only"
msgstr "Warnung - ignoriere nicht-I2P Tracker in \"{0}\", publiziere nur zu I2P Open Tracker"
#: ../java/src/org/klomp/snark/SnarkManager.java:494
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!"
msgstr "Warnung - Ignoriere nicht-I2P Tracker in \"{0}\" und Open Tracker sind deaktiviert, Sie müssen Open Tracker aktivieren bevor sie den Torrent starten!"
#: ../java/src/org/klomp/snark/SnarkManager.java:513
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Torrent in \"{0}\" ist nicht gültig"
#: ../java/src/org/klomp/snark/SnarkManager.java:528
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent hinzugefügt und gestartet: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:530
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent hinzugefügt: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:627
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Zu viele Dateien in \"{0}\" ({1}), lösche es! "
#: ../java/src/org/klomp/snark/SnarkManager.java:629
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Torrent Datei \"{0}\" darf nicht mit '.torrent' enden, lösche es!"
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "Keine Teile in \"{0}\", entferne es!"
#: ../java/src/org/klomp/snark/SnarkManager.java:633
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Zu viele Teile in \"{0}\" , das Limit sind {1}, lösche es!"
#: ../java/src/org/klomp/snark/SnarkManager.java:635
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Teile sind zu Groß in \"{0}\" ({1}B), lösche es."
#: ../java/src/org/klomp/snark/SnarkManager.java:636
#, java-format
msgid "Limit is {0}B"
msgstr "Limit ist \"{0}\"Byte"
#: ../java/src/org/klomp/snark/SnarkManager.java:644
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Torrents größer als \"{0}\"Bytes werden nicht unterstützt, lösche \"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:660
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Fehler: konnte den torrent \"{0}\" nicht entfernen"
#: ../java/src/org/klomp/snark/SnarkManager.java:681
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent angehalten:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:696
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent entfernt:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "Download finished: \"{0}\""
msgstr "Download beendet:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "size: {0}B"
msgstr "Größe: {0}Byte"
#: ../java/src/org/klomp/snark/SnarkManager.java:757
msgid "Unable to connect to I2P!"
msgstr "Konnte nicht mit I2P verbinden!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:174
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Anonymer BitTorrent Klient"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "Torrents"
msgstr "Torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:193
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:191
msgid "Refresh page"
msgstr "Aktualisiere Seite"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:195
msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:240
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289
msgid "Status"
msgstr "Status"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
msgid "Hide Peers"
msgstr "Verstecke Teilnehmer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:249
msgid "Show Peers"
msgstr "Zeige Teilnehmer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:256
msgid "ETA"
msgstr "ETA"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Downloaded"
msgstr "Heruntergeladen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260
msgid "Uploaded"
msgstr "Hochgeladen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:262
msgid "Down Rate"
msgstr "Down Rate"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
msgid "Up Rate"
msgstr "Up Rate"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:271
msgid "Stop all torrents and the I2P tunnel"
msgstr "Stoppe alle Torrents und den I2P Tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:273
msgid "Stop All"
msgstr "Stoppe alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:278
msgid "Start all torrents and the I2P tunnel"
msgstr "Starte alle Torrents und den I2P Tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:280
msgid "Start All"
msgstr "Starte alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "No torrents loaded."
msgstr "Keine Torrents geladen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302
msgid "Totals"
msgstr "Total"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "1 Torrent"
msgstr[1] "{0} Torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:307
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 verbundener Teilnehmer"
msgstr[1] "{0} verbundene Teilnehmer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:336
#, java-format
msgid "Torrent file {0} does not exist"
msgstr "Torrent Datei {0} existiert nicht"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1476
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent rennt schon: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:348
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1478
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent ist schon in der Queue: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352
#, java-format
msgid "Copying torrent to {0}"
msgstr "Kopiere Torrent nach {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr "Konnte den Torrent nicht nach {0} kopieren"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
#, java-format
msgid "from {0}"
msgstr "von {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:363
#, java-format
msgid "Fetching {0}"
msgstr "Hole {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:367
msgid "Invalid URL - must start with http://"
msgstr "Ungültige URL - muß mit http:// anfangen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:397
#, java-format
msgid "Starting up torrent {0}"
msgstr "Starte Torrent {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:417
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:435
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Torrent Datei gelöscht: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451
#, java-format
msgid "Data file deleted: {0}"
msgstr "Daten Datei gelöscht: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:443
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Datendatei konnte nicht gelöscht werden: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:462
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Datenverzeichnis wurde gelöscht: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494
msgid "Error creating torrent - you must select a tracker"
msgstr "Fehler beim Erstellen des Torrent - Sie müssen einen Tracker auswählen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent erstellt für \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:512
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "Viele I2P Tracker erfordern eine Registrierung bevor der Torrent verteilt wird - bitte machen Sie dieses vor dem Start von \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Fehler beim Erstellen eines Torrent für \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Kann keinen Torrent für nicht existierende Daten erstellen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:520
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Fehler beim Erstellen des Torrent - Sie müssen eine Datei oder Verzeichnis angeben."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:523
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Stoppt alle Torrents und beendet den I2P Tunnel."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:532
msgid "I2P tunnel closed."
msgstr "I2P Tunnel geschlossen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Öffnet den I2P Tunnel und startet alle Torrents."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:851
msgid "Unknown"
msgstr "Unbekannt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670
msgid "TrackerErr"
msgstr "TrackerFehler"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:688
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:691
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:696
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:699
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 Teilnehmer"
msgstr[1] "{0} Teilnehmer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:674
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
msgid "Seeding"
msgstr "Verteile"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1327
msgid "Complete"
msgstr "Komplett"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:685
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:693
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:698
msgid "Stalled"
msgstr "Gedrosselt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:701
msgid "No Peers"
msgstr "Keine Teilnehmer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:703
msgid "Stopped"
msgstr "Gestoppt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:718
msgid "View files"
msgstr "Betrachte Dateien"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:720
msgid "Open file"
msgstr "Öffne Datei"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:967
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:751
msgid "Details"
msgstr "Details"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785
msgid "Stop the torrent"
msgstr "Stoppe den Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
msgid "Stop"
msgstr "Stop"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793
msgid "Start the torrent"
msgstr "Starte den Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:795
msgid "Start"
msgstr "Start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:800
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Entfernt den Torrent von der aktiven Liste und löscht die .torrent Datei"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#, java-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgstr "Sind Sie sicher, das Sie die Datei \\''{0}.torrent\\'' löschen wollen (heruntergeladene Daten werden nicht gelöscht)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:807
msgid "Remove"
msgstr "Entfernen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:811
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Löscht die .torrent Datei und dazugehörigen Daten Datei(en)"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:816
#, java-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgstr "Sind Sie sicher, das die die Torrentdatei \\''{0}\\'' und alle heruntergeladene Daten löschen wollen?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
msgid "Delete"
msgstr "Löschen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861
msgid "Seed"
msgstr "Quelle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Uninteressiert (Der Teilnehmer hat keine Teile die wir benötigen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:881
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Gedrosselt (der Teilnehmer hat uns nicht erlaubt Teile anzufordern)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:895
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Uninteressiert (Wir haben keine Teile die der Teilnehmer benötigt)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:897
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Gedrosselt (Wir erlauben dem Teilnehmer nicht Teile anzufordern)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:927
msgid "Add Torrent"
msgstr "Füge Torrent hinzu"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:929
msgid "From URL"
msgstr "Quell URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:934
msgid "Add torrent"
msgstr "Füge Torrent hinzu"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:937
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "Alternativ können Sie die .torrent Dateien auch nach {0} kopieren."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:939
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "Entfernen der .torrent Datei stoppt einen Torrent."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Create Torrent"
msgstr "Erstelle einen Torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:961
msgid "Data to seed"
msgstr "Daten zum Verteilen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:965
msgid "File or directory to seed (must be within the specified path)"
msgstr "Datei oder Verzeichnis zum Verteilen (muß im angegebenen Pfad sein)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Select a tracker"
msgstr "Wähle einen Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "or"
msgstr "oder"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:985
msgid "Specify custom tracker announce URL"
msgstr "Geben Sie eine Tracker Announce URL an"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:988
msgid "Create torrent"
msgstr "Erstelle Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1133
msgid "Configuration"
msgstr "Einstellungen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Data directory"
msgstr "Daten Verzeichnis"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1012
msgid "Directory to store torrents and data"
msgstr "Verzeichnis zum speichern von Torrent Dateien und Daten"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1014
msgid "Edit i2psnark.config and restart to change"
msgstr "Editiere i2psnark.config zum ändern und starte neu."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1018
msgid "Auto start"
msgstr "Auto Start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1022
msgid "If checked, automatically start torrents that are added"
msgstr "Wenn markiert werden hinzugefügte Torrents automatisch gestartet."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1026
msgid "Startup delay"
msgstr "Startverzögerung"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "minutes"
msgstr "Minuten"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1052
msgid "Total uploader limit"
msgstr "Totales Uploader Limit."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1055
msgid "peers"
msgstr "Teilnehmer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1059
msgid "Up bandwidth limit"
msgstr "Upload Bandbreiten Limit."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1062
msgid "Half available bandwidth recommended."
msgstr "Halbe verfügbare Bandbreite ist empfohlen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1064
msgid "View or change router bandwidth"
msgstr "Router Bandbreite ansehen oder ändern"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1068
msgid "Use open trackers also"
msgstr "Benutze auch Open Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1072
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "Wenn markiert wird der Torrent neben dem angegebenen Tracker auch bei den Open Trackers bekannt gegeben."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1076
msgid "Open tracker announce URLs"
msgstr "Open Tracker Announce URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1088
msgid "Inbound Settings"
msgstr "Eingangseinstellungen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
msgid "Outbound Settings"
msgstr "Ausgangseinstellungen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "I2CP host"
msgstr "I2CP Host"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1106
msgid "I2CP port"
msgstr "I2CP Port"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1118
msgid "I2CP options"
msgstr "I2CP Optionen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1124
msgid "Save configuration"
msgstr "Speichere Einstellungen"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1141
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 Zwischenstation"
msgstr[1] "{0} Zwischenstationen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "1 Tunnel"
msgstr[1] "{0} Tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
msgid "Up to higher level directory"
msgstr "Eine Hierachie nach oben"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "File"
msgstr "Datei"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "Size"
msgstr "Größe"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1311
msgid "Directory"
msgstr "Daten Verzeichnis"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1316
msgid "Torrent not found?"
msgstr "Torrentdatei nicht gefunden?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1324
msgid "File not found in torrent?"
msgstr "Datei nicht gefunden im Torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1330
msgid "complete"
msgstr "Komplett"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1331
msgid "bytes remaining"
msgstr "Bytes noch übrig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1456
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent geholt von {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1484
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent bei {0} war nicht gültig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent wurde nicht geladen von {0}"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr ""
#~ "Kann nicht die I2CP Einstellungen ändern während Torrents aktiv sind."
#~ msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
#~ msgstr ""
#~ "Nicht-I2P Tracker in\"{0}\", entferne ihn aus unserer Liste der Tracker!"
#~ msgid "{0} torrents"
#~ msgstr "{0} Torrents"
#~ msgid "Uninteresting"
#~ msgstr "nicht interessiert"
#~ msgid "Choked"
#~ msgstr "Gestaut"
#~ msgid "Uninterested"
#~ msgstr "Nicht interessiert"
#~ msgid "Choking"
#~ msgstr "Stau"
#~ msgid "Custom tracker URL"
#~ msgstr "Spezifische Tracker URL"
#~ msgid "Configure"
#~ msgstr "Einstellungen"

View File

@ -0,0 +1,775 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-07-05 11:48+0000\n"
"PO-Revision-Date: 2010-06-15 09:07+0100\n"
"Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>, monkeybrains <monkeybrains@mail.i2p>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Dutch\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:88
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Torrents toevoegen in {0} minuten"
#: ../java/src/org/klomp/snark/SnarkManager.java:258
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Totale uploaders limiet gewijzigd in {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:260
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "Minimum totale uploaders limiet is {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:272
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Up bandbreedte limiet gewijzigd in {0}KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:274
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Minimum up bandbreedte limiet is {0}KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:286
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "Startup vertragings limiet gewijzigd in {0} minuten"
#: ../java/src/org/klomp/snark/SnarkManager.java:333
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "I2CP en tunnel wijzigingen hebben pas effect na het stoppen van alle torrents"
#: ../java/src/org/klomp/snark/SnarkManager.java:339
msgid "Disconnecting old I2CP destination"
msgstr "Oude I2CP destination wordt afgesloten"
#: ../java/src/org/klomp/snark/SnarkManager.java:343
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "I2CP instellingen gewijzigd in {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:347
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Kan geen connectie maken met de nieuwe instellingen, we keren terug naar oude I2CP instellingen"
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Unable to reconnect with the old settings!"
msgstr "Kan niet opnieuw verbinden met de oude instellingen!"
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Reconnected on the new I2CP destination"
msgstr "Opnieuw verbonden met de nieuwe I2CP destination"
#: ../java/src/org/klomp/snark/SnarkManager.java:364
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "I2CP listener herstart voor \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:375
msgid "Enabled autostart"
msgstr "Autostart ingeschakeld"
#: ../java/src/org/klomp/snark/SnarkManager.java:377
msgid "Disabled autostart"
msgstr "Autostart uitgeschakeld"
#: ../java/src/org/klomp/snark/SnarkManager.java:383
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Open Trackers ingeschakeld - torrent herstart nodig."
#: ../java/src/org/klomp/snark/SnarkManager.java:385
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Open Trackers uitgeschakeld - torrent herstart nodig."
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Open Tracker lijst gewijzigd - torrent herstart nodig."
#: ../java/src/org/klomp/snark/SnarkManager.java:399
msgid "Configuration unchanged."
msgstr "Configuratie ongewijzigd."
#: ../java/src/org/klomp/snark/SnarkManager.java:409
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Kan de configuratie niet opslaan in {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Connecting to I2P"
msgstr "Verbinden met I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:448
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Fout bij verbinden met I2P - controlleer je I2CP instellingen!"
#: ../java/src/org/klomp/snark/SnarkManager.java:457
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Fout: Kan de torrent {0} niet toevoegen"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:479
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Kan \"{0}\" niet openen"
#: ../java/src/org/klomp/snark/SnarkManager.java:492
#, java-format
msgid ""
"Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open "
"trackers only"
msgstr "Waarschuwing - Niet-I2P tracker in \"{0}\" wordt genegeerd, zal alleen aankondigen naar i2p open trackers"
#: ../java/src/org/klomp/snark/SnarkManager.java:494
#, java-format
msgid ""
"Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are "
"disabled, you must enable open trackers before starting the torrent!"
msgstr "Waarschuwing - Niet-I2P tracker in \"{0}\" wordt genegeerd, en open trackers zijn uitgeschakeld, je moet open trackers inschakelen voor het starten van de torrent!"
#: ../java/src/org/klomp/snark/SnarkManager.java:513
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Torrent in \"{0}\" is ongeldig"
#: ../java/src/org/klomp/snark/SnarkManager.java:528
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent toegevoegd en gestart: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:530
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent toegevoegd: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:627
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Te veel bestanden in \"{0}\" ({1}), wordt verwijderd!"
#: ../java/src/org/klomp/snark/SnarkManager.java:629
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Torrent bestand \"{0}\" kan niet eindigen in \".torrent\", wordt verwijderd!"
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "Geen stukken in \"{0}\", wordt verwijderd!"
#: ../java/src/org/klomp/snark/SnarkManager.java:633
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Te veel stukken in \"{0}\", limiet is {1}, wordt verwijderd!"
#: ../java/src/org/klomp/snark/SnarkManager.java:635
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Stukken zijn te groot in \"{0}\" ({1}B), wordt verwijderd."
#: ../java/src/org/klomp/snark/SnarkManager.java:636
#, java-format
msgid "Limit is {0}B"
msgstr "Limiet is {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:644
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Torrents groter dan {0}B worden nog niet ondersteund, verwijder \"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:660
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Fout: Kan de torrent {0} niet verwijderen"
#: ../java/src/org/klomp/snark/SnarkManager.java:681
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent gestopt: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:696
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent verwijderd: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "Download finished: \"{0}\""
msgstr "Download gereed: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "size: {0}B"
msgstr "grootte: {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:757
msgid "Unable to connect to I2P!"
msgstr "Kan niet verbinden met I2P!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:174
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Anonieme BitTorrent Client"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "Torrents"
msgstr "Torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:193
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:191
msgid "Refresh page"
msgstr "Ververs pagina"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:195
msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:240
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289
msgid "Status"
msgstr "Status"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
msgid "Hide Peers"
msgstr "Verberg Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:249
msgid "Show Peers"
msgstr "Toon Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:256
msgid "ETA"
msgstr "ETA"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Downloaded"
msgstr "Gedownload"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260
msgid "Uploaded"
msgstr "Geupload"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:262
msgid "Down Rate"
msgstr "Down Snelheid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
msgid "Up Rate"
msgstr "Up Snelheid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:271
msgid "Stop all torrents and the I2P tunnel"
msgstr "Stop alle torrents en de I2P tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:273
msgid "Stop All"
msgstr "Stop Alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:278
msgid "Start all torrents and the I2P tunnel"
msgstr "Start alle torrents en de I2P tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:280
msgid "Start All"
msgstr "Start Alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "No torrents loaded."
msgstr "Geen torrents geladen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302
msgid "Totals"
msgstr "Totalen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "1 torrent"
msgstr[1] "{0} torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:307
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 verbonden peer"
msgstr[1] "{0} verbonden peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:336
#, java-format
msgid "Torrent file {0} does not exist"
msgstr "Torrent bestand {0} bestaat niet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1476
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent draait al: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:348
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1478
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent zit al in de wachtrij: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352
#, java-format
msgid "Copying torrent to {0}"
msgstr "Kopieer torrent naar {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr "Kan de de torrent niet kopieren naar {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
#, java-format
msgid "from {0}"
msgstr "van {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:363
#, java-format
msgid "Fetching {0}"
msgstr "Downloaden {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:367
msgid "Invalid URL - must start with http://"
msgstr "Ongeldige URL - moet beginnen met http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:397
#, java-format
msgid "Starting up torrent {0}"
msgstr "Starten met torrent {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:417
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:435
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Torrent bestand verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451
#, java-format
msgid "Data file deleted: {0}"
msgstr "Data bestand verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:443
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Kan data bestand niet verwijderen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:462
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Data directory verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494
msgid "Error creating torrent - you must select a tracker"
msgstr "Fout bij maken van torrent - je moet een tracker selecteren"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent gemaakt voor \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:512
#, java-format
msgid ""
"Many I2P trackers require you to register new torrents before seeding - "
"please do so before starting \"{0}\""
msgstr "Veel I2P trackers vereisen dat je de nieuwe torrent registreert voor het seeden - "
"doe dit voordat je \"{0}\" start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Fout bij het maken van een torrent voor \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Kan geen torrent maken voor niet-bestaande data: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:520
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Fout bij het maken van de torrent - je moet een bestand of directory invullen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:523
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Stoppen van alle torrents en sluiten van I2P tunnel."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:532
msgid "I2P tunnel closed."
msgstr "I2P tunnel gesloten."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Openen van de I2P tunnel en starten van alle torrents."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:851
msgid "Unknown"
msgstr "Onbekend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670
msgid "TrackerErr"
msgstr "TrackerErr"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:688
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:691
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:696
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:699
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 peer"
msgstr[1] "{0} peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:674
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
msgid "Seeding"
msgstr "Seeding"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1327
msgid "Complete"
msgstr "Voltooid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:685
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:693
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:698
msgid "Stalled"
msgstr "Vastgelopen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:701
msgid "No Peers"
msgstr "Geen Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:703
msgid "Stopped"
msgstr "Gestopt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:718
msgid "View files"
msgstr "Bekijk bestanden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:720
msgid "Open file"
msgstr "Open bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:967
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:751
msgid "Details"
msgstr "Details"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785
msgid "Stop the torrent"
msgstr "Stop de torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
msgid "Stop"
msgstr "Stop"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793
msgid "Start the torrent"
msgstr "Start de torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:795
msgid "Start"
msgstr "Start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:800
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Verwijder de torrent van de actieve lijst, het .torrent bestand wordt verwijderd"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
"data will not be deleted) ?"
msgstr "Weet je zeker dat je het bestand \\''{0}.torrent\\'' wilt verwijderen (gedownloade data zal niet worden verwijderd) ?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:807
msgid "Remove"
msgstr "Weghalen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:811
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Verwijder het .torrent bestand en de gerelateerde data bestand(en)"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:816
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
"data?"
msgstr "Weet je zeker dat je de torrent \\''{0}\\'' en alle gedownloade data wilt verwijderen?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
msgid "Delete"
msgstr "Verwijderen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861
msgid "Seed"
msgstr "Seed"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Niet interessant (De peer heeft geen stukken die we nodig hebben)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:881
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Verstikt (De peer laat ons niet toe om stukken op te vragen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:895
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Niet geïnteresseerd (We heben geen stukken die de peer nodig heeft)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:897
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Verstikt (We laten de peer niet toe om stukken op te vragen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:927
msgid "Add Torrent"
msgstr "Torrent Toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:929
msgid "From URL"
msgstr "Van URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:934
msgid "Add torrent"
msgstr "Torrent toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:937
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "Als alternatief kan je het .torrent bestand kopieren naar de directory {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:939
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "Verwijderen van een .torrent bestand zorgt dat de torrent stopt."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Create Torrent"
msgstr "Creëer Torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:961
msgid "Data to seed"
msgstr "Data om te seeden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:965
msgid "File or directory to seed (must be within the specified path)"
msgstr "Bestand of directory om te seeden (moet binnen het gespecificeerde pad zijn)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Select a tracker"
msgstr "Selecteer een tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "or"
msgstr "of"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:985
msgid "Specify custom tracker announce URL"
msgstr "Specificeer aangepaste tracker aankondigings URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:988
msgid "Create torrent"
msgstr "Creëer torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1133
msgid "Configuration"
msgstr "Configuratie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Data directory"
msgstr "Data directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1012
msgid "Directory to store torrents and data"
msgstr "Directory om torrents en data op te slaan"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1014
msgid "Edit i2psnark.config and restart to change"
msgstr "Bewerk i2psnark.config en herstart de wijziging"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1018
msgid "Auto start"
msgstr "Auto start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1022
msgid "If checked, automatically start torrents that are added"
msgstr "Indien aangevinkt, start toegevoegde torrents automatisch"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1026
msgid "Startup delay"
msgstr "Startup vertraging"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "minutes"
msgstr "minuten"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1052
msgid "Total uploader limit"
msgstr "Totale uploader limiet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1055
msgid "peers"
msgstr "peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1059
msgid "Up bandwidth limit"
msgstr "Up bandbreedte limiet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1062
msgid "Half available bandwidth recommended."
msgstr "Helft van beschikbare bandbreedte aanbevolen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1064
msgid "View or change router bandwidth"
msgstr "Bekijk of wijzig router bandbreedte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1068
msgid "Use open trackers also"
msgstr "Gebruik ook open trackers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1072
msgid ""
"If checked, announce torrents to open trackers as well as the tracker listed "
"in the torrent file"
msgstr "Indien aangevinkt, kondig torrents ook aan bij de tracker uit het torrent bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1076
msgid "Open tracker announce URLs"
msgstr "Open tracker aankondigings URLs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1088
msgid "Inbound Settings"
msgstr "Inkomende Instellingen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
msgid "Outbound Settings"
msgstr "Uitgaande Instellingen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "I2CP host"
msgstr "I2CP host"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1106
msgid "I2CP port"
msgstr "I2CP poort"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1118
msgid "I2CP options"
msgstr "I2CP opties"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1124
msgid "Save configuration"
msgstr "Configuratie opslaan"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1141
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 hop"
msgstr[1] "{0} hops"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "1 tunnel"
msgstr[1] "{0} tunnels"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
msgid "Up to higher level directory"
msgstr "Naar bovenliggende directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "File"
msgstr "Bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "Size"
msgstr "Grootte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1311
msgid "Directory"
msgstr "Directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1316
msgid "Torrent not found?"
msgstr "Torrent niet gevonden?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1324
msgid "File not found in torrent?"
msgstr "Bestand niet gevonden in torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1330
msgid "complete"
msgstr "voltooid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1331
msgid "bytes remaining"
msgstr "bytes resterend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1456
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent gedownload van {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1484
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent op {0} was niet geldig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent was niet ontvangen van {0}"

View File

@ -0,0 +1,772 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-06-26 21:02+0000\n"
"PO-Revision-Date: 2010-06-26 21:13+0000\n"
"Last-Translator: 4get <forget@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Russian\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:88
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Торренты будут подгружены через {0} минут(ы)"
#: ../java/src/org/klomp/snark/SnarkManager.java:258
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Новое значение лимита количества слотов отдачи: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:260
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "Минимально допустимое значение для количества слотов: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:272
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Новое значение лимита скорости отдачи: {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:274
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Минимально допустимое значение для лимита скорости отдачи: {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:286
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "Новое значение задержки запуска: {0} минут(ы)"
#: ../java/src/org/klomp/snark/SnarkManager.java:333
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "Изменения настроек I2CP и туннелей вступят в силу после остановки всех торрентов."
#: ../java/src/org/klomp/snark/SnarkManager.java:339
msgid "Disconnecting old I2CP destination"
msgstr "Рассоединяемся по старому адресу I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:343
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "Новые параметры I2CP: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:347
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Не удалось соединиться с использованием новых настроек I2CP, возвращаемся к старым настройкам"
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Unable to reconnect with the old settings!"
msgstr "Не удалось пересоединиться с использованием старых настроек I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Reconnected on the new I2CP destination"
msgstr "Пересоединились по новому адресу I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:364
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "I2CP-приёмник перезапущен для \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:375
msgid "Enabled autostart"
msgstr "Автостарт включен"
#: ../java/src/org/klomp/snark/SnarkManager.java:377
msgid "Disabled autostart"
msgstr "Автостарт выключен"
#: ../java/src/org/klomp/snark/SnarkManager.java:383
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Включено использование открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу."
#: ../java/src/org/klomp/snark/SnarkManager.java:385
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Отключено использование открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу."
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Изменен список открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу."
#: ../java/src/org/klomp/snark/SnarkManager.java:399
msgid "Configuration unchanged."
msgstr "Настройки не изменились."
#: ../java/src/org/klomp/snark/SnarkManager.java:409
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Не удалось сохранить настройки в {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Connecting to I2P"
msgstr "Устанавливается соединение с I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:448
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Ошибка соединения с I2P, проверьте настройки I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:457
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Ошибка: Не удалось добавить торрент {0}"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:479
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Не удалось открыть \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:492
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only"
msgstr "Внимание: указанные в \"{0}\" не-i2p трекеры будут проигнорированы, будут использоваться только открытые i2p трекеры"
#: ../java/src/org/klomp/snark/SnarkManager.java:494
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!"
msgstr "Внимание: указанные в \"{0}\" не-i2p трекеры будут проигнорированы, однако использование открытых i2p трекеров отключено, Вы должны включить поддержку открытых i2p трекеров перед запуском этого торрента!"
#: ../java/src/org/klomp/snark/SnarkManager.java:513
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Торрент в \"{0}\" некорректен"
#: ../java/src/org/klomp/snark/SnarkManager.java:528
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Торрент добавлен и запущен: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:530
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Торрент добавлен: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:627
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Слишком много файлов в торренте \"{0}\" ({1}), удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:629
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Торрент \"{0}\" содержит единственный файл заканчивающийся на \".torrent\", удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "В торренте \"{0}\" не оказалось ни одной части, удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:633
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Слишком много частей в торренте \"{0}\" (наш предел {1}), удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:635
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Слишком крупные части в торренте \"{0}\" ({1}B), удаляем его."
#: ../java/src/org/klomp/snark/SnarkManager.java:636
#, java-format
msgid "Limit is {0}B"
msgstr "Наш предел {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:644
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Торренты крупнее чем {0}B пока не поддерживается, удаляем \"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:660
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Ошибка: Невозможно удалить торрент {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:681
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Торрент остановлен: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:696
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Торрент удален: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "Download finished: \"{0}\""
msgstr "Завершена загрузка: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "size: {0}B"
msgstr "размер: {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:757
msgid "Unable to connect to I2P!"
msgstr "Не удалось установить соединение с I2P!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:168
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark — Анонимный BitTorrent Клиент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:179
msgid "Torrents"
msgstr "Торренты"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:181
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "Refresh page"
msgstr "Обновить страницу"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:189
msgid "Forum"
msgstr "Форум"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:234
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
msgid "Status"
msgstr "Статус"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:240
msgid "Hide Peers"
msgstr "спрятать список пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:243
msgid "Show Peers"
msgstr "показать список пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:248
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1265
msgid "Torrent"
msgstr "Торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:250
msgid "ETA"
msgstr "Осталось"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:252
msgid "Downloaded"
msgstr "Получено"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
msgid "Uploaded"
msgstr "Отдано"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:256
msgid "Down Rate"
msgstr "Скорость загрузки"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Up Rate"
msgstr "Скорость отдачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:265
msgid "Stop all torrents and the I2P tunnel"
msgstr "Остановить все торренты и закрыть соединение с I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267
msgid "Stop All"
msgstr "Остановить все"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:272
msgid "Start all torrents and the I2P tunnel"
msgstr "Запустить все торренты и открыть соединение с I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:274
msgid "Start All"
msgstr "Запустить все"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291
msgid "No torrents loaded."
msgstr "Нет загруженных торрентов."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:296
msgid "Totals"
msgstr "Всего"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "{0} торрент"
msgstr[1] "{0} торрента"
msgstr[2] "{0} торрентов"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:301
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "{0} подсоединенный пир"
msgstr[1] "{0} подсоединенных пиров"
msgstr[2] "{0} подсоединенных пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:330
#, java-format
msgid "Torrent file {0} does not exist"
msgstr "Торрент {0} не существует"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:340
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1470
#, java-format
msgid "Torrent already running: {0}"
msgstr "Торрент уже запущен: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1472
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Торрент уже в очереди: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
#, java-format
msgid "Copying torrent to {0}"
msgstr "Копируем торрент в: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:349
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr "Не удалось скопировать торрент в: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:349
#, java-format
msgid "from {0}"
msgstr "из: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:357
#, java-format
msgid "Fetching {0}"
msgstr "Получение торрента: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:361
msgid "Invalid URL - must start with http://"
msgstr "Некорректный URL, должен начинаться с http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:391
#, java-format
msgid "Starting up torrent {0}"
msgstr "Запускаем торрент: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:429
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Удален торрент: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:435
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445
#, java-format
msgid "Data file deleted: {0}"
msgstr "Файл удален: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:437
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:447
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Не удалось удалить файл: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:456
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Директория удалена: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:488
msgid "Error creating torrent - you must select a tracker"
msgstr "Торрент не создан — вы должны указать трекер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Создан торрент для \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:506
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "Многие I2P трекеры требуют зарегистрировать на них торрент перед началом раздачи — пожалуйста проверьте требуется ли это перед запуском \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Ошибка при создании торрента для: \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Невозможно создать торрент для несуществующего файла или директории: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Торрент не создан — вы должны указать файл или директорию"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Останавливаем все торренты и закрываем соединение с I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:526
msgid "I2P tunnel closed."
msgstr "Соединение с I2P закрыто."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Соединяемся с I2P и запускаем все торренты."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:651
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
msgid "Unknown"
msgstr "Неизвестный"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:654
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:659
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:664
msgid "TrackerErr"
msgstr "ОшибкаТрекера"
# TODO should replace "uploader limit NN peers" with "global number of upload slots: NN"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:671
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:674
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:685
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:693
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "{0} пир"
msgstr[1] "{0} пира"
msgstr[2] "{0} пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:668
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:673
msgid "Seeding"
msgstr "Раздается"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1321
msgid "Complete"
msgstr "Завершен"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:684
msgid "OK"
msgstr "Загружается"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:687
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:692
msgid "Stalled"
msgstr "Простаивает"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:695
msgid "No Peers"
msgstr "Нет Пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697
msgid "Stopped"
msgstr "Остановлен"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:712
msgid "View files"
msgstr "Открыть директорию"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:714
msgid "Open file"
msgstr "Открыть файл"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:961
msgid "Tracker"
msgstr "Трекер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:745
msgid "Details"
msgstr "Подробнее"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:779
msgid "Stop the torrent"
msgstr "Остановить торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:781
msgid "Stop"
msgstr "Остановить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
msgid "Start the torrent"
msgstr "Запустить торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:789
msgid "Start"
msgstr "Запустить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:794
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Удалить торрент из списка и с диска"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:799
#, java-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgstr "Вы действительно хотите удалить \\''{0}.torrent\\''? (загруженные файлы удаляться НЕ будут)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
msgid "Remove"
msgstr "Удалить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Удалить торрент и стереть загруженные файлы"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#, java-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgstr "Вы действительно хотите удалить торрент \\''{0}\\'' и все загруженные файлы?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812
msgid "Delete"
msgstr "Стереть"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:855
msgid "Seed"
msgstr "Сид"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:873
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Uninteresting (У пира нет нужных нам частей торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:875
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Choked (Этот пир не позволяет нам запрашивать части торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:889
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Uninterested (У нас нужных этому пиру частей торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:891
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Choking (Мы не позволяем этому пиру запрашивать у нас части торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:921
msgid "Add Torrent"
msgstr "Добавить Торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:923
msgid "From URL"
msgstr "Из URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:928
msgid "Add torrent"
msgstr "Добавить торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:931
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "Ну или вы можете скопировать .torrent-файлы в директорию {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "Удаление .torrent-файла приведет к остановке торрента."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:952
msgid "Create Torrent"
msgstr "Создать Торрент"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955
msgid "Data to seed"
msgstr "Файлы для раздачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:959
msgid "File or directory to seed (must be within the specified path)"
msgstr "Файл или директория для раздачи (вводите только название файла или директории, указание абсолютных путей не поддерживается)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:963
msgid "Select a tracker"
msgstr "Выбрать трекер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:976
msgid "or"
msgstr "или"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979
msgid "Specify custom tracker announce URL"
msgstr "Задать URL анонсера вручную"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "Create torrent"
msgstr "Создать торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1000
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1127
msgid "Configuration"
msgstr "Настройки"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1003
msgid "Data directory"
msgstr "Директория для файлов"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
msgid "Directory to store torrents and data"
msgstr "Директория, где будут храниться торренты и загружаемые файлы"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008
msgid "Edit i2psnark.config and restart to change"
msgstr "Для изменения отредактируйте файл i2psnark.config и перезагрузите I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1012
msgid "Auto start"
msgstr "Автозапуск"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1016
msgid "If checked, automatically start torrents that are added"
msgstr "Автоматически запускать торренты после добавления"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1020
msgid "Startup delay"
msgstr "Задержка запуска"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1022
msgid "minutes"
msgstr "минут"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1046
msgid "Total uploader limit"
msgstr "Ограничение количества слотов отдачи"
# TODO should replace "uploader limit NN peers" with "global number of upload slots: NN"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1049
msgid "peers"
msgstr "пир."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1053
msgid "Up bandwidth limit"
msgstr "Ограничение скорости отдачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1056
msgid "Half available bandwidth recommended."
msgstr "Рекомендуется использовать половину от доступной пропускной способности."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1058
msgid "View or change router bandwidth"
msgstr "Посмотреть/настроить ограничения скорости в маршрутизаторе I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1062
msgid "Use open trackers also"
msgstr "Дополнительно использовать открытые трекеры"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1066
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "Анонсировать торренты на открытых трекерах, дополнительно к тем, что указаны внутри торрента"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1070
msgid "Open tracker announce URLs"
msgstr "URL открытых трекеров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082
msgid "Inbound Settings"
msgstr "Входящие туннели"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1088
msgid "Outbound Settings"
msgstr "Исходящие туннели"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1095
msgid "I2CP host"
msgstr "Адрес I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1100
msgid "I2CP port"
msgstr "Порт I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112
msgid "I2CP options"
msgstr "Параметры I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1118
msgid "Save configuration"
msgstr "Сохранить настройки"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1135
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "{0} хоп"
msgstr[1] "{0} хопа"
msgstr[2] "{0} хопов"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1136
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "{0} туннель"
msgstr[1] "{0} туннеля"
msgstr[2] "{0} туннелей"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277
msgid "Up to higher level directory"
msgstr "Перейти в директорию уровнем выше"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282
msgid "File"
msgstr "Файл"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282
msgid "Size"
msgstr "Размер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305
msgid "Directory"
msgstr "Директория"
# This debug error message intentionally left in English
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310
msgid "Torrent not found?"
msgstr "Torrent not found?"
# This debug error message intentionally left in English
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1318
msgid "File not found in torrent?"
msgstr "File not found in torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1324
msgid "complete"
msgstr "скачано"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1325
msgid "bytes remaining"
msgstr "байт осталось"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Получен торрент из: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1478
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Торрент полученный из {0} некорректен"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1483
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Не удалось получить торрент из: {0}"

View File

@ -0,0 +1,770 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-07-01 04:52+0000\n"
"PO-Revision-Date: 2010-07-01 12:53+0800\n"
"Last-Translator: walking <walking@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Chinese\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:88
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "{0}分钟内完成添加"
#: ../java/src/org/klomp/snark/SnarkManager.java:258
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "总上传种子数限制已更新为{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:260
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "最低上传种子数限制为{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:272
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "上传带宽限制改为 {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:274
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "最小上传带宽限制为 {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:286
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "启动延迟已更新为{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:333
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "I2CP与隧道设置的变化在所有种子停止后才能生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:339
msgid "Disconnecting old I2CP destination"
msgstr "正在断开旧的I2CP目标"
#: ../java/src/org/klomp/snark/SnarkManager.java:343
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "I2CP设置改为{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:347
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "无法通过新设置连接恢复I2CP的旧设置"
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Unable to reconnect with the old settings!"
msgstr "旧设置也无法连接!"
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Reconnected on the new I2CP destination"
msgstr "重新连接新I2CP目标"
#: ../java/src/org/klomp/snark/SnarkManager.java:364
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "\"{0}\"的I2CP监听端口已启动"
#: ../java/src/org/klomp/snark/SnarkManager.java:375
msgid "Enabled autostart"
msgstr "启用自动启动"
#: ../java/src/org/klomp/snark/SnarkManager.java:377
msgid "Disabled autostart"
msgstr "禁用自动启动"
#: ../java/src/org/klomp/snark/SnarkManager.java:383
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "启用OpenTracker-重新启动种子后生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:385
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "禁用OpenTracker - 重新启动种子后生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "OpenTracker列表已改变 - 重新启动种子后生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:399
msgid "Configuration unchanged."
msgstr "设置未改变"
#: ../java/src/org/klomp/snark/SnarkManager.java:409
#, java-format
msgid "Unable to save the config to {0}"
msgstr "无法保存设置到{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Connecting to I2P"
msgstr "正在连接到I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:448
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "连接I2P时发生错误 - 请检查I2CP设置!"
#: ../java/src/org/klomp/snark/SnarkManager.java:457
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "错误:无法添加种子{0}"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:479
#, java-format
msgid "Cannot open \"{0}\""
msgstr "无法打开 \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:492
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only"
msgstr "警告 - 忽略\"{0}\"文件中I2P网络外的Tracker服务器文件将仅发布至 I2P 内的 Open Tracker 服务器。"
#: ../java/src/org/klomp/snark/SnarkManager.java:494
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!"
msgstr "警告 - 忽略\"{0}\"文件中I2P网络外的Tracker服务器OpenTracker已禁用启动此种子前您必须启用OpenTracker。"
#: ../java/src/org/klomp/snark/SnarkManager.java:513
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "无效种子 \"{0}\" "
#: ../java/src/org/klomp/snark/SnarkManager.java:528
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "已添加并启动种子:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:530
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "已添加种子:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:627
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "\"{0}\" ({1}) 含有太多文件,删除之!"
#: ../java/src/org/klomp/snark/SnarkManager.java:629
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "种子文件 \"{0}\" 不以 \".torrent\"结尾,正在删除!"
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "\"{0}\" 中没有数据片,删除之!"
#: ../java/src/org/klomp/snark/SnarkManager.java:633
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "\"{0}\" 中文件分片太多,限额为{1},删除之!"
#: ../java/src/org/klomp/snark/SnarkManager.java:635
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "\"{0}\" ({1}B) 中文件分片过大,删除之。"
#: ../java/src/org/klomp/snark/SnarkManager.java:636
#, java-format
msgid "Limit is {0}B"
msgstr "限额为 {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:644
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "目前不支持大于{0}B 的种子,正在删除\"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:660
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "错误:无法删除种子{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:681
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "种子已停止:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:696
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "种子已删除:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "Download finished: \"{0}\""
msgstr "下载已完成:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:729
#, java-format
msgid "size: {0}B"
msgstr "大小:{0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:757
msgid "Unable to connect to I2P!"
msgstr "无法连接至I2P!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:174
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - 匿名BitTorrent客户端"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "Torrents"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:193
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
msgid "I2PSnark"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:191
msgid "Refresh page"
msgstr "刷新页面"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:195
msgid "Forum"
msgstr "论坛"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:240
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289
msgid "Status"
msgstr "状态"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
msgid "Hide Peers"
msgstr "隐藏用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:249
msgid "Show Peers"
msgstr "显示用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271
msgid "Torrent"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:256
msgid "ETA"
msgstr "预计剩余时间"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Downloaded"
msgstr "已下载"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260
msgid "Uploaded"
msgstr "已上传"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:262
msgid "Down Rate"
msgstr "下载速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
msgid "Up Rate"
msgstr "上传速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:271
msgid "Stop all torrents and the I2P tunnel"
msgstr "停止全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:273
msgid "Stop All"
msgstr "停止全部"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:278
msgid "Start all torrents and the I2P tunnel"
msgstr "启动全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:280
msgid "Start All"
msgstr "启动全部"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "No torrents loaded."
msgstr "未载入任何种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302
msgid "Totals"
msgstr "总计"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "{0}个种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:307
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "{0}个已连接用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:336
#, java-format
msgid "Torrent file {0} does not exist"
msgstr "种子文件{0}不存在"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1476
#, java-format
msgid "Torrent already running: {0}"
msgstr "种子已启动:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:348
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1478
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "种子排队中:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352
#, java-format
msgid "Copying torrent to {0}"
msgstr "正在复制种子到{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr "无法复制种子文件到{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
#, java-format
msgid "from {0}"
msgstr "来源{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:363
#, java-format
msgid "Fetching {0}"
msgstr "正在获取{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:367
msgid "Invalid URL - must start with http://"
msgstr "无效链接 - 必须以http:// 开头"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:397
#, java-format
msgid "Starting up torrent {0}"
msgstr "正在启动种子{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:417
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:435
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "种子文件已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451
#, java-format
msgid "Data file deleted: {0}"
msgstr "数据文件已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:443
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "无法删除数据文件:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:462
#, java-format
msgid "Data dir deleted: {0}"
msgstr "数据文件夹已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494
msgid "Error creating torrent - you must select a tracker"
msgstr "创建种子时发生错误 - 您必须选择一个Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "种子创建成功\"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:512
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "多数I2PTracker需要用户在做种前注册新种子 - 请在启动 \"{0}\"前到所使用的Tracker进行注册。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "创建种子时发生错误 \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "无法为不存在的数据文件创建种子:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:520
msgid "Error creating torrent - you must enter a file or directory"
msgstr "创建种子时发生错误 - 必须指定文件或文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:523
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "正在停用所有种子并关闭I2P隧道。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:532
msgid "I2P tunnel closed."
msgstr "I2P隧道已关闭"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "正在打开I2P隧道并启动所有种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:851
msgid "Unknown"
msgstr "未知"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670
msgid "TrackerErr"
msgstr "Tracker错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:688
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:691
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:696
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:699
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "{0}个用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:674
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
msgid "Seeding"
msgstr "正做种"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1327
msgid "Complete"
msgstr "完成"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:685
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690
msgid "OK"
msgstr "确定"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:693
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:698
msgid "Stalled"
msgstr "等待"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:701
msgid "No Peers"
msgstr "没有用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:703
msgid "Stopped"
msgstr "已停用"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:718
msgid "View files"
msgstr "浏览文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:720
msgid "Open file"
msgstr "打开文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:967
msgid "Tracker"
msgstr "Tracker服务器"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:751
msgid "Details"
msgstr "详情"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785
msgid "Stop the torrent"
msgstr "停止种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
msgid "Stop"
msgstr "停止"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793
msgid "Start the torrent"
msgstr "启动种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:795
msgid "Start"
msgstr "启动"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:800
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "取消下载任务并删除对应种子文件。"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#, java-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgstr "您确定要删除文件“{0}.torrent”(下载的数据文件不会被删除)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:807
msgid "Remove"
msgstr "移除"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:811
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "删除种子及所下载的文件"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:816
#, java-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgstr "您确定要删除种子“{0}”(下载的数据文件会一并被删除)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
msgid "Delete"
msgstr "删除"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861
msgid "Seed"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "无需要部分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:881
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:895
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "无需要部分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:897
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:927
msgid "Add Torrent"
msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:929
msgid "From URL"
msgstr "从URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:934
msgid "Add torrent"
msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:937
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "或者您可以将.torrent文件复制到以下目录{0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:939
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "删除种子文件将导致中止该下载任务。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Create Torrent"
msgstr "创建种子"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:961
msgid "Data to seed"
msgstr "做种数据"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:965
msgid "File or directory to seed (must be within the specified path)"
msgstr "做种文件或文件夹(必须下面为Snark指定的文件夹中)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Select a tracker"
msgstr "选择一个Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "or"
msgstr "或"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:985
msgid "Specify custom tracker announce URL"
msgstr "指定Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:988
msgid "Create torrent"
msgstr "创建种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1133
msgid "Configuration"
msgstr "设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Data directory"
msgstr "数据文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1012
msgid "Directory to store torrents and data"
msgstr "种子及被做种文件的保存位置。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1014
msgid "Edit i2psnark.config and restart to change"
msgstr "编辑 i2psnark.config 并重启Snark后生效"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1018
msgid "Auto start"
msgstr "自动启动"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1022
msgid "If checked, automatically start torrents that are added"
msgstr "选中后Snark将自动启动已添加的所有种子。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1026
msgid "Startup delay"
msgstr "启动延迟"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "minutes"
msgstr "分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1052
msgid "Total uploader limit"
msgstr "限制总上传种子数为"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1055
msgid "peers"
msgstr "用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1059
msgid "Up bandwidth limit"
msgstr "上传带宽限制"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1062
msgid "Half available bandwidth recommended."
msgstr "推荐设置为可用带宽的一半。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1064
msgid "View or change router bandwidth"
msgstr "浏览或修改路由器带宽"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1068
msgid "Use open trackers also"
msgstr "同时使用OpenTracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1072
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "选择后在OpenTracker及种子文件中的Tracker上同时发布。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1076
msgid "Open tracker announce URLs"
msgstr "Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1088
msgid "Inbound Settings"
msgstr "入站设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
msgid "Outbound Settings"
msgstr "出站设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "I2CP host"
msgstr "I2CP主机"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1106
msgid "I2CP port"
msgstr "I2CP端口"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1118
msgid "I2CP options"
msgstr "I2CP选项"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1124
msgid "Save configuration"
msgstr "保存设置"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1141
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "{0}跳"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "{0}隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
msgid "Up to higher level directory"
msgstr "上一层文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "File"
msgstr "文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "Size"
msgstr "大小"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1311
msgid "Directory"
msgstr "文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1316
msgid "Torrent not found?"
msgstr "种子未找到"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1324
msgid "File not found in torrent?"
msgstr "种子中没有发现文件?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1330
msgid "complete"
msgstr "完成"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1331
msgid "bytes remaining"
msgstr "剩余字节数"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1456
#, java-format
msgid "Torrent fetched from {0}"
msgstr "从{0}获取种子成功"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1484
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "{0}的种子中有错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "从{0}获得种子失败"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr "正在下载/上传无法更改I2CP设置"
#~ msgid "{0} torrents"
#~ msgstr "{0} 个种子"
#~ msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
#~ msgstr ""
#~ "【匿名性警告】\"{0}\" 中含有非I2P Tracker程序将从Tracker列表中将其删除。"
#~ msgid "Custom tracker URL"
#~ msgstr "自定义TrackerURL"
#~ msgid "Configure"
#~ msgstr "设置"

View File

@ -0,0 +1,17 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
# zzz - public domain
#
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
## need to cd into our orignal path - where we call sh.exe from.
cd $CALLFROM
## echo $PWD
## except this everything is the same with bundle-message.sh
## walking - public domain :-D
source bundle-messages.sh $PARAS

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="i2ptunnel">
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar" />
<target name="build" depends="builddep, jar, war" />
<target name="builddep">
<ant dir="../../ministreaming/java/" target="build" />
<ant dir="../../jetty/" target="build" />
@ -34,6 +34,10 @@
<compilerarg line="${javac.compilerargs}" />
</javac>
</target>
<!-- TODO: Move the web classes from the jar to the war - they are not part of the API
- This will require sponge to rewrite some seedless stuff that uses it.
-->
<target name="jar" depends="builddep, compile">
<jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class">
<manifest>
@ -41,14 +45,47 @@
<attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
</manifest>
</jar>
<ant target="war" />
</target>
<target name="war" depends="precompilejsp">
<target name="bundle" depends="compile, precompilejsp">
<!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
</exec>
</target>
<target name="poupdate" depends="compile, precompilejsp">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
<arg value="-p" />
</exec>
</target>
<target name="war" depends="precompilejsp, bundle">
<war destfile="build/i2ptunnel.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, **/*.java, *.jsp">
</war>
</target>
<target name="precompilejsp" unless="precompilejsp.uptodate">
<target name="precompilejsp" depends="jar" unless="precompilejsp.uptodate">
<delete dir="../jsp/WEB-INF/" />
<delete file="../jsp/web-fragment.xml" />
<delete file="../jsp/web-out.xml" />
@ -113,11 +150,7 @@
<delete file="../jsp/web-out.xml" />
</target>
<target name="cleandep" depends="clean">
<!-- ministreaming will clean core -->
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
<target name="distclean" depends="clean">
<!-- ministreaming will clean core -->
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
</project>

View File

@ -0,0 +1,26 @@
@echo off
set Callfrom=%cd%
set Paras=%1
rem before calling make sure you have msys and mingw 's "bin" path
rem in your current searching path
rem type "set path" to check
if not exist ..\locale\*.only goto updateALL
rem put a messages_xx.only(eg messages_zh.only) into locale folder
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
for %%i in (..\locale\*.only) do set PO=%%~ni
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
call sh --login %cd%\bmsg.sh
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
goto end
:updateALL
call sh --login %cd%\bmsg.sh
:end
echo End of Message Bundling

View File

@ -0,0 +1,87 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
#
# usage:
# bundle-messages.sh (generates the resource bundle from the .po file)
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
#
# zzz - public domain
#
CLASS=net.i2p.i2ptunnel.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
if [ "$1" = "-p" ]
then
POUPDATE=1
fi
# add ../java/ so the refs will work in the po file
JPATHS="../java/src ../jsp/WEB-INF"
for i in ../locale/messages_*.po
do
# get language
LG=${i#../locale/messages_}
LG=${LG%.po}
if [ "$POUPDATE" = "1" ]
then
# make list of java files newer than the .po file
find $JPATHS -name *.java -newer $i > $TMPFILE
fi
if [ -s ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web/messages_$LG.class -a \
../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web/messages_$LG.class -nt $i -a \
! -s $TMPFILE ]
then
continue
fi
if [ "$POUPDATE" = "1" ]
then
echo "Updating the $i file from the tags..."
# extract strings from java and jsp files, and update messages.po files
# translate calls must be one of the forms:
# _("foo")
# _x("foo")
# intl._("foo")
# intl.title("foo")
# In a jsp, you must use a helper or handler that has the context set.
# To start a new translation, copy the header from an old translation to the new .po file,
# then ant distclean updater.
find $JPATHS -name *.java > $TMPFILE
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
rm -f ${i}t
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
rm -f ${i}t
break
fi
rm -f ${i}t
# so we don't do this again
touch $i
fi
echo "Generating ${CLASS}_$LG ResourceBundle..."
# convert to class files in build/obj
msgfmt --java --statistics -r $CLASS -l $LG -d ../jsp/WEB-INF/classes $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
break
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0

View File

@ -1,72 +0,0 @@
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
* (c) 2003 - 2004 mihi
*/
package net.i2p.i2ptunnel;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import net.i2p.util.Log;
/**
* Read what i2ptunnel logs, and expose it in a buffer
*
*/
class BufferLogger implements Logging {
private final static Log _log = new Log(BufferLogger.class);
private ByteArrayOutputStream _baos; // FIXME should be final and use a factory. FIXME
private boolean _ignore;
/**
* Constructs a buffered logger.
*/
public BufferLogger() {
_baos = new ByteArrayOutputStream(512);
_ignore = false;
}
private final static String EMPTY = "";
/**
* Retrieves the buffer
* @return the buffer
*/
public String getBuffer() {
if (_ignore)
return EMPTY;
return new String(_baos.toByteArray());
}
/**
* We don't care about anything else the logger receives. This is useful
* for loggers passed in to servers and clients, since they will continue
* to add info to the logger, but if we're instantiated by the tunnel manager,
* its likely we only care about the first few messages it sends us.
*
*/
public void ignoreFurtherActions() {
_ignore = true;
synchronized (_baos) {
_baos.reset();
}
_baos = null;
}
/**
* Pass in some random data
* @param s String containing what we're logging.
*/
public void log(String s) {
if (_ignore) return;
if (s != null) {
_log.debug("logging [" + s + "]");
try {
_baos.write(s.getBytes());
_baos.write('\n');
} catch (IOException ioe) {
_log.error("Error logging [" + s + "]");
}
}
}
}

View File

@ -20,7 +20,7 @@ import java.util.zip.GZIPInputStream;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -124,13 +124,13 @@ class HTTPResponseOutputStream extends FilterOutputStream {
* Tweak that first HTTP response line (HTTP 200 OK, etc)
*
*/
protected String filterResponseLine(String line) {
protected static String filterResponseLine(String line) {
return line;
}
/** we ignore any potential \r, since we trim it on write anyway */
private static final byte NL = '\n';
private boolean isNL(byte b) { return (b == NL); }
private static boolean isNL(byte b) { return (b == NL); }
/** ok, received, now munge & write it */
private void writeHeader() throws IOException {
@ -219,7 +219,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
//out.flush();
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
new I2PThread(new Pusher(pi, out), "HTTP decompresser").start();
new I2PAppThread(new Pusher(pi, out), "HTTP decompresser").start();
out = po;
}
@ -275,7 +275,8 @@ class HTTPResponseOutputStream extends FilterOutputStream {
_context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, end-start);
}
}
private class InternalGZIPInputStream extends GZIPInputStream {
private static class InternalGZIPInputStream extends GZIPInputStream {
public InternalGZIPInputStream(InputStream in) throws IOException {
super(in);
}
@ -318,6 +319,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
return super.toString() + ": " + _in;
}
/*******
public static void main(String args[]) {
String simple = "HTTP/1.1 200 OK\n" +
"foo: bar\n" +
@ -367,7 +369,6 @@ class HTTPResponseOutputStream extends FilterOutputStream {
"A:\n" +
"\n";
/* */
test("Simple", simple, true);
test("Filtered", filtered, true);
test("Filtered windows", winfilter, true);
@ -382,7 +383,6 @@ class HTTPResponseOutputStream extends FilterOutputStream {
test("Invalid (bad headers)", invalid5, true);
test("Invalid (bad headers2)", invalid6, false);
test("Invalid (bad headers3)", invalid7, false);
/* */
}
private static void test(String name, String orig, boolean shouldPass) {
@ -401,4 +401,5 @@ class HTTPResponseOutputStream extends FilterOutputStream {
System.out.println("Properly fails with " + e.getMessage());
}
}
******/
}

View File

@ -61,6 +61,7 @@ import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.socks.I2PSOCKSIRCTunnel;
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
import net.i2p.i2ptunnel.streamr.StreamrConsumer;
import net.i2p.i2ptunnel.streamr.StreamrProducer;
@ -68,6 +69,9 @@ import net.i2p.util.EventDispatcher;
import net.i2p.util.EventDispatcherImpl;
import net.i2p.util.Log;
/**
* Todo: Most events are not listened to elsewhere, so error propagation is poor
*/
public class I2PTunnel implements Logging, EventDispatcher {
private Log _log;
private EventDispatcherImpl _event;
@ -162,7 +166,12 @@ public class I2PTunnel implements Logging, EventDispatcher {
System.out.print("I2PTunnel>");
String cmd = r.readLine();
if (cmd == null) break;
runCommand(cmd, this);
if (cmd.length() <= 0) continue;
try {
runCommand(cmd, this);
} catch (Throwable t) {
t.printStackTrace();
}
}
} catch (IOException ex) {
ex.printStackTrace();
@ -179,6 +188,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
/** @return non-null */
List<I2PSession> getSessions() {
synchronized (_sessions) {
return new ArrayList(_sessions);
@ -236,6 +246,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
runServer(args, l);
} else if ("httpserver".equals(cmdname)) {
runHttpServer(args, l);
} else if ("httpbidirserver".equals(cmdname)) {
runHttpBidirServer(args, l);
} else if ("ircserver".equals(cmdname)) {
runIrcServer(args, l);
} else if ("textserver".equals(cmdname)) {
@ -300,6 +312,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("ping <args>");
l.log("server <host> <port> <privkeyfile>");
l.log("httpserver <host> <port> <spoofedhost> <privkeyfile>");
l.log("httpbidirserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>");
l.log("textserver <host> <port> <privkey>");
l.log("genkeys <privkeyfile> [<pubkeyfile>]");
l.log("gentextkeys");
@ -347,6 +360,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {hostname, portNumber, privKeyFilename}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runServer(String args[], Logging l) {
if (args.length == 3) {
@ -359,7 +373,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Error resolving " + args[0] + uhe.getMessage());
}
try {
@ -368,17 +382,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[1]);
privKeyFile = new File(args[2]);
if (!privKeyFile.isAbsolute())
privKeyFile = new File(_context.getConfigDir(), args[2]);
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
l.log(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Cannot open private key file " + args[2]);
}
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
@ -396,6 +411,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
/**
* Same args as runServer
* (we should stop duplicating all this code...)
* @throws IllegalArgumentException on config problem
*/
public void runIrcServer(String args[], Logging l) {
if (args.length == 3) {
@ -408,7 +424,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Error resolving " + args[0] + uhe.getMessage());
}
try {
@ -417,17 +433,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[1]);
privKeyFile = new File(args[2]);
if (!privKeyFile.isAbsolute())
privKeyFile = new File(_context.getConfigDir(), args[2]);
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
l.log(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Cannot open private key file " + args[2]);
}
I2PTunnelServer serv = new I2PTunnelIRCServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
@ -453,6 +470,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {hostname, portNumber, spoofedHost, privKeyFilename}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runHttpServer(String args[], Logging l) {
if (args.length == 4) {
@ -465,7 +483,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Error resolving " + args[0] + uhe.getMessage());
}
try {
@ -474,8 +492,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[1]);
String spoofedHost = args[2];
@ -483,10 +502,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (!privKeyFile.isAbsolute())
privKeyFile = new File(_context.getConfigDir(), args[3]);
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
l.log(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Cannot open private key file " + args[3]);
}
I2PTunnelHTTPServer serv = new I2PTunnelHTTPServer(serverHost, portNum, privKeyFile, args[3], spoofedHost, l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
@ -503,16 +522,97 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
/**
* Run the HTTP server pointing at the host and port specified using the private i2p
* destination loaded from the specified file, replacing the HTTP headers
* so that the Host: specified is the one spoofed. Also runs an HTTP proxy for
* bidirectional communications on the same tunnel destination.<p />
*
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
*
* @param args {hostname, portNumber, proxyPortNumber, spoofedHost, privKeyFilename}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runHttpBidirServer(String args[], Logging l) {
if (args.length == 5) {
InetAddress serverHost = null;
int portNum = -1;
int port2Num = -1;
File privKeyFile = null;
try {
serverHost = InetAddress.getByName(args[0]);
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
throw new IllegalArgumentException(getPrefix() + "Error resolving " + args[0] + uhe.getMessage());
}
try {
portNum = Integer.parseInt(args[1]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
try {
port2Num = Integer.parseInt(args[2]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[2], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[1]);
if (port2Num <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[2]);
String spoofedHost = args[3];
privKeyFile = new File(args[4]);
if (!privKeyFile.isAbsolute())
privKeyFile = new File(_context.getConfigDir(), args[4]);
if (!privKeyFile.canRead()) {
l.log(getPrefix() + "Private key file does not exist or is not readable: " + args[4]);
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[4]);
notifyEvent("serverTaskId", Integer.valueOf(-1));
throw new IllegalArgumentException(getPrefix() + "Cannot open private key file " + args[4]);
}
I2PTunnelHTTPBidirServer serv = new I2PTunnelHTTPBidirServer(serverHost, portNum, port2Num, privKeyFile, args[3], spoofedHost, l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("httpserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>");
l.log(" creates a bidirectional 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,"
+ " and listens to host:proxyport to proxy HTTP requests.");
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
}
/**
* Run the server pointing at the host and port specified using the private i2p
* destination loaded from the given base64 stream. <p />
*
* Deprecated? Why run a server with a private destination?
* Not available from the war GUI
*
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
*
* @param args {hostname, portNumber, privKeyBase64}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runTextServer(String args[], Logging l) {
if (args.length == 3) {
@ -524,7 +624,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
throw new IllegalArgumentException(getPrefix() + "Error resolving " + args[0] + uhe.getMessage());
}
try {
@ -533,8 +633,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[1]);
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
@ -560,6 +661,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {portNumber, destinationBase64 or "file:filename"[, sharedClient [, privKeyFile]]}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runClient(String args[], Logging l) {
boolean isShared = true;
@ -573,8 +675,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("clientTaskId", Integer.valueOf(-1));
return;
}
if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
I2PTunnelTask task;
ownDest = !isShared;
try {
@ -588,6 +692,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
_log.error(getPrefix() + "Invalid I2PTunnel config to create a client [" + host + ":"+ port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
notifyEvent("clientTaskId", Integer.valueOf(-1));
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
// so this probably leaves the tunnel open if called from the CLI
throw iae;
}
} else {
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>] [<privKeyFile>]");
@ -609,6 +718,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {portNumber[, sharedClient][, proxy to be used for the WWW]}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runHttpClient(String args[], Logging l) {
if (args.length >= 1 && args.length <= 3) {
@ -619,8 +729,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
return;
}
if (clientPort <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
String proxy = "";
boolean isShared = true;
@ -655,6 +766,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ clientPort + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + clientPort + "]");
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
// so this probably leaves the tunnel open if called from the CLI
throw iae;
}
} else {
l.log("httpclient <port> [<sharedClient>] [<proxy>]");
@ -671,6 +787,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {portNumber[, sharedClient][, proxy to be used for the WWW]}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runConnectClient(String args[], Logging l) {
if (args.length >= 1 && args.length <= 3) {
@ -679,8 +796,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
_port = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
return;
}
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
String proxy = "";
boolean isShared = true;
@ -711,7 +829,12 @@ public class I2PTunnel implements Logging, EventDispatcher {
task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, (EventDispatcher) this, this);
addtask(task);
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ _port + "]", iae);
_log.error(getPrefix() + "Invalid I2PTunnel config to create a connect client [" + host + ":"+ _port + "]", iae);
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
// so this probably leaves the tunnel open if called from the CLI
throw iae;
}
} else {
l.log("connectclient <port> [<sharedClient>] [<proxy>]");
@ -731,6 +854,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {portNumber,destinationBase64 or "file:filename" [, sharedClient [, privKeyFile]]}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runIrcClient(String args[], Logging l) {
if (args.length >= 2) {
@ -741,8 +865,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
return;
}
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
boolean isShared = true;
if (args.length > 2) {
@ -770,6 +895,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ _port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + _port + "]");
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
// so this probably leaves the tunnel open if called from the CLI
throw iae;
}
} else {
l.log("ircclient <port> [<sharedClient> [<privKeyFile>]]");
@ -789,6 +919,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {portNumber [, sharedClient]}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runSOCKSTunnel(String args[], Logging l) {
if (args.length >= 1 && args.length <= 2) {
@ -799,8 +930,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
return;
}
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
boolean isShared = false;
if (args.length > 1)
@ -808,7 +940,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
ownDest = !isShared;
I2PTunnelTask task;
task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this);
task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this, null);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} else {
@ -818,11 +950,51 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
/**
* Run an SOCKS IRC tunnel on the given port number
* @param args {portNumber [, sharedClient]} or (portNumber, ignored (false), privKeyFile)
* @throws IllegalArgumentException on config problem
* @since 0.7.12
*/
public void runSOCKSIRCTunnel(String args[], Logging l) {
if (args.length >= 1 && args.length <= 3) {
int _port = -1;
try {
_port = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
}
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
boolean isShared = false;
if (args.length == 2)
isShared = "true".equalsIgnoreCase(args[1].trim());
ownDest = !isShared;
String privateKeyFile = null;
if (args.length == 3)
privateKeyFile = args[2];
I2PTunnelTask task;
task = new I2PSOCKSIRCTunnel(_port, l, ownDest, (EventDispatcher) this, this, privateKeyFile);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} else {
l.log("socksirctunnel <port> [<sharedClient> [<privKeyFile>]]");
l.log(" creates a tunnel for SOCKS IRC.");
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
}
}
/**
* Streamr client
*
* @param args {targethost, targetport, destinationString}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runStreamrClient(String args[], Logging l) {
if (args.length == 3) {
@ -843,8 +1015,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("streamrtunnelTaskId", Integer.valueOf(-1));
return;
}
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
StreamrConsumer task = new StreamrConsumer(_host, _port, args[2], l, (EventDispatcher) this, this);
task.startRunning();
@ -862,6 +1035,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
* @param args {port, privkeyfile}
* @param l logger to receive events and output
* @throws IllegalArgumentException on config problem
*/
public void runStreamrServer(String args[], Logging l) {
if (args.length == 2) {
@ -872,8 +1046,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("streamrtunnelTaskId", Integer.valueOf(-1));
return;
}
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
File privKeyFile = new File(args[1]);
if (!privKeyFile.isAbsolute())
@ -1414,7 +1589,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
private String getPrefix() { return '[' + _tunnelId + "]: "; }
private String getPrefix() { return "[" + _tunnelId + "]: "; }
public I2PAppContext getContext() { return _context; }

View File

@ -20,7 +20,7 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
private static final Log _log = new Log(I2PTunnelClient.class);
/** list of Destination objects that we point at */
protected List dests;
protected List<Destination> dests;
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1
protected long readTimeout = DEFAULT_READ_TIMEOUT;
@ -54,10 +54,21 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
}
}
if (dests.size() <= 0) {
l.log("No target destinations found");
if (dests.isEmpty()) {
l.log("No valid target destinations found");
notifyEvent("openClientResult", "error");
return;
// Nothing is listening for the above event, so it's useless
// Maybe figure out where to put a waitEventValue("openClientResult") ??
// In the meantime, let's do this the easy way
// Note that b32 dests will often not be resolvable at instantiation time;
// a delayed resolution system would be even better.
// Don't close() here, because it does a removeSession() and then
// TunnelController can't acquire() it to release() it.
//close(true);
// Unfortunately, super() built the whole tunnel before we get here.
throw new IllegalArgumentException("No valid target destinations found");
//return;
}
setName(getLocalPort() + " -> " + destinations);
@ -78,8 +89,9 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
i2ps.setReadTimeout(readTimeout);
new I2PTunnelRunner(s, i2ps, sockLock, null, mySockets);
} catch (Exception ex) {
_log.info("Error connecting", ex);
l.log(ex.getMessage());
if (_log.shouldLog(Log.INFO))
_log.info("Error connecting", ex);
//l.log("Error connecting: " + ex.getMessage());
closeSocket(s);
if (i2ps != null) {
synchronized (sockLock) {
@ -97,8 +109,8 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
return null;
}
if (size == 1) // skip the rand in the most common case
return (Destination)dests.get(0);
return dests.get(0);
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
return (Destination)dests.get(index);
return dests.get(index);
}
}

View File

@ -27,7 +27,7 @@ import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
@ -67,7 +67,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// private Object conLock = new Object();
/** List of Socket for those accept()ed but not yet started up */
private List _waitingSockets = new ArrayList(); // FIXME should be final and use a factory. FIXME
protected final List _waitingSockets = new ArrayList(4); // FIXME should be final and use a factory. FIXME
/** How many connections will we allow to be in the process of being built at once? */
private int _numConnectionBuilders;
/** How long will we allow sockets to sit in the _waitingSockets map before killing them? */
@ -89,12 +89,52 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static final int DEFAULT_NUM_CONNECTION_BUILDERS = 5;
private static final int DEFAULT_MAX_WAIT_TIME = 30*1000;
//public I2PTunnelClientBase(int localPort, boolean ownDest,
// Logging l) {
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
//}
// true if we are chained from a server.
private boolean chained = false;
public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {
super(localPort + " (uninitialized)", notifyThis, tunnel);
chained = true;
sockMgr = sktMgr;
_clientId = clientId;
this.localPort = localPort;
this.l = l;
this.handlerName = handlerName + _clientId;
_ownDest = true; // == ! shared client
_context = tunnel.getContext();
_context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
listenerReady = false;
t.start();
open = true;
synchronized (this) {
while (!listenerReady && open) {
try {
wait();
} catch (InterruptedException e) {
// ignore
}
}
}
configurePool(tunnel);
if (open && listenerReady) {
l.log("Ready! Port " + getLocalPort());
notifyEvent("openBaseClientResult", "ok");
} else {
l.log("Error listening - please see the logs!");
notifyEvent("openBaseClientResult", "error");
}
}
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
I2PTunnel tunnel) throws IllegalArgumentException {
@ -153,7 +193,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
} // else delay creating session until createI2PSocket() is called
Thread t = new I2PThread(this);
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
listenerReady = false;
t.start();
@ -188,7 +228,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
*
*/
private void configurePool(I2PTunnel tunnel) {
_waitingSockets = new ArrayList(4);
//_waitingSockets = new ArrayList(4);
Properties opts = tunnel.getClientOptions();
String maxWait = opts.getProperty(PROP_MAX_WAIT_TIME, DEFAULT_MAX_WAIT_TIME+"");
@ -207,7 +247,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
for (int i = 0; i < _numConnectionBuilders; i++) {
String name = "ClientBuilder" + _clientId + '.' + i;
I2PThread b = new I2PThread(new TunnelConnectionBuilder(), name);
I2PAppThread b = new I2PAppThread(new TunnelConnectionBuilder(), name);
b.setDaemon(true);
b.start();
}
@ -350,7 +390,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* called by derived classes after initialization.
*
*/
public final void startRunning() {
public void startRunning() {
synchronized (startLock) {
startRunning = true;
startLock.notify();
@ -490,7 +530,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected void manageConnection(Socket s) {
if (s == null) return;
if (_numConnectionBuilders <= 0) {
new I2PThread(new BlockingRunner(s), "Clinet run").start();
new I2PAppThread(new BlockingRunner(s), "Clinet run").start();
return;
}
@ -543,6 +583,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
public boolean close(boolean forced) {
if (_log.shouldLog(Log.INFO))
_log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr);
if (!open) return true;
// FIXME: here we might have to wait quite a long time if
// there is a connection attempt atm. But without waiting we
@ -559,10 +601,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
return false;
}
I2PSession session = sockMgr.getSession();
if (session != null) {
getTunnel().removeSession(session);
}
if (!chained) {
I2PSession session = sockMgr.getSession();
if (session != null) {
getTunnel().removeSession(session);
}
} // else the app chaining to this one closes it!
}
l.log("Closing client " + toString());
open = false;
@ -599,7 +643,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
while (open) {
try {
synchronized (_waitingSockets) {
if (_waitingSockets.size() <= 0)
if (_waitingSockets.isEmpty())
_waitingSockets.wait();
else
s = (Socket)_waitingSockets.remove(0);

View File

@ -0,0 +1,54 @@
/**
* 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.i2ptunnel;
// import java.util.ArrayList;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.EventDispatcher;
/**
* Reuse HTTP server's I2PSocketManager for a proxy with no outproxy capability.
*
* @author sponge
*/
public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runnable {
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
*/
public I2PTunnelHTTPBidirProxy(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) {
super(localPort, l, sockMgr, tunnel, notifyThis, clientId);
// proxyList = new ArrayList();
setName(getLocalPort() + " -> HTTPClient [NO PROXIES]");
startRunning();
notifyEvent("openHTTPClientResult", "ok");
}
}

View File

@ -0,0 +1,44 @@
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
* (c) 2003 - 2004 mihi
*/
package net.i2p.i2ptunnel;
import java.io.File;
import java.io.InputStream;
import java.net.InetAddress;
import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer {
private final static Log log = new Log(I2PTunnelHTTPBidirServer.class);
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, spoofHost, l, notifyThis, tunnel);
finishSetupI2PTunnelHTTPBidirServer(l, proxyport);
}
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, File privkey, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privkey, privkeyname, spoofHost, l, notifyThis, tunnel);
finishSetupI2PTunnelHTTPBidirServer(l, proxyport);
}
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, InputStream privData, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, privkeyname, spoofHost, l, notifyThis, tunnel);
finishSetupI2PTunnelHTTPBidirServer(l, proxyport);
}
private void finishSetupI2PTunnelHTTPBidirServer(Logging l, int proxyport) {
localPort = proxyport;
bidir = true;
/* start the httpclient */
task = new I2PTunnelHTTPBidirProxy(localPort, l, sockMgr, getTunnel(), getEventDispatcher(), __serverId);
sockMgr.setName("Server"); // TO-DO: Need to change this to "Bidir"!
getTunnel().addSession(sockMgr.getSession());
l.log("Ready!");
notifyEvent("openServerResult", "ok");
}
}

View File

@ -24,13 +24,16 @@ import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Base32;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.Translate;
/**
* Act as a mini HTTP proxy, handling various different types of requests,
@ -41,10 +44,16 @@ import net.i2p.util.Log;
* $method $path $protocolVersion\nHost: $site
* or
* $method http://i2p/$b64key/$path $protocolVersion
* or
* or
* $method /$site/$path $protocolVersion
* or (deprecated)
* $method /eepproxy/$site/$path $protocolVersion
* </pre>
*
* Note that http://i2p/$b64key/... and /eepproxy/$site/... are not recommended
* in browsers or other user-visible applications, as relative links will not
* resolve correctly, cookies won't work, etc.
*
* If the $site resolves with the I2P naming service, then it is directed towards
* that eepsite, otherwise it is directed towards this client's outproxy (typically
* "squid.i2p"). Only HTTP is supported (no HTTPS, ftp, mailto, etc). Both GET
@ -54,7 +63,7 @@ import net.i2p.util.Log;
public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClient.class);
private final List proxyList;
protected final List proxyList = new ArrayList();
private HashMap addressHelpers = new HashMap();
@ -70,7 +79,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"<html><body><H1>I2P ERROR: REQUEST DENIED</H1>"+
"You attempted to connect to a non-I2P website or location.<BR>")
.getBytes();
private final static byte[] ERR_DESTINATION_UNKNOWN =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -80,10 +89,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"That I2P Destination was not found. Perhaps you pasted in the "+
"wrong BASE64 I2P Destination or the link you are following is "+
"bad. The host (or the WWW proxy, if you're using one) could also "+
"be temporarily offline. You may want to <b>retry</b>. "+
"be temporarily offline. You may want to <b>retry</b>. "+
"Could not find the following Destination:<BR><BR><div>")
.getBytes();
/*****
private final static byte[] ERR_TIMEOUT =
("HTTP/1.1 504 Gateway Timeout\r\n"+
@ -107,7 +116,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"Your request was for a site outside of I2P, but you have no "+
"HTTP outproxy configured. Please configure an outproxy in I2PTunnel")
.getBytes();
private final static byte[] ERR_AHELPER_CONFLICT =
("HTTP/1.1 409 Conflict\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -123,7 +132,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"discarding the host entry from your host database, "+
"or naming one of them differently.<p>")
.getBytes();
private final static byte[] ERR_BAD_PROTOCOL =
("HTTP/1.1 403 Bad Protocol\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -133,7 +142,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"The request uses a bad protocol. "+
"The I2P HTTP Proxy supports http:// requests ONLY. Other protocols such as https:// and ftp:// are not allowed.<BR>")
.getBytes();
private final static byte[] ERR_LOCALHOST =
("HTTP/1.1 403 Access Denied\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -142,23 +151,31 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"<html><body><H1>I2P ERROR: REQUEST DENIED</H1>"+
"Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.<BR>")
.getBytes();
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
private static final File _errorDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs");
public I2PTunnelHTTPClient(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) {
super(localPort, l, sockMgr, tunnel, notifyThis, clientId);
// proxyList = new ArrayList();
setName(getLocalPort() + " -> HTTPClient [NO PROXIES]");
startRunning();
notifyEvent("openHTTPClientResult", "ok");
}
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
*/
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest,
String wwwProxy, EventDispatcher notifyThis,
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest,
String wwwProxy, EventDispatcher notifyThis,
I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
proxyList = new ArrayList();
//proxyList = new ArrayList(); // We won't use outside of i2p
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openHTTPClientResult", "error");
return;
@ -178,14 +195,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
private String selectProxy() {
synchronized (proxyList) {
int size = proxyList.size();
if (size <= 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Proxy list is empty - no outproxy available");
l.log("Proxy list is emtpy - no outproxy available");
l.log("Proxy list is empty - no outproxy available");
return null;
}
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
@ -195,8 +212,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private static final int DEFAULT_READ_TIMEOUT = 60*1000;
/**
/**
* create the default options (using the default timeout, etc)
* unused?
*/
@ -212,8 +229,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
return opts;
}
/**
/**
* create the default options (using the default timeout, etc)
*
*/
@ -233,12 +250,37 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
return opts;
}
private InternalSocketRunner isr;
/**
* Actually start working on incoming connections.
* Overridden to start an internal socket too.
*
*/
@Override
public void startRunning() {
super.startRunning();
this.isr = new InternalSocketRunner(this);
}
/**
* Overridden to close internal socket too.
*/
@Override
public boolean close(boolean forced) {
boolean rv = super.close(forced);
if (this.isr != null)
this.isr.stopRunning();
return rv;
}
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";
public static final String PROP_JUMP_SERVERS = "i2ptunnel.httpclient.jumpServers";
private static long __requestId = 0;
protected void clientConnectionRun(Socket s) {
InputStream in = null;
@ -258,23 +300,25 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
line = line.trim();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Line=[" + line + "]");
String lowercaseLine = line.toLowerCase();
if (lowercaseLine.startsWith("connection: ") ||
lowercaseLine.startsWith("keep-alive: ") ||
if (lowercaseLine.startsWith("connection: ") ||
lowercaseLine.startsWith("keep-alive: ") ||
lowercaseLine.startsWith("proxy-connection: "))
continue;
if (method == null) { // first line (GET /base64/realaddr)
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Method is null for [" + line + "]");
_log.debug(getPrefix(requestId) + "First line [" + line + "]");
int pos = line.indexOf(" ");
if (pos == -1) break;
method = line.substring(0, pos);
// TODO use Java URL class to make all this simpler and more robust
// That will also fix IPV6 [a:b:c]
String request = line.substring(pos + 1);
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
// what is this for ???
request = "http://i2p" + request;
} else if (request.startsWith("/eepproxy/")) {
// /eepproxy/foo.i2p/bar/baz.html HTTP/1.0
@ -286,6 +330,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
// "http://" + "foo.i2p/bar/baz.html" + " HTTP/1.0"
request = "http://" + uri + subRequest.substring(protopos);
} else if (request.toLowerCase().startsWith("http://i2p/")) {
// http://i2p/b64key/bar/baz.html HTTP/1.0
String subRequest = request.substring("http://i2p/".length());
int protopos = subRequest.indexOf(" ");
String uri = subRequest.substring(0, protopos);
if (uri.indexOf("/") == -1) {
uri = uri + "/";
}
// "http://" + "b64key/bar/baz.html" + " HTTP/1.0"
request = "http://" + uri + subRequest.substring(protopos);
}
pos = request.indexOf("//");
@ -298,29 +352,53 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
targetRequest = request;
// pos is the start of the path
pos = request.indexOf("/");
if (pos == -1) {
method = null;
break;
}
host = request.substring(0, pos);
// parse port
int posPort = host.indexOf(":");
int port = 80;
if(posPort != -1) {
String[] parts = host.split(":");
try {
host = parts[0];
} catch (ArrayIndexOutOfBoundsException ex) {
if (out != null) {
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
writeFooter(out);
}
s.close();
return;
}
try {
port = Integer.parseInt(parts[1]);
} catch(Exception exc) {
// TODO: log this
}
}
if (host.toLowerCase().equals("proxy.i2p")) {
// Go through the various types of host names, set
// the host and destination variables accordingly,
// and transform the first line.
// For all i2p network hosts, ensure that the host is a
// Base 32 hostname so that we do not reveal our name for it
// in our addressbook (all naming is local),
// and it is removed from the request line.
if (host.length() >= 516 && host.indexOf(".") < 0) {
// http://b64key/bar/baz.html
destination = host;
host = getHostName(destination);
line = method + ' ' + request.substring(pos);
} else if (host.toLowerCase().equals("proxy.i2p")) {
// so we don't do any naming service lookups
destination = "proxy.i2p";
destination = host;
usingInternalServer = true;
} else if (host.toLowerCase().endsWith(".i2p")) {
// Destination gets the host name
@ -334,7 +412,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// and split the request into it's component parts for rebuilding later
String ahelperKey = null;
boolean ahelperConflict = false;
String fragments = request.substring(pos2 + 1);
String uriPath = request.substring(0, pos2);
pos2 = fragments.indexOf(" ");
@ -348,15 +426,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
pos2 = fragments.indexOf("&");
fragment = fragments.substring(0, pos2);
fragments = fragments.substring(pos2 + 1);
// Fragment looks like addresshelper key
if (fragment.startsWith("i2paddresshelper=")) {
pos2 = fragment.indexOf("=");
ahelperKey = fragment.substring(pos2 + 1);
// Key contains data, lets not ignore it
if (ahelperKey != null) {
// ahelperKey will be validated later
// Host resolvable only with addresshelper
if ( (host == null) || ("i2p".equals(host)) )
{
@ -365,12 +444,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} else {
// Host resolvable from database, verify addresshelper key
// Silently bypass correct keys, otherwise alert
if (!host.equals(ahelperKey))
String destB64 = null;
try {
Destination _dest = I2PTunnel.destFromName(host);
if (_dest != null)
destB64 = _dest.toBase64();
} catch (DataFormatException dfe) {}
if (destB64 != null && !destB64.equals(ahelperKey))
{
// Conflict: handle when URL reconstruction done
ahelperConflict = true;
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination + "], trusted key [" + host + "], specified key [" + ahelperKey + "].");
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination + "], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
}
}
}
@ -380,26 +465,34 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if ("".equals(urlEncoding)) {
urlEncoding = "?" + fragment;
} else {
urlEncoding = urlEncoding + "&" + fragment;
urlEncoding = urlEncoding + "&" + fragment;
}
}
}
// Reconstruct the request minus the i2paddresshelper GET var
request = uriPath + urlEncoding + " " + protocolVersion;
// Did addresshelper key conflict?
if (ahelperConflict)
{
if (out != null) {
// Fixme untranslated
long alias = I2PAppContext.getGlobalContext().random().nextLong();
String trustedURL = protocol + uriPath + urlEncoding;
String conflictURL = protocol + alias + ".i2p/?" + initialFragments;
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
out.write(header);
out.write(("To visit the destination in your host database, click <a href=\"" + trustedURL + "\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"" + conflictURL + "\">here</a>.<p></div>").getBytes());
writeFooter(out);
// convert ahelperKey to b32
String alias = getHostName(ahelperKey);
if (alias.equals("i2p")) {
// bad ahelperKey
byte[] header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
writeErrorMessage(header, out, targetRequest, false, destination, null);
} else {
String trustedURL = protocol + uriPath + urlEncoding;
// Fixme - any path is lost
String conflictURL = protocol + alias + '/' + urlEncoding;
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
out.write(header);
out.write(_("To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, click <a href=\"{1}\">here</a>.", trustedURL, conflictURL).getBytes("UTF-8"));
out.write(("<p></div>").getBytes());
writeFooter(out);
}
}
s.close();
return;
@ -412,9 +505,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
host = getHostName(destination);
ahelper = 1;
}
line = method + " " + request.substring(pos);
} else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1")) {
} else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1") ||
host.startsWith("192.168.")) {
// if somebody is trying to get to 192.168.example.com, oh well
if (out != null) {
out.write(getErrorPage("localhost", ERR_LOCALHOST));
writeFooter(out);
@ -446,6 +541,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
} else {
// what is left for here? a hostname with no dots, and != "i2p"
// and not a destination ???
// Perhaps something in privatehosts.txt ...
request = request.substring(pos + 1);
pos = request.indexOf("/");
if (pos < 0) {
@ -458,33 +556,51 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
return;
}
destination = request.substring(0, pos);
host = getHostName(destination);
line = method + " " + request.substring(pos);
} // end host name processing
if (port != 80 && !usingWWWProxy) {
if (out != null) {
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
writeFooter(out);
}
s.close();
return;
}
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
if (!isValid) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "notValid(" + host + ")");
method = null;
destination = null;
break;
} else if ((!usingWWWProxy) && (!usingInternalServer)) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "host=getHostName(" + destination + ")");
host = getHostName(destination); // hide original host
}
// don't do this, it forces yet another hostname lookup,
// and in all cases host was already set above
//if ((!usingWWWProxy) && (!usingInternalServer)) {
// String oldhost = host;
// host = getHostName(destination); // hide original host
// if (_log.shouldLog(Log.INFO))
// _log.info(getPrefix(requestId) + " oldhost " + oldhost + " newhost " + host + " dest " + destination);
//}
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(getPrefix(requestId) + "METHOD:" + method + ":");
_log.debug(getPrefix(requestId) + "PROTOC:" + protocol + ":");
_log.debug(getPrefix(requestId) + "HOST :" + host + ":");
_log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
_log.debug(getPrefix(requestId) + "METHOD: \"" + method + "\"");
_log.debug(getPrefix(requestId) + "PROTOC: \"" + protocol + "\"");
_log.debug(getPrefix(requestId) + "HOST : \"" + host + "\"");
_log.debug(getPrefix(requestId) + "DEST : \"" + destination + "\"");
}
// end first line processing
} else {
if (lowercaseLine.startsWith("host: ") && !usingWWWProxy) {
// Note that we only pass the original Host: line through to the outproxy
// But we don't create a Host: line if it wasn't sent to us
line = "Host: " + host;
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Setting host = " + host);
} else if (lowercaseLine.startsWith("user-agent: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
@ -514,7 +630,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
if (line.length() == 0) {
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
boolean gzip = DEFAULT_GZIP;
if (ok != null)
@ -526,9 +642,14 @@ 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");
}
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");
if (!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
// let's not advertise to external sites that we are from I2P
if (usingWWWProxy)
newRequest.append("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6\r\n");
else
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
}
newRequest.append("Connection: close\r\n\r\n");
break;
} else {
newRequest.append(line).append("\r\n"); // HTTP spec
@ -539,7 +660,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
if (method == null || destination == null) {
l.log("No HTTP method found in the request.");
//l.log("No HTTP method found in the request.");
if (out != null) {
if ("http://".equalsIgnoreCase(protocol))
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
@ -550,10 +671,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
s.close();
return;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Destination: " + destination);
// Serve local proxy files (images, css linked from error pages)
// Ignore all the headers
if (usingInternalServer) {
@ -562,13 +683,22 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
return;
}
Destination clientDest = I2PTunnel.destFromName(destination);
// If the host is "i2p", the getHostName() lookup failed, don't try to
// look it up again as the naming service does not do negative caching
// so it will be slow.
Destination clientDest;
if ("i2p".equals(host))
clientDest = null;
else
clientDest = I2PTunnel.destFromName(destination);
if (clientDest == null) {
//l.log("Could not resolve " + destination + ".");
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest);
byte[] header;
boolean showAddrHelper = false;
String jumpServers = null;
if (usingWWWProxy)
header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
else if(ahelper != 0)
@ -577,14 +707,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
header = getErrorPage("dnf", ERR_DESTINATION_UNKNOWN);
else {
header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN);
showAddrHelper = true;
jumpServers = getTunnel().getClientOptions().getProperty(PROP_JUMP_SERVERS);
if (jumpServers == null)
jumpServers = DEFAULT_JUMP_SERVERS;
}
writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination, showAddrHelper);
writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination, jumpServers);
s.close();
return;
}
String remoteID;
Properties opts = new Properties();
//opts.setProperty("i2p.streaming.inactivityTimeout", ""+120*1000);
// 1 == disconnect. see ConnectionOptions in the new streaming lib, which i
@ -595,24 +727,27 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
I2PTunnelRunner runner = new I2PTunnelHTTPClientRunner(s, i2ps, sockLock, data, mySockets, onTimeout);
} catch (SocketException ex) {
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
l.log(ex.getMessage());
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
//l.log("Error connecting: " + ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
} catch (IOException ex) {
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
l.log(ex.getMessage());
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
//l.log("Error connecting: " + ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
} catch (I2PException ex) {
_log.info("getPrefix(requestId) + Error trying to connect", ex);
l.log(ex.getMessage());
if (_log.shouldLog(Log.INFO))
_log.info("getPrefix(requestId) + Error trying to connect", ex);
//l.log("Error connecting: " + ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
} catch (OutOfMemoryError oom) {
IOException ex = new IOException("OOM");
_log.info("getPrefix(requestId) + Error trying to connect", ex);
l.log(ex.getMessage());
_log.error("getPrefix(requestId) + Error trying to connect", oom);
//l.log("Error connecting: " + ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
}
@ -624,6 +759,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
* We can't use BufferedReader for POST because we can't have readahead,
* since we are passing the stream on to I2PTunnelRunner for the POST data.
*
* Warning - BufferedReader removes \r, DataHelper does not
* Warning - DataHelper limits line length, BufferedReader does not
* Todo: Limit line length for buffered reads, or go back to unbuffered for all
*/
private static class InputReader {
BufferedReader _br;
@ -633,20 +771,27 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_s = s;
}
String readLine(String method) throws IOException {
if (method == null || "POST".equals(method))
// Use unbuffered until we can find a BufferedReader that limits line length
//if (method == null || "POST".equals(method))
return DataHelper.readLine(_s);
if (_br == null)
_br = new BufferedReader(new InputStreamReader(_s, "ISO-8859-1"));
return _br.readLine();
//if (_br == null)
// _br = new BufferedReader(new InputStreamReader(_s, "ISO-8859-1"));
//return _br.readLine();
}
}
/**
* @return b32hash.b32.i2p, or "i2p" on lookup failure.
* Prior to 0.7.12, returned b64 key
*/
private final static String getHostName(String host) {
if (host == null) return null;
if (host.length() == 60 && host.toLowerCase().endsWith(".b32.i2p"))
return host;
try {
Destination dest = I2PTunnel.destFromName(host);
if (dest == null) return "i2p";
return dest.toBase64();
return Base32.encode(dest.calculateHash().getData()) + ".b32.i2p";
} catch (DataFormatException dfe) {
return "i2p";
}
@ -728,21 +873,22 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Timeout occured requesting " + _target);
handleHTTPClientException(new RuntimeException("Timeout"), _out,
handleHTTPClientException(new RuntimeException("Timeout"), _out,
_target, _usingProxy, _wwwProxy, _requestId);
closeSocket(_socket);
}
}
private static String jumpServers[] = {
"http://i2host.i2p/cgi-bin/i2hostjump?",
// "http://orion.i2p/jump/",
"http://stats.i2p/cgi-bin/jump.cgi?a=",
// "http://trevorreznik.i2p/cgi-bin/jump.php?hostname=",
"http://i2jump.i2p/"
};
private static String DEFAULT_JUMP_SERVERS =
"http://i2host.i2p/cgi-bin/i2hostjump?," +
"http://stats.i2p/cgi-bin/jump.cgi?a=," +
"http://i2jump.i2p/";
/**
* @param jumpServers comma- or space-separated list, or null
*/
private static void writeErrorMessage(byte[] errMessage, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy, boolean showAddrHelper) throws IOException {
boolean usingWWWProxy, String wwwProxy, String jumpServers) throws IOException {
if (out != null) {
out.write(errMessage);
if (targetRequest != null) {
@ -758,12 +904,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
out.write(uri.getBytes());
out.write("</a>".getBytes());
if (usingWWWProxy) out.write(("<br>WWW proxy: " + wwwProxy).getBytes());
if (showAddrHelper) {
// Fixme untranslated
out.write("<br><br>Click a link below to look for an address helper by using a \"jump\" service:<br>".getBytes());
for (int i = 0; i < jumpServers.length; i++) {
if (jumpServers != null && jumpServers.length() > 0) {
out.write("<br><br>".getBytes());
out.write(_("Click a link below to look for an address helper by using a \"jump\" service:").getBytes("UTF-8"));
out.write("<br>".getBytes());
StringTokenizer tok = new StringTokenizer(jumpServers, ", ");
while (tok.hasMoreTokens()) {
String jurl = tok.nextToken();
if (!jurl.startsWith("http://"))
continue;
// Skip jump servers we don't know
String jumphost = jumpServers[i].substring(7); // "http://"
String jumphost = jurl.substring(7); // "http://"
jumphost = jumphost.substring(0, jumphost.indexOf('/'));
try {
Destination dest = I2PTunnel.destFromName(jumphost);
@ -773,10 +925,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
out.write("<br><a href=\"".getBytes());
out.write(jumpServers[i].getBytes());
out.write(jurl.getBytes());
out.write(uri.getBytes());
out.write("\">".getBytes());
out.write(jumpServers[i].getBytes());
out.write(jurl.getBytes());
out.write(uri.getBytes());
out.write("</a>".getBytes());
}
@ -789,7 +941,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
private static void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy, long requestId) {
// static
//if (_log.shouldLog(Log.WARN))
// _log.warn(getPrefix(requestId) + "Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
@ -800,7 +952,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
header = getErrorPage(I2PAppContext.getGlobalContext(), "dnfp", ERR_DESTINATION_UNKNOWN);
else
header = getErrorPage(I2PAppContext.getGlobalContext(), "dnf", ERR_DESTINATION_UNKNOWN);
writeErrorMessage(header, out, targetRequest, usingWWWProxy, wwwProxy, false);
writeErrorMessage(header, out, targetRequest, usingWWWProxy, wwwProxy, null);
} catch (IOException ioe) {
// static
//_log.warn(getPrefix(requestId) + "Error writing out the 'destination was unknown' " + "message", ioe);
@ -813,8 +965,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
private final static String SUPPORTED_HOSTS[] = { "i2p", "www.i2p.com", "i2p."};
/** @param host ignored */
private static boolean isSupportedAddress(String host, String protocol) {
if ((host == null) || (protocol == null)) return false;
/****
* Let's not look up the name _again_
* and now that host is a b32, this was failing
*
boolean found = false;
String lcHost = host.toLowerCase();
for (int i = 0; i < SUPPORTED_HOSTS.length; i++) {
@ -831,7 +989,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} catch (DataFormatException dfe) {
}
}
****/
return protocol.equalsIgnoreCase("http://");
}
@ -910,4 +1068,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
out.flush();
} catch (IOException ioe) {}
}
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
/** lang in routerconsole.lang property, else current locale */
public static String _(String key) {
return Translate.getString(key, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}
/** {0} and {1} */
public static String _(String key, Object o, Object o2) {
return Translate.getString(key, o, o2, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}
}

View File

@ -17,7 +17,7 @@ import java.util.zip.GZIPOutputStream;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataHelper;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.data.Base32;
@ -39,21 +39,21 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
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", 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 });
setupI2PTunnelHTTPServer(spoofHost);
}
public I2PTunnelHTTPServer(InetAddress host, int port, File privkey, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privkey, privkeyname, 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 });
setupI2PTunnelHTTPServer(spoofHost);
}
public I2PTunnelHTTPServer(InetAddress host, int port, InputStream privData, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, privkeyname, l, notifyThis, tunnel);
_spoofHost = spoofHost;
setupI2PTunnelHTTPServer(spoofHost);
}
private void setupI2PTunnelHTTPServer(String spoofHost) {
_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 });
}
@ -118,7 +118,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
useGZIP = true;
if (allowGZIP && useGZIP) {
I2PThread req = new I2PThread(new CompressedRequestor(s, socket, modifiedHeader), Thread.currentThread().getName()+".hc");
I2PAppThread req = new I2PAppThread(new CompressedRequestor(s, socket, modifiedHeader), Thread.currentThread().getName()+".hc");
req.start();
} else {
new I2PTunnelRunner(s, socket, slock, null, modifiedHeader.getBytes(), null);
@ -151,7 +151,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
_log.warn("Took a while to handle the request [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
}
private class CompressedRequestor implements Runnable {
private static class CompressedRequestor implements Runnable {
private Socket _webserver;
private I2PSocket _browser;
private String _headers;
@ -174,7 +174,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
_log.info("request headers: " + _headers);
serverout.write(_headers.getBytes());
browserin = _browser.getInputStream();
I2PThread sender = new I2PThread(new Sender(serverout, browserin, "server: browser to server"), Thread.currentThread().getName() + "hcs");
I2PAppThread sender = new I2PAppThread(new Sender(serverout, browserin, "server: browser to server"), Thread.currentThread().getName() + "hcs");
sender.start();
browserout = _browser.getOutputStream();
@ -214,7 +214,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
}
private class Sender implements Runnable {
private static class Sender implements Runnable {
private OutputStream _out;
private InputStream _in;
private String _name;
@ -248,7 +249,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
}
private class CompressedResponseOutputStream extends HTTPResponseOutputStream {
private static class CompressedResponseOutputStream extends HTTPResponseOutputStream {
private InternalGZIPOutputStream _gzipOut;
public CompressedResponseOutputStream(OutputStream o) {
super(o);
@ -287,7 +289,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
return 0;
}
}
private class InternalGZIPOutputStream extends GZIPOutputStream {
private static class InternalGZIPOutputStream extends GZIPOutputStream {
public InternalGZIPOutputStream(OutputStream target) throws IOException {
super(target);
}
@ -309,7 +312,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
private String formatHeaders(Properties headers, StringBuilder command) {
private static String formatHeaders(Properties headers, StringBuilder command) {
StringBuilder buf = new StringBuilder(command.length() + headers.size() * 64);
buf.append(command.toString().trim()).append("\r\n");
for (Iterator iter = headers.keySet().iterator(); iter.hasNext(); ) {
@ -321,6 +324,9 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
return buf.toString();
}
/** ridiculously long, just to prevent OOM DOS @since 0.7.13 */
private static final int MAX_HEADERS = 60;
private Properties readHeaders(InputStream in, StringBuilder command) throws IOException {
Properties headers = new Properties();
StringBuilder buf = new StringBuilder(128);
@ -344,7 +350,10 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if (trimmed > 0)
getTunnel().getContext().statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
int i = 0;
while (true) {
if (++i > MAX_HEADERS)
throw new IOException("Too many header lines - max " + MAX_HEADERS);
buf.setLength(0);
ok = DataHelper.readLine(in, buf);
if (!ok) throw new IOException("EOF reached before the end of the headers [" + buf.toString() + "]");

View File

@ -14,9 +14,12 @@ import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
* Todo: Can we extend I2PTunnelClient instead and remove some duplicated code?
*/
public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelIRCClient.class);
@ -25,7 +28,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
private static volatile long __clientId = 0;
/** list of Destination objects that we point at */
protected List dests;
protected List<Destination> dests;
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1
protected long readTimeout = DEFAULT_READ_TIMEOUT;
@ -47,7 +50,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
"IRCHandler " + (++__clientId), tunnel, pkf);
StringTokenizer tok = new StringTokenizer(destinations, ", ");
dests = new ArrayList(1);
dests = new ArrayList(2);
while (tok.hasMoreTokens()) {
String destination = tok.nextToken();
try {
@ -61,10 +64,21 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
}
}
if (dests.size() <= 0) {
if (dests.isEmpty()) {
l.log("No target destinations found");
notifyEvent("openClientResult", "error");
return;
// Nothing is listening for the above event, so it's useless
// Maybe figure out where to put a waitEventValue("openClientResult") ??
// In the meantime, let's do this the easy way
// Note that b32 dests will often not be resolvable at instantiation time;
// a delayed resolution system would be even better.
// Don't close() here, because it does a removeSession() and then
// TunnelController can't acquire() it to release() it.
//close(true);
// Unfortunately, super() built the whole tunnel before we get here.
throw new IllegalArgumentException("No valid target destinations found");
//return;
}
setName(getLocalPort() + " -> IRCClient");
@ -82,15 +96,15 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
try {
i2ps = createI2PSocket(clientDest);
i2ps.setReadTimeout(readTimeout);
StringBuilder expectedPong = new StringBuilder();
Thread in = new I2PThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in");
StringBuffer expectedPong = new StringBuffer();
Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in", true);
in.start();
Thread out = new I2PThread(new IrcOutboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " out");
Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " out", true);
out.start();
} catch (Exception ex) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting", ex);
l.log(ex.getMessage());
//l.log("Error connecting: " + ex.getMessage());
closeSocket(s);
if (i2ps != null) {
synchronized (sockLock) {
@ -109,27 +123,28 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return null;
}
if (size == 1) // skip the rand in the most common case
return (Destination)dests.get(0);
return dests.get(0);
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
return (Destination)dests.get(index);
return dests.get(index);
}
/*************************************************************************
*
*/
private class IrcInboundFilter implements Runnable {
public static class IrcInboundFilter implements Runnable {
private Socket local;
private I2PSocket remote;
private StringBuilder expectedPong;
private StringBuffer expectedPong;
IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuilder pong) {
public IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
remote=_remote;
expectedPong=pong;
}
public void run() {
// Todo: Don't use BufferedReader - IRC spec limits line length to 512 but...
BufferedReader in;
OutputStream output;
try {
@ -191,19 +206,20 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
/*************************************************************************
*
*/
private class IrcOutboundFilter implements Runnable {
public static class IrcOutboundFilter implements Runnable {
private Socket local;
private I2PSocket remote;
private StringBuilder expectedPong;
private StringBuffer expectedPong;
IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuilder pong) {
public IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
remote=_remote;
expectedPong=pong;
}
public void run() {
// Todo: Don't use BufferedReader - IRC spec limits line length to 512 but...
BufferedReader in;
OutputStream output;
try {
@ -266,7 +282,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
*
*/
public String inboundFilter(String s, StringBuilder expectedPong) {
public static String inboundFilter(String s, StringBuffer expectedPong) {
String field[]=s.split(" ",4);
String command;
@ -353,7 +369,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return null;
}
public String outboundFilter(String s, StringBuilder expectedPong) {
public static String outboundFilter(String s, StringBuffer expectedPong) {
String field[]=s.split(" ",3);
String command;
@ -371,14 +387,15 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
// "QUIT", // replace with a filtered QUIT to hide client quit messages
"SILENCE",
"MAP", // seems safe enough, the ircd should protect themselves though
"PART",
// "PART", // replace with filtered PART to hide client part messages
"OPER",
// "PONG", // replaced with a filtered PING/PONG since some clients send the server IP (thanks aardvax!)
// "PING",
"KICK",
"HELPME",
"RULES",
"TOPIC"
"TOPIC",
"ISON" // jIRCii uses this for a ping (response is 303)
};
if(field[0].length()==0)
@ -390,7 +407,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
command = field[0].toUpperCase();
if ("PING".equalsIgnoreCase(command)) {
if ("PING".equals(command)) {
// Most clients just send a PING and are happy with any old PONG. Others,
// like BitchX, actually expect certain behavior. It sends two different pings:
// "PING :irc.freshcoffee.i2p" and "PING 1234567890 127.0.0.1" (where the IP is the proxy)
@ -426,19 +443,19 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return rv;
}
if ("PONG".equalsIgnoreCase(command))
if ("PONG".equals(command))
return "PONG 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
// Allow all allowedCommands
for(int i=0;i<allowedCommands.length;i++)
{
if(allowedCommands[i].equalsIgnoreCase(command))
if(allowedCommands[i].equals(command))
return s;
}
// mIRC sends "NOTICE user :DCC Send file (IP)"
// in addition to the CTCP version
if("NOTICE".equalsIgnoreCase(command))
if("NOTICE".equals(command))
{
String msg = field[2];
if(msg.startsWith(":DCC "))
@ -447,7 +464,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
}
// Allow PRIVMSG, but block CTCP (except ACTION).
if("PRIVMSG".equalsIgnoreCase(command) || "NOTICE".equalsIgnoreCase(command))
if("PRIVMSG".equals(command) || "NOTICE".equals(command))
{
String msg;
msg = field[2];
@ -465,14 +482,21 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return s;
}
if("USER".equalsIgnoreCase(command)) {
if("USER".equals(command)) {
int idx = field[2].lastIndexOf(":");
if(idx<0)
return "USER user hostname localhost :realname";
String realname = field[2].substring(idx+1);
String ret = "USER "+field[1]+" hostname localhost :"+realname;
return ret;
} else if ("QUIT".equalsIgnoreCase(command)) {
}
if ("PART".equals(command)) {
// hide client message
return "PART " + field[1] + " :leaving";
}
if ("QUIT".equals(command)) {
return "QUIT :leaving";
}

View File

@ -31,6 +31,9 @@ import net.i2p.util.Log;
*
* There are three options for mangling the desthash. Put the option in the
* "custom options" section of i2ptunnel.
* - ircserver.method unset: Defaults to user.
* - ircserver.method=user: Use method described above.
* - ircserver.method=webirc: Use the WEBIRC protocol.
* - ircserver.cloakKey unset: Cloak with a random value that is persistent for
* the life of this tunnel. This is the default.
* - ircserver.cloakKey=somepassphrase: Cloak with the hash of the passphrase. Use this to
@ -39,6 +42,8 @@ import net.i2p.util.Log;
* be able to track users even when they switch servers.
* Note: don't quote or put spaces in the passphrase,
* the i2ptunnel gui can't handle it.
* - ircserver.webircPassword=password The password to use for the WEBIRC protocol.
* - ircserver.webircSpoofIP=IP The IP
* - ircserver.fakeHostname=%f.b32.i2p: Set the fake hostname sent by I2PTunnel,
* %f is the full B32 destination hash
* %c is the cloaked hash.
@ -48,7 +53,12 @@ import net.i2p.util.Log;
* @author zzz
*/
public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
public static final String PROP_METHOD="ircserver.method";
public static final String PROP_METHOD_DEFAULT="user";
public static final String PROP_CLOAK="ircserver.cloakKey";
public static final String PROP_WEBIRC_PASSWORD="ircserver.webircPassword";
public static final String PROP_WEBIRC_SPOOF_IP="ircserver.webircSpoofIP";
public static final String PROP_WEBIRC_SPOOF_IP_DEFAULT="127.0.0.1";
public static final String PROP_HOSTNAME="ircserver.fakeHostname";
public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p";
@ -67,7 +77,20 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
/** generate a random 32 bytes, or the hash of the passphrase */
private void initCloak(I2PTunnel tunnel) {
// get the properties of this server-tunnel
Properties opts = tunnel.getClientOptions();
// get method of host faking
this.method = opts.getProperty(PROP_METHOD, PROP_METHOD_DEFAULT);
assert this.method != null;
// get the password for the webirc method
this.webircPassword = opts.getProperty(PROP_WEBIRC_PASSWORD);
// get the spoof IP for the webirc method
this.webircSpoofIP = opts.getProperty(PROP_WEBIRC_SPOOF_IP, PROP_WEBIRC_SPOOF_IP_DEFAULT);
// get the cloaking passphrase
String passphrase = opts.getProperty(PROP_CLOAK);
if (passphrase == null) {
this.cloakKey = new byte[Hash.HASH_LENGTH];
@ -76,17 +99,30 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
this.cloakKey = SHA256Generator.getInstance().calculateHash(passphrase.trim().getBytes()).getData();
}
// get the fake hostmask to use
this.hostname = opts.getProperty(PROP_HOSTNAME, PROP_HOSTNAME_DEFAULT);
}
@Override
protected void blockingHandle(I2PSocket socket) {
try {
// give them 15 seconds to send in the request
socket.setReadTimeout(15*1000);
InputStream in = socket.getInputStream();
String modifiedRegistration = filterRegistration(in, cloakDest(socket.getPeerDestination()));
socket.setReadTimeout(readTimeout);
String modifiedRegistration;
if(!this.method.equals("webirc")) {
// give them 15 seconds to send in the request
socket.setReadTimeout(15*1000);
InputStream in = socket.getInputStream();
modifiedRegistration = filterRegistration(in, cloakDest(socket.getPeerDestination()));
socket.setReadTimeout(readTimeout);
} else {
StringBuffer buf = new StringBuffer("WEBIRC ");
buf.append(this.webircPassword);
buf.append(" cgiirc ");
buf.append(cloakDest(socket.getPeerDestination()));
buf.append(' ');
buf.append(this.webircSpoofIP);
buf.append("\r\n");
modifiedRegistration = buf.toString();
}
Socket s = new Socket(remoteHost, remotePort);
new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
} catch (SocketException ex) {
@ -134,7 +170,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
}
/** keep reading until we see USER or SERVER */
private String filterRegistration(InputStream in, String newHostname) throws IOException {
private static String filterRegistration(InputStream in, String newHostname) throws IOException {
StringBuilder buf = new StringBuilder(128);
int lineCount = 0;
@ -185,4 +221,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
private byte[] cloakKey; // 32 bytes of stuff to scramble the dest with
private String hostname;
private String method;
private String webircPassword;
private String webircSpoofIP;
}

View File

@ -16,10 +16,10 @@ import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Clock;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorListener {
public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErrorListener {
private final static Log _log = new Log(I2PTunnelRunner.class);
private static volatile long __runnerId;
@ -124,11 +124,14 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
OutputStream i2pout = i2ps.getOutputStream(); //new BufferedOutputStream(i2ps.getOutputStream(), MAX_PACKET_SIZE);
if (initialI2PData != null) {
synchronized (slock) {
// this does not increment totalSent
i2pout.write(initialI2PData);
// do NOT flush here, it will block and then onTimeout.run() won't happen on fail.
//i2pout.flush();
}
}
if (initialSocketData != null) {
// this does not increment totalReceived
out.write(initialSocketData);
}
if (_log.shouldLog(Log.DEBUG))
@ -150,6 +153,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
if (_log.shouldLog(Log.DEBUG))
_log.debug("runner has a timeout job, totalReceived = " + totalReceived
+ " totalSent = " + totalSent + " job = " + onTimeout);
// should we only look at totalReceived?
if ( (totalSent <= 0) && (totalReceived <= 0) )
onTimeout.run();
}
@ -222,7 +226,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
}
}
private class StreamForwarder extends I2PThread {
private class StreamForwarder extends I2PAppThread {
InputStream in;
OutputStream out;
@ -271,7 +275,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Flushing after sending " + len + " bytes through");
if (_log.shouldLog(Log.DEBUG))
_log.debug(direction + ": " + len + " bytes flushed through to "
_log.debug(direction + ": " + len + " bytes flushed through " + (_toI2P ? "to " : "from ")
+ i2ps.getPeerDestination().calculateHash().toBase64().substring(0,6));
try {
Thread.sleep(I2PTunnel.PACKET_DELAY);

View File

@ -4,6 +4,7 @@
package net.i2p.i2ptunnel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -24,7 +25,7 @@ import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.data.Base64;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
@ -48,26 +49,29 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
protected long readTimeout = DEFAULT_READ_TIMEOUT;
private static final boolean DEFAULT_USE_POOL = false;
protected static volatile long __serverId = 0;
private static final String PROP_HANDLER_COUNT = "i2ptunnel.blockingHandlerCount";
private static final int DEFAULT_HANDLER_COUNT = 10;
protected I2PTunnelTask task = null;
protected boolean bidir = false;
private int DEFAULT_LOCALPORT = 4488;
protected int localPort = DEFAULT_LOCALPORT;
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privData, notifyThis, tunnel);
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
String usePool = tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
SetUsePool(tunnel);
init(host, port, bais, privData, l);
}
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
String usePool = tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
SetUsePool(tunnel);
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);
@ -83,12 +87,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
String usePool = tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
SetUsePool(tunnel);
init(host, port, privData, privkeyname, l);
}
private void SetUsePool(I2PTunnel Tunnel) {
String usePool = Tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
init(host, port, privData, privkeyname, l);
}
private void init(InetAddress host, int port, InputStream privData, String privkeyname, Logging l) {
@ -106,17 +115,29 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
// copy the privData to a new BAIS, so we can always reset() it if we have to retry
ByteArrayInputStream privDataCopy;
try {
privDataCopy = copyOfInputStream(privData);
} catch (IOException ioe) {
_log.log(Log.CRIT, "Cannot read private key data for " + privkeyname, ioe);
return;
}
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
while (sockMgr == null) {
synchronized (slock) {
sockMgr = I2PSocketManagerFactory.createManager(privData, getTunnel().host, portNum,
sockMgr = I2PSocketManagerFactory.createManager(privDataCopy, getTunnel().host, portNum,
props);
}
if (sockMgr == null) {
_log.log(Log.CRIT, "Unable to create socket manager");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
privDataCopy.reset();
}
}
sockMgr.setName("Server");
getTunnel().addSession(sockMgr.getSession());
l.log("Ready!");
@ -124,15 +145,31 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
open = true;
}
private static volatile long __serverId = 0;
/**
* Copy input stream to a byte array, so we can retry
* @since 0.7.10
*/
private static ByteArrayInputStream copyOfInputStream(InputStream is) throws IOException {
byte[] buf = new byte[128];
ByteArrayOutputStream os = new ByteArrayOutputStream(768);
try {
int read;
while ((read = is.read(buf)) >= 0) {
os.write(buf, 0, read);
}
} finally {
try { is.close(); } catch (IOException ioe) {}
// don't need to close BAOS
}
return new ByteArrayInputStream(os.toByteArray());
}
/**
* Start running the I2PTunnelServer.
*
*/
public void startRunning() {
Thread t = new I2PThread(this);
Thread t = new I2PAppThread(this);
t.setName("Server " + (++__serverId));
t.start();
}
@ -158,6 +195,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
public boolean close(boolean forced) {
if (!open) return true;
if (task != null) {
task.close(forced);
}
synchronized (lock) {
if (!forced && sockMgr.listSockets().size() != 0) {
l.log("There are still active connections!");
@ -173,7 +213,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
sockMgr.getSession().destroySession();
} catch (I2PException ex) {
_log.error("Error destroying the session", ex);
System.exit(1);
//System.exit(1);
}
l.log("Server shut down.");
open = false;
@ -181,9 +221,6 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
private static final String PROP_HANDLER_COUNT = "i2ptunnel.blockingHandlerCount";
private static final int DEFAULT_HANDLER_COUNT = 10;
protected int getHandlerCount() {
int rv = DEFAULT_HANDLER_COUNT;
String cnt = getTunnel().getClientOptions().getProperty(PROP_HANDLER_COUNT);
@ -204,7 +241,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
int handlers = getHandlerCount();
for (int i = 0; i < handlers; i++) {
I2PThread handler = new I2PThread(new Handler(i2pS_S), "Handle Server " + i);
I2PAppThread handler = new I2PAppThread(new Handler(i2pS_S), "Handle Server " + i);
handler.start();
}
} else {
@ -213,7 +250,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
try {
final I2PSocket i2ps = i2pS_S.accept();
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
new I2PThread(new Runnable() { public void run() { blockingHandle(i2ps); } }).start();
new I2PAppThread(new Runnable() { public void run() { blockingHandle(i2ps); } }).start();
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
@ -257,6 +294,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
protected void blockingHandle(I2PSocket socket) {
if (_log.shouldLog(Log.INFO))
_log.info("Incoming connection to '" + toString() + "' from: " + socket.getPeerDestination().calculateHash().toBase64());
long afterAccept = I2PAppContext.getGlobalContext().clock().now();
long afterSocket = -1;
//local is fast, so synchronously. Does not need that many

View File

@ -14,7 +14,7 @@ import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2Ping extends I2PTunnelTask implements Runnable {
@ -59,7 +59,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
sockMgr = I2PTunnelClient.getSocketManager(tunnel);
}
}
Thread t = new I2PThread(this);
Thread t = new I2PAppThread(this);
t.setName("Client");
t.start();
open = true;
@ -188,7 +188,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
}
}
public class PingHandler extends I2PThread {
public class PingHandler extends I2PAppThread {
private String destination;
public PingHandler(String dest) {

View File

@ -0,0 +1,56 @@
package net.i2p.i2ptunnel;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import net.i2p.util.I2PAppThread;
import net.i2p.util.InternalServerSocket;
import net.i2p.util.Log;
/**
* Listen for in-JVM connections on the internal "socket"
*
* @author zzz
* @since 0.7.9
*/
class InternalSocketRunner implements Runnable {
private I2PTunnelClientBase client;
private int port;
private ServerSocket ss;
private boolean open;
private static final Log _log = new Log(InternalSocketRunner.class);
/** starts the runner */
InternalSocketRunner(I2PTunnelClientBase client) {
this.client = client;
this.port = client.getLocalPort();
Thread t = new I2PAppThread(this, "Internal socket port " + this.port, true);
t.start();
}
public final void run() {
try {
this.ss = new InternalServerSocket(this.port);
this.open = true;
while (true) {
Socket s = this.ss.accept();
this.client.manageConnection(s);
}
} catch (IOException ex) {
if (this.open) {
_log.error("Error listening for internal connections on " + this.port, ex);
}
this.open = false;
}
}
void stopRunning() {
if (this.open) {
try {
this.ss.close();
} catch (IOException ex) {}
this.open = false;
}
}
}

View File

@ -16,7 +16,7 @@ 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.I2PAppThread;
import net.i2p.util.Log;
/**
@ -29,8 +29,8 @@ public class TunnelController implements Logging {
private Log _log;
private Properties _config;
private I2PTunnel _tunnel;
private List _messages;
private List _sessions;
private List<String> _messages;
private List<I2PSession> _sessions;
private boolean _running;
private boolean _starting;
@ -46,6 +46,7 @@ public class TunnelController implements Logging {
public TunnelController(Properties config, String prefix) {
this(config, prefix, true);
}
/**
*
* @param createKey for servers, whether we want to create a brand new destination
@ -58,17 +59,21 @@ public class TunnelController implements Logging {
setConfig(config, prefix);
_messages = new ArrayList(4);
_running = false;
boolean keyOK = true;
if (createKey && (getType().endsWith("server") || getPersistentClientKey()))
createPrivateKey();
_starting = getStartOnLoad();
keyOK = createPrivateKey();
_starting = keyOK && getStartOnLoad();
}
private void createPrivateKey() {
/**
* @return success
*/
private boolean createPrivateKey() {
I2PClient client = I2PClientFactory.createClient();
String filename = getPrivKeyFile();
if ( (filename == null) || (filename.trim().length() <= 0) ) {
log("No filename specified for the private key");
return;
return false;
}
File keyFile = new File(getPrivKeyFile());
@ -76,7 +81,7 @@ public class TunnelController implements Logging {
keyFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), getPrivKeyFile());
if (keyFile.exists()) {
//log("Not overwriting existing private keys in " + keyFile.getAbsolutePath());
return;
return true;
} else {
File parent = keyFile.getParentFile();
if ( (parent != null) && (!parent.exists()) )
@ -94,19 +99,22 @@ public class TunnelController implements Logging {
if (_log.shouldLog(Log.ERROR))
_log.error("Error creating new destination", ie);
log("Error creating new destination: " + ie.getMessage());
return false;
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error creating writing the destination to " + keyFile.getAbsolutePath(), ioe);
log("Error writing the keys to " + keyFile.getAbsolutePath());
return false;
} finally {
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
}
return true;
}
public void startTunnelBackground() {
if (_running) return;
_starting = true;
new I2PThread(new Runnable() { public void run() { startTunnel(); } }).start();
new I2PAppThread(new Runnable() { public void run() { startTunnel(); } }).start();
}
/**
@ -120,9 +128,16 @@ public class TunnelController implements Logging {
} catch (Exception e) {
_log.error("Error starting up the tunnel", e);
log("Error starting up the tunnel - " + e.getMessage());
// if we don't acquire() then the release() in stopTunnel() won't work
acquire();
stopTunnel();
}
_starting = false;
}
/**
* @throws IllegalArgumentException via methods in I2PTunnel
*/
private void doStartTunnel() {
if (_running) {
if (_log.shouldLog(Log.INFO))
@ -144,6 +159,8 @@ public class TunnelController implements Logging {
startIrcClient();
} else if("sockstunnel".equals(type)) {
startSocksClient();
} else if("socksirctunnel".equals(type)) {
startSocksIRCClient();
} else if("connectclient".equals(type)) {
startConnectClient();
} else if ("client".equals(type)) {
@ -154,6 +171,8 @@ public class TunnelController implements Logging {
startServer();
} else if ("httpserver".equals(type)) {
startHttpServer();
} else if ("httpbidirserver".equals(type)) {
startHttpBidirServer();
} else if ("ircserver".equals(type)) {
startIrcServer();
} else if ("streamrserver".equals(type)) {
@ -209,6 +228,19 @@ public class TunnelController implements Logging {
_tunnel.runSOCKSTunnel(new String[] { listenPort, sharedClient }, this);
}
/** @since 0.7.12 */
private void startSocksIRCClient() {
setListenOn();
String listenPort = getListenPort();
String sharedClient = getSharedClient();
if (getPersistentClientKey()) {
String privKeyFile = getPrivKeyFile();
_tunnel.runSOCKSIRCTunnel(new String[] { listenPort, "false", privKeyFile }, this);
} else {
_tunnel.runSOCKSIRCTunnel(new String[] { listenPort, sharedClient }, this);
}
}
/*
* Streamr client is a UDP server, use the listenPort field for targetPort
* and the listenOnInterface field for the targetHost
@ -239,15 +271,18 @@ public class TunnelController implements Logging {
* closed by some other tunnels
*/
private void acquire() {
List sessions = _tunnel.getSessions();
if (sessions != null) {
List<I2PSession> sessions = _tunnel.getSessions();
if (!sessions.isEmpty()) {
for (int i = 0; i < sessions.size(); i++) {
I2PSession session = (I2PSession)sessions.get(i);
I2PSession session = sessions.get(i);
if (_log.shouldLog(Log.INFO))
_log.info("Acquiring session " + session);
TunnelControllerGroup.getInstance().acquire(this, session);
}
_sessions = sessions;
} else {
_log.error("No sessions to acquire?");
if (_log.shouldLog(Log.WARN))
_log.warn("No sessions to acquire? for " + getName());
}
}
@ -256,13 +291,16 @@ public class TunnelController implements Logging {
* no other tunnels are using them, close them.
*/
private void release() {
if (_sessions != null) {
if (_sessions != null && !_sessions.isEmpty()) {
for (int i = 0; i < _sessions.size(); i++) {
I2PSession s = (I2PSession)_sessions.get(i);
I2PSession s = _sessions.get(i);
if (_log.shouldLog(Log.INFO))
_log.info("Releasing session " + s);
TunnelControllerGroup.getInstance().release(this, s);
}
} else {
_log.error("No sessions to release?");
if (_log.shouldLog(Log.WARN))
_log.warn("No sessions to release? for " + getName());
}
}
@ -294,6 +332,16 @@ public class TunnelController implements Logging {
_tunnel.runHttpServer(new String[] { targetHost, targetPort, spoofedHost, privKeyFile }, this);
}
private void startHttpBidirServer() {
setListenOn();
String targetHost = getTargetHost();
String targetPort = getTargetPort();
String listenPort = getListenPort();
String spoofedHost = getSpoofedHost();
String privKeyFile = getPrivKeyFile();
_tunnel.runHttpBidirServer(new String[] { targetHost, targetPort, listenPort, spoofedHost, privKeyFile }, this);
}
private void startIrcServer() {
String targetHost = getTargetHost();
String targetPort = getTargetPort();
@ -343,7 +391,7 @@ public class TunnelController implements Logging {
_tunnel.port = "7654";
}
}
public void stopTunnel() {
_tunnel.runClose(new String[] { "forced", "all" }, this);
release();
@ -405,14 +453,16 @@ public class TunnelController implements Logging {
public String getListenPort() { return _config.getProperty("listenPort"); }
public String getTargetDestination() { return _config.getProperty("targetDestination"); }
public String getProxyList() { return _config.getProperty("proxyList"); }
/** default true */
public String getSharedClient() { return _config.getProperty("sharedClient", "true"); }
/** default true */
public boolean getStartOnLoad() { return "true".equalsIgnoreCase(_config.getProperty("startOnLoad", "true")); }
public boolean getPersistentClientKey() { return Boolean.valueOf(_config.getProperty("option.persistentClientKey")).booleanValue(); }
public String getMyDestination() {
if (_tunnel != null) {
List sessions = _tunnel.getSessions();
List<I2PSession> sessions = _tunnel.getSessions();
for (int i = 0; i < sessions.size(); i++) {
I2PSession session = (I2PSession)sessions.get(i);
I2PSession session = sessions.get(i);
Destination dest = session.getMyDestination();
if (dest != null)
return dest.toBase64();
@ -423,9 +473,9 @@ public class TunnelController implements Logging {
public String getMyDestHashBase32() {
if (_tunnel != null) {
List sessions = _tunnel.getSessions();
List<I2PSession> sessions = _tunnel.getSessions();
for (int i = 0; i < sessions.size(); i++) {
I2PSession session = (I2PSession)sessions.get(i);
I2PSession session = sessions.get(i);
Destination dest = session.getMyDestination();
if (dest != null)
return Base32.encode(dest.calculateHash().getData());
@ -527,9 +577,9 @@ public class TunnelController implements Logging {
if ( (opts != null) && (opts.length() > 0) )
buf.append("Network options: ").append(opts).append("<br />\n");
if (_running) {
List sessions = _tunnel.getSessions();
List<I2PSession> sessions = _tunnel.getSessions();
for (int i = 0; i < sessions.size(); i++) {
I2PSession session = (I2PSession)sessions.get(i);
I2PSession session = sessions.get(i);
Destination dest = session.getMyDestination();
if (dest != null) {
buf.append("Destination hash: ").append(dest.calculateHash().toBase64()).append("<br />\n");
@ -568,7 +618,7 @@ public class TunnelController implements Logging {
*
* @return list of messages pulled off (each is a String, earliest first)
*/
public List clearMessages() {
public List<String> clearMessages() {
List rv = null;
synchronized (this) {
rv = new ArrayList(_messages);

View File

@ -18,20 +18,21 @@ import net.i2p.I2PAppContext;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
* Coordinate a set of tunnels within the JVM, loading and storing their config
* to disk, and building new ones as requested.
*
* Warning - this is a singleton. Todo: fix
*/
public class TunnelControllerGroup {
private Log _log;
private final Log _log;
private static TunnelControllerGroup _instance;
static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config";
private List _controllers;
private final List<TunnelController> _controllers;
private String _configFile = DEFAULT_CONFIG_FILE;
/**
@ -40,7 +41,7 @@ public class TunnelControllerGroup {
* no more tunnels are using it)
*
*/
private final Map _sessions;
private final Map<I2PSession, Set<TunnelController>> _sessions;
public static TunnelControllerGroup getInstance() {
synchronized (TunnelControllerGroup.class) {
@ -94,7 +95,7 @@ public class TunnelControllerGroup {
_controllers.add(controller);
i++;
}
I2PThread startupThread = new I2PThread(new StartControllers(), "Startup tunnels");
I2PAppThread startupThread = new I2PAppThread(new StartControllers(), "Startup tunnels");
startupThread.start();
if (_log.shouldLog(Log.INFO))
@ -104,7 +105,7 @@ public class TunnelControllerGroup {
private class StartControllers implements Runnable {
public void run() {
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = (TunnelController)_controllers.get(i);
TunnelController controller = _controllers.get(i);
if (controller.getStartOnLoad())
controller.startTunnel();
}
@ -141,10 +142,10 @@ public class TunnelControllerGroup {
*
* @return list of messages from the controller as it is stopped
*/
public List removeController(TunnelController controller) {
public List<String> removeController(TunnelController controller) {
if (controller == null) return new ArrayList();
controller.stopTunnel();
List msgs = controller.clearMessages();
List<String> msgs = controller.clearMessages();
_controllers.remove(controller);
msgs.add("Tunnel " + controller.getName() + " removed");
return msgs;
@ -155,10 +156,10 @@ public class TunnelControllerGroup {
*
* @return list of messages the tunnels generate when stopped
*/
public List stopAllControllers() {
List msgs = new ArrayList();
public List<String> stopAllControllers() {
List<String> msgs = new ArrayList();
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = (TunnelController)_controllers.get(i);
TunnelController controller = _controllers.get(i);
controller.stopTunnel();
msgs.addAll(controller.clearMessages());
}
@ -172,10 +173,10 @@ public class TunnelControllerGroup {
*
* @return list of messages the tunnels generate when started
*/
public List startAllControllers() {
List msgs = new ArrayList();
public List<String> startAllControllers() {
List<String> msgs = new ArrayList();
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = (TunnelController)_controllers.get(i);
TunnelController controller = _controllers.get(i);
controller.startTunnelBackground();
msgs.addAll(controller.clearMessages());
}
@ -190,10 +191,10 @@ public class TunnelControllerGroup {
*
* @return list of messages the tunnels generate when restarted
*/
public List restartAllControllers() {
List msgs = new ArrayList();
public List<String> restartAllControllers() {
List<String> msgs = new ArrayList();
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = (TunnelController)_controllers.get(i);
TunnelController controller = _controllers.get(i);
controller.restartTunnel();
msgs.addAll(controller.clearMessages());
}
@ -207,10 +208,10 @@ public class TunnelControllerGroup {
*
* @return list of messages the tunnels have generated
*/
public List clearAllMessages() {
List msgs = new ArrayList();
public List<String> clearAllMessages() {
List<String> msgs = new ArrayList();
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = (TunnelController)_controllers.get(i);
TunnelController controller = _controllers.get(i);
msgs.addAll(controller.clearMessages());
}
return msgs;
@ -240,7 +241,7 @@ public class TunnelControllerGroup {
TreeMap map = new TreeMap();
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = (TunnelController)_controllers.get(i);
TunnelController controller = _controllers.get(i);
Properties cur = controller.getConfig("tunnel." + i + ".");
map.putAll(cur);
}
@ -296,7 +297,7 @@ public class TunnelControllerGroup {
*
* @return list of TunnelController objects
*/
public List getControllers() { return _controllers; }
public List<TunnelController> getControllers() { return _controllers; }
/**
@ -306,7 +307,7 @@ public class TunnelControllerGroup {
*/
void acquire(TunnelController controller, I2PSession session) {
synchronized (_sessions) {
Set owners = (Set)_sessions.get(session);
Set<TunnelController> owners = _sessions.get(session);
if (owners == null) {
owners = new HashSet(1);
_sessions.put(session, owners);
@ -326,10 +327,10 @@ public class TunnelControllerGroup {
void release(TunnelController controller, I2PSession session) {
boolean shouldClose = false;
synchronized (_sessions) {
Set owners = (Set)_sessions.get(session);
Set<TunnelController> owners = _sessions.get(session);
if (owners != null) {
owners.remove(controller);
if (owners.size() <= 0) {
if (owners.isEmpty()) {
if (_log.shouldLog(Log.INFO))
_log.info("After releasing session " + session + " by " + controller + ", no more owners remain");
shouldClose = true;

View File

@ -0,0 +1,63 @@
/* I2PSOCKSTunnel is released under the terms of the GNU GPL,
* with an additional exception. For further details, see the
* licensing terms in I2PTunnel.java.
*
* Copyright (c) 2004 by human
*/
package net.i2p.i2ptunnel.socks;
import java.net.Socket;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.Logging;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/*
* Pipe SOCKS IRC connections through I2PTunnelIRCClient filtering,
* to get the best of both worlds:
*
* - SOCKS lets you specify the host so you don't have to set up
* a tunnel for each IRC server in advance
* - IRC filtering for security
*
* @since 0.7.12
* @author zzz
*/
public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PSOCKSIRCTunnel.class);
private static int __clientId = 0;
/** @param pkf private key file name or null for transient key */
public I2PSOCKSIRCTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) {
super(localPort, l, ownDest, notifyThis, tunnel, pkf);
setName(getLocalPort() + " -> SOCKSIRCTunnel");
}
/**
* Same as in I2PSOCKSTunnel, but run the filters from I2PTunnelIRCClient
* instead of I2PTunnelRunner
*/
@Override
protected void clientConnectionRun(Socket s) {
try {
//_log.error("SOCKS IRC Tunnel Start");
SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(s);
Socket clientSock = serv.getClientSocket();
I2PSocket destSock = serv.getDestinationI2PSocket(this);
StringBuffer expectedPong = new StringBuffer();
Thread in = new I2PAppThread(new I2PTunnelIRCClient.IrcInboundFilter(clientSock, destSock, expectedPong), "SOCKS IRC Client " + (++__clientId) + " in", true);
in.start();
Thread out = new I2PAppThread(new I2PTunnelIRCClient.IrcOutboundFilter(clientSock, destSock, expectedPong), "SOCKS IRC Client " + __clientId + " out", true);
out.start();
} catch (SOCKSException e) {
_log.error("Error from SOCKS connection", e);
closeSocket(s);
}
}
}

View File

@ -33,8 +33,9 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
// I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null);
//}
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel);
/** @param pkf private key file name or null for transient key */
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel, pkf);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openSOCKSTunnelResult", "error");

View File

@ -224,7 +224,7 @@ public class SOCKS4aServer extends SOCKSServer {
throw new SOCKSException(err);
} else {
List<String> proxies = t.getProxies(connPort);
if (proxies == null || proxies.size() <= 0) {
if (proxies == null || proxies.isEmpty()) {
String err = "No outproxy configured for port " + connPort + " and no default configured either - host: " + connHostName;
_log.error(err);
try {

View File

@ -89,10 +89,10 @@ public class SOCKS5Server extends SOCKSServer {
int method = Method.NO_ACCEPTABLE_METHODS;
for (int i = 0; i < nMethods; ++i) {
method = in.readByte() & 0xff;
if (method == Method.NO_AUTH_REQUIRED) {
int meth = in.readByte() & 0xff;
if (meth == Method.NO_AUTH_REQUIRED) {
// That's fine, we do support this method
break;
method = meth;
}
}
@ -119,7 +119,7 @@ public class SOCKS5Server extends SOCKSServer {
int socksVer = in.readByte() & 0xff;
if (socksVer != SOCKS_VERSION_5) {
_log.debug("error in SOCKS5 request (protocol != 5? wtf?)");
throw new SOCKSException("Invalid protocol version in request");
throw new SOCKSException("Invalid protocol version in request: " + socksVer);
}
int command = in.readByte() & 0xff;
@ -332,7 +332,7 @@ public class SOCKS5Server extends SOCKSServer {
throw new SOCKSException(err);
} else {
List<String> proxies = t.getProxies(connPort);
if (proxies == null || proxies.size() <= 0) {
if (proxies == null || proxies.isEmpty()) {
String err = "No outproxy configured for port " + connPort + " and no default configured either";
_log.error(err);
try {

View File

@ -20,7 +20,7 @@ public class SOCKSServerFactory {
private final static Log _log = new Log(SOCKSServerFactory.class);
private final static String ERR_REQUEST_DENIED =
"HTTP/1.1 403 Access Denied\r\n" +
"HTTP/1.1 403 Access Denied - This is a SOCKS proxy, not a HTTP proxy\r\n" +
"Content-Type: text/html; charset=iso-8859-1\r\n" +
"Cache-control: no-cache\r\n" +
"\r\n" +

View File

@ -50,7 +50,7 @@ public class SOCKSUDPUnwrapper implements Source, Sink {
int headerlen = h.getBytes().length;
byte unwrapped[] = new byte[data.length - headerlen];
System.arraycopy(unwrapped, 0, data, headerlen, unwrapped.length);
System.arraycopy(data, headerlen, unwrapped, 0, unwrapped.length);
this.sink.send(dest, unwrapped);
}

View File

@ -39,8 +39,8 @@ public class SOCKSUDPWrapper implements Source, Sink {
byte[] header = h.getBytes();
byte wrapped[] = new byte[header.length + data.length];
System.arraycopy(wrapped, 0, header, 0, header.length);
System.arraycopy(wrapped, header.length, data, 0, data.length);
System.arraycopy(header, 0, wrapped, 0, header.length);
System.arraycopy(data, 0, wrapped, header.length, data.length);
this.sink.send(from, wrapped);
}

View File

@ -16,7 +16,7 @@ public class Pinger implements Source, Runnable {
public void start() {
this.running = true;
this.waitlock = new Object();
//this.waitlock = new Object();
this.thread.start();
}
@ -54,6 +54,6 @@ public class Pinger implements Source, Runnable {
protected Sink sink;
protected Thread thread;
protected Object waitlock; // FIXME should be final and use a factory. FIXME
private final Object waitlock = new Object();
protected boolean running;
}

View File

@ -29,7 +29,7 @@ public class I2PSink implements Sink {
// create maker
if (!raw)
this.maker = new I2PDatagramMaker(this.sess);
this.maker.setI2PDatagramMaker(this.sess);
}
/** @param src ignored */
@ -54,20 +54,8 @@ public class I2PSink implements Sink {
}
}
protected boolean raw;
protected I2PSession sess;
protected Destination dest;
protected I2PDatagramMaker maker; // FIXME should be final and use a factory. FIXME
protected final I2PDatagramMaker maker= new I2PDatagramMaker(); // FIXME should be final and use a factory. FIXME
}

View File

@ -28,7 +28,7 @@ public class I2PSinkAnywhere implements Sink {
// create maker
if (!raw)
this.maker = new I2PDatagramMaker(this.sess);
this.maker.setI2PDatagramMaker(this.sess);
}
/** @param to - where it's going */
@ -52,20 +52,8 @@ public class I2PSinkAnywhere implements Sink {
}
}
protected boolean raw;
protected I2PSession sess;
protected Destination dest;
protected I2PDatagramMaker maker; // FIXME should be final and use a factory. FIXME
protected final I2PDatagramMaker maker = new I2PDatagramMaker();
}

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