Compare commits

..

605 Commits

Author SHA1 Message Date
zzz
5b6ed48ec0 0.9.10 2014-01-22 01:30:33 +00:00
zzz
96f6865835 bump for review 2014-01-21 00:51:08 +00:00
meeh
fa50f9f246 * Adding http(s) uk.reseed.i2p2.no (Meeh)
* Adding http i2p-netdb.innovatio.no (Sindu)
2014-01-21 00:00:27 +00:00
kytv
538b4b10d7 Translation updates from Transifex 2014-01-20 17:00:24 +00:00
kytv
bdb3e26d07 geoip (v4 and v6) updates 2014-01-20 16:17:32 +00:00
kytv
ec87600e80 Chinese language update 2014-01-20 16:13:31 +00:00
zzz
0624f46e67 * Console: Change www.i2p2.i2p links to i2p-projekt.i2p
* Reseed: Remove netdb.i2p2.de
2014-01-20 15:52:14 +00:00
str4d
ece1198dd4 Fixed NPE 2014-01-15 02:31:07 +00:00
zzz
8bbab31872 * NetDB: Fix handling of DSM down client tunnels 2014-01-12 19:21:52 +00:00
zzz
8c6922ac5f * NetDB: Fix handling of DSRM down client tunnels
ISJ log tweak
2014-01-12 15:24:13 +00:00
zzz
6b67f399f6 * NetDB:
- Reduce min part tunnels for ffs to 35
   - Use client tunnels for LS lookups from OCMOSJ (ticket #1166)
2014-01-12 01:10:38 +00:00
str4d
a9598633b3 Missing file from BOB logging fix 2014-01-11 17:14:09 +00:00
str4d
1fb2672b67 BOB: Pass through I2CP host/port (ticket #827) 2014-01-11 04:30:59 +00:00
str4d
4308ce6347 Fixed logging for BOB-one.jar 2014-01-11 01:56:47 +00:00
str4d
32b095efbd BOB: Implement ClientApp interface (ticket #347) 2014-01-10 21:11:55 +00:00
zzz
eb4bdfcefb add i2pjump 2014-01-10 16:31:39 +00:00
kytv
fc6554cabc typo fix (a03adeb0, part 2) 2014-01-10 11:44:37 +00:00
str4d
058590f69b Fixed language names in routerconsole 2014-01-10 06:15:17 +00:00
kytv
9825fcf97b update of en source files, bump build 2014-01-09 19:33:54 +00:00
kytv
1ed96d72b2 i2prouter translation updates 2014-01-09 19:24:45 +00:00
kytv
a29935abb3 New Brazilian Portuguese translation
- New translation from Transifex
- Update langbox widths
2014-01-09 19:24:11 +00:00
kytv
e92a5da5a5 tx: update hostname in config, add pt_BR 2014-01-09 19:21:38 +00:00
kytv
f08e0299ef Updated translations from Transifex 2014-01-09 19:17:38 +00:00
zzz
9757435b09 NewsFetcher: Delay news fetch on new installs (ticket #1153) 2014-01-09 14:03:49 +00:00
zzz
80fadb4580 Kad: Fix NPE when removing yourself 2014-01-09 12:27:18 +00:00
str4d
8658c23974 susimail: Fixed pagination with zero entries (ticket #1168) 2014-01-09 04:31:30 +00:00
str4d
0264cc9030 susimail: UTF-8 support from wockenfuss (ticket #508) 2014-01-09 03:34:45 +00:00
str4d
bd5b6b32b5 Updated history 2014-01-09 03:33:57 +00:00
str4d
dc0a1281bf Migrated overlap fix from Fux (ticket #773) 2014-01-09 03:10:50 +00:00
zzz
44e7110c9a Fix StandardServerSocket.isClosed() and close()
thx cacapo
ref: http://zzz.i2p/topics/1547
2014-01-08 00:32:51 +00:00
zzz
c860c49c6b Add jisko.i2p to home page
Icon source: http://jisko.i2p/wiki/File:Jisko_console_icon.png
Icon license: Copyleft: This work of art is free; you can redistribute it and/or modify it.
ref: http://zzz.i2p/topics/1539
2014-01-08 00:30:28 +00:00
zab2
3b06f0b83c Change the test url to www.i2p-projekt.i2p 2014-01-06 16:06:20 +00:00
dg2-new
dc60c2b478 * Console: Change /configclients 'advanced warning' to include 'toopie, no red 2014-01-04 23:40:41 +00:00
zzz
b59aa1fb69 move I2PSocketOptionsImpl from mini to impl 2014-01-04 22:10:10 +00:00
zab2
54a21bfa7b Fix compilation of non-JUnit tests (disabled by default) 2014-01-04 19:57:47 +00:00
zab2
50f55877f8 make public method protected 2014-01-04 19:56:55 +00:00
dg2-new
f9ff262318 Fix junit tests for streaming, thank you zab (and thank you zzz) for helping out. 2014-01-04 19:45:52 +00:00
dg2-new
91ba76f2a6 merge of '1fd43bf251a91d33bb1ea9b06f2b35a40be3b9c9'
and '766a92b57cdf82d3b1d1e3a71ef2a3109e883add'
2014-01-04 17:41:15 +00:00
dg2-new
ec97bc2f81 Stab at fixing streaming tests.
Add javadoc package.html
Fix import order
2014-01-04 17:39:32 +00:00
zzz
b91b242a1a bump 2014-01-04 16:54:12 +00:00
zzz
38186c8f75 TunnelPoolSettings:
Split out the defaults for expl/client IB/OB.
  Client default now 3 hops.
  Expl default still 2 hops, with OB Expl + 0-1,
  en route to 3+0.
2014-01-04 16:48:45 +00:00
zzz
1b3aefbbce PeerManager: Remove small same-country bonus
This was done back when we were desperate for
 build improvement but it's bad for anonymity
 and probably a little slow also
2014-01-04 16:43:54 +00:00
zzz
c03511b971 exception causes 2014-01-04 16:40:06 +00:00
zzz
78e7599a8a better wording 2014-01-04 16:39:10 +00:00
zzz
dc871cf1eb XSS 2014-01-04 16:38:05 +00:00
dg2-new
e98b9d0af5 bump for testing 2014-01-04 14:27:51 +00:00
dg2-new
2a09d5baa6 * Streaming: Move streaming to new package (ticket #1135) 2014-01-04 14:09:33 +00:00
dg2-new
1feb317f8b typo 2013-12-25 09:39:19 +00:00
dg2-new
09668453d0 * Console: Add 'advanced warning' to /confgiclients
* SOCKS5Server: Remove redundant, commented out line from my previous findbugs
2013-12-25 09:37:46 +00:00
zzz
bf485d8bce history update and date fixes 2013-12-21 18:01:04 +00:00
zzz
38c02b44b9 Streaming: final, volatile, logging 2013-12-19 12:24:51 +00:00
zzz
04a596899a NetDB: Fixes for ExpireRoutersJob
- Don't expire if too few routers
  - Don't expire if net is disconnected
  - Don't run in VMCommSystem
2013-12-19 12:23:29 +00:00
zzz
ee1ed1bb82 Nice message during graceful shutdown
May need to tweak the wording
2013-12-19 12:20:32 +00:00
zzz
2b39d28e99 fix comment 2013-12-19 12:16:39 +00:00
zzz
8cb503d8bb EepGet: Allow override of the User-Agent
i2psnark: Set User-Agent
2013-12-15 15:16:54 +00:00
zzz
efff25a87c NetDB:
- Just before midnight, flood to new location too so lookups
   don't fail after keyspace rotation (ticket #510)
 - Refactor RoutingKeyGenerator and UpdateRoutingKeyModifierJob
   in support of the above
 - Display next key on LS debug page
2013-12-14 14:38:00 +00:00
zzz
6e2583ad92 NetDB:
- Increase new kad size to K=24, B=4
 - Fix router count by counting in the data store, not the kbuckets
 - Randomize the order we load router infos at startup so we
   don't bias the kbuckets
2013-12-13 17:50:39 +00:00
zzz
af84bcf945 i2ptunnel:
- Show destination for persistent client key only if available;
   show b32 for the key as well
2013-12-13 17:45:35 +00:00
zzz
3dc429415b use advanced setting to show LS debug 2013-12-13 17:31:13 +00:00
zzz
ec9dd25631 sort i2ptunnel CLI help for sanity 2013-12-13 17:30:18 +00:00
zzz
2bda87d5a7 comment out main 2013-12-13 17:29:43 +00:00
kytv
a7a816e0a7 wrapper: 3.5.23 updates for win64 2013-12-10 23:23:06 +00:00
zzz
3d9d722cee history for props, -1 2013-12-10 11:39:45 +00:00
zzz
289a8e7b40 merge of '3f93d2c09c89b5c68487c33fd700ef7c2feeeb61'
and 'b2c58f8462ab5c08682b711436c387b421bdd0c2'
2013-12-10 11:11:08 +00:00
str4d
7d3aa33c25 Fixed type argument problem causing infinite recursion 2013-12-10 05:55:19 +00:00
zzz
0db1314595 propagate from branch 'i2p.i2p.zzz.netdbkad' (head bc7310e940f01e68bd6be0ed0681eb624dada332)
to branch 'i2p.i2p' (head 98569f30891693e6888913f50b88d1f37969fe45)
2013-12-10 02:31:08 +00:00
zzz
68641626aa propagate from branch 'i2p.i2p.zzz.test2' (head ec8e362ce8b93280b518c599a3cc075b89085d2b)
to branch 'i2p.i2p' (head c9b1eef91f61f4482ad11c4f2b2d01be67a17ad2)
2013-12-10 02:26:32 +00:00
zzz
5b9fb403c9 Jetty 7.6.14.v20131031 2013-12-10 02:26:00 +00:00
str4d
a4114b96fd Deprecation warning fixes 2013-12-09 20:45:11 +00:00
str4d
de184ed139 propagate from branch 'i2p.i2p.str4d.cleanup' (head 736423cc308e964bab55068e625f8a1852932ec5)
to branch 'i2p.i2p' (head 0ac335d5dc4ccaeb113af4fb5c0e993a6f42fdbe)
2013-12-09 19:51:39 +00:00
zzz
04c342ec6a PrivateKeyFile: Fix ISE (ticket #1145)
broken in 0.9.9
2013-12-09 16:38:00 +00:00
zzz
27ce28027d i2ptunnel: Disable streaming pings for clients (ticket #1142)
i2psnark: Disable streaming pings (ticket #1142)
2013-12-09 16:11:53 +00:00
zzz
f8a54bde19 0.9.9 2013-12-07 15:30:29 +00:00
zzz
3acfdbe8f7 i2ptunnel IRC client: Do not filter server PING or client PONG (ticket #1141) 2013-12-06 15:26:12 +00:00
zzz
d9fed57c89 more finals 2013-12-05 16:25:16 +00:00
zzz
46e7e9be82 finals 2013-12-05 16:21:36 +00:00
zzz
d87d4eb232 I2CP: Disconnect client on attempt to publish invalid leaseset 2013-12-05 16:14:51 +00:00
zzz
88ea451f81 propagate from branch 'i2p.i2p' (head 2634e424f06e58231c47f1ec318e9ae21c94a8b3)
to branch 'i2p.i2p.zzz.test2' (head 68ca880caf69a06c0fd01fc70675df795aef1de2)
2013-12-05 16:07:32 +00:00
kytv
822ec4aa53 Debian: patch refresh 2013-12-04 18:46:28 +00:00
zzz
7b0b07933f finals 2013-12-04 14:21:03 +00:00
zzz
7fe8573df4 i2psnark ConnectionAcceptor:
- Fix ConnectionAcceptor not restarting after tunnel
    restart, preventing incoming connections
  - locking tweaks
  - cleaner reschedule tweaks
  - don't store server socket locally
  - constructor tweaks / finals
  - Stop acceptor when tunnel disconnects
  - javadocs
2013-12-04 14:17:38 +00:00
str4d
c180292358 Style fix: leave brackets around for() one-liners 2013-12-04 03:51:02 +00:00
str4d
a3fa48dcbe Removed dead code 2013-12-04 03:50:26 +00:00
zzz
445e4301d5 bump for review 2013-12-01 21:27:43 +00:00
kytv
736da22bba update geoip from maxmind's 2013-11-05 db 2013-12-01 20:15:32 +00:00
kytv
f29c64cd70 merge of '37bb29ce149260c55fb90ec8e56262262382fd9d'
and 'c4f7358a50c9982c5d63e9e5201f4e3f9562422f'
2013-12-01 20:13:49 +00:00
kytv
aa4b4b9d2b French, Italian, Romanian, Spanish, and Swedish translation updates 2013-12-01 20:09:16 +00:00
str4d
1112fc8544 Yes it's deprecated, it should still use proper generics 2013-11-30 12:52:50 +00:00
dg2-new
9b361ac445 Fixed history. Last commit was actually blocking "X-Powered-By". Oops. 2013-11-28 21:12:35 +00:00
dg2-new
0ff423fc57 I2PTunnel: Don't send 'X-Forwarded-For' on HTTP server tunnels for anonymity reasons (reported by 'trixie' on IRC). 2013-11-28 21:03:19 +00:00
str4d
efe3bd2c05 Use for each when Iterator not needed 2013-11-28 11:56:54 +00:00
str4d
f112baac48 propagate from branch 'i2p.i2p' (head cbfe85d22c4d0b05c901db3fa751b57889d9b2d6)
to branch 'i2p.i2p.str4d.cleanup' (head 94fe1764f50b459da18222434034ad46d604c7a1)
2013-11-28 11:12:41 +00:00
str4d
707f616498 Changes from -rc diff review 2013-11-28 11:10:57 +00:00
str4d
ed2feb3ff7 Core: findbugs 2013-11-27 23:22:49 +00:00
str4d
a17b1b99c0 Moved StatLogSplitter to i2p.scripts/java-utils 2013-11-27 22:48:46 +00:00
str4d
27bc32f2f3 Core: findbugs exclusions (for use in Eclipse or Jenkins) 2013-11-27 11:17:17 +00:00
str4d
b535054e13 generics 2013-11-27 11:14:16 +00:00
str4d
97a9a6090a Use copy constructor instead of clone() 2013-11-27 01:55:29 +00:00
str4d
8b8e2c88c1 type argument 2013-11-27 01:55:14 +00:00
str4d
9d7ee30c15 More cleanups 2013-11-27 01:42:34 +00:00
str4d
4ee144533a Another warning suppression to be removed at Java6 2013-11-27 01:25:20 +00:00
str4d
0f2a983bb7 i2psnark: type arguments, warning suppression (to be removed at Java6) 2013-11-27 01:11:48 +00:00
str4d
8fd2f9090e propagate from branch 'i2p.i2p' (head 7903431c2a396fceb1e0428b2be3dde03ba24635)
to branch 'i2p.i2p.str4d.cleanup' (head cfbae7380c3fa106f578d5de399701cfb72d5747)
2013-11-27 00:57:19 +00:00
str4d
8770d7eae0 i2psnark: Comparable type arguments 2013-11-26 21:09:36 +00:00
str4d
c59ef24acf i2psnark: more type arguments 2013-11-26 20:16:45 +00:00
str4d
85aa2fb083 i2psnark: MetaInfo type arguments (thx zzz) 2013-11-26 19:54:53 +00:00
zzz
434b9fa0d1 GeoIP: Thread the periodic lookup so it doesn't clog the timer queue 2013-11-26 16:28:24 +00:00
zzz
56116ad8c2 PeerManager: Thread the periodic reorg so it doesn't clog the timer queue 2013-11-26 15:51:00 +00:00
zzz
c0ef19a281 i2psnark: Fix mixed public/private tracker detection
(thx str4d)
2013-11-26 03:07:21 +00:00
str4d
9804e5b7d9 i2psnark: more type arguments 2013-11-26 01:34:08 +00:00
str4d
2f33186e58 i2psnark: type arguments, unused imports, for each 2013-11-26 00:20:03 +00:00
str4d
0347c56c96 Deprecation fixes 2013-11-25 23:29:48 +00:00
str4d
e77409e57a Close resources 2013-11-25 23:14:09 +00:00
str4d
615ba94559 propagate from branch 'i2p.i2p' (head d12a1fd746cd9314de5de5e1000c02cf4c59100d)
to branch 'i2p.i2p.str4d.cleanup' (head e20c143dd50a9c802999068a95e12198b07e4c36)
2013-11-25 22:36:27 +00:00
str4d
ce0596d5b1 Reseed: Listen to "Require SSL" config option 2013-11-25 21:11:56 +00:00
zab2
35b6926e4f Ticket #1047 : Do not adjust window on receiving dups. 2013-11-25 19:21:27 +00:00
zzz
76925fa3bd console: add debug link if advanced config is set 2013-11-25 15:59:34 +00:00
zzz
dbdf36d85c Update: Increase torrent from 30% to 60% 2013-11-25 15:34:49 +00:00
zzz
60aa8c57a4 I2PTunnel: Fix a shared client configured with i2cp.newDestOnResume
not restarting correctly, caused by previous checkin
2013-11-24 23:42:53 +00:00
zzz
001070f677 fix setting of BC_AVAILABLE thx str4d 2013-11-24 23:42:13 +00:00
str4d
c6f2d4948b Class generics 2013-11-24 23:41:06 +00:00
zzz
8699c82614 Kad unit tests:
- Port KBSTest from i2p.zzz.kademlia branch
  - Fix RandomTrimmer so it always returns true, so it may be used
    as the trimmer in the unit tests
2013-11-24 23:39:47 +00:00
zzz
1d7eedd463 Kad unit tests:
- Move KBucketSetTest to new directory
  - Fix testSelf() as new implementation will never include myself
  - Delete KBucketImplTest, not applicable/useful now
  Next todo: port KBSTest from i2p.zzz.kademlia branch
2013-11-24 21:58:42 +00:00
zzz
796a231f54 NetDB:
- Move net.i2p.kademlia package from i2psnark to core, and convert
    netdb to use it.
  - Delete old implementation in netdb
  - Fixups in netdb for generics
  - Add debug output to /debug

  This is the next step in the development plan, in which we previously:
    - Copied the code from netdb to the i2p.zzz.kademlia branch, fixed it,
      and made it generic for hash size (June 2012);
    - Moved it from the i2p.zzz.kademlia branch to the i2p.i2p.zzz.dhtsnark
      branch, and implemented KRPC with it (June 2012);
    - Propped it from i2p.i2p.zzz.dhtsnark to trunk for 0.9.2 (July-Sept. 2012);
    - Proved it out in 0.9.2 - 0.9.9 (Oct. 2012 - Nov. 2013)

  The plan was to maintain the KBucketSet public methods throughout the development
  so we could drop the new version back into netdb, so here we drop it in.

  Setting of K=16, B=3 is just an initial guess, to be reviewed.
  This moves about 18 KB from i2psnark.jar to i2p.jar and removes about 12 KB from router.jar.
  Unit test fixup: todo.
2013-11-24 16:38:51 +00:00
str4d
e1fcad686c propagate from branch 'i2p.i2p' (head 72c44737466e553fec443a79fffa7636894fe383)
to branch 'i2p.i2p.str4d.cleanup' (head 5a2425d7523b732840e55039f88cea5699f1aa83)
2013-11-24 01:20:11 +00:00
zzz
ffa03f2b83 IterativeSearchJob:
- Recheck completion status just before sending out a wrapped message
 - log tweaks
2013-11-23 17:56:40 +00:00
zzz
54fb91ba8e I2PTunnel: Call destroySocketManager() when replacing
a client socket manager configured with i2cp.newDestOnResume,
  or a shared client.
  This prevents lots of orphaned StreamingTimer threads.
  There are still cases where these threads may stick around,
  when a tunnel is stopped but not restarted. We don't know in
  some cases when a tunnel could be restarted and when it can't.
  destroySocketManager() should always be called when discarding a
  SocketManager but i2ptunnel doesn't do that now. More to do,
  but this fixes the most common case of leaked threads.
  Related tickets: ##642 #961
2013-11-23 17:54:01 +00:00
zzz
e498e2113f Snark: make a set of the default trackers so the config array
can be private and the lookup for the form is more efficient.
2013-11-23 14:45:38 +00:00
zzz
f42ac71fe0 UDP PeerState findbugs volatile/atomic/synch 2013-11-23 14:37:33 +00:00
zzz
74f2fd06cc Deprecate Signature.FAKE_SIGNATURE 2013-11-23 14:33:58 +00:00
zzz
143a0dfc47 Transport: Reduce target connections from 60% to 45% of limit.
This will improve network capacity.
   Apparent problems with lower limits were actually due to
   unrelated bugs that were fixed by 0.9.8.1-22.
   This can go lower still; I've been testing 33% without issues.
2013-11-23 14:29:23 +00:00
str4d
fdb0097934 Temporarily moved old help.jsp translations back 2013-11-23 11:44:07 +00:00
str4d
0dde4162e6 susimail: Fix NPE when deleting last message (ticket #414) 2013-11-23 04:24:30 +00:00
zzz
844bae18ba fixup after prop 2013-11-22 22:19:06 +00:00
zzz
9e4d5c0e61 propagate from branch 'i2p.i2p' (head da40262a8b7685de3877c1d7d6d16a155caa9e7c)
to branch 'i2p.i2p.zzz.test2' (head 6263bb149b8301059d0471bcc1d47caeca660f4e)
2013-11-22 17:29:45 +00:00
zzz
9b8d3eb688 Startup:
Wait a while and recheck if a recent ping file is there,
    so that a crashed router doesn't prevent a restart (ticket #633)
2013-11-22 17:27:49 +00:00
str4d
8478bfbddc BOB: for each 2013-11-22 11:46:39 +00:00
str4d
d6bb5f6a4d i2ptunnel: type arguments 2013-11-22 11:41:12 +00:00
str4d
e9fec9354b ministreaming: type arguments 2013-11-22 11:37:44 +00:00
str4d
f9f0e6d0a2 SAM: for each 2013-11-22 11:36:26 +00:00
str4d
3bc0be1cbe susidns: type arguments, for each 2013-11-22 11:25:22 +00:00
str4d
8d826cee93 susimail:
- Generics in Folder
- for each
- type arguments
2013-11-22 11:18:41 +00:00
str4d
e853d9a40b Router: more type arguments, for each 2013-11-22 10:16:34 +00:00
str4d
15bf94b479 Core: type arguments 2013-11-22 09:34:42 +00:00
str4d
6314f33d8f desktopgui: unused imports 2013-11-22 04:25:48 +00:00
str4d
5fa0376f58 SAM: type arguments, unused imports 2013-11-22 04:22:14 +00:00
str4d
552dd189a5 streaming: type arguments, unused imports 2013-11-22 04:18:26 +00:00
str4d
57144f3e6a Added Eclipse projects for SAM and streaming 2013-11-22 03:58:02 +00:00
zzz
0454639db8 bump -30-rc 2013-11-21 23:02:21 +00:00
str4d
c32b451733 i2psnark: type arguments, unused imports 2013-11-21 12:43:45 +00:00
str4d
2f4765665d routerconsole: type arguments, unused imports 2013-11-21 11:31:50 +00:00
str4d
bff79cdae8 susimail: type arguments 2013-11-21 10:49:15 +00:00
str4d
4bddf8ae0b susidns: type arguments, unused imports 2013-11-21 10:17:35 +00:00
str4d
ae79deff39 net.i2p.jetty.*: type arguments, unused imports 2013-11-21 10:13:34 +00:00
str4d
e3aeb267f8 Eclipse classpath consolidation 2013-11-21 09:38:09 +00:00
str4d
c5c26c440d Eclipse Ant builders for core, router and jettylib 2013-11-21 09:11:42 +00:00
str4d
77971624b4 Created Eclipse project for installer/resources
Reverts a change in 7fe82070
This project can be added to the classpath of a JUnit runner
2013-11-21 08:54:42 +00:00
str4d
f5621c5082 Converted lib Eclipse project to standard folder 2013-11-21 08:52:04 +00:00
str4d
3fa7fe9733 Updated routerconsole Eclipse classpath 2013-11-21 08:40:05 +00:00
str4d
c97d07e10a org.cybergarage.*: more type arguments 2013-11-21 06:08:41 +00:00
str4d
567c328331 org.cybergarage.*: type arguments, unused imports 2013-11-21 05:58:54 +00:00
str4d
3aa982529e org.xlattice.crypto.*: type arguments 2013-11-21 05:56:14 +00:00
str4d
0c07f9ff96 More type arguments in UDPTransport 2013-11-21 05:23:35 +00:00
str4d
f0055ccbfe Made type argument for Transport.getClockSkews() consistent 2013-11-21 02:27:53 +00:00
str4d
693cc828c2 Type arguments in OutNetMessage 2013-11-21 02:27:03 +00:00
str4d
688dd23111 gnu.crypto.prng.*: type arguments 2013-11-21 02:18:59 +00:00
str4d
e38db5eb44 i2ptunnel: type arguments, unused imports 2013-11-20 23:36:39 +00:00
str4d
817f531619 merge of '743aa294fa15c3243bb6ad56d4de64f5eff15051'
and '85fa37bf6c3090c0d4c10f4b7b2d679549090c37'
2013-11-20 23:15:31 +00:00
str4d
53623da2eb addressbook: type arguments, unused imports 2013-11-20 23:14:40 +00:00
kytv
4910266d9b merge of '63ea1d70b3fd3886a050d7b196cd7ae261844164'
and '6a57f7039fe5697b9770d642ac1d4653e4b9878c'
2013-11-20 23:10:52 +00:00
str4d
24ae66df6d Core JUnit tests: type arguments, unused imports 2013-11-20 23:06:17 +00:00
str4d
228bd980db Router JUnit tests: type arguments, unused imports 2013-11-20 22:47:14 +00:00
str4d
f161a2dfc9 BOB: NamedDB accesses are synchronized, correct findbugs fix is to remove volatile 2013-11-20 22:12:44 +00:00
str4d
abe1dc676e Dead code, type arguments 2013-11-20 22:05:37 +00:00
zzz
9de57a5d5a log tweak; bump -29-rc 2013-11-20 21:16:13 +00:00
str4d
2cc742c3ed Fixed stupid pasting bug 2013-11-20 19:54:10 +00:00
dg2-new
5bcfe025d5 fix build 2013-11-20 15:40:21 +00:00
zab2
6dc6ca7713 avoid <? extends Object> generics 2013-11-20 15:11:35 +00:00
dg2-new
eabcc96a99 remove useless string 2013-11-20 14:52:44 +00:00
dg2-new
28b6675979 findbugs BOB/SAM. more to do. 2013-11-20 12:02:44 +00:00
str4d
413ad6b0e6 BOB findbugs 2013-11-20 09:56:57 +00:00
str4d
a7a7e96188 Findbugs in imported core code 2013-11-20 09:15:12 +00:00
str4d
796dbc5d2e Fixed bug hidden by Set<RouterInfo> -> Set -> Set<Hash> unchecked conversion 2013-11-20 04:18:15 +00:00
str4d
c86845078c Reverted change in net.i2p.router.Router 2013-11-20 04:06:59 +00:00
str4d
89dcceefee Core: type arguments, unused imports 2013-11-20 04:02:28 +00:00
str4d
bacce17990 Router: type arguments, unused imports 2013-11-20 02:46:24 +00:00
kytv
e61e950713 update patch / update debian changelog 2013-11-20 00:50:39 +00:00
kytv
244209d3b7 Translation updates, addition of Japanese language
-28
2013-11-19 23:59:46 +00:00
zzz
dbe0a8240e Translations:
- Add support for country variants (ticket #1133)
  - Refactor data in ConfigUIHelper
Config files: Allow empty values
2013-11-18 23:18:46 +00:00
zzz
7e3e08532f more static atomics 2013-11-17 15:03:10 +00:00
zzz
1d4190734d Findbugs all over
- volatile -> atomic
 - unused code and fields
 - closing streams
 - hashCode / equals
 - known non-null
 - Number.valueOf
 - new String
 Still avoiding SAM, BOB, SusiMail
2013-11-16 13:22:05 +00:00
zzz
96cf1d60c2 * Jetty: Fix eepsite and webapp cache control directives.
Eepsite fix for new installs only.
  Fix i2psnark BasicServlet javadoc about param prefix.
  (ticket #1128)
2013-11-15 18:51:14 +00:00
kytv
3aa33378c1 i2prouter: s/3\.5\.20/3.5.22/g 2013-11-15 01:02:37 +00:00
kytv
747bd0c5a3 Update Java Service Wrapper to v3.5.22
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
  changed from Tanuki's default to Itoopie.
- Linux ARMv6: Compiled on a RaspberryPi using gcc 4.6.3-14+rpi1,
  Icedtea6 6b27-1.12.5-1+rpi1 and stripped
- All other binaries are from the "community edition" deltapack offered by
  Tanuki.
2013-11-15 01:01:49 +00:00
zzz
ea7b42810f * InboundMessageDistributor:
- Put garlicked DSM messages in the InNetMessagePool instead of handling directly,
     so the IterativeSearchJob will see the response and declare success.
     Only affected LS lookups as we do not request encrypted replies for RI lookups.
     Similar to the fix for verifies 6dc5bed94321ae2b290cfe351511d18465e08f91
     This bug was causing initial lookups to fail but subsequent ones to succeed.
     Broken since 0.9.7 when encrypted replies was introduced.
     Ticket #1125
2013-11-14 17:39:31 +00:00
zzz
19022baa27 log tweaks, final 2013-11-14 17:36:57 +00:00
zab2
e8248f5005 volatile 2013-11-14 15:18:46 +00:00
zab2
f8178b7165 ticket #1125: revert previous change as it is not relevant
to test failure
2013-11-13 11:43:24 +00:00
kytv
79b5d9748d patch refresh 2013-11-13 01:03:19 +00:00
zzz
b53ed94e8f Findbugs:
- Fix several 'increment of volatile is not atomic' all over
    Remaining: UDP PeerState.java, to be checked in separately
  - Comment out all of unused MessageStateMonitor
2013-11-12 19:28:23 +00:00
zzz
df84a2fcd0 save server status text to return to user 2013-11-12 19:19:21 +00:00
str4d
25e7dea370 merge of '4f6d64a50c7c5c27682914984831fc581724659d'
and 'e5def490e4eba793ca0d2bcb739771dcdf8c0242'
2013-11-11 23:49:02 +00:00
str4d
90919ebf6b Make ObjectCounter Serializable 2013-11-11 23:48:15 +00:00
zzz
76078deb3f handle numeric private value in metainfo 2013-11-11 23:24:14 +00:00
kytv
1b95a03d2e merge of '3a7591d75dacb165b1b1d26c6bdd94184076fb03'
and 'ba02b6daf2d660339ff05cfe0479344391e6e34f'
2013-11-10 23:27:39 +00:00
dg2-new
108039de08 partial revert of 6df9f4e154d148867ee158cbe9e9acf3fb73d680 2013-11-10 23:00:57 +00:00
dg2-new
addd2e6d6a merge of '3f85581f65aedde0f96729d197aaab223174f2e4'
and '6df9f4e154d148867ee158cbe9e9acf3fb73d680'
2013-11-10 22:22:10 +00:00
dg2-new
5c38d5a6c9 Findbugs: More findbugs fixes. Including but not limited to: null check fixes and some synchronization 2013-11-10 22:20:13 +00:00
zzz
69489dd19e use DataHelper.skip() in a few more places 2013-11-10 22:20:06 +00:00
zzz
3fce0e8e45 xlattice findbugs 2013-11-10 22:19:45 +00:00
zab2
35fb332c2c moar test cases 2013-11-10 21:13:42 +00:00
zzz
1b5309be05 junit test for new DataHelper.skip() 2013-11-10 20:42:24 +00:00
zzz
d2a1025b3f about 20 findbugs fixes all over 2013-11-10 20:07:46 +00:00
dg2-new
0a8f79f0e3 Findbugs: A stab at squashing some issues across the board. Probably more to follow. 2013-11-10 19:04:57 +00:00
zzz
18e4c2ac63 log tweak 2013-11-10 15:34:44 +00:00
zzz
90c2e08489 Streaming:
- Fix uncaught exception when log level = WARN, broken in -23
2013-11-10 15:32:54 +00:00
zzz
598ef67c4e Tunnel fragments:
- more checks, don't allow fragment #0 in follow-on fragment
  - Set message ID in constructor
2013-11-10 15:27:28 +00:00
zzz
1b9d870b91 i2psnark: Don't announce more than torrent size as downloaded amount 2013-11-10 15:20:07 +00:00
zzz
68f67b7c8e UPnP:
(ticket #1123)
 - Add new config i2np.upnp.ignore to specify UDNs of ignored devices
 - Add display of ignored devices on /peers
2013-11-10 15:17:42 +00:00
kytv
d2f0c251c0 use four digit umask in wrapper.config
According to http://wrapper.tanukisoftware.com/doc/english/prop-umask.html the
umask is a four digit number.
2013-11-09 16:19:33 +00:00
zzz
2b2f34b3f1 A better killyourtv.i2p icon
New icon from FatCow, licensed as specified in our docs.
   ref: http://zzz.i2p/topics/1492
2013-11-08 18:28:35 +00:00
zzz
4e680479da Home page: replace all default eepsite icons.
New icons from FatCow, licensed as specified in our docs.
   ref: http://zzz.i2p/topics/1492
2013-11-08 15:26:32 +00:00
zzz
d1b93e0705 DeliveryInstructions:
- Comment out unused encryption fields to save space
  - New static immutable LOCAL instruction to reduce object churn
2013-11-08 14:39:43 +00:00
zzz
4382def62f log tweak 2013-11-08 14:35:28 +00:00
zzz
952a56c537 JobQueue: Log a warning if a job is scheduled too far in the future,
to catch bugs like the one in -7 where requeue() is called
          with an absolute time instead of a delay
2013-11-08 14:34:33 +00:00
zzz
67aead214b Tunnel Endpoints:
- Reject type 3 (undefined) delivery instructions at both OBEP and IBEP,
     would be treated as LOCAL
   - Reject type 0 (LOCAL) delivery instructions at OBEP, no current usage,
     would cause NPE if handled
2013-11-08 14:31:14 +00:00
zzz
50f45a50a7 minor optimization 2013-11-08 14:24:06 +00:00
zab2
6b326c3705 merge of '15e16e2fd4c5be75a63b28616b413a8d1e13e1d6'
and '2449ac4142097e34b7ad4c4c4cb16c163a786a16'
2013-11-07 20:39:59 +00:00
zab2
919ec3af01 work on failing JUnit test 2013-11-07 20:38:52 +00:00
kytv
ca5a301a4f i2prouter: create i2p.dir.config with umask from wrapper.config 2013-11-07 19:56:01 +00:00
zzz
ae76a6ee1a findbugs correctness fixes, all over the place 2013-11-07 19:20:25 +00:00
zzz
5cbecb3599 log IP change in event log 2013-11-07 13:13:21 +00:00
zzz
5a34e1de4f * NetDB: Fix RI publish interval, broken in -7 2013-11-07 12:31:46 +00:00
zzz
c810694e07 * i2psnark: Fix file links, broken in -12 (ticket #1114) 2013-11-07 12:29:05 +00:00
zzz
ca866d48e6 * Logging: Track duplicates across flush interval (ticket #1110) 2013-11-07 12:23:37 +00:00
kytv
f1e77499e2 allow webapps.config to be 'preseeded' with values 2013-11-04 22:05:22 +00:00
zzz
9007db1485 Expire wasUnreachable entries, so inbound tunnel build failures don't escalate
and the peer doesn't have a severe penalty in the CapacityCalculator forever.
This may fix the tunnel build problems that started in -10. Or not.
2013-11-03 15:26:21 +00:00
zzz
85c998e500 HTTP proxy: Fix addressbook name on redirect page 2013-11-03 15:04:37 +00:00
zzz
8296f8229e + * NetDB: Allow store of leaseset as long as one lease has not expired 2013-11-03 15:01:31 +00:00
zzz
059ae3a80e - Add network status to event log 2013-11-03 15:00:00 +00:00
kytv
67e242c441 Debian patch refresh and readme file update 2013-11-02 17:31:31 +00:00
zzz
e23f3b4875 comments 2013-11-02 14:10:06 +00:00
zzz
06ea9af733 i2psnark: Log name of offending file causing IOException (ticket #1099) 2013-11-02 14:09:00 +00:00
zzz
884818f518 log tweaks, generics 2013-11-02 13:58:12 +00:00
zzz
3f39bd0f7b remove unused static log 2013-11-02 13:53:42 +00:00
str4d
48cce6435b routerconsole war dies with .jsp files in a subdir 2013-11-01 11:00:37 +00:00
zzz
777e08c8b6 * Transport: Fix GeoIPv6 (ticket #1096)
due to int/long problem, they were being corrupted
   and then looked up as IPv4
2013-11-01 01:44:29 +00:00
zzz
8c4b0b7c00 merge of '0af9bde8ae97c3b08f2c934236532121ce135817'
and 'b324a96172089b549e53fb1c0c2a01807fe64699'
2013-10-31 21:30:02 +00:00
zzz
dae8b25374 Transports:
- Increase threshold for idle timeout reduction from 33% to 60%.
   This was reduced from 75% to 33% in -10 and it caused significant
   tunnel build problems, for reasons that aren't entirely clear.
 - Don't change the SSU idle timeout quicker when firewalled.
 - log tweaks
2013-10-31 21:27:26 +00:00
str4d
2ae293444e Split routerconsole help into several files (no frontend change)
The old full-page translations of help.jsp are deprecated. The help text will
be tagged for translation on Transifex.
2013-10-31 21:22:24 +00:00
zzz
0f11d3566a log tweaks 2013-10-31 21:15:09 +00:00
zzz
fa70d439c3 minor optimization 2013-10-31 21:08:02 +00:00
zzz
0010581405 TunnelPoolSettings:
- Make dest hash final
 - Ensure allowZeroHop is always true for exploratory
2013-10-31 21:07:11 +00:00
zzz
1d659e4f8a i2psnark: Always verify file lengths at startup (ticket #1099) 2013-10-31 21:02:59 +00:00
zab2
509f00c5e2 Override toString() 2013-10-30 18:09:40 +00:00
dg2-new
aeb3241abb * i2psnark: Start torrents by default (ticket #1072) 2013-10-29 23:05:50 +00:00
zzz
8909df3c88 * i2psnark: Fix start and start-all buttons on text-mode browsers
and Opera (ticket #1093)
2013-10-29 21:49:20 +00:00
zzz
1cffcae36b merge of '2c288e0ac5d4a6039b3f08e6bbae9439bb038955'
and 'fa8975b2dbcb60d5f181bc21fc1245d5f82baef0'
2013-10-29 21:04:40 +00:00
zzz
d2ee5b96ad Log tweaks and minor cleanups, -15 2013-10-29 21:03:20 +00:00
zzz
0506a5915b * Tunnels:
- Build a new exploratory fallback tunnel in the BuildExecutor
     loop if we run out.
   - Don't use closest expl. tunnel as the paired tunnel for a build,
     use a random one instead (partially back out change from -12)
   - Log tweaks
2013-10-29 21:01:53 +00:00
zzz
91ef3fd0bc * InboundMessageDistributor:
- Don't discard an encrypted DSRM received
     down a tunnel, just strip the hashes like we do for unencrypted
   - Send a store of our own encrypted LS received down a tunnel to
     the InNetMessagePool so the FloodfillVerifyStoreJob will see it.
 * NetDB: Fix LS store verifies with encrypted replies
   by storing the tagset with the correct SKM for the inbound tunnel used.
   Broken since 0.9.7 when it was introduced.
2013-10-29 20:57:00 +00:00
dg2-new
79f5484f87 Fix history. 2013-10-29 20:38:32 +00:00
meeh
6afd2c4b97 * Adding no.i2p registrar 2013-10-29 00:05:06 +00:00
zzz
06b09f89de add SU3File bulksign CLI 2013-10-28 23:22:17 +00:00
zzz
bd0eee6aa9 * configstats: Page will now always reflect results of a previous
change, by querying the config instead of StatSummarizer to
   determine if a stat is graphed.
  - Don't append to a string in a loop
  - parseConfig() return a Set instead of List to avoid O(n**2) behavior
    when deteriming config changes
2013-10-28 21:48:02 +00:00
dg2-new
5bc13c16dc merge of '40e39576b76cc1261e0eda2c63a052544021f2e3' and '81c0ce21efaae02bbc2b5d3ce4e25b2d315dc2eb' 2013-10-28 20:09:57 +00:00
dg2-new
626daeb86e * I2PTunnel: Enable persistent keying for SOCKS tunnels (ticket #1088) 2013-10-28 19:15:46 +00:00
zzz
a92913da4c * Streaming:
- Ensure minimum randomized initial conn throttle period
   - Change order of throttle checks again
   - Don't continue throttle checks if throttled
2013-10-28 17:59:50 +00:00
zzz
f0f363e8c3 * Streaming: Fix instantiation failure with blacklist entries,
caused by bad fix for ticket #1070
2013-10-27 17:09:29 +00:00
zzz
7839c0fec3 * Tunnels:
- Don't use fallback expl. tunnels as the paired tunnel
     for a client tunnel build.
     This will cause more client tunnel breakage but it's
     really bad to use a zero-hop for this.
   - Fix selection of an expl. tunnel close to a hash
   - Don't update build generation stat if the generation failed
   - log tweaks
2013-10-26 20:52:56 +00:00
zzz
4d24d65c1f * Profiles: Ensure we select random peers even before the first reorganization -
we were picking the not-failing peers in-order for early expl. tunnel builds
2013-10-26 20:47:41 +00:00
zzz
ddf761b1f8 * Streaming: Randomize end of first conn limit period
to prevent correlation
2013-10-26 20:45:30 +00:00
zzz
2814fe75b1 sort custom options 2013-10-26 20:44:19 +00:00
zzz
7316c82ef3 * i2psnark: Display base name, not torrent file name (ticket #985) 2013-10-26 20:42:16 +00:00
zzz
e04646bd37 finals 2013-10-26 14:21:53 +00:00
zzz
8f8022347d * I2PTunnel HTTPServer:
New POST limiter
2013-10-26 14:21:26 +00:00
str4d
acc0ab66a3 My RSA 4096 pubkey for update signing 2013-10-26 11:25:07 +00:00
zzz
5a6acf1d85 * Router: Only log pingfile error once (ticket #1086) 2013-10-25 19:55:09 +00:00
zzz
ca45194c30 * Streaming:
- Check blacklist/whitelist before connection limits, so
     a blacklisted peer does not increment the counters
   - Don't increment total throttle if peer is throttled
   - Fix blacklist NPE after config change (ticket #1070)
2013-10-25 14:09:02 +00:00
zzz
102506ebe8 * Transports: Reduce connection idle time sooner 2013-10-25 14:05:50 +00:00
zzz
d06f1c4a30 /confighome: Remove config when restoring default so user will again see changes from updates 2013-10-24 21:46:03 +00:00
zzz
c732c1c038 I2PTunnel: Catch unchecked exceptions in server accept loop (ticket #1070) 2013-10-24 20:56:37 +00:00
zzz
4aa1bba575 * NetDB:
- We don't verify RI stores any more, so save RI-last-published time when we store it.
2013-10-24 20:54:21 +00:00
zzz
9d3925eb20 * i2psnark:
- Drop incoming connections on HTTP port
   - Define port 6881 in one place
   - Don't let random DHT port be 6881
   - Exception tweak
2013-10-24 20:52:37 +00:00
zzz
80fdf4e917 * I2PTunnel - fix anonymity characterization in dropdowns
(2 hops is not high anonymity)
2013-10-24 19:18:53 +00:00
zzz
35a86e603b * I2PTunnel standard, HTTP, and IRC servers:
Route connections to specific targets based on incoming I2P port
   with custom option targetForPort.xxxx=myserver:yyyy
   This allows multiple services on a single server tunnel (ticket #1066)
2013-10-24 11:38:28 +00:00
zzz
8f7b31aed3 * I2PTunnel standard and IRC clients:
- Allow host:port targets; set defaults in i2ptunnel.config (ticket #1066)
   - Don't fail start if hostname is unresolvable; retry at connect time (ticket #946)
   - Output IRC message on connect fail
   - Update target list on-the-fly when configuration changes
2013-10-23 20:20:54 +00:00
zzz
0f5a0b6b1b * NetDB:
- Increase RI publish interval to reduce the connection load on ffs
   - Save RI-last-published time; check it before publishing
   - Minor cleanups
2013-10-23 14:56:27 +00:00
zzz
4cf3906ed2 * Home page:
- Add salt.i2p. Icon from efkt, free to use.
   - Change icon for stats.i2p. Icon from Fat Cow, see license info in LICENSES.txt
2013-10-23 12:41:36 +00:00
zzz
57875586cf reduce same-country bonus, less countries 2013-10-19 22:10:03 +00:00
zzz
ad8ec011d0 more transport categories 2013-10-19 22:09:23 +00:00
zzz
0d93b86a56 sfv mime type 2013-10-19 22:09:07 +00:00
zzz
63712002e2 merge of '4eee3780cfb882747ad68e39ac08b721f91c48a7'
and 'cca89ae05036ab7a2fe0080fdd1cfac19968246a'
2013-10-19 21:27:59 +00:00
zzz
67af1a17c1 - Don't display UPnP info on peers page in Android
to prevent crash
2013-10-19 21:26:23 +00:00
zzz
9cac546547 add IPv6 categories to /netdb transport chart 2013-10-19 16:37:13 +00:00
zzz
3ffb321f46 * NetDB: Reinstate ExpireRoutersJob 2013-10-19 14:51:11 +00:00
zzz
14ea6d8d0a delay multiple ExploreJobs slightly 2013-10-19 14:47:27 +00:00
zzz
8e0dbf31ba * NetDB (ticket #1076)
- Reduce flood redundancy from 4 to 3
   - Reduce min part. tunnels for ff from 100 to 50
2013-10-19 14:45:52 +00:00
zzz
5187bf1eae * I2PTunnelHTTPServer: Start timer before reading the first line (ticket #1071) 2013-10-19 14:40:34 +00:00
zzz
99471d8e1b css tweak to fix i2ptunnel ssl box layout on firefox 2013-10-19 14:37:28 +00:00
zzz
012e999354 fix unit tests broken by previous checkin 2013-10-18 19:58:39 +00:00
zzz
bdd9900d0d * OutNetMessage: Remove setters, make fields final 2013-10-18 18:42:48 +00:00
zzz
c71b485083 mark ipv6 only as experimental on /confignet 2013-10-18 18:38:39 +00:00
zzz
a78d34ab4b * I2PTunnel SSL cleanup, log SSL exceptions as errors to help find cert problems 2013-10-18 18:37:25 +00:00
zzz
255ebe7efb * Streaming: Throw IOE if socket is closed (ticket #1077),
never return null from stream getters
2013-10-17 13:39:00 +00:00
zzz
5f7a761e42 * I2CP: Move SSL client socket code to util,
move cert location to certificates/i2cp.
 * I2PTunnel: Support SSL for connection to local server
   for Standard, HTTP, and IRC server tunnels.
   Put server cert in certificates/i2ptunnel if necessary.
2013-10-17 13:22:17 +00:00
zzz
09548358fa increase translate initial map size, clear on exit 2013-10-17 11:17:58 +00:00
zzz
df381c37ff 3gp mime type 2013-10-17 11:15:20 +00:00
kytv
31e96b416d Update Trac links: s|http://trac\.i2p2\.de|https://trac.i2p2.de|g 2013-10-16 23:12:11 +00:00
kytv
53b0f7b579 french updates 2013-10-16 23:11:06 +00:00
zzz
45deaa3a87 * open4you icon and text
from hosting@mail.i2p
   image free to use
2013-10-14 20:06:57 +00:00
zzz
0c8eabcdf6 merge of '2bb222d33ec817b78fcf506c32da44d10b1eff3b'
and '59e86e3176465259a67927b042c1307cd0a94aa4'
2013-10-14 17:10:55 +00:00
zzz
f9571740ae address check cleanup 2013-10-14 17:02:08 +00:00
zzz
eb2af2b5fd * ClientManager: Remove setters, make all fields final 2013-10-14 17:01:32 +00:00
zzz
ded00300b4 javadoc fixes 2013-10-14 17:00:14 +00:00
zzz
811819af69 * Tests:
- Fix LogSettingsTest broken by recent LogManager changes
   - Remove empty LogSettings.java
2013-10-14 16:58:50 +00:00
kytv
1804c852bb French language translation updates from Transifex 2013-10-14 15:43:39 +00:00
zzz
3ec602865d * Translations: Move country names to a new resource bundle 2013-10-14 15:29:12 +00:00
zzz
0c0a25b038 merge of 'ad0ab5020bb253c5233ac2f036c0cf4f40001d51'
and 'bc7c0fa32e955a7d8185456815652d4baab500ae'
2013-10-13 19:38:48 +00:00
zzz
208192f445 * I2CP: Fix bug in handling external I2CP clients, introduced in -2
by the immutable destination patch
2013-10-13 19:33:04 +00:00
zab2
d0f635e30c ticket #1062 - count duplicate packets towards RTT if we have
never sampled it
2013-10-13 17:05:59 +00:00
zzz
20b2f7dcb1 fix date, restore tunnel length changed in previous checkin 2013-10-13 12:03:57 +00:00
zzz
cf66951818 cleanup after prop, history for prop, -2 2013-10-13 11:55:23 +00:00
zzz
c6f41cc8fa crypto cleanup 2013-10-13 11:53:43 +00:00
zzz
45a579403a propagate from branch 'i2p.i2p.zzz.test2' (head 5c1b78bd78845b0c8b90fbb60412c68e7dc4f3e6)
to branch 'i2p.i2p' (head 8bdc25c8e6f40491f20b533d94eacab012adba35)
2013-10-13 11:48:12 +00:00
zzz
74a57abfb4 Streaming:
- Make I2PSocketFull.close() nonblocking; it will now cause any user-side
     writes blocked in I/O (Connection.packetSendChoke()) to throw
     an exception (tickets #629, #1041)
   - Don't ignore InterruptedExceptions; throw InterruptedIOException
   - Back out static disconnect exception
   - MessageInputStream locking fixes
   - Cleanups
 I2PSnark:
   - Close socket before closing output stream to avoid blocking in
     Peer.disconnect(), and prevent Peer.disconnect() loop
2013-10-12 17:39:49 +00:00
zzz
380783c1ba Snark DHT:
- Combine getPeers and announce into a single method, as we must announce to
     the closest from the getPeers, not the closest from the kbuckets
   - Stop getPeers when nothing closer is found
2013-10-09 21:09:34 +00:00
zab2
c8843a736d make _ackSinceCongestion atomic 2013-10-09 14:08:44 +00:00
zab2
e69fefda62 cleanup: remove boolean parameter that is always true 2013-10-09 14:06:16 +00:00
zab2
513da3b743 cleanup: remove no-op invocation 2013-10-09 14:04:34 +00:00
zzz
7513d42e9e Snark DHT:
- Increase dest lookup and search timeouts
   - Increase max search depth
   - Loop tracker client faster when in magnet mode
   - Loop tracker client faster if DHT announce fails
   - Don't return an empty peers list if we only know about the requestor
   - volatiles, log tweaks
   - Major fixes of getPeers() to follow
2013-10-09 13:06:47 +00:00
zzz
8872437caf Another snark refactoring bug, log tweaks 2013-10-08 01:17:36 +00:00
kytv
712c77a4b6 add my "su3" certificate 2013-10-08 00:17:41 +00:00
zzz
38cef14cf4 synch cleanup thx zab 2013-10-07 19:26:33 +00:00
zzz
05c3b0d391 Fix bug causing writes past end of file, introduced in refactoring, not in trunk 2013-10-07 15:47:44 +00:00
zzz
854090e9d8 - Console: Set per-connector acceptors back to 1, Jetty default changed to 2? 2013-10-07 14:51:49 +00:00
zzz
f035815f7a - Don't truncate initial news header if it appears in summary bar
(unlikely as we don't show the "hide news" button for initial news)
     Also prevent string IOOBE
2013-10-07 14:45:11 +00:00
zzz
df4302dda0 * Update:
- Thread news fetcher so it doesn't clog the scheduler
2013-10-07 14:43:18 +00:00
zzz
31f117e74c * Data Structures:
- Make Destination and RouterIdentity keys and cert immutable
   - Add Destination cache
2013-10-07 13:04:01 +00:00
zzz
890f40b2ac more log tweaks 2013-10-07 12:11:42 +00:00
zzz
3ac8083faf log tweaks 2013-10-07 12:10:10 +00:00
zzz
249319f76f * Disallow 2001:db8::/32 (RFC 3849) addresses 2013-10-07 11:22:54 +00:00
zzz
efe87060b4 add missing start.jar thx kytv 2013-10-06 22:55:59 +00:00
zzz
afe3ff57cf history for prop, -1 2013-10-06 17:13:29 +00:00
zzz
6bb1505d3b propagate from branch 'i2p.i2p.zzz.ecdsa' (head 1dd9522809f801ca68dd331cfba1c5c914dc1481)
to branch 'i2p.i2p' (head a1c2ba4663abc7470f427c6a14854707d58b486a)


 Prop from branch i2p.i2p.zzz.ecdsa:
 * Build:
   - Generate su3 file in release target
   - Add zzz's new RSA 4096 pubkey cert for updates
   - Fix checkcerts.sh
 * Console: Move advanced setting to HelperBase
 * DSAEngine changes:
   - Implement raw sign/verify for other SigTypes
   - Add sign/verify methods using Java keys
 * ECDSA Support:
   - Add ECConstants which looks for named curves and falls back to
     explicitly defining the curves
   - Add support for ECDSA to SigType, DSAEngine and KeyGenerator
   - Attempt to add BC as a Provider
   - genSpec: fallback to BC provider
 * EepGet:
   - Fix non-proxied PartialEepGet
   - Prevent non-proxied eepget for an I2P host
 * KeyGenerator changes:
   - Generate key pairs for all supported SigTypes
   - KeyPairGen: Catch ProviderException, fallback to BC provider
   - Add KeyGenerator main() tests
 * KeyRing and DirKeyRing added: simple backend for storing X.509 certs
 * KeyStoreUtil added:
   - Consolidate KeyStore code from SSLEepGet, I2CPSSLSocketFactory,
     SSLClientListenerRunner, and RouterConsoleRunner into new
     KeyStoreUtil and CertUtil classes in net.i2p.crypto (ticket #744)
   - Change default to RSA 2048 (ticket #1017)
   - Set file modes on written keys
   - Overwrite check in createKeys()
   - New getCert(), getKey()
   - Extend keygen max wait
   - Read back private key to verify after keygen
   - Validate cert after reading from file
   - Validate CN in cert
   - Specify cert signature algorithm when generating keys
 * NativeBigInteger: Tweak to prevent early context instantiation
 * RSA support added: constants, parameters, sig types, support in DSAEngine, KeyGenerator, SigUtil
 * SHA1Hash: Add no-arg constructor
 * SigType changes:
   - Add parameters (curve specs) to SigTypes
   - Add getHashInstance()
   - Add RSA, fix ECDSA
   - Renumber, rename, comment out types that are too short.
 * SigUtil added:
   - Converters from Java formats (ASN.1, X.509, PKCS#8)
     to I2P formats for Signatures and SigningKeys
   - Move ASN.1 converter from DSAEngine to SigUtil, generalize
     for variable length, add support for longer sequences,
     add more sanity checks, add more exceptions
   - Move I2P-to-Java DSA key conversion from DSAEngine to SigUtil
   - Add Java-to-I2P DSA key conversion
   - Add Java key import
   - New split() and combine() methods
 * SSLEepGet: Move all certificates to certificates/ssl, in preparation
   for other certificate uses by SU3File
 * SU3File changes:
   - Support all SigTypes
   - Implement keygen
   - Readahead to get sigtype on verify, as we need the hash type
   - Enum for content type
   - Add unknown content type, make default
   - Fix NPE if private key not found or sign fails
   - Store generated keys in keystore, and get private key from keystore
     for signing, in Java format
   - Use Java keys to sign and verify so we don't
     lose the key parameters in the conversion to I2P keys
   - Type checking of Java private key vs. type when signing
   - Use certs instead of public keys for verification
   - Fix arg processing
   - Improve validate-without-extract
   - New extract command
   - Change static fields to avoid early context init
   - Reduce PRNG buffer size for faster signing
 * Update: Preliminary work for su3 router updates:
   - New ROUTER_SIGNED_SU3 UpdateType
   - Add support for torrent and HTTP
   - Refactor UpdateRunners to return actual UpdateType
   - Deal with signed/su3 conflicts
   - Verify and extract su3 files.
   - Stub out support for clearnet su3 updating
   - New config for proxying news, separate from proxying update
   - PartialEepGet and SSLEepGet tweaks to support clearnet update
   - Remove proxy, key, and url config from /configupdate
   - More URI checks in UpdateRunner
   - Add https support for news fetch
   - Add su3 mime type
   - Reset found version in update loop so we don't fetch from
     the next host too.
   - Prevent NPE on version after SSL fetch
2013-10-06 17:09:56 +00:00
zzz
a1c8e3eae3 reduce search limit 2013-10-06 17:08:51 +00:00
zzz
aa171bbaa6 less scary message 2013-10-06 17:07:56 +00:00
zzz
845b70fe0c add missing sidebar 2013-10-06 17:07:27 +00:00
zzz
82b1eb7c18 * Update:
- Check proxy setting before calling runner for method
2013-10-06 16:39:30 +00:00
zzz
4bd27ea1d3 * Update:
- Reset found version in update loop so we don't fetch from
     the next host too.
   - Prevent NPE on version after SSL fetch
   - Fix su3 version check
 * EepGet:
   - Fix non-proxied PartialEepGet
   - Prevent non-proxied eepget for an I2P host
   - Fail if no hostname in URL
2013-10-06 16:02:33 +00:00
zzz
d0f6be3161 fix cert dir 2013-10-06 01:15:40 +00:00
zzz
7764257e41 more synching for coherence 2013-10-06 00:43:12 +00:00
zzz
af0e72ac4d * SSU: More efficient ImboundMessageState
(reduce ByteArray[] size where possible)
2013-10-05 18:38:55 +00:00
zzz
0534440695 - Treat 6bone 3ffe::/16 as local 2013-10-05 14:04:40 +00:00
zzz
c2fa2d0c5b * Logging:
- Require strict match of class name component
   - parseLimits() cleanup
2013-10-05 13:07:33 +00:00
zzz
887017b54c * Transport: Treat more IPs as local
25/8 - Hamachi (moved from 5/8 Nov. 2012)
   2620:9b::/32 - Hamachi
   0::/8 - Includes IPv4 compatibility addresses ::xxxx:xxxx
2013-10-05 12:56:39 +00:00
zzz
3a4f5a2f1b jetty 7.6.13.v20130916 2013-10-04 23:43:38 +00:00
zzz
3fb4643742 - Add https support for news fetch 2013-10-04 20:28:43 +00:00
zzz
a5e3bc9b85 Update:
- New config for proxying news, separate from proxying update
 - Default logic cleanup
2013-10-04 20:21:54 +00:00
zzz
8a0c3f10f4 Update:
- Stub out support for clearnet su3 updating
 - PartialEepGet and SSLEepGet tweaks to support clearnet update
 - Remove proxy, key, and url config from /configupdate
 - More URI checks in UpdateRunner
 - Add su3 mime type
 - Move advanced setting to HelperBase
2013-10-04 19:06:39 +00:00
zzz
e1d808a284 add msg when stopping tunnel on idle 2013-10-04 16:50:37 +00:00
zzz
e755051ebe * i2psnark:
- Add torrent auto-stop support; enable for update file
   - Add tunnel auto-close when no torrents are running
   - Log/msg tweaks on add/create failures
2013-10-04 16:40:14 +00:00
zzz
d7c3ffa4de 0.9.8.1 2013-10-02 14:14:18 +00:00
zzz
cba3b249dd * Startup: Fix rekeying on Windows (tickets #1056, 1057) 2013-10-01 14:22:17 +00:00
zzz
32f250003e NBI: Tweak to prevent early context instantiation 2013-09-30 19:25:21 +00:00
zzz
e004b0e6e9 Build:
- Generate su3 file in release target
  - Add my new RSA 4096 pubkey cert for updates
  - Fix checkcerts.sh
2013-09-30 19:21:25 +00:00
zzz
a5c5917a5f add key length to RSA SigType names 2013-09-30 17:13:35 +00:00
kytv
cbd24946b6 refresh patch, en po 2013-09-30 16:33:01 +00:00
zzz
9b4842931a 0.9.8 2013-09-30 12:57:13 +00:00
zzz
e04cf132cc HTTPServer: Log tweak for better diagnosis of delays 2013-09-29 16:40:50 +00:00
zzz
7d237b4cf6 Watchdog: Format messages better 2013-09-29 16:38:57 +00:00
zzz
3cbfd09722 Console: Tag strings on /jobs (ticket #969) 2013-09-29 16:36:32 +00:00
zzz
0ae774dd68 bump for review 2013-09-28 12:00:20 +00:00
zzz
2884df873e * Streaming: Major rework of connection disconnect process. Tickets 1040-1042.
- Prevent multiple calls or reentrancy in disconnect() (ticket #1041)
   - Implement processing of close to skip TIME-WAIT, and
     wait for all packets to be acked (not just the CLOSE) before
     doing so, if possible (ticket #1042)
   - Don't call disconnect() or disconnectComplete() from I2PSocketFull.destroy()
     so retransmissions and acks can still happen (removes some close loops)
   - Don't call disconnect() until we have both sent and received a CLOSE (ticket #1040)
   - Don't reset the connection from CPH just because we sent a CLOSE
     and it was acked (ticket #1040)
   - Ack packets even if we sent a CLOSE  (ticket #1040)
   - Retransmit CLOSE if not acked (ticket #1040)
   - Send received packets to the MessageInputStream even if we haven't received a SYN
   - Don't call MessageInputStream.messageReceived() for ack-only packets, that was pointless
   - Don't send a RESET after timeout of an outbound connection
   - Work around bugs on other end by limiting retransmission of CLOSE packets
   - Make _isInbound final
   - More cleanups, javadocs, log tweaks
2013-09-28 11:47:47 +00:00
kytv
d4d1424c4f update debian changelog 2013-09-27 20:15:02 +00:00
kytv
33827f9aaf switch from elipsis to three "."s 2013-09-27 20:14:36 +00:00
zzz
30a666c833 Streaming: Don't queue a message for an unknown connection on the SYN queue
if it has a send ID set, it must be for a recently closed connection
2013-09-27 01:50:38 +00:00
zzz
9a00621fa4 log tweaks 2013-09-27 01:48:12 +00:00
kytv
46bc479884 update geoip based on Maxmind GeoLite Country database from 2013-09-03 2013-09-26 21:47:53 +00:00
kytv
6ab6abf4dd French, German, Russian, and Swedish translation updates from Transifex 2013-09-26 21:47:06 +00:00
zzz
0c6a9ff2a0 proof delimiter tweak 2013-09-25 23:13:42 +00:00
zzz
aefc5b5317 javadoc fix 2013-09-25 17:42:37 +00:00
zzz
25682fdea7 log tweaks, javadoc 2013-09-25 17:42:13 +00:00
zzz
9318099845 * Streaming:
- Cleanups
   - Remove setCloseReceivedOn(), unused outside Connection
   - OR the isFlagSet parameter instead of multiple calls
   - Remove acked packets from _outboundPackets inside synced iterator
   - Short-circuit _outboundPackets iterator if empty
   - Small optimization if not logging in ConnectionPacketHandler
   - Stub out processing of close ack (ticket #1042)
2013-09-24 16:01:20 +00:00
zzz
fdf38a952d atomic default value cleanup 2013-09-24 14:45:30 +00:00
zzz
fb40ab1f00 * Streaming: Atomics for close/reset send/receive
so we only do things once. (Ticket #1041)
2013-09-24 14:01:48 +00:00
zzz
3499ed7bb0 * Streaming: Consolidate scheduling of DisconnectEvent, and ensure
we only do it once. (Ticket #1041)
2013-09-24 13:22:46 +00:00
zzz
b05906a3c2 SigType: Renumber, comment out all the types that are
too short or for testing. Turn off debug logging.
2013-09-24 12:55:22 +00:00
zzz
61d5f46295 * Streaming: Fix active stream counting so it doesn't count streams
that are closed and in TIME-WAIT state. Also, break out of the
   counting loop as soon as we know the answer. (Ticket #1039)
2013-09-24 12:40:35 +00:00
zzz
9ebfccd8f6 * Console: Add /proof page which can copied to prove you run a router 2013-09-23 16:39:40 +00:00
zzz
4fb3e86e4d Truncate and linkify magnet link in summary bar update message 2013-09-23 12:13:44 +00:00
zzz
837517e94e Update: Verify and extract su3 files.
untested...
2013-09-22 19:19:36 +00:00
zzz
f47ec65b8f Update: Preliminary work for su3 router updates:
- new ROUTER_SIGNED_SU3 UpdateType
   - Add support for torrent and HTTP
   - Refactor UpdateRunners to return actual UpdateType
   - Deal with signed/su3 conflicts
   - unpack/verify stubbed only
2013-09-22 18:03:56 +00:00
zzz
6fede7f524 log tweaks 2013-09-22 14:13:50 +00:00
zzz
bd0c18b2e3 * Console: Implement webapp state detection and stop button for webapps
on /configclients (Ticket #1025)
2013-09-21 16:11:55 +00:00
zzz
fba596c78c geoipv6 Sept 19 2013 from Maxmind 2013-09-21 12:30:06 +00:00
kytv
61f2b49022 another extraneous script name 2013-09-20 23:09:27 +00:00
kytv
e71a1a5c4d remove extraneous script name 2013-09-20 23:07:11 +00:00
kytv
683ce3254f testscripts build target: check shell scripts for validity
(also adding missing shebang lines)
2013-09-20 22:32:05 +00:00
kytv
df555731c4 minor script changes
- mbuild.sh: don't require bash
- Slackware/i2p/doinst.sh: add bash shebang
2013-09-20 22:17:48 +00:00
kytv
641fc0cae9 fix langbox alignment, bump build number 2013-09-20 21:06:57 +00:00
kytv
5ab1d6896a jbigi scripts: look in /usr/local (for *BSD) 2013-09-20 19:39:25 +00:00
zzz
0ae2d92fcd * Update: Support notification of updates that cannot be downloaded
due to "constraints". Add constraint checks for java version,
   router version, configuration, and base permissions. (ticket #1024)
2013-09-20 18:56:54 +00:00
zzz
26c8201e03 spellcheck off 2013-09-20 18:42:51 +00:00
kytv
37521c69a2 look for openjdk6 in OpenBSD if v7 isn't available 2013-09-20 18:33:11 +00:00
kytv
43383a5b3c changes to fix compilation on OpenBSD 2013-09-20 10:44:56 +00:00
kytv
bfea3e4dd6 translation updates from Transifex 2013-09-20 10:43:13 +00:00
kytv
35b02a52e1 redirect output of which command to /dev/null 2013-09-20 02:00:41 +00:00
kytv
8e3e566915 typo fix 2013-09-20 01:45:09 +00:00
kytv
968b9a0304 fix previous check-in 2013-09-20 01:38:20 +00:00
kytv
c97f0f3d22 OpenBSD compilation fix: set JAVAC in bundle targets if javac not found and require.gettext is set to true
This solves the following problem which was found on OpenBSD:

bundle:
     [exec] Generating net.i2p.desktopgui.messages_ar ResourceBundle...
     [exec] ERROR - msgfmt failed on locale/messages_ar.po, not updating translations
     [exec] msgfmt: Java compiler not found, try installing gcj or set $JAVAC
     [exec] msgfmt: compilation of Java class failed, please try --verbose or set $JAVAC
     [exec] 9 translated messages.


In OpenBSD 5.4, neither java nor javac are in the PATH.
2013-09-20 01:21:43 +00:00
kytv
65b1124d81 various updates to i2prouter
- check status of i2psvc with ldd
- only warn about libiconv in FreeBSD if the package isn't installed. In recent
  versions of FreeBSD, OpenJDK depends on libiconv so it should always be
  available.
2013-09-19 20:56:56 +00:00
zzz
89034e1f9d SU3File:
- Fix arg processing again
   - Change static fields to avoid early context init
   - Reduce PRNG buffer size for faster signing
2013-09-19 15:21:53 +00:00
zzz
9f2fa6a8be fix arg processing 2013-09-19 13:59:39 +00:00
zzz
19cf8787d8 - Allow getRawAlgo() for public keys
- SU3File better arg processing, implement content type arg
   - Type checking of Java private key vs. type when signing
   - Add unknown content type, make default
2013-09-18 16:53:38 +00:00
zzz
a80c34c1df * i2psnark:
- Refactor Storage file data structures
   - Sort files when creating torrents
2013-09-18 15:41:10 +00:00
zzz
ab8900f910 * I2PTunnelHTTPServer: Don't thread a receiver for GET or HEAD 2013-09-18 15:39:12 +00:00
zzz
ce2d0b0e12 - Revert expl. default back to 2 hops, wait for next release
- Eepsite index.html better help on redirects
   - Remove exotrack (again)
2013-09-17 13:53:20 +00:00
zzz
87d98781a9 Read back private key to verify after keygen
Validate cert after reading from file
   Validate CN in cert
   Javadoc fixes
2013-09-16 15:48:54 +00:00
zzz
79dc95dd66 Fix RSA_SHA384
Fix DSAEngine for RSA
   Fix KeyGenerator for RSA
   New split() and combine() methods in SigUtil
   Fix private key conversions for RSA
2013-09-15 16:49:59 +00:00
zzz
c6533202f7 Add RSAConstants
Specify RSA parameters
  Add RSA sig types
  Specify cert signature algorithm when generating keys
  Extend keygen max wait
  Catch NPE if sign fails in SU3File
  Fix signature conversion for RSA
  Fix public key conversion for RSA
2013-09-15 15:12:07 +00:00
zzz
b5dc9bc0ba DSAEngine: Add sign/verify methods using Java keys
SU3File: Use Java keys to sign and verify so we don't
           lose the key parameters in the conversion to I2P keys
2013-09-14 15:53:08 +00:00
zzz
79891c6677 open4you.i2p 2013-09-14 15:28:36 +00:00
zzz
68aa1aea8e stub out RSA 2013-09-13 15:26:38 +00:00
zzz
4ffaf4128e SU3File:
- enum for content type
  - fix NPE if private key not found
  - use certs instead of public keys for verification
  - improve validate-without-extract
  - new extract command
2013-09-13 13:02:37 +00:00
zzz
801ca47a0c add Koblitz curves for testing 2013-09-13 00:49:10 +00:00
zzz
43f5062169 SSLEepGet: Move all certificates to certificates/ssl, in preparation
for other certificate uses by SU3File
2013-09-12 21:47:25 +00:00
zzz
7ab4dd7f4b KeyStoreUtil:
- Overwrite check in createKeys()
  - New getCert(), getKey()
  SU3File:
  - Store generated keys in keystore
  - Get private key for signing from keystore
2013-09-12 20:22:30 +00:00
zzz
71c0104236 Add base algorithm type in prep for RSA 2013-09-12 18:23:28 +00:00
zzz
a608d21571 KeyStore: change keygen default to RSA 2048 (ticket #1017)
fix key length setting
2013-09-12 14:55:16 +00:00
zzz
935ddaa0b2 fix default expiration 2013-09-12 14:41:25 +00:00
zzz
945e7b75fd Crypto - prep for using certificates in SU3File:
Consolidate KeyStore code from SSLEepGet, I2CPSSLSocketFactory,
  SSLClientListenerRunner, and RouterConsoleRunner into new
  KeyStoreUtil and CertUtil classes in net.i2p.crypto (ticket #744)
2013-09-12 14:27:16 +00:00
kytv
5e90780590 jbigi/jcpuid build scripts: Look for OpenJDK7 in kFreeBSD (it has landed in Debian testing) 2013-09-11 14:04:58 +00:00
zzz
a8a21ea7ce propagate from branch 'i2p.i2p' (head 6667c4a9f9fcc0705e407006d1933dd31942ffb2)
to branch 'i2p.i2p.zzz.ecdsa' (head bf746450400fc5ffa0e727ed0cd6a3966f6ce51f)
2013-09-10 13:03:40 +00:00
zzz
23444e4b81 * Router: Log new router hash in event log after rekeying 2013-09-10 12:25:24 +00:00
zzz
a3ea1f9429 remove static log 2013-09-10 12:23:45 +00:00
zzz
78d4b6d8a7 - Simple DirKeyRing backend for testing 2013-09-09 19:46:24 +00:00
zzz
3e3399adc6 - Add Java key import to SigUtil
- Import priv key to SU3File in Java encoded format instead of I2P format
  - New KeyRing stub
2013-09-09 00:49:14 +00:00
zzz
1e554dd0fe - Move I2P-to-Java DSA key conversion from DSAEngine to SigUtil
- Add Java-to-I2P DSA key conversion to SigUtil
  - Export keys from SU3File in Java encoded format instead of I2P format
2013-09-08 21:47:48 +00:00
meeh
388e7088e1 Updating cert for reseed.info 2013-09-08 16:14:53 +00:00
zab2
e65289cd0d Document logCloseLoop() methods 2013-09-08 15:23:09 +00:00
zab2
c4d68a8352 minor cleanup 2013-09-08 15:21:25 +00:00
zab2
7be0a93251 Use AtomicBoolean to prevent multiple close()-s 2013-09-08 13:18:47 +00:00
zab2
175f47293a Ticket #1012 - remove nested locking on close() and
finishInboundEstablishment()
2013-09-08 13:13:14 +00:00
zzz
27936fce04 cache key conversion 2013-09-08 13:06:30 +00:00
zab2
592680302f make the logCloseLoop() methods members of the Log class
so they can be used everywhere
2013-09-08 12:55:05 +00:00
zzz
55318cf14b Crypto: Set file modes on written keys; don't overwrite existing files 2013-09-08 11:57:15 +00:00
zzz
83ead0c304 - SU3File: Readahead to get sigtype on verify, as we need the hash type 2013-09-07 20:24:40 +00:00
zzz
38ec55bc72 - DSAEngine: Implement raw ECDSA sign/verify
- SU3File: Implement keygen
2013-09-07 19:37:02 +00:00
zzz
c4f97ed65e - DSAEngine: Start of support for signing hashes with other SigTypes
- KeyGenerator: Measure sign and verify separately in test
 - SU3File: Start to support other SigTypes
 - SigType: Add getHashInstance(), fix hash length for ECDSA_SHA256_P192
 - SHA1Hash: Add no-arg constructor
2013-09-07 18:12:19 +00:00
zzz
78a426e9ac * Crypto: Don't use "short exponent" on faster platforms.
Rebuild router identity if key length doesn't match setting.
   This affects RI and LS encryption keys, and DH and YK.
   Faster = 64 bit with working jbigi, non-ARM, non-GNU (for now)
   Override default with crypto.elGamal.useLongKey=true/false
   LS key is built at client startup (Dest key unused)
   This will churn most of the RIs at the release.
 * SystemVersion: Add isARM()
2013-09-07 13:43:28 +00:00
zzz
928b4bbbe5 - genSpec: fallback to BC provider 2013-09-06 13:53:15 +00:00
zzz
d27c465371 - KeyPairGen: Catch ProviderException, fallback to BC provider 2013-09-06 13:30:47 +00:00
zzz
4d62f63c71 * Start of ECDSA branch:
- Add ECConstants which looks for named curves and falls back to
     explicitly defining the curves
   - Add SigUtil with converters from Java formats (ASN.1, X.509,
     PKCS#8) to I2P formats for Signatures and SigningKeys
   - Move ASN.1 converter from DSAEngine to SigUtil, generalize
     for variable length, add support for longer sequences,
     add more sanity checks, add more exceptions
   - Attempt to add BC as a Provider
   - Add parameters (curve specs) to SigTypes
   - Add support for ECDSA to DSAEngine and KeyGenerator
   - Add KeyGenerator main() tests
   - More javadocs

  All is Java 1.5 compatible but the actual algorithms, curves,
  and other support aren't necessarily present in any JVM.
  Todo: More tests, more fallbacks for various JVMs
2013-09-06 12:04:22 +00:00
zzz
f4039b085a * Crypto: SigType tweaks, prep for parameters, show type in toString()
* NativeBigInteger: Don't use native for negative arguments, which aren't supported in jbigi.c
2013-09-06 11:40:50 +00:00
kytv
53ed10cfc8 typo fix (s/lt/le/) 2013-09-04 01:42:12 +00:00
zzz
0859dbe57f * i2ptunnel: Reduce buffer size and use cache in HTTPServer
* Jetty: Increase maxIdleTime
2013-09-04 00:46:43 +00:00
zzz
42bc4bb1f4 reduce log level 2013-09-03 12:13:07 +00:00
zzz
caead8a3a4 consolidate maxMemory() calls 2013-09-03 11:37:36 +00:00
zzz
7394c7997b change pw restart warning to error so people dont miss it 2013-09-03 10:25:18 +00:00
zzz
0298e4ab4c use different sort for floodfill profiles display 2013-09-01 12:12:40 +00:00
zzz
e3a5cdbbc2 deprecate most of LeaseSetKeys 2013-09-01 12:12:05 +00:00
zab2
6ae46abac0 fix ticket number 2013-08-31 18:42:07 +00:00
zab2
615a5f3c39 update history 2013-08-31 18:40:39 +00:00
zab2
6812dc1db8 Ticket #1007 use only non-retransmitted packets in RTT
sampling.  (RFC 6298)
2013-08-31 18:39:29 +00:00
zzz
41595cafce * Addressbook: Don't write to log file on Android (ticket #859) 2013-08-31 15:35:57 +00:00
zzz
d6c4e411be highlight snark table rows on hover 2013-08-31 15:19:00 +00:00
zzz
6ca797ec1f * Console: Display "accepting tunnels" instead of "rejecting tunnels" after 20 minutes (ticket #902) 2013-08-30 12:07:42 +00:00
zzz
8655988c66 * NTCP: Handle race where peer's NTCP address goes away 2013-08-30 12:01:51 +00:00
zzz
de5f2940ce * SSU, confignet: Add support for specifiying multiple addresses 2013-08-30 10:27:22 +00:00
zzz
1933e6239b * SusiDNS: Don't require last subscription to be terminated by newline (ticket #1000) 2013-08-30 10:21:57 +00:00
zzz
8aec1e2eb6 * Addresses: Treat Teredo addresses 2001:0::/32 as local 2013-08-30 10:20:43 +00:00
zab2
def30c5903 javadoc update 2013-08-14 20:29:40 +00:00
zab2
193f0bbc42 More elegant 2013-08-11 20:21:06 +00:00
kytv
b7a3b7bf05 debian: add missing timestamp to changelog 2013-08-11 17:00:26 +00:00
kytv
a2bd45fa9b * Translation updates from Transifex
- French, Portugeuse, Russian, Spanish, and Turkish updates from Transifex
   - Start of Romanian translation from Transifex
   - Update English POs for sending to TX
 * Debian: Update changelog
2013-08-11 16:58:19 +00:00
zab2
fd297118f9 fix NPE if stats are not enabled 2013-08-11 11:58:51 +00:00
zzz
7171edad24 Jetty 7.6.12.v20130726 2013-08-11 11:28:33 +00:00
zzz
d8466333f3 more snark mime types 2013-08-11 11:26:57 +00:00
zzz
a5e4d586eb dont display jump server msg if we dont know any 2013-08-11 11:26:40 +00:00
kytv
28a1c22438 Update Java Service Wrapper to v3.5.20
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
      changed from Tanuki's default to Itoopie.
    - Linux ARMv6: Compiled on a RaspberryPi using gcc 4.6.3-14+rpi1,
      Icedtea6 6b27-1.12.5-1+rpi1 and stripped
    - All other binaries are from the "community edition" deltapack offered by
      Tanuki.
2013-08-11 01:26:19 +00:00
zab2
74e238322d bump version for testing 2013-08-10 21:53:47 +00:00
zab2
1f3227409b Reduce initial ack delay to 1000
Rework the logic for acking duplicate packets
2013-08-10 21:03:05 +00:00
zab2
afda1da9c3 volatile 2013-08-10 21:00:09 +00:00
zzz
f2857e8f97 bump after prop 2013-08-10 17:16:50 +00:00
zzz
4802b1e2cd propagate from branch 'i2p.i2p.0971' (head 6cb629b61e0177deda1e539b2f85a2473f3af7fb)
to branch 'i2p.i2p' (head 8e86ef70afbbbbdc2db06cec34f17dedd528c7e7)
2013-08-10 17:06:17 +00:00
zzz
0328304f04 dont specify i2p.i2p branch so we can release from a different branch 2013-08-10 16:23:23 +00:00
zzz
06d2db0046 0.9.7.1 2013-08-10 16:00:46 +00:00
zab2
0539610219 volatile 2013-08-09 21:06:39 +00:00
zzz
170be8f033 Extend IB tunnel expiration
applied changes from 2f2fc980d396aa295ce972afc4298e8f2e763fea
             through c2bc3b29484ec8a689c72f2ab4e823a2a72f6430

New update hosts, thx Meeh and dg
2013-08-08 22:13:38 +00:00
zzz
ca0bb1ab76 Plucks from trunk for 0.9.7.1:
Streaming RTO changes:
 apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java
 apps/streaming/java/src/net/i2p/client/streaming/TCBShare.java
 apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptionsImpl.java

new reseed:
 applied changes from dbfea0ca35dbf9df85b5703db6f97a9579beb364
             through 325a9ed6f0f47eeabb33710073edf973671c63c9

disable RI verifies:
 applied changes from 4ef48b93946923e3371ab62719a474d869520697
             through a77990850b3534101571c88db4704676645914df

i2prouter bashism fix:
 applied changes from b5a0148f96728466561ece9be0e50ac9ad3f1468
             through e301d0499f4c688ed3a5febe30bf8098c7f2cdf9

i2psnark increase max piece size, mime type updates:
 apps/i2psnark/java/src/org/klomp/snark/Storage.java
 apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
 apps/i2psnark/mime.properties

UPnP fix:
 applied changes from 3d4a5cd3d933f75fdff7696f560c569f4674bd73
             through 75e5f5d4e0f0dd44140908bb6e73830e3448bdde
2013-08-08 12:07:16 +00:00
zzz
cdccb51456 * Start of 0.9.7.1 branch
* i2psnark: Increase update-via-torrent to 30%
2013-08-07 17:36:55 +00:00
str4d
870ecb847f Updated Eclipse files 2013-08-04 00:02:22 +00:00
kytv
8ba493c60e debian: compress package with xz
All currently supported distros support this format.
2013-08-01 23:29:34 +00:00
zab2
f3affff5be Atomic 2013-07-31 16:01:26 +00:00
zzz
5941a52a0d * Tunnels: Extend local expiration of IB tunnels, to allow for
more clock skew and not drop valid messages at their destination
2013-07-30 22:10:02 +00:00
zzz
04e6beb43c javadoc, log, comment, and su3file help tweaks 2013-07-30 22:05:46 +00:00
zzz
1284c7ace0 * i2psnark: Increase max piece size to 4 MB (ticket #993) 2013-07-30 21:50:07 +00:00
zab2
63414f0348 Override prepareOutbound() in VerifiedEstablishState 2013-07-30 17:13:34 +00:00
meeh
c8f22fdfd0 Adding new reseed host. Thanks to isdf! 2013-07-29 23:01:04 +00:00
zzz
7737bf5212 * GeoIPv6: Fix NPE (ticket #992) 2013-07-29 14:02:08 +00:00
zzz
4340f70d72 * Signatures:
- Prep for new signature algorithms; new SigType enum;
     Signature, SigningPublicKey, SigningPrivateKey store type
   - New Hash384 and Hash512 classes
   - Remove length field in SimpleDataStructure
   - New SU3File generator/verifier/extractor
2013-07-29 13:49:05 +00:00
zzz
6dbd8a6d1a add mobi mime type 2013-07-28 13:21:01 +00:00
zzz
076871fe44 * NetDB: Disable RI verifies for now 2013-07-28 13:02:12 +00:00
zzz
be753d7a1a * Addresses: Treat RFC 4193 addresses fc00::/7 as local 2013-07-28 12:52:41 +00:00
zzz
e3f02553fd javadoc 2013-07-28 12:52:10 +00:00
zzz
767ef8c489 add webm mime type 2013-07-28 12:52:00 +00:00
zzz
482787fbc3 * Transports:
- Really fix IPv6-only option
   - Treat RFC 4193 addresses fc00::/7 as local
   - Log tweaks, javadocs
2013-07-26 22:39:35 +00:00
kytv
b2d72f90ce merge of '5ad8235a14f2f52799755969e5c877f4f1c159cc'
and 'f5d75b2ebc648c43182d685f30e96242e43caa69'
2013-07-25 20:08:31 +00:00
zab2
dd181a90e1 Fix NPE when cancelling PacketLocal's 2013-07-25 20:07:12 +00:00
zzz
19faa352e3 * Transports:
- Prefer IPv6 by default
   - Fix IPv6-only option
   - Don't try NTCP IPv6 addresses unless we have one
   - Fix non-%16 SSU padding in data and session confirmed packets; enable by default
   - Log tweaks
2013-07-25 18:52:45 +00:00
zzz
ffda7f6326 * Tunnels:
- Make expl. default 3 hops  (ticket #966)
   - Allow expl. fallback up to -2 hops
2013-07-25 18:49:22 +00:00
zzz
8ebacf4c10 log tweak 2013-07-25 18:47:47 +00:00
zzz
a02cc25844 UPnP Fix for devices that return base URLs with trailing '/' (ticket #986) 2013-07-24 18:03:50 +00:00
zzz
8aeca5b433 catch NPE in main when no state table available 2013-07-24 14:24:29 +00:00
zzz
7b4855d7cf * UPnP: main() tweaks for debugging 2013-07-24 12:38:15 +00:00
zzz
803d7ff282 * GeoIP: Fix lookups, broken in IPv6 branch 2013-07-24 12:36:36 +00:00
zab2
a1c724f866 reduce initialRTO to 9000 2013-07-23 14:18:51 +00:00
zab2
96609e9173 change default loglevel for duplicate close()s to INFO 2013-07-23 14:17:26 +00:00
zzz
f5518739e2 javadoc fixes 2013-07-23 00:49:37 +00:00
zzz
e7c8d28b99 * HashComparator:
- Don't pollute Hash cache with hashes
   - cleanups, less object churn
2013-07-22 23:07:37 +00:00
zzz
dff357a658 unit test compile fix 2013-07-22 15:14:58 +00:00
zzz
cc271de7df * BuildReplyHandler:
- Make non-static
   - Don't pollute Hash cache with build response record hashes
   - Use SimpleByteCache
   - cleanups
2013-07-22 14:25:30 +00:00
zzz
a7485ab5a3 * I2CP:
- Oops, must enforce property length limits even when inside router JVM
     as the properties are serialized for signing.
2013-07-21 20:17:42 +00:00
zab2
7133736702 Fix more NPEs ticket #984 2013-07-21 19:41:48 +00:00
zab2
2313d82369 toclet #984 : fix deadlock introduced in -4 (ticket #972) 2013-07-21 14:54:36 +00:00
zzz
1b42d99e66 * Console: Fix /peers table summary alignment
* I2CP:
   - Don't NPE when loglevel=warn
   - Don't enforce property length limits when inside router JVM
 * I2PSnark: Log uncaught error in ThreadedStarter to router log
 * I2PThread: Log uncaught error to wrapper log
2013-07-21 14:04:27 +00:00
zab2
d709f46183 Update unit test 2013-07-20 18:45:19 +00:00
zab2
97c1676bcb Rework locking and state management of NTCP connections
trac ticket #972
	up version to -4
2013-07-20 17:37:46 +00:00
zzz
02b92ac3fe fix compile for test 2013-07-20 13:46:50 +00:00
zzz
29eb1d5dc5 fixup after prop; history for prop; -3 2013-07-20 13:41:31 +00:00
zzz
a87fc68cfd propagate from branch 'i2p.i2p.zzz.ipv6' (head 5c147c6e394fae03752dcf497923a90e3f2db529)
to branch 'i2p.i2p' (head 7af6987d5546664f76589afe0cbeeb780f4b5d58)
2013-07-20 12:59:03 +00:00
zzz
bc1cf64df4 remove extra 2013-07-20 12:35:38 +00:00
zzz
b607d7b223 generic 2013-07-20 12:34:24 +00:00
zzz
4e00eaf9a3 checkpo fix; history for prop; -2 2013-07-20 12:25:31 +00:00
zzz
90cc71d14d propagate from branch 'i2p.i2p.zzz.test2' (head d80f8632ef0a2aa350eee9a38ba6a4c56471f5bc)
to branch 'i2p.i2p' (head e8b712c826e44211217f06eb3a4da2703323a42f)
2013-07-20 11:53:41 +00:00
zzz
554a3a6b0e * PRNG:
- Don't delay the refiller if we need more (don't limit max output)
   - Add FortunaRandomSource.main() to output to stdout for testing e.g. with dieharder
2013-07-19 21:31:25 +00:00
zzz
8505e8a1ca fix streaming property 2013-07-19 21:28:14 +00:00
str4d
54ec878698 merge of '90720c051863f44c6386493f3d5df546d988a663'
and 'fa509893effa9445a0833115160aed8fe6fed268'
2013-07-19 00:18:08 +00:00
zab2
ea4606fe79 Prepare for merge 2013-07-18 22:45:11 +00:00
zab2
96de87fdde compute rttDev in updateRTT 2013-07-18 22:33:23 +00:00
zab2
55d571ffec Hardcode TCP constants
Various suggestions by zzz
2013-07-18 22:25:10 +00:00
zab2
ae347c4fa1 sync getters 2013-07-18 15:52:40 +00:00
str4d
e93beb7c63 Updated .mtn-ignore 2013-07-18 13:48:36 +00:00
zab2
018098b8ef better loading from cache 2013-07-18 01:52:46 +00:00
zab2
1e2fb4bea5 propagate from branch 'i2p.i2p' (head e301d0499f4c688ed3a5febe30bf8098c7f2cdf9)
to branch 'i2p.i2p.979' (head 2dfdeb022c9495461b2ec1d90f28ef9cd0bd9e22)
2013-07-17 23:04:04 +00:00
zab2
171f0d2671 Implement RTT update on first ack 2013-07-17 21:13:19 +00:00
kytv
175cb0817e fix bashim in i2prouter 2013-07-17 19:45:43 +00:00
zzz
3b46acc285 * I2CP client session - improvements after review:
- Move more cleanups to finally block
   - Bounded wait
   - Don't ignore InterruptedExceptions, wrap in I2PSessionException and throw
   - More finals
   - Synch tweaks
2013-07-17 18:56:26 +00:00
zzz
d31ce49e77 change resource name 2013-07-17 18:55:12 +00:00
zab2
8937c4bf2a Store stdev of rtt in the TCB cache as per RFC 2140 2013-07-17 18:13:42 +00:00
kytv
2902a708f9 debian updates
- check script validity in build target
- refresh patch
- changelog update
2013-07-16 22:17:50 +00:00
zzz
c1210b1c04 * Translations:
- Tag initialNews.xml for TranslateReader
   - Drop static translated initialNews pages
   - Add new routerconsole bundle for the news alone, shipped in the jar
   - Use TranslateReader in HTTP proxy for initial news
   - Initial translations created manually from translated xml filesx
   - Add translated proxy error pages and initial news to deletelist.txt
   TODO: ar translation fails checkpo.sh
2013-07-13 23:38:11 +00:00
zzz
71038c311f * Translations:
- New varargs method in Translate
   - New TranslateReader to translate static files on-the-fly using _("") tagging
   - Tag proxy error pages for TranslateReader
   - Drop static translated proxy error pages
   - Add new i2ptunnel bundle for the proxy alone, shipped in the jar
   - Use TranslateReader in HTTP proxy for error pages
   - Move HTTP proxy strings from the web *war) to proxy (jar) bundle so they will be loaded
   - Initial translations created by msgmerge from i2ptunnel and routerconsole po files, un-fuzzied
2013-07-13 19:58:11 +00:00
zzz
70a8ab1d1a * DHSessionKeyBuilder: Fix for session and mac keys if DH key is between 32 and 63 bytes.
Was: NPE. Now: mac key is hash of ssession key. Won't ever happen. (Ticket #963)
   javadocs
2013-07-10 18:59:46 +00:00
zzz
f3c4a26483 * I2CP/I2PTunnel locking fixes (partial fixes for tickets 650. 815, 946, 947, 953):
- I2PSocketManagerFactory: New createDisconnectedManager(), javadocs
   - I2PSessionImpl: Rewrite state management and locking, prevent multiple
     connect() calls, but allow disconnect() to interrupt connect()
   - I2PSimpleSession: Changes to match I2PSessionImpl
   - I2PTunnelServer: Don't connect in constructor, use createDisconnectedManager()
     for a final manager, finals and cleanups
   Lightly tested.
   Todo: I2PTunnelClientBase
2013-07-10 18:54:25 +00:00
zzz
9a1e1a92ca dont use == on doubles 2013-07-10 18:42:13 +00:00
zzz
732eddd1b9 toString() fix (NO_ACK) 2013-07-10 18:14:18 +00:00
zzz
2caa6ad975 * Router I2CP:
- Make classes extensible for router-side test stubs
   - Add router-side local-only test implementation, no full router required.
     Only tested with external clients, probably doesn't work in-JVM.
   - Don't start threads in ClientManager constructor
   - Remove unused Reader param in ClientMessageEventListener methods
   - Cleanups, volatiles, finals, javadocs
2013-07-10 18:12:47 +00:00
zzz
d3e0161a6b * Transports: Consolidate translation methods in super,
ngettext fix for "peers" string
2013-07-10 17:59:10 +00:00
zzz
aabbdc1c1b Hopefully fix SSU NPE (ticket #967) 2013-07-06 13:25:11 +00:00
zzz
3aafea0d98 add ipv6 to /confignet 2013-06-29 15:13:05 +00:00
zzz
79f8e88e5f propagate from branch 'i2p.i2p' (head 2a2c708bf9fee43e69469bdf896dfe489c32bdea)
to branch 'i2p.i2p.zzz.ipv6' (head c33552d7026b0a445d1dd7e138bf454144130eb2)
2013-06-28 16:10:49 +00:00
zzz
34b7081303 change congestion cost increment back to 1 for now 2013-06-14 16:13:20 +00:00
zzz
e0cd71069f propagate from branch 'i2p.i2p' (head 1acb4077a56ccb4079538caa28648e27f0bf5b8b)
to branch 'i2p.i2p.zzz.ipv6' (head f87d396c445dc58e677a56d8ed69544c7f5ecab1)
2013-06-14 14:46:08 +00:00
zzz
378c5a0d4e propagate from branch 'i2p.i2p' (head fd10b04ca3a6cf66e669bfad32d3011ed9f7e33c)
to branch 'i2p.i2p.zzz.ipv6' (head 6f6e16f14691f359322e665a7ad5ab65cbe1ca5e)
2013-05-29 00:22:15 +00:00
zzz
6c62c1f362 enable IPv6 geoip lookup 2013-05-24 14:11:35 +00:00
zzz
3daf287de8 GeoIPv6:
- Handle gzipped input data in merge tool
  - Add script to generate compressed data
  - Add local additions
  - Add compressed data file, generated from Maxmind data fetched 2013-05-24
  - Include data in installer and updater
  - Update Maxmind license info, now CC-SA 3.0
2013-05-24 13:46:17 +00:00
zzz
9a4cd11748 * SSU: "rectify" IPv4/v6 MTUs differently due to different header size (mod 16)
* Penalize addresses w/o IP in sort
2013-05-21 21:10:23 +00:00
zzz
c0350702fd * RouterAddress:
- Deprecate some setters
  - Add warning about setCost()
  - Change cost storage from int to short
  - Cost range checks
* NTCP:
  - Republish even if only changing cost
* Transports:
  - Sort multiple peer addresses by cost, with adjustment for local IPv6 preference
  - Add default IPv6Config for ease of changing later
2013-05-19 18:36:29 +00:00
zzz
55880844a5 * SSUDemo: Adapt for NTCP testing too
* RouterAddress and RouterInfo toString() cleanups; don't cache RI in _stringified
* NTCP: Fix publishing address when host specified but interface is not
* log tweaks
2013-05-19 15:18:45 +00:00
zzz
729282c0c4 * UDPAddress: Remove dependency in console; make package private 2013-05-18 20:10:10 +00:00
zzz
d603c3b5cd - UDPAddress reduce object churn, check intro key length,
don't look for ihost3, reject ports < 1024, cleanups
2013-05-18 19:58:10 +00:00
zzz
5cda1ec703 - Handle IPv6 in too-close checks 2013-05-18 19:24:16 +00:00
zzz
ec3756a69f * SSUDemo: Use IPv6; don't use System properties 2013-05-18 18:30:38 +00:00
zzz
0b49fa98f9 * SSU: Fixes for i2np.udp.allowLocal, log tweaks, sender/receiver thread name tweaks
* Limit tunnel GW pumper threads when testing
2013-05-18 18:00:17 +00:00
zzz
226c7eb8e3 * SSUDemo: configuration fixes, delete RI on exit, log tweaks 2013-05-18 14:27:11 +00:00
zzz
be262c6a70 * NetDb:
- Add floodfillEnabled() to NetworkDatabaseFacade so callers don't
    have to cast to FNDF, and Dummy NDF will work
  - Remove static FNDF.floodfillEnabled()
* SSUDemo: cleanups
2013-05-17 15:11:23 +00:00
zzz
a374f00613 * Fix UDPEndpointTestStandalone:
- init context
  - Add unit test buildPacket() method to PacketBuilder
  - Fix NPE in MessageHistory
* Minor PacketPusher optimization
2013-05-16 23:08:06 +00:00
zzz
fcdf837f33 * New buildTest and prepTest targets
* Fix UDPEndpoint usage in unit tests:
  - Restore receive()
  - Handle null UDPTransport
* Fix UDPEndpointTestStandalone compilation
2013-05-16 17:57:33 +00:00
zzz
febc0a5237 RouterContext: Fix disabling client manager with i2p.dummyClientFacade=true 2013-05-16 15:35:23 +00:00
zzz
a19140e186 GeoIPv6 2013-05-13 20:43:30 +00:00
zzz
e0b25cdcf9 remove unused method 2013-05-13 20:39:32 +00:00
zzz
e332c8bc27 FloodfillPeerSelector, ProfileOrganizer: Use 8 bytes for IPv6 check
Transports:
- Add IPv6 column on /peers
- Other minor /peers cleanup
2013-05-13 13:57:15 +00:00
zzz
7318632db9 strip scope from returned address strings 2013-05-12 15:23:02 +00:00
zzz
1b38a6478b UPnP:
- Pass device IP back in forward port callback
 - Only declare success if forwarded IP is public

NTCP: Bad bind config not fatal

GeoIP:
 - Use cached IP in RouterAddresses
 - Use both NTCP and SSU addresses
 - Skip IPv6 for now

Blocklist:
 - Add IPv6 in-memory single list
 - Limit in-memory single list size
 - Fix dup check in getAddresses()
2013-05-12 14:44:42 +00:00
zzz
6ceea60c92 addresses:
- blocklist 192.88.88.0/24 6to4 anycast
- invalidate 2002::/16
2013-05-12 00:24:01 +00:00
zzz
fcaebb4416 * Fix UPnP address received before startListening(),
broken by isAlive() check
* log tweakws
2013-05-11 22:11:02 +00:00
zzz
0be3beb30e * SSU fixes for per-address and IPv6 MTU
* MTU.main() print all interfaces
2013-05-11 21:39:25 +00:00
zzz
5e51c6abef * CSFI compile fix
* Start transports in a standard order to make testing easier
* When transports learn of interface addresses before being started, save them
  and use them at startup
* Pick SSU random port before startListening() and have the TransportManager
  pass it to NTCP before starting
* Only restart NTCP after changing addresses when necessary;
  prevent thrashing at startup (ticket #459)
* Only call rebuildRouterInfo() once at startup
* More checking of min/max SSU port config
* Invalid SSU bind config no longer fatal
* Allow "true" for ipv6 config
* log tweaks
* javadocs
2013-05-11 19:22:20 +00:00
zzz
5e953b0857 * Fixes for IPv4 and other breakage after basic testing
* Catch exception from UPnP callback
* Log tweaks
2013-05-10 18:34:02 +00:00
zzz
c76c80043f * NTCP:
- Drop NTCPAddress, just use RouterAddress
  - Drop _myAddress field, use super's currentAddress
2013-05-09 17:32:29 +00:00
zzz
3a49d6d28f * NTCP:
Move SSU address notification handling from CSFI to NTCPTransport
2013-05-09 16:18:58 +00:00
zzz
94e34ff366 RouterAddress:
- Add new constructor
 - Add add getHost() and deepEquals()
 - Compare host string, not IP, in equals()

SSU:
 - Remove all _external* fields; use _currentAddresses in super
 - Big rework of externalAddressReceived(), rebuildExternalAddress(),
   needsRebuild(), and replaceAddress() for multiple addresses and IPv6
 - Add caching in UDPAddress
 - More IPv6 flavors of utility methods
 - Remove two-art replaceAddress()
2013-05-08 16:48:39 +00:00
zzz
af27c76b2c * Only treat IPv6 addresses as valid if we have a public IPv6 address
* SSU Introduction:
 - Document that Alice-Bob RelayRequest/RelayResponse may be IPv4 or IPv6,
   but don't implement IPv6 yet.
   Changes required in IntroductionManager and PacketBuilder to send Alice's
   IPv4 address in the RelayRequest packet over IPv6, and to publish
   IPv6 introducer IPs.
 - Bob-Charlie RelayIntro must be IPv4
 - Only offer/accept relay tags as Bob or Charlie if the Bob-Charlie session is IPv4
 - Alice-Charlie communication must be IPv4
 - javadocs
2013-05-07 22:46:55 +00:00
zzz
60336c9555 - Shuffle SSU addresses before picking one
- Change address sources to enum
2013-05-07 19:49:13 +00:00
zzz
a85b7aa9f8 - Hash IPv6 addresses in IPThrottler
- CSFI: Pass TransportManager instead of CSFI to GetBidsJob;
        remove unused methods
- Add i2np.disable property for testing
2013-05-07 18:22:20 +00:00
zzz
228e6d7d03 fixup after prop 2013-05-06 13:30:11 +00:00
zzz
31531ee882 propagate from branch 'i2p.i2p' (head 17371fd6f9ef94bbb60a66c6bacb6828d6a4cde5)
to branch 'i2p.i2p.zzz.ipv6' (head 065a076899a2581b4196e626f2b0654c3d39518a)
2013-05-06 11:27:10 +00:00
zzz
368c2073b2 - Fix multiple-detection code in externalAddressReceived()
- Synchronize tracking of last IP/port
- Don't accept IPv6 address changes from peers
- Remove unused getLocalAddress()
- Pkg private getLocalPort()

Peer tests:
 - Use only IPv4 peer for Alice and Bob in peer tests; Charlie may be an IPv6 peer.
 - Enforce IPv4 (Alice's) address inside PeerTest packet
2013-05-05 12:08:28 +00:00
zzz
757df8c726 prep for multiple address discovery 2013-05-03 16:34:02 +00:00
zzz
c6121cb31e Prep for multiple SSU sockets:
- Change from single UDPEndpoint to a List of UDPEndpoints
 - Move (single) receive queue from UDPReceiver to PacketHandler
 - Multiple transmit queues (one for each UDPEndpoint/UDPSender),
   select queue in PacketPusher
 - Throw exception on UDPEndpoint.startup() failure
2013-05-03 15:03:55 +00:00
zzz
eecab472eb IPv6 SSU MTU adjustments 2013-05-03 11:27:21 +00:00
zzz
b71631d2ec Fixes to isPubliclyRoutable() based on IPv6 config 2013-05-02 14:12:53 +00:00
zzz
3ec78e27b4 Start new IPv6 branch
- Add new TransportUtil for getting/setting IPv6 config
- Prep for supporting multiple RouterAddresses per-transport
- RouterAddress hashCode/equals tweaks
2013-05-02 12:55:35 +00:00
1103 changed files with 149184 additions and 97996 deletions

View File

@@ -1,5 +1,7 @@
# Just to try and prevent some noob disasters.
# Use mtn add --no-respect-ignore foo.jar to ignore this ignore list
# Temporary/build files
_jsp\.java$
\.bz2$
\.tar$
@@ -19,13 +21,27 @@ _jsp\.java$
.\deb$
\.zip$
^\.
^build
^pkg-temp/
~$
web-fragment.xml
web-out.xml
# Temporary/build dirs
^build
^pkg-temp
/build
/classes/
/classes
/dist
/mo
/tmp
^apps/jetty/jettylib
# Debian-related
^debian/copyright
^debian/changelog
# Build property overrides
override.properties
# Reporting
sloccount.sc
^reports/

View File

@@ -9,16 +9,40 @@ trans.es = apps/i2ptunnel/locale/messages_es.po
trans.fr = apps/i2ptunnel/locale/messages_fr.po
trans.hu = apps/i2ptunnel/locale/messages_hu.po
trans.it = apps/i2ptunnel/locale/messages_it.po
trans.ja = apps/i2ptunnel/locale/messages_ja.po
trans.nb = apps/i2ptunnel/locale/messages_nb.po
trans.nl = apps/i2ptunnel/locale/messages_nl.po
trans.pl = apps/i2ptunnel/locale/messages_pl.po
trans.pt = apps/i2ptunnel/locale/messages_pt.po
trans.pt_BR = apps/i2ptunnel/locale/messages_pt_BR.po
trans.ru_RU = apps/i2ptunnel/locale/messages_ru.po
trans.sv_SE = apps/i2ptunnel/locale/messages_sv.po
trans.uk_UA = apps/i2ptunnel/locale/messages_uk.po
trans.vi = apps/i2ptunnel/locale/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale/messages_zh.po
[I2P.proxy]
source_file = apps/i2ptunnel/locale-proxy/messages_en.po
source_lang = en
trans.ar = apps/i2ptunnel/locale-proxy/messages_ar.po
trans.cs = apps/i2ptunnel/locale-proxy/messages_cs.po
trans.de = apps/i2ptunnel/locale-proxy/messages_de.po
trans.es = apps/i2ptunnel/locale-proxy/messages_es.po
trans.fr = apps/i2ptunnel/locale-proxy/messages_fr.po
trans.hu = apps/i2ptunnel/locale-proxy/messages_hu.po
trans.it = apps/i2ptunnel/locale-proxy/messages_it.po
trans.nb = apps/i2ptunnel/locale-proxy/messages_nb.po
trans.nl = apps/i2ptunnel/locale-proxy/messages_nl.po
trans.pl = apps/i2ptunnel/locale-proxy/messages_pl.po
trans.pt = apps/i2ptunnel/locale-proxy/messages_pt.po
trans.pt_BR = apps/i2ptunnel/locale-proxy/messages_pt_BR.po
trans.ro = apps/i2ptunnel/locale-proxy/messages_ro.po
trans.ru_RU = apps/i2ptunnel/locale-proxy/messages_ru.po
trans.sv_SE = apps/i2ptunnel/locale-proxy/messages_sv.po
trans.uk_UA = apps/i2ptunnel/locale-proxy/messages_uk.po
trans.vi = apps/i2ptunnel/locale-proxy/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale-proxy/messages_zh.po
[I2P.routerconsole]
source_file = apps/routerconsole/locale/messages_en.po
source_lang = en
@@ -33,10 +57,13 @@ trans.fi = apps/routerconsole/locale/messages_fi.po
trans.fr = apps/routerconsole/locale/messages_fr.po
trans.hu = apps/routerconsole/locale/messages_hu.po
trans.it = apps/routerconsole/locale/messages_it.po
trans.ja = apps/routerconsole/locale/messages_ja.po
trans.nb = apps/routerconsole/locale/messages_nb.po
trans.nl = apps/routerconsole/locale/messages_nl.po
trans.pl = apps/routerconsole/locale/messages_pl.po
trans.pt = apps/routerconsole/locale/messages_pt.po
trans.pt_BR = apps/routerconsole/locale/messages_pt_BR.po
trans.ro = apps/routerconsole/locale/messages_ro.po
trans.ru_RU = apps/routerconsole/locale/messages_ru.po
trans.sv_SE = apps/routerconsole/locale/messages_sv.po
trans.tr_TR = apps/routerconsole/locale/messages_tr.po
@@ -44,6 +71,51 @@ trans.uk_UA = apps/routerconsole/locale/messages_uk.po
trans.vi = apps/routerconsole/locale/messages_vi.po
trans.zh_CN = apps/routerconsole/locale/messages_zh.po
[I2P.welcome]
source_file = apps/routerconsole/locale-news/messages_en.po
source_lang = en
trans.ar = apps/routerconsole/locale-news/messages_ar.po
trans.de = apps/routerconsole/locale-news/messages_de.po
trans.es = apps/routerconsole/locale-news/messages_es.po
trans.fr = apps/routerconsole/locale-news/messages_fr.po
trans.ja = apps/routerconsole/locale-news/messages_ja.po
trans.it = apps/routerconsole/locale-news/messages_it.po
trans.nl = apps/routerconsole/locale-news/messages_nl.po
trans.pl = apps/routerconsole/locale-news/messages_pl.po
trans.pt = apps/routerconsole/locale-news/messages_pt.po
trans.pt_BR = apps/routerconsole/locale-news/messages_pt_BR.po
trans.ro = apps/routerconsole/locale-news/messages_ro.po
trans.ru_RU = apps/routerconsole/locale-news/messages_ru.po
trans.sv_SE = apps/routerconsole/locale-news/messages_sv.po
trans.tr_TR = apps/routerconsole/locale-news/messages_tr.po
trans.zh_CN = apps/routerconsole/locale-news/messages_zh.po
[I2P.countries]
type = PO
source_file = apps/routerconsole/locale-countries/messages_en.po
source_lang = en
trans.da = apps/routerconsole/locale-countries/messages_da.po
trans.de = apps/routerconsole/locale-countries/messages_de.po
trans.el = apps/routerconsole/locale-countries/messages_el.po
trans.es = apps/routerconsole/locale-countries/messages_es.po
trans.et_EE = apps/routerconsole/locale-countries/messages_et.po
trans.fi = apps/routerconsole/locale-countries/messages_fi.po
trans.fr = apps/routerconsole/locale-countries/messages_fr.po
trans.hu = apps/routerconsole/locale-countries/messages_hu.po
trans.it = apps/routerconsole/locale-countries/messages_it.po
trans.ja = apps/routerconsole/locale-countries/messages_ja.po
trans.nb = apps/routerconsole/locale-countries/messages_nb.po
trans.nl = apps/routerconsole/locale-countries/messages_nl.po
trans.pl = apps/routerconsole/locale-countries/messages_pl.po
trans.pt = apps/routerconsole/locale-countries/messages_pt.po
trans.pt_BR = apps/routerconsole/locale-countries/messages_pt_BR.po
trans.ro = apps/routerconsole/locale-countries/messages_ro.po
trans.ru_RU = apps/routerconsole/locale-countries/messages_ru.po
trans.sv_SE = apps/routerconsole/locale-countries/messages_sv.po
trans.tr_TR = apps/routerconsole/locale-countries/messages_tr.po
trans.vi = apps/routerconsole/locale-countries/messages_vi.po
trans.zh_CN = apps/routerconsole/locale-countries/messages_zh.po
[I2P.i2psnark]
source_file = apps/i2psnark/locale/messages_en.po
source_lang = en
@@ -58,6 +130,7 @@ trans.nb = apps/i2psnark/locale/messages_nb.po
trans.nl = apps/i2psnark/locale/messages_nl.po
trans.pl = apps/i2psnark/locale/messages_pl.po
trans.pt = apps/i2psnark/locale/messages_pt.po
trans.ro = apps/i2psnark/locale/messages_ro.po
trans.ru_RU = apps/i2psnark/locale/messages_ru.po
trans.sv_SE = apps/i2psnark/locale/messages_sv.po
trans.vi = apps/i2psnark/locale/messages_vi.po
@@ -75,9 +148,12 @@ trans.es = apps/susidns/locale/messages_es.po
trans.fr = apps/susidns/locale/messages_fr.po
trans.hu = apps/susidns/locale/messages_hu.po
trans.it = apps/susidns/locale/messages_it.po
trans.ja = apps/susidns/locale/messages_ja.po
trans.nl = apps/susidns/locale/messages_nl.po
trans.pl = apps/susidns/locale/messages_pl.po
trans.pt = apps/susidns/locale/messages_pt.po
trans.pt_BR = apps/susidns/locale/messages_pt_BR.po
trans.ro = apps/susidns/locale/messages_ro.po
trans.ru_RU = apps/susidns/locale/messages_ru.po
trans.sv_SE = apps/susidns/locale/messages_sv.po
trans.uk_UA = apps/susidns/locale/messages_uk.po
@@ -96,8 +172,11 @@ trans.es = apps/desktopgui/locale/messages_es.po
trans.fr = apps/desktopgui/locale/messages_fr.po
trans.hu = apps/desktopgui/locale/messages_hu.po
trans.it = apps/desktopgui/locale/messages_it.po
trans.ja = apps/desktopgui/locale/messages_ja.po
trans.nl = apps/desktopgui/locale/messages_nl.po
trans.pl = apps/desktopgui/locale/messages_pl.po
trans.pt_BR = apps/desktopgui/locale/messages_pt_BR.po
trans.ro = apps/desktopgui/locale/messages_ro.po
trans.ru_RU = apps/desktopgui/locale/messages_ru.po
trans.sv_SE = apps/desktopgui/locale/messages_sv.po
trans.uk_UA = apps/desktopgui/locale/messages_uk.po
@@ -119,6 +198,8 @@ trans.ru_RU = apps/susimail/locale/messages_ru.po
trans.sv_SE = apps/susimail/locale/messages_sv.po
trans.pl = apps/susimail/locale/messages_pl.po
trans.pt = apps/susimail/locale/messages_pt.po
trans.pt_BR = apps/susimail/locale/messages_pt_BR.po
trans.ro = apps/susimail/locale/messages_ro.po
trans.uk_UA = apps/susimail/locale/messages_uk.po
trans.vi = apps/susimail/locale/messages_vi.po
trans.zh_CN = apps/susimail/locale/messages_zh.po
@@ -135,6 +216,7 @@ trans.it = debian/po/it.po
trans.hu = debian/po/hu.po
trans.pl = debian/po/pl.po
trans.pt = debian/po/pt.po
trans.ro = debian/po/ro.po
trans.ru_RU = debian/po/ru.po
trans.sv_SE = debian/po/sv.po
trans.uk_UA = debian/po/uk.po
@@ -145,13 +227,17 @@ trans.zh_CN = debian/po/zh.po
source_file = installer/resources/locale/po/messages_en.po
source_lang = en
trans.de = installer/resources/locale/po/messages_de.po
trans.es = installer/resources/locale/po/messages_es.po
trans.fr = installer/resources/locale/po/messages_fr.po
trans.it = installer/resources/locale/po/messages_it.po
trans.pt = installer/resources/locale/po/messages_pt.po
trans.pt_BR = installer/resources/locale/po/messages_pt_BR.po
trans.ro = installer/resources/locale/po/messages_ro.po
trans.sv_SE = installer/resources/locale/po/messages_sv.po
trans.ru_RU = installer/resources/locale/po/messages_ru.po
trans.tr_TR = installer/resources/locale/po/messages_tr.po
trans.zh_CN = installer/resources/locale/po/messages_zh.po
[main]
host = http://www.transifex.net
host = https://www.transifex.com

View File

@@ -42,4 +42,4 @@ Supported JVMs:
Windows: Latest available from http://java.com/download (1.5+ supported)
Linux: Latest available from http://java.com/download (1.5+ supported)
FreeBSD: 1.5-compatible (NIO required)
Other operating systems and JVMs: See http://trac.i2p2.de/wiki/java
Other operating systems and JVMs: See https://trac.i2p2.de/wiki/java

View File

@@ -2,7 +2,7 @@ I2P source installation instructions
Prerequisites to build from source:
Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher
Non-linux operating systems and JVMs: See http://trac.i2p2.de/wiki/java
Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java
Apache Ant 1.7.0 or higher
The xgettext, msgfmt, and msgmerge tools installed
from the GNU gettext package http://www.gnu.org/software/gettext/

View File

@@ -177,7 +177,7 @@ Applications:
By welterde.
See licenses/LICENSE-GPLv2.txt
Jetty 7.6.11.v20130520:
Jetty 7.6.14.v20131031:
See licenses/ABOUT-Jetty.html
See licenses/NOTICE-Jetty.html
See licenses/LICENSE-Apache2.0.txt
@@ -207,7 +207,7 @@ Applications:
FatCow icons: See licenses/LICENSE-FatCowIcons.txt
GeoIP Data:
Copyright (c) 2008 MaxMind, Inc. All Rights Reserved.
This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/
See licenses/LICENSE-GeoIP.txt
Router Console and I2PSnark themes:

View File

@@ -1,6 +1,6 @@
Prerequisites to build from source:
Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher
Non-linux operating systems and JVMs: See http://trac.i2p2.de/wiki/java
Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java
Apache Ant 1.7.0 or higher
The xgettext, msgfmt, and msgmerge tools installed
from the GNU gettext package http://www.gnu.org/software/gettext/
@@ -22,13 +22,13 @@ Documentation:
API: run 'ant javadoc' then start at build/javadoc/index.html
Latest release:
http://www.i2p2.de/download.html
http://www.i2p2.de/download
To get development branch from source control:
http://www.i2p2.de/newdevelopers.html
http://www.i2p2.de/newdevelopers
FAQ:
http://www.i2p2.de/faq.html
http://www.i2p2.de/faq
Need help?
IRC irc.freenode.net #i2p

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
INST_DIR=directory

8
apps/BOB/.classpath Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2p_sdk"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/ministreaming"/>
<classpathentry kind="output" path="build"/>
</classpath>

17
apps/BOB/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>BOB</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -15,6 +15,8 @@
*/
package net.i2p.BOB;
import static net.i2p.app.ClientAppState.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -25,12 +27,17 @@ import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Arrays;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import net.i2p.I2PAppContext;
import net.i2p.app.*;
import net.i2p.client.I2PClient;
import net.i2p.util.Log;
import net.i2p.util.I2PAppThread;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer2;
@@ -105,57 +112,76 @@ import net.i2p.util.SimpleTimer2;
*
* @author sponge
*/
public class BOB {
public class BOB implements Runnable, ClientApp {
public final static String PROP_CONFIG_LOCATION = "BOB.config";
public final static String PROP_BOB_PORT = "BOB.port";
public final static String PROP_BOB_HOST = "BOB.host";
public final static String PROP_CFG_VER = "BOB.CFG.VER";
private static NamedDB database;
private static Properties props = new Properties();
private static AtomicBoolean spin = new AtomicBoolean(true);
private static BOB _bob;
private NamedDB database;
private Properties props = new Properties();
private AtomicBoolean spin = new AtomicBoolean(true);
private static final String P_RUNNING = "RUNNING";
private static final String P_STARTING = "STARTING";
private static final String P_STOPPING = "STOPPING";
private static AtomicBoolean lock = new AtomicBoolean(false);
private AtomicBoolean lock = new AtomicBoolean(false);
// no longer used.
// private static int maxConnections = 0;
/**
* Log a warning
*
* @param arg
*/
public static void info(String arg) {
System.out.println("INFO:" + arg);
(new Log(BOB.class)).info(arg);
}
private final Logger _log;
private final ClientAppManager _mgr;
private final String[] _args;
private volatile ClientAppState _state = UNINITIALIZED;
/**
* Log a warning
*
* @param arg
*/
public static void warn(String arg) {
System.out.println("WARNING:" + arg);
(new Log(BOB.class)).warn(arg);
}
/**
* Log an error
*
* @param arg
*/
public static void error(String arg) {
System.out.println("ERROR: " + arg);
(new Log(BOB.class)).error(arg);
}
private volatile ServerSocket listener;
private volatile Thread _runner;
/**
* Stop BOB gracefully
* @deprecated unused
*/
public static void stop() {
spin.set(false);
_bob.shutdown(null);
}
/**
* For ClientApp interface.
* Does NOT open the listener socket or start threads; caller must call startup()
*
* @param mgr may be null
* @param args non-null
* @throws Exception on bad args
* @since 0.9.10
*/
public BOB(I2PAppContext context, ClientAppManager mgr, String[] args) {
// If we were run from command line, log to stdout
boolean logToStdout = false;
URL classResource = BOB.class.getResource("BOB.class");
if (classResource != null) {
String classPath = classResource.toString();
if (classPath.startsWith("jar")) {
String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) +
"/META-INF/MANIFEST.MF";
try {
Manifest manifest = new Manifest(new URL(manifestPath).openStream());
Attributes attrs = manifest.getMainAttributes();
String mainClass = attrs.getValue("Main-Class");
if ("net.i2p.BOB.Main".equals(mainClass))
logToStdout = true;
} catch (IOException ioe) {}
}
}
_log = new Logger(context.logManager().getLog(BOB.class), logToStdout);
_mgr = mgr;
_args = args;
_state = INITIALIZED;
database = new NamedDB();
loadConfig();
}
/**
@@ -164,8 +190,22 @@ public class BOB {
* @param args
*/
public static void main(String[] args) {
database = new NamedDB();
ServerSocket listener = null;
try {
_bob = new BOB(I2PAppContext.getGlobalContext(), null, args);
_bob.startup();
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @since 0.9.10
*/
private void loadConfig() {
int i = 0;
boolean save = false;
// Set up all defaults to be passed forward to other threads.
@@ -176,116 +216,140 @@ public class BOB {
SimpleTimer2 Y2 = SimpleTimer2.getInstance();
i = Y1.hashCode();
i = Y2.hashCode();
Log _log = new Log(BOB.class);
try {
{
File cfg = new File(configLocation);
if (!cfg.isAbsolute()) {
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
}
try {
FileInputStream fi = new FileInputStream(cfg);
props.load(fi);
fi.close();
} catch (FileNotFoundException fnfe) {
warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.");
warn(fnfe.toString());
save = true;
} catch (IOException ioe) {
warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.");
warn(ioe.toString());
}
{
File cfg = new File(configLocation);
if (!cfg.isAbsolute()) {
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
}
// Global router and client API configurations that are missing are set to defaults here.
if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
save = true;
}
if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
save = true;
}
if (!props.containsKey(PROP_BOB_PORT)) {
props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
save = true;
}
if (!props.containsKey("inbound.length")) {
props.setProperty("inbound.length", "1");
save = true;
}
if (!props.containsKey("outbound.length")) {
props.setProperty("outbound.length", "1");
save = true;
}
if (!props.containsKey("inbound.lengthVariance")) {
props.setProperty("inbound.lengthVariance", "0");
save = true;
}
if (!props.containsKey("outbound.lengthVariance")) {
props.setProperty("outbound.lengthVariance", "0");
save = true;
}
if (!props.containsKey(PROP_BOB_HOST)) {
props.setProperty(PROP_BOB_HOST, "localhost");
save = true;
}
// PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
if (!props.containsKey(PROP_CFG_VER)) {
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
props.setProperty(PROP_CFG_VER,"1");
save = true;
}
if (save) {
File cfg = new File(configLocation);
if (!cfg.isAbsolute()) {
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
}
try {
warn("Writing new defaults file " + cfg.getAbsolutePath());
FileOutputStream fo = new FileOutputStream(cfg);
props.store(fo, cfg.getAbsolutePath());
fo.close();
} catch (IOException ioe) {
error("IOException on BOB config file " + cfg.getAbsolutePath() + ", " + ioe);
}
}
i = 0;
boolean g = false;
spin.set(true);
try {
info("BOB is now running.");
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;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
Thread t = new Thread(conn_c);
t.setName("BOB.DoCMDS " + i);
t.start();
i++;
}
}
FileInputStream fi = new FileInputStream(cfg);
props.load(fi);
fi.close();
} catch (FileNotFoundException fnfe) {
_log.warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.", fnfe);
save = true;
} catch (IOException ioe) {
error("IOException on socket listen: " + ioe);
ioe.printStackTrace();
_log.warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.", ioe);
}
}
// Global router and client API configurations that are missing are set to defaults here.
if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
save = true;
}
if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
save = true;
}
if (!props.containsKey(PROP_BOB_PORT)) {
props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
save = true;
}
if (!props.containsKey("inbound.length")) {
props.setProperty("inbound.length", "1");
save = true;
}
if (!props.containsKey("outbound.length")) {
props.setProperty("outbound.length", "1");
save = true;
}
if (!props.containsKey("inbound.lengthVariance")) {
props.setProperty("inbound.lengthVariance", "0");
save = true;
}
if (!props.containsKey("outbound.lengthVariance")) {
props.setProperty("outbound.lengthVariance", "0");
save = true;
}
if (!props.containsKey(PROP_BOB_HOST)) {
props.setProperty(PROP_BOB_HOST, "localhost");
save = true;
}
// PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
if (!props.containsKey(PROP_CFG_VER)) {
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
props.setProperty(PROP_CFG_VER,"1");
save = true;
}
if (save) {
File cfg = new File(configLocation);
if (!cfg.isAbsolute()) {
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
}
try {
_log.warn("Writing new defaults file " + cfg.getAbsolutePath());
FileOutputStream fo = new FileOutputStream(cfg);
props.store(fo, cfg.getAbsolutePath());
fo.close();
} catch (IOException ioe) {
_log.error("IOException on BOB config file " + cfg.getAbsolutePath(), ioe);
}
}
}
/**
* @since 0.9.10
*/
private void startListener() throws IOException {
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
listener.setSoTimeout(500); // .5 sec
}
/**
* @since 0.9.10
*/
private void startThread() {
I2PAppThread t = new I2PAppThread(this, "BOBListener");
t.start();
_runner = t;
}
/**
* @since 0.9.10
*/
public void run() {
if (listener == null) return;
changeState(RUNNING);
_log.info("BOB is now running.");
if (_mgr != null)
_mgr.register(this);
int i = 0;
boolean g = false;
spin.set(true);
try {
Socket server = null;
while (spin.get()) {
//DoCMDS connection;
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (ConnectException ce) {
g = false;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
Thread t = new Thread(conn_c);
t.setName("BOB.DoCMDS " + i);
t.start();
i++;
}
}
changeState(STOPPING);
} catch (Exception e) {
if (spin.get())
_log.error("Unexpected error while listening for connections", e);
else
e = null;
changeState(STOPPING, e);
} finally {
info("BOB is now shutting down...");
_log.info("BOB is now shutting down...");
// Clean up everything.
try {
listener.close();
@@ -308,7 +372,7 @@ public class BOB {
database.releaseReadLock();
database.getWriteLock();
nickinfo.getWriteLock();
nickinfo.add(P_STOPPING, new Boolean(true));
nickinfo.add(P_STOPPING, Boolean.valueOf(true));
nickinfo.releaseWriteLock();
database.releaseWriteLock();
} else {
@@ -316,8 +380,8 @@ public class BOB {
database.releaseReadLock();
}
}
info("BOB is now stopped.");
changeState(STOPPED);
_log.info("BOB is now stopped.");
}
}
@@ -369,4 +433,86 @@ public class BOB {
waitjoin(groups[i], level + 1, groups[i].getName());
}
}
////// begin ClientApp interface
/**
* @since 0.9.10
*/
@Override
public void startup() throws IOException {
if (_state != INITIALIZED)
return;
changeState(STARTING);
try {
startListener();
} catch (IOException e) {
_log.error("Error starting BOB on"
+ props.getProperty(PROP_BOB_HOST)
+ ":" + props.getProperty(PROP_BOB_PORT), e);
changeState(START_FAILED, e);
throw e;
}
startThread();
}
/**
* @since 0.9.10
*/
@Override
public void shutdown(String[] args) {
if (_state != RUNNING)
return;
changeState(STOPPING);
spin.set(false);
if (_runner != null)
_runner.interrupt();
else
changeState(STOPPED);
}
/**
* @since 0.9.10
*/
@Override
public ClientAppState getState() {
return _state;
}
/**
* @since 0.9.10
*/
@Override
public String getName() {
return "BOB";
}
/**
* @since 0.9.10
*/
@Override
public String getDisplayName() {
return "BOB " + Arrays.toString(_args);
}
////// end ClientApp interface
////// begin ClientApp helpers
/**
* @since 0.9.10
*/
private void changeState(ClientAppState state) {
changeState(state, null);
}
/**
* @since 0.9.10
*/
private synchronized void changeState(ClientAppState state, Exception e) {
_state = state;
if (_mgr != null)
_mgr.notify(this, state, null, e);
}
////// end ClientApp helpers
}

View File

@@ -31,7 +31,6 @@ import net.i2p.client.I2PClientFactory;
//import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
//import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.util.Log;
// needed only for debugging.
// import java.util.logging.Level;
// import java.util.logging.Logger;
@@ -56,7 +55,7 @@ public class DoCMDS implements Runnable {
private ByteArrayOutputStream prikey;
private boolean dk, ns, ip, op;
private NamedDB nickinfo;
private Log _log;
private Logger _log;
private AtomicBoolean LIVE;
private AtomicBoolean lock;
/* database strings */
@@ -164,7 +163,7 @@ public class DoCMDS implements Runnable {
* @param database
* @param _log
*/
DoCMDS(AtomicBoolean LIVE, AtomicBoolean lock, Socket server, Properties props, NamedDB database, Log _log) {
DoCMDS(AtomicBoolean LIVE, AtomicBoolean lock, Socket server, Properties props, NamedDB database, Logger _log) {
this.lock = lock;
this.LIVE = LIVE;
this.server = server;
@@ -606,7 +605,7 @@ public class DoCMDS implements Runnable {
break die;
}
} catch (I2PException ipe) {
BOB.error("Error generating keys" + ipe);
_log.error("Error generating keys", ipe);
out.println("ERROR generating keys");
}
@@ -665,7 +664,7 @@ public class DoCMDS implements Runnable {
break die;
}
try {
nickinfo.add(P_QUIET, new Boolean(Boolean.parseBoolean(Arg) == true));
nickinfo.add(P_QUIET, Boolean.valueOf(Arg));
} catch (Exception ex) {
try {
wunlock();
@@ -817,10 +816,10 @@ public class DoCMDS implements Runnable {
try {
database.add(Arg, nickinfo);
nickinfo.add(P_NICKNAME, Arg);
nickinfo.add(P_STARTING, new Boolean(false));
nickinfo.add(P_RUNNING, new Boolean(false));
nickinfo.add(P_STOPPING, new Boolean(false));
nickinfo.add(P_QUIET, new Boolean(false));
nickinfo.add(P_STARTING, Boolean.valueOf(false));
nickinfo.add(P_RUNNING, Boolean.valueOf(false));
nickinfo.add(P_STOPPING, Boolean.valueOf(false));
nickinfo.add(P_QUIET, Boolean.valueOf(false));
nickinfo.add(P_INHOST, "localhost");
nickinfo.add(P_OUTHOST, "localhost");
Properties Q = new Properties();
@@ -989,7 +988,7 @@ public class DoCMDS implements Runnable {
prt = Integer.parseInt(Arg);
if (prt > 1 && prt < 65536) {
try {
nickinfo.add(P_INPORT, new Integer(prt));
nickinfo.add(P_INPORT, Integer.valueOf(prt));
} catch (Exception ex) {
try {
wunlock();
@@ -1076,7 +1075,7 @@ public class DoCMDS implements Runnable {
prt = Integer.parseInt(Arg);
if (prt > 1 && prt < 65536) {
try {
nickinfo.add(P_OUTPORT, new Integer(prt));
nickinfo.add(P_OUTPORT, Integer.valueOf(prt));
} catch (Exception ex) {
try {
wunlock();
@@ -1355,7 +1354,7 @@ public class DoCMDS implements Runnable {
break die;
}
nickinfo.add(P_STOPPING, new Boolean(true));
nickinfo.add(P_STOPPING, Boolean.valueOf(true));
try {
wunlock();

View File

@@ -22,7 +22,6 @@ import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log;
/**
* Listen on I2P and connect to TCP
@@ -32,7 +31,7 @@ import net.i2p.util.Log;
public class I2Plistener implements Runnable {
private NamedDB info, database;
private Log _log;
private Logger _log;
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
private AtomicBoolean lives;
@@ -45,7 +44,7 @@ public class I2Plistener implements Runnable {
* @param database
* @param _log
*/
I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Log _log, AtomicBoolean lives) {
I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
this.database = database;
this.info = info;
this._log = _log;

View File

@@ -15,7 +15,7 @@
*/
package net.i2p.BOB;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
/**
@@ -39,10 +39,8 @@ public class Lifted {
*
**/
public static void copyProperties(Properties src_prop, Properties dest_prop) {
for (Enumeration propertyNames = src_prop.propertyNames();
propertyNames.hasMoreElements();) {
Object key = propertyNames.nextElement();
dest_prop.put(key, src_prop.get(key));
for (Map.Entry<Object, Object> e : src_prop.entrySet()) {
dest_prop.put((String)e.getKey(), (String)e.getValue());
}
}
}

View File

@@ -0,0 +1,44 @@
package net.i2p.BOB;
import net.i2p.util.Log;
public class Logger {
public Log log;
private boolean logToStdout;
public Logger(Log log, boolean logToStdout) {
this.log = log;
this.logToStdout = logToStdout;
}
public void info(String msg) {
if (logToStdout)
System.out.println("INFO: " + msg);
if (log.shouldLog(Log.INFO))
log.info(msg);
}
public void warn(String msg) {
warn(msg, null);
}
public void warn(String msg, Throwable e) {
if (logToStdout) {
System.out.println("WARNING: " + msg);
if (e != null)
e.printStackTrace();
}
if (log.shouldLog(Log.WARN))
log.warn(msg, e);
}
public void error(String msg, Throwable e) {
if (logToStdout) {
System.out.println("ERROR: " + msg);
if (e != null)
e.printStackTrace();
}
if (log.shouldLog(Log.ERROR))
log.error(msg, e);
}
}

View File

@@ -22,6 +22,7 @@ import java.net.ServerSocket;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
@@ -36,7 +37,7 @@ import net.i2p.util.Log;
public class MUXlisten implements Runnable {
private NamedDB database, info;
private Log _log;
private Logger _log;
private I2PSocketManager socketManager;
private ByteArrayInputStream prikey;
private ThreadGroup tg;
@@ -57,7 +58,7 @@ public class MUXlisten implements Runnable {
* @throws net.i2p.I2PException
* @throws java.io.IOException
*/
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Logger _log) throws I2PException, IOException, RuntimeException {
try {
int port = 0;
InetAddress host = null;
@@ -70,7 +71,7 @@ public class MUXlisten implements Runnable {
this.database.getWriteLock();
this.info.getWriteLock();
this.info.add("STARTING", new Boolean(true));
this.info.add("STARTING", Boolean.valueOf(true));
this.info.releaseWriteLock();
this.database.releaseWriteLock();
this.database.getReadLock();
@@ -96,15 +97,25 @@ public class MUXlisten implements Runnable {
this.database.releaseReadLock();
this.info.releaseReadLock();
String i2cpHost = Q.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
int i2cpPort = 7654;
String i2cpPortStr = Q.getProperty(I2PClient.PROP_TCP_PORT, "7654");
try {
i2cpPort = Integer.parseInt(i2cpPortStr);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Invalid I2CP port specified [" + i2cpPortStr + "]");
}
if (this.come_in) {
this.listener = new ServerSocket(port, backlog, host);
}
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
socketManager = I2PSocketManagerFactory.createManager(
prikey, i2cpHost, i2cpPort, Q);
} catch (IOException e) {
// Something went bad.
this.database.getWriteLock();
this.info.getWriteLock();
this.info.add("STARTING", new Boolean(false));
this.info.add("STARTING", Boolean.valueOf(false));
this.info.releaseWriteLock();
this.database.releaseWriteLock();
throw new IOException(e.toString());
@@ -112,7 +123,7 @@ public class MUXlisten implements Runnable {
// Something went bad.
this.database.getWriteLock();
this.info.getWriteLock();
this.info.add("STARTING", new Boolean(false));
this.info.add("STARTING", Boolean.valueOf(false));
this.info.releaseWriteLock();
this.database.releaseWriteLock();
throw new RuntimeException(e);
@@ -120,7 +131,7 @@ public class MUXlisten implements Runnable {
// Something else went bad.
this.database.getWriteLock();
this.info.getWriteLock();
this.info.add("STARTING", new Boolean(false));
this.info.add("STARTING", Boolean.valueOf(false));
this.info.releaseWriteLock();
this.database.releaseWriteLock();
e.printStackTrace();
@@ -160,7 +171,7 @@ public class MUXlisten implements Runnable {
try {
wlock();
try {
info.add("RUNNING", new Boolean(true));
info.add("RUNNING", Boolean.valueOf(true));
} catch (Exception e) {
lock.set(false);
wunlock();
@@ -204,7 +215,7 @@ public class MUXlisten implements Runnable {
try {
wlock();
try {
info.add("STARTING", new Boolean(false));
info.add("STARTING", Boolean.valueOf(false));
} catch (Exception e) {
wunlock();
break quit;
@@ -258,9 +269,9 @@ public class MUXlisten implements Runnable {
try {
wlock();
try {
info.add("STARTING", new Boolean(false));
info.add("STOPPING", new Boolean(true));
info.add("RUNNING", new Boolean(false));
info.add("STARTING", Boolean.valueOf(false));
info.add("STOPPING", Boolean.valueOf(true));
info.add("RUNNING", Boolean.valueOf(false));
} catch (Exception e) {
lock.set(false);
wunlock();
@@ -309,9 +320,9 @@ public class MUXlisten implements Runnable {
try {
wlock();
try {
info.add("STARTING", new Boolean(false));
info.add("STOPPING", new Boolean(false));
info.add("RUNNING", new Boolean(false));
info.add("STARTING", Boolean.valueOf(false));
info.add("STOPPING", Boolean.valueOf(false));
info.add("RUNNING", Boolean.valueOf(false));
} catch (Exception e) {
lock.set(false);
wunlock();

View File

@@ -23,7 +23,7 @@ package net.i2p.BOB;
public class NamedDB {
private volatile Object[][] data;
private volatile int index, writersWaiting, readers;
private int index, writersWaiting, readers;
/**
* make initial NULL object
@@ -31,7 +31,6 @@ public class NamedDB {
*/
public NamedDB() {
this.data = new Object[1][2];
this.index = this.writersWaiting = this.readers = 0;
}
synchronized public void getReadLock() {

View File

@@ -116,7 +116,6 @@ public class TCPio implements Runnable {
Aout.close();
} catch (IOException ex) {
}
return;
}
}
}

View File

@@ -22,7 +22,6 @@ import java.net.SocketTimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log;
/**
* Listen on TCP port and connect to I2P
@@ -32,7 +31,7 @@ import net.i2p.util.Log;
public class TCPlistener implements Runnable {
private NamedDB info, database;
private Log _log;
private Logger _log;
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
private ServerSocket listener;
@@ -45,7 +44,7 @@ public class TCPlistener implements Runnable {
* @param database
* @param _log
*/
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log, AtomicBoolean lives) {
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
this.database = database;
this.info = info;
this._log = _log;

View File

@@ -70,12 +70,10 @@ public class TCPtoI2P implements Runnable {
* @throws IOException
*/
private static String lnRead(InputStream in) throws IOException {
String S;
StringBuilder builder = new StringBuilder();
int b;
char c;
S = new String();
while (true) {
b = in.read();
if (b == 13) {
@@ -87,9 +85,9 @@ public class TCPtoI2P implements Runnable {
break;
}
c = (char) (b & 0x7f); // We only care about ASCII
S = new String(S + c);
builder.append(c);
}
return S;
return builder.toString();
}
/**
@@ -101,7 +99,7 @@ public class TCPtoI2P implements Runnable {
*/
private void Emsg(String e, OutputStream out) throws IOException {
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
out.write("ERROR ".concat(e).getBytes());
out.write("ERROR ".concat(e).getBytes("UTF-8"));
out.write(13);
out.write(10);
out.flush();

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="java/src"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2p_sdk"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/jetty/jettylib/javax.servlet.jar"/>
<classpathentry kind="output" path="build"/>
</classpath>

17
apps/addressbook/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>addressbook</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -120,11 +120,11 @@ class AddressBook {
subscription.setLastFetched(I2PAppContext.getGlobalContext().clock().now());
subf = tmp;
} else {
a = Collections.EMPTY_MAP;
a = Collections.emptyMap();
tmp.delete();
}
} catch (IOException ioe) {
a = Collections.EMPTY_MAP;
a = Collections.emptyMap();
}
this.addresses = a;
this.subFile = subf;
@@ -148,7 +148,7 @@ class AddressBook {
try {
a = ConfigParser.parse(file);
} catch (IOException exp) {
a = new HashMap();
a = new HashMap<String, String>();
}
this.addresses = a;
this.subFile = null;
@@ -260,7 +260,7 @@ class AddressBook {
* An AddressBook to merge with.
* @param overwrite True to overwrite
* @param log
* The log to write messages about new addresses or conflicts to.
* The log to write messages about new addresses or conflicts to. May be null.
*
* @throws IllegalStateException if this was created with the Subscription constructor.
*/

View File

@@ -138,7 +138,8 @@ class ConfigIterator implements Iterator<Map.Entry<String, String>> {
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry) o;
@SuppressWarnings("unchecked")
Map.Entry<Object, Object> e = (Map.Entry<Object, Object>) o;
return key.equals(e.getKey()) && value.equals(e.getValue());
}
}

View File

@@ -87,7 +87,7 @@ class ConfigParser {
*
*/
public static Map<String, String> parse(BufferedReader input) throws IOException {
Map<String, String> result = new HashMap();
Map<String, String> result = new HashMap<String, String>();
String inputLine;
inputLine = input.readLine();
while (inputLine != null) {
@@ -179,7 +179,7 @@ class ConfigParser {
*/
public static List<String> parseSubscriptions(BufferedReader input)
throws IOException {
List<String> result = new LinkedList();
List<String> result = new LinkedList<String>();
String inputLine = input.readLine();
while (inputLine != null) {
inputLine = ConfigParser.stripComments(inputLine).trim();

View File

@@ -37,6 +37,7 @@ import net.i2p.client.naming.SingleFileNamingService;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SystemVersion;
/**
* Main class of addressbook. Performs updates, and runs the main loop.
@@ -168,7 +169,7 @@ public class Daemon {
if (publishedNS == null)
publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
success = publishedNS.putIfAbsent(key, dest);
if (!success) {
if (log != null && !success) {
try {
log.append("Save to published address book " + published.getCanonicalPath() + " failed for new key " + key);
} catch (IOException ioe) {}
@@ -250,14 +251,14 @@ public class Daemon {
}
delay *= 60 * 60 * 1000;
List<String> defaultSubs = new LinkedList();
List<String> defaultSubs = new LinkedList<String>();
// defaultSubs.add("http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/hosts.txt");
defaultSubs.add("http://www.i2p2.i2p/hosts.txt");
SubscriptionList subscriptions = new SubscriptionList(subscriptionFile,
etagsFile, lastModifiedFile, lastFetchedFile, delay, defaultSubs, settings
.get("proxy_host"), Integer.parseInt(settings.get("proxy_port")));
Log log = new Log(logFile);
Log log = SystemVersion.isAndroid() ? null : new Log(logFile);
// If false, add hosts via naming service; if true, write hosts.txt file directly
// Default false
@@ -330,7 +331,7 @@ public class Daemon {
homeFile = new SecureDirectory(System.getProperty("user.dir"));
}
Map<String, String> defaultSettings = new HashMap();
Map<String, String> defaultSettings = new HashMap<String, String>();
defaultSettings.put("proxy_host", "127.0.0.1");
defaultSettings.put("proxy_port", "4444");
defaultSettings.put("master_addressbook", "../userhosts.txt");

View File

@@ -81,7 +81,7 @@ class SubscriptionIterator implements Iterator<AddressBook> {
// DataHelper.formatDuration(I2PAppContext.getGlobalContext().clock().now() - sub.getLastFetched()) +
// " ago but the minimum delay is " +
// DataHelper.formatDuration(this.delay));
return new AddressBook(Collections.EMPTY_MAP);
return new AddressBook(Collections.<String, String> emptyMap());
}
}

View File

@@ -69,7 +69,7 @@ class SubscriptionList {
public SubscriptionList(File locationsFile, File etagsFile,
File lastModifiedFile, File lastFetchedFile, long delay, List<String> defaultSubs, String proxyHost,
int proxyPort) {
this.subscriptions = new LinkedList();
this.subscriptions = new LinkedList<Subscription>();
this.etagsFile = etagsFile;
this.lastModifiedFile = lastModifiedFile;
this.lastFetchedFile = lastFetchedFile;
@@ -84,17 +84,17 @@ class SubscriptionList {
try {
etags = ConfigParser.parse(etagsFile);
} catch (IOException exp) {
etags = new HashMap();
etags = new HashMap<String, String>();
}
try {
lastModified = ConfigParser.parse(lastModifiedFile);
} catch (IOException exp) {
lastModified = new HashMap();
lastModified = new HashMap<String, String>();
}
try {
lastFetched = ConfigParser.parse(lastFetchedFile);
} catch (IOException exp) {
lastFetched = new HashMap();
lastFetched = new HashMap<String, String>();
}
for (String location : locations) {
this.subscriptions.add(new Subscription(location, etags.get(location),
@@ -121,9 +121,9 @@ class SubscriptionList {
* won't be read back correctly; the '=' should be escaped.
*/
public void write() {
Map<String, String> etags = new HashMap();
Map<String, String> lastModified = new HashMap();
Map<String, String> lastFetched = new HashMap();
Map<String, String> etags = new HashMap<String, String>();
Map<String, String> lastModified = new HashMap<String, String>();
Map<String, String> lastFetched = new HashMap<String, String>();
for (Subscription sub : this.subscriptions) {
if (sub.getEtag() != null) {
etags.put(sub.getLocation(), sub.getEtag());

View File

@@ -44,6 +44,7 @@
<target name="bundle" unless="no.bundle">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@@ -16,6 +16,10 @@ TMPFILE=build/javafiles.txt
export TZ=UTC
RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ]
then
POUPDATE=1

View File

@@ -11,6 +11,7 @@ msgstr ""
"POT-Creation-Date: 2011-02-20 11:53+0000\n"
"PO-Revision-Date: 2011-02-26 19:46-0000\n"
"Last-Translator: hamada <hamada@mail.i2p>\n"
"Language: ar\n"
"Language-Team: duck <duck@mail.i2p>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -3,19 +3,19 @@
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
#
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-01-09 18:07+0000\n"
"PO-Revision-Date: 2011-03-22 15:49+0000\n"
"Last-Translator: blabla <blabla@trash-mail.com>\n"
"Language-Team: German <>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
@@ -46,10 +46,10 @@ msgstr "I2P neustarten"
msgid "Stop I2P"
msgstr "I2P beenden"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43
msgid "Tray icon configuration"
msgstr "Systemleistensymbol konfigurieren"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46
msgid "Should tray icon be enabled?"
msgstr "Systemleistensymbol aktivieren?"

View File

@@ -8,11 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P desktopgui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"POT-Creation-Date: 2014-01-09 19:27+0000\n"
"PO-Revision-Date: 2010-06-15 14:09+0100\n"
"Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>\n"
"Language: \n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -46,10 +46,10 @@ msgstr ""
msgid "Stop I2P"
msgstr ""
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43
msgid "Tray icon configuration"
msgstr ""
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46
msgid "Should tray icon be enabled?"
msgstr ""

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
#
# Translators:
# blabla <blabla@trash-mail.com>, 2011
# ducki2p <ducki2p@gmail.com>, 2011
@@ -11,15 +11,16 @@
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-01-09 19:14+0000\n"
"PO-Revision-Date: 2013-06-08 04:50+0000\n"
"Last-Translator: Boxoa590\n"
"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/fr/)\n"
"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/"
"fr/)\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
@@ -50,10 +51,10 @@ msgstr "Redémarrer I2P"
msgid "Stop I2P"
msgstr "Arrêter I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43
msgid "Tray icon configuration"
msgstr "Configuration de l'icône de notification"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46
msgid "Should tray icon be enabled?"
msgstr "Activer l'icône de notification ?"

View File

@@ -0,0 +1,56 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# plazmism <gomidori@live.jp>, 2013
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2013-11-26 10:38+0000\n"
"Last-Translator: plazmism <gomidori@live.jp>\n"
"Language-Team: Japanese (http://www.transifex.com/projects/p/I2P/language/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "I2P を開始"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P 起動中!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "起動中"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "I2P ブラウザを起動"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "desktopgui を設定"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "I2P を再起動"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "I2P を停止"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "トレイアイコン設定"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "トレイアイコンを有効にしますか?"

View File

@@ -0,0 +1,56 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# blueboy, 2013
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2013-11-23 16:31+0000\n"
"Last-Translator: blueboy\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/I2P/language/pt_BR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Conectar-se à I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "Conectando-se a I2P!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Conectando"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Reinicializar o roteador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Interromper o roteador I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr ""
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr ""

View File

@@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-01-09 19:03+0000\n"
"PO-Revision-Date: 2013-11-11 11:31+0000\n"
"Last-Translator: polearnik <polearnik@mail.ru>\n"
"Language-Team: Romanian (http://www.transifex.com/projects/p/I2P/language/"
"ro/)\n"
"Language: ro\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?"
"2:1));\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Start I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P se pornește!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Începere"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Lansare I2P Browser"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Configurarea desktopgui"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Restart I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Stop I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43
msgid "Tray icon configuration"
msgstr "Configurare pictogramei din bara de sistem"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46
msgid "Should tray icon be enabled?"
msgstr "Ar trebui să fie activata pictograma din bara de sistem?"

View File

@@ -6,14 +6,14 @@
# Translators:
# ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009
# Roman Azarenko <x12ozmouse@ya.ru>, 2013
# Роман Азаренко <transifex@basicxp.ru>, 2013
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2013-07-07 11:44+0000\n"
"Last-Translator: Roman Azarenko <x12ozmouse@ya.ru>\n"
"PO-Revision-Date: 2013-12-04 11:46+0000\n"
"Last-Translator: Bergitte <alvina_alexandrova@mail.ru>\n"
"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/I2P/language/ru_RU/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -7,9 +7,6 @@ package net.i2p.desktopgui;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import java.awt.GraphicsEnvironment;
import net.i2p.I2PAppContext;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.desktopgui.util.*;
import net.i2p.util.Log;

View File

@@ -1,28 +1,15 @@
package net.i2p.desktopgui;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.Desktop.Action;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.swing.SwingWorker;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.desktopgui.util.BrowseException;
import net.i2p.desktopgui.util.ConfigurationManager;
import net.i2p.desktopgui.util.I2PDesktop;
import net.i2p.util.Log;
/**

View File

@@ -32,7 +32,6 @@ public class DesktopguiConfigurationFrame extends javax.swing.JFrame {
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
@@ -115,7 +114,7 @@ public class DesktopguiConfigurationFrame extends javax.swing.JFrame {
System.out.println("Enabling desktopgui");
}
try {
RouterManager.getRouterContext().setProperty(property, value);
RouterManager.getRouterContext().router().saveConfig(property, value);
} catch (Exception ex) {
Logger.getLogger(DesktopguiConfigurationFrame.class.getName()).log(Level.SEVERE, null, ex);
}

View File

@@ -5,8 +5,6 @@ import java.io.IOException;
import org.tanukisoftware.wrapper.WrapperManager;
import net.i2p.I2PAppContext;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.desktopgui.util.ConfigurationManager;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;

View File

@@ -1,13 +1,8 @@
package net.i2p.desktopgui.util;
import java.awt.Desktop;
import java.awt.TrayIcon;
import java.awt.Desktop.Action;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.util.Log;
public class I2PDesktop {

View File

@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="java/src"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2p_sdk"/>
<classpathentry combineaccessrules="false" kind="src" path="/ministreaming"/>
<classpathentry kind="lib" path="/jetty/jettylib/javax.servlet.jar"/>
<classpathentry kind="lib" path="/jetty/jettylib/jetty-util.jar"/>
<classpathentry kind="lib" path="/jetty/jettylib/org.mortbay.jetty.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/i2p_sdk"/>
<classpathentry combineaccessrules="false" kind="src" path="/jetty"/>
<classpathentry combineaccessrules="false" kind="src" path="/ministreaming"/>
<classpathentry kind="output" path="java/build/obj"/>
</classpath>

View File

@@ -130,6 +130,7 @@
<!-- 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="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@@ -15,6 +15,10 @@ TMPFILE=build/javafiles.txt
export TZ=UTC
RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ]
then
POUPDATE=1

View File

@@ -4,7 +4,6 @@
*/
package org.klomp.snark;
import java.util.Arrays;
import java.util.Properties;
import net.i2p.client.I2PSessionException;

View File

@@ -41,51 +41,49 @@ import net.i2p.util.SimpleTimer2;
class ConnectionAcceptor implements Runnable
{
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ConnectionAcceptor.class);
private I2PServerSocket serverSocket;
private PeerAcceptor peeracceptor;
private final PeerAcceptor peeracceptor;
private Thread thread;
private final I2PSnarkUtil _util;
private final ObjectCounter<Hash> _badCounter = new ObjectCounter();
private final ObjectCounter<Hash> _badCounter = new ObjectCounter<Hash>();
private final SimpleTimer2.TimedEvent _cleaner;
private volatile boolean stop;
private boolean socketChanged;
// protocol errors before blacklisting.
private static final int MAX_BAD = 1;
private static final long BAD_CLEAN_INTERVAL = 30*60*1000;
/**
* Multitorrent
* Multitorrent. Caller MUST call startAccepting()
*/
public ConnectionAcceptor(I2PSnarkUtil util) {
public ConnectionAcceptor(I2PSnarkUtil util, PeerCoordinatorSet set) {
_util = util;
_cleaner = new Cleaner();
peeracceptor = new PeerAcceptor(set);
}
public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) {
if (serverSocket != socket) {
if ( (peeracceptor == null) || (peeracceptor.coordinators != set) )
peeracceptor = new PeerAcceptor(set);
serverSocket = socket;
/**
* May be called even when already running. May be called to start up again after halt().
*/
public synchronized void startAccepting() {
stop = false;
socketChanged = true;
if (_log.shouldLog(Log.WARN))
_log.warn("ConnectionAcceptor startAccepting new thread? " + (thread == null));
if (thread == null) {
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
_cleaner.schedule(BAD_CLEAN_INTERVAL);
_cleaner.reschedule(BAD_CLEAN_INTERVAL, false);
}
}
}
/**
* Unused (single torrent)
* Unused (single torrent).
* Do NOT call startAccepting().
*/
public ConnectionAcceptor(I2PSnarkUtil util, I2PServerSocket serverSocket,
public ConnectionAcceptor(I2PSnarkUtil util,
PeerAcceptor peeracceptor)
{
this.serverSocket = serverSocket;
this.peeracceptor = peeracceptor;
_util = util;
@@ -95,55 +93,79 @@ class ConnectionAcceptor implements Runnable
_cleaner = new Cleaner();
}
public void halt()
/**
* May be restarted later with startAccepting().
*/
public synchronized void halt()
{
if (stop) return;
stop = true;
locked_halt();
Thread t = thread;
if (t != null) {
t.interrupt();
thread = null;
}
}
I2PServerSocket ss = serverSocket;
if (ss != null)
/**
* Caller must synch
* @since 0.9.9
*/
private void locked_halt()
{
I2PServerSocket ss = _util.getServerSocket();
if (ss != null) {
try
{
ss.close();
}
catch(I2PException ioe) { }
Thread t = thread;
if (t != null)
t.interrupt();
}
_badCounter.clear();
_cleaner.cancel();
}
/**
* Effectively unused, would only be called if we changed
* I2CP host/port, which is hidden in the gui if in router context
* FIXME this only works if already running
*/
public void restart() {
serverSocket = _util.getServerSocket();
socketChanged = true;
public synchronized void restart() {
Thread t = thread;
if (t != null)
t.interrupt();
_cleaner.schedule(BAD_CLEAN_INTERVAL);
}
public int getPort()
{
return 6881; // serverSocket.getLocalPort();
return TrackerClient.PORT; // serverSocket.getLocalPort();
}
public void run()
{
try {
run2();
} finally {
synchronized(this) {
thread = null;
}
}
}
private void run2()
{
while(!stop)
{
if (socketChanged) {
// ok, already updated
socketChanged = false;
}
I2PServerSocket serverSocket = _util.getServerSocket();
while ( (serverSocket == null) && (!stop)) {
if (!(_util.isConnecting() || _util.connected())) {
stop = true;
break;
}
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
serverSocket = _util.getServerSocket();
if (serverSocket == null)
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
}
if(stop)
break;
@@ -151,25 +173,25 @@ class ConnectionAcceptor implements Runnable
{
I2PSocket socket = serverSocket.accept();
if (socket == null) {
if (socketChanged) {
continue;
} else {
I2PServerSocket ss = _util.getServerSocket();
if (ss != serverSocket) {
serverSocket = ss;
socketChanged = true;
}
}
} else {
if (socket.getPeerDestination().equals(_util.getMyDestination())) {
_log.error("Incoming connection from myself");
try { socket.close(); } catch (IOException ioe) {}
continue;
}
int bad = _badCounter.count(socket.getPeerDestination().calculateHash());
Hash h = socket.getPeerDestination().calculateHash();
if (socket.getLocalPort() == 80) {
_badCounter.increment(h);
if (_log.shouldLog(Log.WARN))
_log.error("Dropping incoming HTTP from " + h);
try { socket.close(); } catch (IOException ioe) {}
continue;
}
int bad = _badCounter.count(h);
if (bad >= MAX_BAD) {
if (_log.shouldLog(Log.WARN))
_log.warn("Rejecting connection from " + socket.getPeerDestination().calculateHash() +
_log.warn("Rejecting connection from " + h +
" after " + bad + " failures, max is " + MAX_BAD);
try { socket.close(); } catch (IOException ioe) {}
continue;
@@ -180,26 +202,34 @@ class ConnectionAcceptor implements Runnable
}
catch (I2PException ioe)
{
if (!socketChanged) {
_log.error("Error while accepting", ioe);
stop = true;
int level = stop ? Log.WARN : Log.ERROR;
if (_log.shouldLog(level))
_log.log(level, "Error while accepting", ioe);
synchronized(this) {
if (!stop) {
locked_halt();
thread = null;
stop = true;
}
}
}
catch (IOException ioe)
{
_log.error("Error while accepting", ioe);
stop = true;
int level = stop ? Log.WARN : Log.ERROR;
if (_log.shouldLog(level))
_log.log(level, "Error while accepting", ioe);
synchronized(this) {
if (!stop) {
locked_halt();
thread = null;
stop = true;
}
}
}
// catch oom?
}
try
{
if (serverSocket != null)
serverSocket.close();
}
catch (I2PException ignored) { }
if (_log.shouldLog(Log.WARN))
_log.warn("ConnectionAcceptor closed");
}
private class Handler implements Runnable {

View File

@@ -43,8 +43,8 @@ abstract class ExtensionHandler {
* @return bencoded outgoing handshake message
*/
public static byte[] getHandshake(int metasize, boolean pexAndMetadata, boolean dht) {
Map<String, Object> handshake = new HashMap();
Map<String, Integer> m = new HashMap();
Map<String, Object> handshake = new HashMap<String, Object>();
Map<String, Integer> m = new HashMap<String, Integer>();
if (pexAndMetadata) {
m.put(TYPE_METADATA, Integer.valueOf(ID_METADATA));
m.put(TYPE_PEX, Integer.valueOf(ID_PEX));
@@ -56,7 +56,7 @@ abstract class ExtensionHandler {
}
// include the map even if empty so the far-end doesn't NPE
handshake.put("m", m);
handshake.put("p", Integer.valueOf(6881));
handshake.put("p", Integer.valueOf(TrackerClient.PORT));
handshake.put("v", "I2PSnark");
handshake.put("reqq", Integer.valueOf(5));
return BEncoder.bencode(handshake);
@@ -110,7 +110,8 @@ abstract class ExtensionHandler {
// drop if we need metainfo and we haven't found anybody yet
synchronized(state) {
if (!state.isInitialized()) {
log.debug("Dropping peer, we need metadata! " + peer);
if (log.shouldLog(Log.DEBUG))
log.debug("Dropping peer, we need metadata! " + peer);
peer.disconnect();
}
}
@@ -124,7 +125,8 @@ abstract class ExtensionHandler {
// drop if we need metainfo and we haven't found anybody yet
synchronized(state) {
if (!state.isInitialized()) {
log.debug("Dropping peer, we need metadata! " + peer);
if (log.shouldLog(Log.DEBUG))
log.debug("Dropping peer, we need metadata! " + peer);
peer.disconnect();
}
}
@@ -274,7 +276,7 @@ abstract class ExtensionHandler {
/** REQUEST and REJECT are the same except for message type */
private static void sendMessage(Peer peer, int type, int piece) {
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("msg_type", Integer.valueOf(type));
map.put("piece", Integer.valueOf(piece));
byte[] payload = BEncoder.bencode(map);
@@ -289,7 +291,7 @@ abstract class ExtensionHandler {
}
private static void sendPiece(Peer peer, int piece, byte[] data) {
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("msg_type", Integer.valueOf(TYPE_DATA));
map.put("piece", Integer.valueOf(piece));
map.put("total_size", Integer.valueOf(data.length));
@@ -332,7 +334,7 @@ abstract class ExtensionHandler {
if (ids.length < HASH_LENGTH)
return;
int len = Math.min(ids.length, (I2PSnarkUtil.MAX_CONNECTIONS - 1) * HASH_LENGTH);
List<PeerID> peers = new ArrayList(len / HASH_LENGTH);
List<PeerID> peers = new ArrayList<PeerID>(len / HASH_LENGTH);
for (int off = 0; off < len; off += HASH_LENGTH) {
byte[] hash = new byte[HASH_LENGTH];
System.arraycopy(ids, off, hash, 0, HASH_LENGTH);
@@ -380,7 +382,7 @@ abstract class ExtensionHandler {
public static void sendPEX(Peer peer, List<Peer> pList) {
if (pList.isEmpty())
return;
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
byte[] peers = new byte[HASH_LENGTH * pList.size()];
int off = 0;
for (Peer p : pList) {
@@ -404,7 +406,7 @@ abstract class ExtensionHandler {
* @since DHT
*/
public static void sendDHT(Peer peer, int qport, int rport) {
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("port", Integer.valueOf(qport));
map.put("rport", Integer.valueOf(rport));
byte[] payload = BEncoder.bencode(map);

View File

@@ -3,16 +3,12 @@ package org.klomp.snark;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PSession;
@@ -33,7 +29,6 @@ import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFile;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.Translate;
@@ -81,6 +76,7 @@ public class I2PSnarkUtil {
public static final int MAX_CONNECTIONS = 16; // per torrent
public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
public static final boolean DEFAULT_USE_DHT = true;
public static final String EEPGET_USER_AGENT = "I2PSnark";
public I2PSnarkUtil(I2PAppContext ctx) {
this(ctx, "i2psnark");
@@ -94,10 +90,10 @@ public class I2PSnarkUtil {
_context = ctx;
_log = _context.logManager().getLog(Snark.class);
_baseName = baseName;
_opts = new HashMap();
_opts = new HashMap<String, String>();
//setProxy("127.0.0.1", 4444);
setI2CPConfig("127.0.0.1", 7654, null);
_banlist = new ConcurrentHashSet();
_banlist = new ConcurrentHashSet<Hash>();
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
_maxUpBW = DEFAULT_MAX_UP_BW;
_maxConnections = MAX_CONNECTIONS;
@@ -220,10 +216,8 @@ public class I2PSnarkUtil {
_log.debug("Connecting to I2P", new Exception("I did it"));
Properties opts = _context.getProperties();
if (_opts != null) {
for (Iterator iter = _opts.keySet().iterator(); iter.hasNext(); ) {
String key = (String)iter.next();
opts.setProperty(key, _opts.get(key).toString());
}
for (Map.Entry<String, String> entry : _opts.entrySet() )
opts.setProperty(entry.getKey(), entry.getValue());
}
if (opts.getProperty("inbound.nickname") == null)
opts.setProperty("inbound.nickname", _baseName.replace("i2psnark", "I2PSnark"));
@@ -259,6 +253,8 @@ public class I2PSnarkUtil {
opts.setProperty("i2p.streaming.enforceProtocol", "true");
if (opts.getProperty("i2p.streaming.disableRejectLogging") == null)
opts.setProperty("i2p.streaming.disableRejectLogging", "true");
if (opts.getProperty("i2p.streaming.answerPings") == null)
opts.setProperty("i2p.streaming.answerPings", "false");
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
_connecting = false;
}
@@ -324,6 +320,8 @@ public class I2PSnarkUtil {
if (_banlist.contains(dest))
throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are banlisted");
try {
// TODO opts.setPort(xxx); connect(addr, opts)
// DHT moved above 6881 in 0.9.9
I2PSocket rv = _manager.connect(addr);
if (rv != null)
_banlist.remove(dest);
@@ -331,7 +329,9 @@ public class I2PSnarkUtil {
} catch (I2PException ie) {
_banlist.add(dest);
_context.simpleScheduler().addEvent(new Unbanlist(dest), 10*60*1000);
throw new IOException("Unable to reach the peer " + peer + ": " + ie.getMessage());
IOException ioe = new IOException("Unable to reach the peer " + peer);
ioe.initCause(ie);
throw ioe;
}
}
@@ -394,6 +394,7 @@ public class I2PSnarkUtil {
}
}
EepGet get = new I2PSocketEepGet(_context, _manager, retries, out.getAbsolutePath(), fetchURL);
get.addHeader("User-Agent", EEPGET_USER_AGENT);
if (get.fetch(timeout)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
@@ -435,6 +436,7 @@ public class I2PSnarkUtil {
}
ByteArrayOutputStream out = new ByteArrayOutputStream(initialSize);
EepGet get = new I2PSocketEepGet(_context, _manager, retries, -1, maxSize, null, out, fetchURL);
get.addHeader("User-Agent", EEPGET_USER_AGENT);
if (get.fetch(timeout)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Fetch successful [" + url + "]: size=" + out.size());
@@ -513,7 +515,7 @@ public class I2PSnarkUtil {
if (_log.shouldLog(Log.INFO))
_log.info("Using existing session for lookup of " + ip);
try {
return sess.lookupDest(h);
return sess.lookupDest(h, 15*1000);
} catch (I2PSessionException ise) {
}
}
@@ -573,7 +575,7 @@ public class I2PSnarkUtil {
*/
public List<String> getOpenTrackers() {
if (!shouldUseOpenTrackers())
return Collections.EMPTY_LIST;
return Collections.emptyList();
return _openTrackers;
}

View File

@@ -22,34 +22,56 @@ import net.i2p.util.SimpleTimer2;
*/
class IdleChecker extends SimpleTimer2.TimedEvent {
private final SnarkManager _mgr;
private final I2PSnarkUtil _util;
private final PeerCoordinatorSet _pcs;
private final Log _log;
private int _consec;
private int _consecNotRunning;
private boolean _isIdle;
private static final long CHECK_TIME = 63*1000;
private static final int MAX_CONSEC_IDLE = 4;
private static final int MAX_CONSEC_NOT_RUNNING = 20;
/**
* Caller must schedule
*/
public IdleChecker(I2PSnarkUtil util, PeerCoordinatorSet pcs) {
super(util.getContext().simpleTimer2());
_log = util.getContext().logManager().getLog(IdleChecker.class);
_util = util;
public IdleChecker(SnarkManager mgr, PeerCoordinatorSet pcs) {
super(mgr.util().getContext().simpleTimer2());
_util = mgr.util();
_log = _util.getContext().logManager().getLog(IdleChecker.class);
_mgr = mgr;
_pcs = pcs;
}
public void timeReached() {
if (_util.connected()) {
boolean torrentRunning = false;
boolean hasPeers = false;
for (PeerCoordinator pc : _pcs) {
if (pc.getPeers() > 0) {
hasPeers = true;
break;
if (!pc.halted()) {
torrentRunning = true;
if (pc.getPeers() > 0) {
hasPeers = true;
break;
}
}
}
if (torrentRunning) {
_consecNotRunning = 0;
} else {
if (_consecNotRunning++ >= MAX_CONSEC_NOT_RUNNING) {
if (_log.shouldLog(Log.WARN))
_log.warn("Closing tunnels on idle");
_util.disconnect();
_mgr.addMessage(_util.getString("I2P tunnel closed."));
schedule(3 * CHECK_TIME);
return;
}
}
if (hasPeers) {
if (_isIdle)
restoreTunnels();
@@ -62,6 +84,7 @@ class IdleChecker extends SimpleTimer2.TimedEvent {
} else {
_isIdle = false;
_consec = 0;
_consecNotRunning = 0;
}
schedule(CHECK_TIME);
}

View File

@@ -6,7 +6,6 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.RandomSource;
@@ -190,7 +189,7 @@ class MagnetState {
*/
public MetaInfo buildMetaInfo() throws Exception {
// top map has nothing in it but the info map (no announce)
Map<String, BEValue> map = new HashMap();
Map<String, BEValue> map = new HashMap<String, BEValue>();
InputStream is = new ByteArrayInputStream(metainfoBytes);
BDecoder dec = new BDecoder(is);
BEValue bev = dec.bdecodeMap();

View File

@@ -133,7 +133,7 @@ public class MagnetURI {
}
if (idx < 0 || idx > uri.length())
return null;
List<String> rv = new ArrayList();
List<String> rv = new ArrayList<String>();
while (true) {
String p = uri.substring(idx);
uri = p;

View File

@@ -156,11 +156,11 @@ public class MetaInfo
if (val == null) {
this.announce_list = null;
} else {
this.announce_list = new ArrayList();
this.announce_list = new ArrayList<List<String>>();
List<BEValue> bl1 = val.getList();
for (BEValue bev : bl1) {
List<BEValue> bl2 = bev.getList();
List<String> sl2 = new ArrayList();
List<String> sl2 = new ArrayList<String>();
for (BEValue bev2 : bl2) {
sl2.add(bev2.getString());
}
@@ -216,7 +216,16 @@ public class MetaInfo
// BEP 27
val = info.get("private");
privateTorrent = val != null && val.getString().equals("1");
if (val != null) {
Object o = val.getValue();
// Is it supposed to be a number or a string?
// i2psnark does it as a string. BEP 27 doesn't say.
// Transmission does numbers.
privateTorrent = "1".equals(o) ||
((o instanceof Number) && ((Number) o).intValue() == 1);
} else {
privateTorrent = false;
}
val = info.get("piece length");
if (val == null)
@@ -250,9 +259,9 @@ public class MetaInfo
if (size == 0)
throw new InvalidBEncodingException("zero size files list");
List<List<String>> m_files = new ArrayList(size);
List<List<String>> m_files_utf8 = new ArrayList(size);
List<Long> m_lengths = new ArrayList(size);
List<List<String>> m_files = new ArrayList<List<String>>(size);
List<List<String>> m_files_utf8 = new ArrayList<List<String>>(size);
List<Long> m_lengths = new ArrayList<Long>(size);
long l = 0;
for (int i = 0; i < list.size(); i++)
{
@@ -278,7 +287,7 @@ public class MetaInfo
if (path_length == 0)
throw new InvalidBEncodingException("zero size file path list");
List<String> file = new ArrayList(path_length);
List<String> file = new ArrayList<String>(path_length);
Iterator<BEValue> it = path_list.iterator();
while (it.hasNext()) {
String s = it.next().getString();
@@ -301,7 +310,7 @@ public class MetaInfo
path_list = val.getList();
path_length = path_list.size();
if (path_length > 0) {
file = new ArrayList(path_length);
file = new ArrayList<String>(path_length);
it = path_list.iterator();
while (it.hasNext())
file.add(it.next().getString());
@@ -517,7 +526,6 @@ public class MetaInfo
* @since 0.9.1
*/
boolean checkPiece(PartialPiece pp) {
MessageDigest sha1 = SHA1.getInstance();
int piece = pp.getPiece();
byte[] hash;
try {
@@ -565,10 +573,10 @@ public class MetaInfo
*/
public MetaInfo reannounce(String announce) throws InvalidBEncodingException
{
Map<String, BEValue> m = new HashMap();
Map<String, BEValue> m = new HashMap<String, BEValue>();
if (announce != null)
m.put("announce", new BEValue(DataHelper.getUTF8(announce)));
Map info = createInfoMap();
Map<String, BEValue> info = createInfoMap();
m.put("info", new BEValue(info));
return new MetaInfo(m);
}
@@ -578,12 +586,12 @@ public class MetaInfo
*/
public synchronized byte[] getTorrentData()
{
Map m = new HashMap();
Map<String, Object> m = new HashMap<String, Object>();
if (announce != null)
m.put("announce", announce);
if (announce_list != null)
m.put("announce-list", announce_list);
Map info = createInfoMap();
Map<String, BEValue> info = createInfoMap();
m.put("info", info);
// don't save this locally, we should only do this once
return BEncoder.bencode(m);
@@ -607,31 +615,42 @@ public class MetaInfo
if (_log.shouldLog(Log.WARN))
_log.warn("Creating new infomap", new Exception());
// otherwise we must create it
Map info = new HashMap();
info.put("name", name);
Map<String, BEValue> info = new HashMap<String, BEValue>();
info.put("name", new BEValue(DataHelper.getUTF8(name)));
if (name_utf8 != null)
info.put("name.utf-8", name_utf8);
info.put("name.utf-8", new BEValue(DataHelper.getUTF8(name_utf8)));
// BEP 27
if (privateTorrent)
info.put("private", "1");
info.put("private", new BEValue(DataHelper.getUTF8("1")));
info.put("piece length", Integer.valueOf(piece_length));
info.put("pieces", piece_hashes);
info.put("piece length", new BEValue(Integer.valueOf(piece_length)));
info.put("pieces", new BEValue(piece_hashes));
if (files == null)
info.put("length", Long.valueOf(length));
info.put("length", new BEValue(Long.valueOf(length)));
else
{
List l = new ArrayList();
List<BEValue> l = new ArrayList<BEValue>();
for (int i = 0; i < files.size(); i++)
{
Map file = new HashMap();
file.put("path", files.get(i));
if ( (files_utf8 != null) && (files_utf8.size() > i) )
file.put("path.utf-8", files_utf8.get(i));
file.put("length", lengths.get(i));
l.add(file);
Map<String, BEValue> file = new HashMap<String, BEValue>();
List<String> fi = files.get(i);
List<BEValue> befiles = new ArrayList<BEValue>(fi.size());
for (int j = 0; j < fi.size(); j++) {
befiles.add(new BEValue(DataHelper.getUTF8(fi.get(j))));
}
file.put("path", new BEValue(befiles));
if ( (files_utf8 != null) && (files_utf8.size() > i) ) {
List<String> fiu = files_utf8.get(i);
List<BEValue> beufiles = new ArrayList<BEValue>(fiu.size());
for (int j = 0; j < fiu.size(); j++) {
beufiles.add(new BEValue(DataHelper.getUTF8(fiu.get(j))));
}
file.put("path.utf-8", new BEValue(beufiles));
}
file.put("length", new BEValue(lengths.get(i)));
l.add(new BEValue(file));
}
info.put("files", l);
info.put("files", new BEValue(l));
}
// TODO if we add the ability for other keys in the first constructor

View File

@@ -31,7 +31,7 @@ import net.i2p.util.SecureFile;
*
* @since 0.8.2
*/
class PartialPiece implements Comparable {
class PartialPiece implements Comparable<PartialPiece> {
// we store the piece so we can use it in compareTo()
private final Piece piece;
@@ -295,8 +295,7 @@ class PartialPiece implements Comparable {
* then rarest first,
* then highest downloaded first
*/
public int compareTo(Object o) throws ClassCastException {
PartialPiece opp = (PartialPiece)o;
public int compareTo(PartialPiece opp) {
int d = this.piece.compareTo(opp.piece);
if (d != 0)
return d;

View File

@@ -28,6 +28,8 @@ import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
@@ -37,7 +39,7 @@ import net.i2p.util.Log;
import org.klomp.snark.bencode.BEValue;
public class Peer implements Comparable
public class Peer implements Comparable<Peer>
{
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(Peer.class);
// Identifying property, the peer id of the other side.
@@ -68,8 +70,10 @@ public class Peer implements Comparable
private I2PSocket sock;
private boolean deregister = true;
private static long __id;
private long _id;
private static final AtomicLong __id = new AtomicLong();
private final long _id;
private final AtomicBoolean _disconnected = new AtomicBoolean();
final static long CHECK_PERIOD = PeerCoordinator.CHECK_PERIOD; // 40 seconds
final static int RATE_DEPTH = PeerCoordinator.RATE_DEPTH; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1};
@@ -98,7 +102,7 @@ public class Peer implements Comparable
this.my_id = my_id;
this.infohash = infohash;
this.metainfo = metainfo;
_id = ++__id;
_id = __id.incrementAndGet();
//_log.debug("Creating a new peer with " + peerID.toString(), new Exception("creating"));
}
@@ -123,7 +127,7 @@ public class Peer implements Comparable
byte[] id = handshake(in, out);
this.peerID = new PeerID(id, sock.getPeerDestination());
_id = ++__id;
_id = __id.incrementAndGet();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating a new peer " + peerID.toString(), new Exception("creating " + _id));
}
@@ -190,7 +194,7 @@ public class Peer implements Comparable
* Compares the PeerIDs.
* @deprecated unused?
*/
public int compareTo(Object o)
public int compareTo(Peer o)
{
Peer p = (Peer)o;
int rv = peerID.compareTo(p.peerID);
@@ -457,6 +461,8 @@ public class Peer implements Comparable
void disconnect()
{
if (!_disconnected.compareAndSet(false, true))
return;
PeerState s = state;
if (s != null)
{
@@ -476,9 +482,11 @@ public class Peer implements Comparable
PeerConnectionIn in = s.in;
if (in != null)
in.disconnect();
PeerConnectionOut out = s.out;
if (out != null)
out.disconnect();
// this is blocking in streaming, so do this after closing the socket
// so it won't really block
//PeerConnectionOut out = s.out;
//if (out != null)
// out.disconnect();
PeerListener pl = s.listener;
if (pl != null)
pl.disconnected(this);
@@ -492,6 +500,13 @@ public class Peer implements Comparable
_log.warn("Error disconnecting " + toString(), ioe);
}
}
if (s != null) {
// this is blocking in streaming, so do this after closing the socket
// so it won't really block
PeerConnectionOut out = s.out;
if (out != null)
out.disconnect();
}
}
/**

View File

@@ -26,8 +26,6 @@ import java.io.IOException;
import java.io.InputStream;
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;
@@ -170,8 +168,7 @@ class PeerAcceptor
if (b != PROTO[i])
throw new IOException("Bad protocol 0x" + Integer.toHexString(b) + " at byte " + i);
}
if (in.skip(8) != 8)
throw new IOException("EOF before hash");
DataHelper.skip(in, 8);
byte buf[] = new byte[20];
int read = DataHelper.read(in, buf);
if (read != buf.length)

View File

@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
@@ -73,7 +72,7 @@ class PeerCheckerTask implements Runnable
// Keep track of peers we remove now,
// we will add them back to the end of the list.
List<Peer> removed = new ArrayList();
List<Peer> removed = new ArrayList<Peer>();
int uploadLimit = coordinator.allowedUploaders();
boolean overBWLimit = coordinator.overUpBWLimit();
DHT dht = _util.getDHT();

View File

@@ -65,7 +65,7 @@ class PeerConnectionIn implements Runnable
try {
din.close();
} catch (IOException ioe) {
_log.warn("Error closing the stream from " + peer, ioe);
//_log.warn("Error closing the stream from " + peer, ioe);
}
}
}

View File

@@ -25,6 +25,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PAppThread;
@@ -42,10 +43,10 @@ class PeerConnectionOut implements Runnable
private boolean quit;
// Contains Messages.
private final List<Message> sendQueue = new ArrayList();
private final List<Message> sendQueue = new ArrayList<Message>();
private static long __id = 0;
private long _id;
private static final AtomicLong __id = new AtomicLong();
private final long _id;
long lastSent;
@@ -53,10 +54,9 @@ class PeerConnectionOut implements Runnable
{
this.peer = peer;
this.dout = dout;
_id = ++__id;
_id = __id.incrementAndGet();
lastSent = System.currentTimeMillis();
quit = false;
}
public void startup() {
@@ -66,7 +66,7 @@ class PeerConnectionOut implements Runnable
/**
* Continuesly monitors for more outgoing messages that have to be send.
* Stops if quit is true of an IOException occurs.
* Stops if quit is true or an IOException occurs.
*/
public void run()
{
@@ -116,10 +116,10 @@ class PeerConnectionOut implements Runnable
// And remove piece messages if we are choking.
// this should get fixed for starvation
Iterator it = sendQueue.iterator();
Iterator<Message> it = sendQueue.iterator();
while (m == null && it.hasNext())
{
Message nm = (Message)it.next();
Message nm = it.next();
if (nm.type == Message.PIECE)
{
if (state.choking) {
@@ -215,13 +215,13 @@ class PeerConnectionOut implements Runnable
thread.interrupt();
sendQueue.clear();
sendQueue.notify();
sendQueue.notifyAll();
}
if (dout != null) {
try {
dout.close();
} catch (IOException ioe) {
_log.warn("Error closing the stream to " + peer, ioe);
//_log.warn("Error closing the stream to " + peer, ioe);
}
}
}
@@ -274,10 +274,10 @@ class PeerConnectionOut implements Runnable
boolean removed = false;
synchronized(sendQueue)
{
Iterator it = sendQueue.iterator();
Iterator<Message> it = sendQueue.iterator();
while (it.hasNext())
{
Message m = (Message)it.next();
Message m = it.next();
if (m.type == type)
{
it.remove();
@@ -360,13 +360,13 @@ class PeerConnectionOut implements Runnable
/** reransmit requests not received in 7m */
private static final int REQ_TIMEOUT = (2 * SEND_TIMEOUT) + (60 * 1000);
void retransmitRequests(List requests)
void retransmitRequests(List<Request> requests)
{
long now = System.currentTimeMillis();
Iterator it = requests.iterator();
Iterator<Request> it = requests.iterator();
while (it.hasNext())
{
Request req = (Request)it.next();
Request req = it.next();
if(now > req.sendTime + REQ_TIMEOUT) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Retransmit request " + req + " to peer " + peer);
@@ -375,12 +375,12 @@ class PeerConnectionOut implements Runnable
}
}
void sendRequests(List requests)
void sendRequests(List<Request> requests)
{
Iterator it = requests.iterator();
Iterator<Request> it = requests.iterator();
while (it.hasNext())
{
Request req = (Request)it.next();
Request req = it.next();
sendRequest(req);
}
}
@@ -391,10 +391,10 @@ class PeerConnectionOut implements Runnable
// (multiple choke/unchokes received cause duplicate requests in the queue)
synchronized(sendQueue)
{
Iterator it = sendQueue.iterator();
Iterator<Message> it = sendQueue.iterator();
while (it.hasNext())
{
Message m = (Message)it.next();
Message m = it.next();
if (m.type == Message.REQUEST && m.piece == req.getPiece() &&
m.begin == req.off && m.length == req.len)
{
@@ -419,10 +419,10 @@ class PeerConnectionOut implements Runnable
int total = 0;
synchronized(sendQueue)
{
Iterator it = sendQueue.iterator();
Iterator<Message> it = sendQueue.iterator();
while (it.hasNext())
{
Message m = (Message)it.next();
Message m = it.next();
if (m.type == Message.PIECE)
total += m.length;
}
@@ -489,10 +489,10 @@ class PeerConnectionOut implements Runnable
// See if it is still in our send queue
synchronized(sendQueue)
{
Iterator it = sendQueue.iterator();
Iterator<Message> it = sendQueue.iterator();
while (it.hasNext())
{
Message m = (Message)it.next();
Message m = it.next();
if (m.type == Message.REQUEST
&& m.piece == req.getPiece()
&& m.begin == req.off
@@ -530,10 +530,10 @@ class PeerConnectionOut implements Runnable
{
synchronized (sendQueue)
{
Iterator it = sendQueue.iterator();
Iterator<Message> it = sendQueue.iterator();
while (it.hasNext())
{
Message m = (Message)it.next();
Message m = it.next();
if (m.type == Message.PIECE
&& m.piece == piece
&& m.begin == begin

View File

@@ -151,12 +151,12 @@ class PeerCoordinator implements PeerListener
this.listener = listener;
this.snark = torrent;
wantedPieces = new ArrayList();
wantedPieces = new ArrayList<Piece>();
setWantedPieces();
partialPieces = new ArrayList(getMaxConnections() + 1);
peers = new LinkedBlockingQueue();
partialPieces = new ArrayList<PartialPiece>(getMaxConnections() + 1);
peers = new LinkedBlockingQueue<Peer>();
magnetState = new MagnetState(infohash, metainfo);
pexPeers = new ConcurrentHashSet();
pexPeers = new ConcurrentHashSet<PeerID>();
// Install a timer to check the uploaders.
// Randomize the first start time so multiple tasks are spread out,
@@ -218,7 +218,7 @@ class PeerCoordinator implements PeerListener
/** for web page detailed stats */
public List<Peer> peerList()
{
return new ArrayList(peers);
return new ArrayList<Peer>(peers);
}
public byte[] getID()
@@ -412,7 +412,7 @@ class PeerCoordinator implements PeerListener
public void halt()
{
halted = true;
List<Peer> removed = new ArrayList();
List<Peer> removed = new ArrayList<Peer>();
synchronized(peers)
{
// Stop peer checker task.
@@ -613,7 +613,7 @@ 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<Peer> interested = new LinkedList();
List<Peer> interested = new LinkedList<Peer>();
int count = 0;
int unchokedCount = 0;
int maxUploaders = allowedUploaders();
@@ -729,7 +729,7 @@ class PeerCoordinator implements PeerListener
}
Piece piece = null;
List<Piece> requested = new ArrayList();
List<Piece> requested = new ArrayList<Piece>();
int wantedSize = END_GAME_THRESHOLD + 1;
synchronized(wantedPieces)
{
@@ -833,7 +833,7 @@ class PeerCoordinator implements PeerListener
_log.debug("Updated piece priorities called but no priorities to set?");
return;
}
List<Piece> toCancel = new ArrayList();
List<Piece> toCancel = new ArrayList<Piece>();
synchronized(wantedPieces) {
// Add incomplete and previously unwanted pieces to the list
// Temp to avoid O(n**2)
@@ -999,13 +999,13 @@ class PeerCoordinator implements PeerListener
}
catch (IOException ioe)
{
snark.stopTorrent();
String msg = "Error writing storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
_log.error(msg, ioe);
if (listener != null) {
listener.addMessage(msg);
listener.addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
}
snark.stopTorrent();
throw new RuntimeException(msg, ioe);
}
wantedPieces.remove(p);
@@ -1019,7 +1019,7 @@ class PeerCoordinator implements PeerListener
// Announce to the world we have it!
// Disconnect from other seeders when we get the last piece
List<Peer> toDisconnect = done ? new ArrayList() : null;
List<Peer> toDisconnect = done ? new ArrayList<Peer>() : null;
for (Peer p : peers) {
if (p.isConnected())
{
@@ -1231,16 +1231,16 @@ class PeerCoordinator implements PeerListener
return pp;
}
}
if (_log.shouldLog(Log.WARN)) {
if (_log.shouldLog(Log.INFO)) {
if (skipped)
_log.warn("Partial piece " + pp + " with multiple peers skipped for seeder");
_log.info("Partial piece " + pp + " with multiple peers skipped for seeder");
else
_log.warn("Partial piece " + pp + " NOT in wantedPieces??");
_log.info("Partial piece " + pp + " NOT in wantedPieces??");
}
}
}
if (_log.shouldLog(Log.WARN) && !partialPieces.isEmpty())
_log.warn("Peer " + peer + " has none of our partials " + partialPieces);
if (_log.shouldLog(Log.INFO) && !partialPieces.isEmpty())
_log.info("Peer " + peer + " has none of our partials " + partialPieces);
}
// ...and this section turns this into the general move-requests-around code!
// Temporary? So PeerState never calls wantPiece() directly for now...

View File

@@ -16,7 +16,7 @@ class PeerCoordinatorSet implements Iterable<PeerCoordinator> {
private final Map<SHA1Hash, PeerCoordinator> _coordinators;
public PeerCoordinatorSet() {
_coordinators = new ConcurrentHashMap();
_coordinators = new ConcurrentHashMap<SHA1Hash, PeerCoordinator>();
}
public Iterator<PeerCoordinator> iterator() {

View File

@@ -24,7 +24,6 @@ import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.data.Base32;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
@@ -43,7 +42,7 @@ import org.klomp.snark.bencode.InvalidBEncodingException;
* and the PeerID is not required.
* Equality is now determined solely by the dest hash.
*/
class PeerID implements Comparable
class PeerID implements Comparable<PeerID>
{
private byte[] id;
private Destination address;
@@ -58,7 +57,7 @@ class PeerID implements Comparable
{
this.id = id;
this.address = address;
this.port = 6881;
this.port = TrackerClient.PORT;
this.destHash = address.calculateHash().getData();
hash = calculateHash();
util = null;
@@ -77,22 +76,22 @@ class PeerID implements Comparable
* Creates a PeerID from a Map containing BEncoded peer id, ip and
* port.
*/
public PeerID(Map m)
public PeerID(Map<String, BEValue> m)
throws InvalidBEncodingException, UnknownHostException
{
BEValue bevalue = (BEValue)m.get("peer id");
BEValue bevalue = m.get("peer id");
if (bevalue == null)
throw new InvalidBEncodingException("peer id missing");
id = bevalue.getBytes();
bevalue = (BEValue)m.get("ip");
bevalue = m.get("ip");
if (bevalue == null)
throw new InvalidBEncodingException("ip missing");
address = I2PSnarkUtil.getDestinationFromBase64(bevalue.getString());
if (address == null)
throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]");
port = 6881;
port = TrackerClient.PORT;
this.destHash = address.calculateHash().getData();
hash = calculateHash();
util = null;
@@ -106,7 +105,7 @@ class PeerID implements Comparable
public PeerID(byte[] dest_hash, I2PSnarkUtil util) throws InvalidBEncodingException
{
// id and address remain null
port = 6881;
port = TrackerClient.PORT;
if (dest_hash.length != 32)
throw new InvalidBEncodingException("bad hash length");
destHash = dest_hash;
@@ -196,10 +195,8 @@ class PeerID implements Comparable
* Compares port, address and id.
* @deprecated unused? and will NPE now that address can be null?
*/
public int compareTo(Object o)
public int compareTo(PeerID pid)
{
PeerID pid = (PeerID)o;
int result = port - pid.port;
if (result != 0)
return result;

View File

@@ -56,7 +56,7 @@ class PeerState implements DataLoader
final PeerConnectionOut out;
// Outstanding request
private final List<Request> outstandingRequests = new ArrayList();
private final List<Request> outstandingRequests = new ArrayList<Request>();
/** the tail (NOT the head) of the request queue */
private Request lastRequest = null;
@@ -451,7 +451,7 @@ class PeerState implements DataLoader
synchronized List<Request> returnPartialPieces()
{
Set<Integer> pcs = getRequestedPieces();
List<Request> rv = new ArrayList(pcs.size());
List<Request> rv = new ArrayList<Request>(pcs.size());
for (Integer p : pcs) {
Request req = getLowestOutstandingRequest(p.intValue());
if (req != null) {
@@ -469,7 +469,7 @@ class PeerState implements DataLoader
* @return all pieces we are currently requesting, or empty Set
*/
synchronized private Set<Integer> getRequestedPieces() {
Set<Integer> rv = new HashSet(outstandingRequests.size() + 1);
Set<Integer> rv = new HashSet<Integer>(outstandingRequests.size() + 1);
for (Request req : outstandingRequests) {
rv.add(Integer.valueOf(req.getPiece()));
if (pendingRequest != null)

View File

@@ -7,7 +7,7 @@ import java.util.Set;
* This class is used solely by PeerCoordinator.
* Caller must synchronize on many of these methods.
*/
class Piece implements Comparable {
class Piece implements Comparable<Piece> {
private final int id;
private final Set<PeerID> peers;
@@ -18,7 +18,7 @@ class Piece implements Comparable {
public Piece(int id) {
this.id = id;
this.peers = new HashSet(I2PSnarkUtil.MAX_CONNECTIONS / 2);
this.peers = new HashSet<PeerID>(I2PSnarkUtil.MAX_CONNECTIONS / 2);
// defer creating requests to save memory
}
@@ -26,11 +26,11 @@ class Piece implements Comparable {
* Highest priority first,
* then rarest first
*/
public int compareTo(Object o) throws ClassCastException {
int pdiff = ((Piece)o).priority - this.priority; // reverse
public int compareTo(Piece op) {
int pdiff = op.priority - this.priority; // reverse
if (pdiff != 0)
return pdiff;
return this.peers.size() - ((Piece)o).peers.size();
return this.peers.size() - op.peers.size();
}
@Override
@@ -82,7 +82,7 @@ class Piece implements Comparable {
public void setRequested(Peer peer, boolean requested) {
if (requested) {
if (this.requests == null)
this.requests = new HashSet(2);
this.requests = new HashSet<PeerID>(2);
this.requests.add(peer.getPeerID());
} else {
if (this.requests != null)

View File

@@ -25,7 +25,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Random;
@@ -34,7 +33,6 @@ import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
@@ -232,11 +230,12 @@ public class Snark
private byte[] id;
private final byte[] infoHash;
private String additionalTrackerURL;
private final I2PSnarkUtil _util;
protected final I2PSnarkUtil _util;
private final Log _log;
private final PeerCoordinatorSet _peerCoordinatorSet;
private String trackerProblems;
private int trackerSeenPeers;
private volatile String trackerProblems;
private volatile int trackerSeenPeers;
private volatile boolean _autoStoppable;
/** from main() via parseArguments() single torrent */
@@ -526,18 +525,17 @@ public class Snark
if (_peerCoordinatorSet != null) {
// multitorrent
_peerCoordinatorSet.add(coordinator);
if (acceptor != null) {
acceptor.startAccepting(_peerCoordinatorSet, serversocket);
} else {
// error
}
} else {
// single torrent
acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator));
acceptor = new ConnectionAcceptor(_util, new PeerAcceptor(coordinator));
}
// TODO pass saved closest DHT nodes to the tracker? or direct to the coordinator?
trackerclient = new TrackerClient(_util, meta, additionalTrackerURL, coordinator, this);
}
// ensure acceptor is running when in multitorrent
if (_peerCoordinatorSet != null && acceptor != null) {
acceptor.startAccepting();
}
stopped = false;
if (coordinator.halted()) {
@@ -761,7 +759,7 @@ public class Snark
PeerCoordinator coord = coordinator;
if (coord != null)
return coord.peerList();
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
/**
@@ -905,6 +903,16 @@ public class Snark
return additionalTrackerURL;
}
/**
* @since 0.9.9
*/
public boolean isAutoStoppable() { return _autoStoppable; }
/**
* @since 0.9.9
*/
public void setAutoStoppable(boolean yes) { _autoStoppable = yes; }
/**
* Sets debug, ip and torrent variables then creates a Snark
* instance. Calls usage(), which terminates the program, if

View File

@@ -14,7 +14,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -35,7 +34,6 @@ import net.i2p.util.Log;
import net.i2p.util.OrderedProperties;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
@@ -114,7 +112,7 @@ public class SnarkManager implements CompleteListener {
* "name", "announceURL=websiteURL" pairs
* '=' in announceURL must be escaped as &#44;
*/
public static final String DEFAULT_TRACKERS[] = {
private static final String DEFAULT_TRACKERS[] = {
// "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
// , "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
// , "Gaytorrents", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php=http://gaytorrents.i2p/"
@@ -128,9 +126,20 @@ public class SnarkManager implements CompleteListener {
,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
,"Diftracker", "http://diftracker.i2p/announce.php=http://diftracker.i2p/"
// , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
};
public static final Set<String> DEFAULT_TRACKER_ANNOUNCES;
static {
Set<String> ann = new HashSet();
for (int i = 1; i < DEFAULT_TRACKERS.length; i += 2) {
String urls[] = DEFAULT_TRACKERS[i].split("=", 2);
ann.add(urls[0]);
}
DEFAULT_TRACKER_ANNOUNCES = Collections.unmodifiableSet(ann);
}
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
public static final String PROP_TRACKERS = "i2psnark.trackers";
@@ -148,20 +157,20 @@ public class SnarkManager implements CompleteListener {
* @since 0.9.6
*/
public SnarkManager(I2PAppContext ctx, String ctxPath, String ctxName) {
_snarks = new ConcurrentHashMap();
_magnets = new ConcurrentHashSet();
_snarks = new ConcurrentHashMap<String, Snark>();
_magnets = new ConcurrentHashSet<String>();
_addSnarkLock = new Object();
_context = ctx;
_contextPath = ctxPath;
_contextName = ctxName;
_log = _context.logManager().getLog(SnarkManager.class);
_messages = new LinkedBlockingQueue();
_messages = new LinkedBlockingQueue<String>();
_util = new I2PSnarkUtil(_context, ctxName);
String cfile = ctxName + CONFIG_FILE_SUFFIX;
_configFile = new File(cfile);
if (!_configFile.isAbsolute())
_configFile = new File(_context.getConfigDir(), cfile);
_trackerMap = new ConcurrentHashMap(4);
_trackerMap = new ConcurrentHashMap<String, Tracker>(4);
loadConfig(null);
}
@@ -171,7 +180,7 @@ public class SnarkManager implements CompleteListener {
public void start() {
_running = true;
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util);
_connectionAcceptor = new ConnectionAcceptor(_util, _peerCoordinatorSet);
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
_monitor.start();
// only if default instance
@@ -180,7 +189,7 @@ public class SnarkManager implements CompleteListener {
_context.simpleScheduler().addEvent(new Register(), 4*60*1000);
// Not required, Jetty has a shutdown hook
//_context.addShutdownTask(new SnarkManagerShutdown());
_idleChecker = new IdleChecker(_util, _peerCoordinatorSet);
_idleChecker = new IdleChecker(this, _peerCoordinatorSet);
_idleChecker.schedule(5*60*1000);
}
@@ -193,6 +202,7 @@ public class SnarkManager implements CompleteListener {
if (_umgr != null) {
_uhandler = new UpdateHandler(_context, _umgr, SnarkManager.this);
_umgr.register(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT, 10);
_umgr.register(_uhandler, UpdateType.ROUTER_SIGNED_SU3, UpdateMethod.TORRENT, 10);
_log.warn("Registering with update manager");
} else {
_log.warn("No update manager to register with");
@@ -210,6 +220,7 @@ public class SnarkManager implements CompleteListener {
if (_umgr != null && _uhandler != null) {
//_uhandler.shutdown();
_umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT);
_umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED_SU3, UpdateMethod.TORRENT);
}
_running = false;
_monitor.interrupt();
@@ -238,8 +249,8 @@ public class SnarkManager implements CompleteListener {
/** newest last */
public List<String> getMessages() {
if (_messages.isEmpty())
return Collections.EMPTY_LIST;
return new ArrayList(_messages);
return Collections.emptyList();
return new ArrayList<String>(_messages);
}
/** @since 0.9 */
@@ -424,7 +435,7 @@ public class SnarkManager implements CompleteListener {
String i2cpHost = _config.getProperty(PROP_I2CP_HOST);
int i2cpPort = getInt(PROP_I2CP_PORT, 7654);
String opts = _config.getProperty(PROP_I2CP_OPTS);
Map i2cpOpts = new HashMap();
Map<String, String> i2cpOpts = new HashMap<String, String>();
if (opts != null) {
StringTokenizer tok = new StringTokenizer(opts, " ");
while (tok.hasMoreTokens()) {
@@ -529,7 +540,7 @@ public class SnarkManager implements CompleteListener {
_util.setStartupDelay(minutes);
changed = true;
_config.setProperty(PROP_STARTUP_DELAY, Integer.toString(minutes));
addMessage(_("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * 60 * 1000)));
addMessage(_("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * (60L * 1000))));
}
}
@@ -593,7 +604,7 @@ public class SnarkManager implements CompleteListener {
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
}
Map<String, String> opts = new HashMap();
Map<String, String> opts = new HashMap<String, String>();
if (i2cpOpts == null) i2cpOpts = "";
StringTokenizer tok = new StringTokenizer(i2cpOpts, " \t\n");
while (tok.hasMoreTokens()) {
@@ -602,7 +613,7 @@ public class SnarkManager implements CompleteListener {
if (split > 0)
opts.put(pair.substring(0, split), pair.substring(split+1));
}
Map<String, String> oldOpts = new HashMap();
Map<String, String> oldOpts = new HashMap<String, String>();
String oldI2CPOpts = _config.getProperty(PROP_I2CP_OPTS);
if (oldI2CPOpts == null) oldI2CPOpts = "";
tok = new StringTokenizer(oldI2CPOpts, " \t\n");
@@ -735,7 +746,7 @@ public class SnarkManager implements CompleteListener {
*/
private List<String> getOpenTrackers() {
if (!_util.shouldUseOpenTrackers())
return Collections.EMPTY_LIST;
return Collections.emptyList();
return getListConfig(PROP_OPENTRACKERS, I2PSnarkUtil.DEFAULT_OPENTRACKERS);
}
@@ -752,7 +763,7 @@ public class SnarkManager implements CompleteListener {
* @since 0.9.1
*/
public void saveOpenTrackers(List<String> ot) {
String val = setListConfig(PROP_OPENTRACKERS, ot);
setListConfig(PROP_OPENTRACKERS, ot);
if (ot == null)
ot = Collections.singletonList(I2PSnarkUtil.DEFAULT_OPENTRACKERS);
_util.setOpenTrackers(ot);
@@ -780,7 +791,7 @@ public class SnarkManager implements CompleteListener {
if (val == null)
val = dflt;
if (val == null)
return Collections.EMPTY_LIST;
return Collections.emptyList();
return Arrays.asList(val.split(","));
}
@@ -831,7 +842,7 @@ public class SnarkManager implements CompleteListener {
* An unsynchronized copy.
*/
public Set<String> listTorrentFiles() {
return new HashSet(_snarks.keySet());
return new HashSet<String>(_snarks.keySet());
}
/**
@@ -902,7 +913,7 @@ public class SnarkManager implements CompleteListener {
filename = sfile.getCanonicalPath();
} catch (IOException ioe) {
_log.error("Unable to add the torrent " + filename, ioe);
addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe.getMessage());
addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe);
return;
}
File dataDir = getDataDir();
@@ -1016,7 +1027,8 @@ public class SnarkManager implements CompleteListener {
* @since 0.8.4
*/
public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) {
addMagnet(name, ih, trackerURL, updateStatus, shouldAutoStart(), this);
// updateStatus is true from UI, false from config file bulk add
addMagnet(name, ih, trackerURL, updateStatus, updateStatus, this);
}
/**
@@ -1383,7 +1395,7 @@ public class SnarkManager implements CompleteListener {
* @return failure message or null on success
*/
private String validateTorrent(MetaInfo info) {
List files = info.getFiles();
List<List<String>> files = info.getFiles();
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
return _("Too many files in \"{0}\" ({1}), deleting it!", info.getName(), files.size());
} else if ( (files == null) && (info.getName().endsWith(".torrent")) ) {
@@ -1399,7 +1411,7 @@ public class SnarkManager implements CompleteListener {
return _("Torrent \"{0}\" has no data, deleting it!", info.getName());
} else if (info.getTotalLength() > Storage.MAX_TOTAL_SIZE) {
System.out.println("torrent info: " + info.toString());
List lengths = info.getLengths();
List<Long> lengths = info.getLengths();
if (lengths != null)
for (int i = 0; i < lengths.size(); i++)
System.out.println("File " + i + " is " + lengths.get(i) + " long.");
@@ -1486,7 +1498,7 @@ public class SnarkManager implements CompleteListener {
private class DirMonitor implements Runnable {
public void run() {
// don't bother delaying if auto start is false
long delay = 60 * 1000 * getStartupDelayMinutes();
long delay = (60L * 1000) * getStartupDelayMinutes();
if (delay > 0 && shouldAutoStart()) {
addMessage(_("Adding torrents in {0}", DataHelper.formatDuration2(delay)));
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
@@ -1651,7 +1663,7 @@ public class SnarkManager implements CompleteListener {
*/
private void monitorTorrents(File dir) {
String fileNames[] = dir.list(TorrentFilenameFilter.instance());
List<String> foundNames = new ArrayList(0);
List<String> foundNames = new ArrayList<String>(0);
if (fileNames != null) {
for (int i = 0; i < fileNames.length; i++) {
try {
@@ -1666,8 +1678,8 @@ public class SnarkManager implements CompleteListener {
if (_log.shouldLog(Log.DEBUG))
_log.debug("DirMon found: " + DataHelper.toString(foundNames) + " existing: " + DataHelper.toString(existingNames));
// lets find new ones first...
for (int i = 0; i < foundNames.size(); i++) {
if (existingNames.contains(foundNames.get(i))) {
for (String name : foundNames) {
if (existingNames.contains(name)) {
// already known. noop
} else {
if (shouldAutoStart() && !_util.connect())
@@ -1675,17 +1687,17 @@ public class SnarkManager implements CompleteListener {
try {
// Snark.fatal() throws a RuntimeException
// don't let one bad torrent kill the whole loop
addTorrent(foundNames.get(i), !shouldAutoStart());
addTorrent(name, !shouldAutoStart());
} catch (Exception e) {
addMessage(_("Unable to add {0}", foundNames.get(i)) + ": " + e);
addMessage(_("Error: Could not add the torrent {0}", name) + ": " + e);
_log.error("Unable to add the torrent " + name, e);
}
}
}
// Don't remove magnet torrents that don't have a torrent file yet
existingNames.removeAll(_magnets);
// now lets see which ones have been removed...
for (Iterator iter = existingNames.iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
for (String name : existingNames) {
if (foundNames.contains(name)) {
// known and still there. noop
} else {
@@ -1737,7 +1749,7 @@ public class SnarkManager implements CompleteListener {
* @since 0.9.1
*/
public List<Tracker> getSortedTrackers() {
List<Tracker> rv = new ArrayList(_trackerMap.values());
List<Tracker> rv = new ArrayList<Tracker>(_trackerMap.values());
Collections.sort(rv, new IgnoreCaseComparator());
return rv;
}
@@ -1863,6 +1875,14 @@ public class SnarkManager implements CompleteListener {
private final Snark snark;
public ThreadedStarter(Snark s) { snark = s; }
public void run() {
try {
run2();
} catch (Exception e) {
_log.error("Error starting", e);
}
}
private void run2() {
if (snark != null) {
if (snark.isStopped())
snark.startTorrent();

View File

@@ -28,6 +28,7 @@ import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -50,17 +51,7 @@ import net.i2p.util.SystemVersion;
public class Storage
{
private final MetaInfo metainfo;
private long[] lengths;
private RandomAccessFile[] rafs;
private String[] names;
private Object[] RAFlock; // lock on RAF access
private long[] RAFtime; // when was RAF last accessed, or 0 if closed
private File[] RAFfile; // File to make it easier to reopen
/** priorities by file; default 0; may be null. @since 0.8.1 */
private int[] priorities;
/** is the file empty and sparse? */
private boolean[] isSparse;
private final List<TorrentFile> _torrentFiles;
private final StorageListener listener;
private final I2PSnarkUtil _util;
private final Log _log;
@@ -78,13 +69,13 @@ public class Storage
/** The default piece size. */
private static final int DEFAULT_PIECE_SIZE = 256*1024;
/** note that we start reducing max number of peer connections above 1MB */
public static final int MAX_PIECE_SIZE = 2*1024*1024;
/** bigger than this will be rejected */
public static final int MAX_PIECE_SIZE = 4*1024*1024;
/** The maximum number of pieces in a torrent. */
public static final int MAX_PIECES = 10*1024;
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
private static final Map<String, String> _filterNameCache = new ConcurrentHashMap();
private static final Map<String, String> _filterNameCache = new ConcurrentHashMap<String, String>();
private static final boolean _isWindows = SystemVersion.isWindows();
@@ -108,6 +99,9 @@ public class Storage
piece_size = metainfo.getPieceLength(0);
pieces = needed;
total_length = metainfo.getTotalLength();
List<List<String>> files = metainfo.getFiles();
int sz = files != null ? files.size() : 1;
_torrentFiles = new ArrayList<TorrentFile>(sz);
}
/**
@@ -130,13 +124,13 @@ public class Storage
_log = util.getContext().logManager().getLog(Storage.class);
this.listener = listener;
// Create names, rafs and lengths arrays.
getFiles(baseFile);
_torrentFiles = getFiles(baseFile);
long total = 0;
ArrayList<Long> lengthsList = new ArrayList();
for (int i = 0; i < lengths.length; i++)
ArrayList<Long> lengthsList = new ArrayList<Long>();
for (TorrentFile tf : _torrentFiles)
{
long length = lengths[i];
long length = tf.length;
total += length;
lengthsList.add(Long.valueOf(length));
}
@@ -166,11 +160,11 @@ public class Storage
bitfield = new BitField(pieces);
needed = 0;
List<List<String>> files = new ArrayList();
for (int i = 0; i < names.length; i++)
List<List<String>> files = new ArrayList<List<String>>();
for (TorrentFile tf : _torrentFiles)
{
List<String> file = new ArrayList();
StringTokenizer st = new StringTokenizer(names[i], File.separator);
List<String> file = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(tf.name, File.separator);
while (st.hasMoreTokens())
{
String part = st.nextToken();
@@ -220,42 +214,29 @@ public class Storage
return piece_hashes;
}
private void getFiles(File base) throws IOException
private List<TorrentFile> getFiles(File base) throws IOException
{
if (base.getAbsolutePath().equals("/"))
throw new IOException("Don't seed root");
ArrayList files = new ArrayList();
List<File> files = new ArrayList<File>();
addFiles(files, base);
int size = files.size();
names = new String[size];
lengths = new long[size];
rafs = new RandomAccessFile[size];
RAFlock = new Object[size];
RAFtime = new long[size];
RAFfile = new File[size];
priorities = new int[size];
isSparse = new boolean[size];
List<TorrentFile> rv = new ArrayList<TorrentFile>(size);
int i = 0;
Iterator it = files.iterator();
while (it.hasNext())
{
File f = (File)it.next();
names[i] = f.getPath();
if (base.isDirectory() && names[i].startsWith(base.getPath()))
names[i] = names[i].substring(base.getPath().length() + 1);
lengths[i] = f.length();
RAFlock[i] = new Object();
RAFfile[i] = f;
i++;
}
for (File f : files) {
rv.add(new TorrentFile(base, f));
}
// Sort to prevent exposing OS type, and to make it more likely
// the same torrent created twice will have the same infohash.
Collections.sort(rv);
return rv;
}
/**
* @throws IOException if too many total files
*/
private void addFiles(List l, File f) throws IOException {
private void addFiles(List<File> l, File f) throws IOException {
if (!f.isDirectory()) {
if (l.size() >= SnarkManager.MAX_FILES_PER_TORRENT)
throw new IOException("Too many files, limit is " + SnarkManager.MAX_FILES_PER_TORRENT + ", zip them?");
@@ -330,8 +311,8 @@ public class Storage
*/
public long remaining(String file) {
long bytes = 0;
for (int i = 0; i < rafs.length; i++) {
File f = RAFfile[i];
for (TorrentFile tf : _torrentFiles) {
File f = tf.RAFfile;
// use canonical in case snark dir or sub dirs are symlinked
String canonical = null;
if (f != null) {
@@ -346,11 +327,11 @@ public class Storage
return 0;
int psz = piece_size;
long start = bytes;
long end = start + lengths[i];
long end = start + tf.length;
int pc = (int) (bytes / psz);
long rv = 0;
if (!bitfield.get(pc))
rv = Math.min(psz - (start % psz), lengths[i]);
rv = Math.min(psz - (start % psz), tf.length);
for (int j = pc + 1; (((long)j) * psz) < end && j < pieces; j++) {
if (!bitfield.get(j)) {
if (((long)(j+1))*psz < end)
@@ -361,7 +342,7 @@ public class Storage
}
return rv;
}
bytes += lengths[i];
bytes += tf.length;
}
return -1;
}
@@ -371,16 +352,16 @@ public class Storage
* @since 0.8.1
*/
public int getPriority(String file) {
if (complete() || metainfo.getFiles() == null || priorities == null)
if (complete() || metainfo.getFiles() == null)
return 0;
for (int i = 0; i < rafs.length; i++) {
File f = RAFfile[i];
for (TorrentFile tf : _torrentFiles) {
File f = tf.RAFfile;
// use canonical in case snark dir or sub dirs are symlinked
if (f != null) {
try {
String canonical = f.getCanonicalPath();
if (canonical.equals(file))
return priorities[i];
return tf.priority;
} catch (IOException ioe) {}
}
}
@@ -395,16 +376,16 @@ public class Storage
* @since 0.8.1
*/
public void setPriority(String file, int pri) {
if (complete() || metainfo.getFiles() == null || priorities == null)
if (complete() || metainfo.getFiles() == null)
return;
for (int i = 0; i < rafs.length; i++) {
File f = RAFfile[i];
for (TorrentFile tf : _torrentFiles) {
File f = tf.RAFfile;
// use canonical in case snark dir or sub dirs are symlinked
if (f != null) {
try {
String canonical = f.getCanonicalPath();
if (canonical.equals(file)) {
priorities[i] = pri;
tf.priority = pri;
return;
}
} catch (IOException ioe) {}
@@ -418,6 +399,15 @@ public class Storage
* @since 0.8.1
*/
public int[] getFilePriorities() {
if (complete())
return null;
int sz = _torrentFiles.size();
if (sz <= 1)
return null;
int[] priorities = new int[sz];
for (int i = 0; i < sz; i++) {
priorities[i] = _torrentFiles.get(i).priority;
}
return priorities;
}
@@ -428,7 +418,18 @@ public class Storage
* @since 0.8.1
*/
void setFilePriorities(int[] p) {
priorities = p;
if (p == null) {
for (TorrentFile tf : _torrentFiles) {
tf.priority = 0;
}
} else {
int sz = _torrentFiles.size();
if (p.length != sz)
throw new IllegalArgumentException();
for (int i = 0; i < sz; i++) {
_torrentFiles.get(i).priority = p[i];
}
}
}
/**
@@ -441,22 +442,23 @@ public class Storage
* @since 0.8.1
*/
public int[] getPiecePriorities() {
if (complete() || metainfo.getFiles() == null || priorities == null)
if (complete() || metainfo.getFiles() == null)
return null;
int[] rv = new int[metainfo.getPieces()];
int file = 0;
long pcEnd = -1;
long fileEnd = lengths[0] - 1;
long fileEnd = _torrentFiles.get(0).length - 1;
int psz = piece_size;
for (int i = 0; i < rv.length; i++) {
pcEnd += psz;
int pri = priorities[file];
while (fileEnd <= pcEnd && file < lengths.length - 1) {
int pri = _torrentFiles.get(file).priority;
while (fileEnd <= pcEnd && file < _torrentFiles.size() - 1) {
file++;
TorrentFile tf = _torrentFiles.get(file);
long oldFileEnd = fileEnd;
fileEnd += lengths[file];
if (priorities[file] > pri && oldFileEnd < pcEnd)
pri = priorities[file];
fileEnd += tf.length;
if (tf.priority > pri && oldFileEnd < pcEnd)
pri = tf.priority;
}
rv[i] = pri;
}
@@ -486,13 +488,18 @@ public class Storage
/**
* Creates (and/or checks) all files from the metainfo file list.
* Only call this once, and only after the constructor with the metainfo.
*/
public void check(String rootDir) throws IOException
{
check(rootDir, 0, null);
}
/** use a saved bitfield and timestamp from a config file */
/**
* Creates (and/or checks) all files from the metainfo file list.
* Use a saved bitfield and timestamp from a config file.
* Only call this once, and only after the constructor with the metainfo.
*/
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
{
File base;
@@ -503,6 +510,8 @@ public class Storage
base = new SecureFile(rootDir, filterName(metainfo.getName()));
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
if (!_torrentFiles.isEmpty())
throw new IllegalStateException();
List<List<String>> files = metainfo.getFiles();
if (files == null)
{
@@ -512,22 +521,14 @@ public class Storage
if (!base.createNewFile() && !base.exists())
throw new IOException("Could not create file " + base);
lengths = new long[1];
rafs = new RandomAccessFile[1];
names = new String[1];
RAFlock = new Object[1];
RAFtime = new long[1];
RAFfile = new File[1];
isSparse = new boolean[1];
lengths[0] = metainfo.getTotalLength();
RAFlock[0] = new Object();
RAFfile[0] = base;
_torrentFiles.add(new TorrentFile(base, base, metainfo.getTotalLength()));
if (useSavedBitField) {
long lm = base.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
else if (base.length() != metainfo.getTotalLength())
useSavedBitField = false;
}
names[0] = base.getName();
}
else
{
@@ -540,23 +541,16 @@ public class Storage
List<Long> ls = metainfo.getLengths();
int size = files.size();
long total = 0;
lengths = new long[size];
rafs = new RandomAccessFile[size];
names = new String[size];
RAFlock = new Object[size];
RAFtime = new long[size];
RAFfile = new File[size];
isSparse = new boolean[size];
for (int i = 0; i < size; i++)
{
List<String> path = files.get(i);
File f = createFileFromNames(base, path, areFilesPublic);
// dup file name check after filtering
for (int j = 0; j < i; j++) {
if (f.equals(RAFfile[j])) {
if (f.equals(_torrentFiles.get(j).RAFfile)) {
// Rename and start the check over again
// Copy path since metainfo list is unmodifiable
path = new ArrayList(path);
path = new ArrayList<String>(path);
int last = path.size() - 1;
String lastPath = path.get(last);
int dot = lastPath.lastIndexOf('.');
@@ -570,16 +564,16 @@ public class Storage
j = 0;
}
}
lengths[i] = ls.get(i).longValue();
RAFlock[i] = new Object();
RAFfile[i] = f;
total += lengths[i];
long len = ls.get(i).longValue();
_torrentFiles.add(new TorrentFile(base, f, len));
total += len;
if (useSavedBitField) {
long lm = f.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
else if (f.length() != len)
useSavedBitField = false;
}
names[i] = f.getName();
}
// Sanity check for metainfo file.
@@ -597,6 +591,8 @@ public class Storage
} else {
// the following sets the needed variable
changed = true;
if (_log.shouldLog(Log.INFO))
_log.info("Forcing check");
checkCreateFiles(false);
}
if (complete()) {
@@ -604,8 +600,6 @@ public class Storage
_log.info("Torrent is complete");
} else {
// fixme saved priorities
if (files != null)
priorities = new int[files.size()];
if (_log.shouldLog(Log.INFO))
_log.info("Still need " + needed + " out of " + metainfo.getPieces() + " pieces");
}
@@ -620,11 +614,11 @@ public class Storage
*/
public void reopen(String rootDir) throws IOException
{
if (RAFfile == null)
if (_torrentFiles.isEmpty())
throw new IOException("Storage not checked yet");
for (int i = 0; i < RAFfile.length; i++) {
if (!RAFfile[i].exists())
throw new IOException("File does not exist: " + RAFfile[i]);
for (TorrentFile tf : _torrentFiles) {
if (!tf.RAFfile.exists())
throw new IOException("File does not exist: " + tf);
}
}
@@ -778,10 +772,10 @@ public class Storage
// Make sure all files are available and of correct length
// The files should all exist as they have been created with zero length by createFilesFromNames()
for (int i = 0; i < rafs.length; i++)
for (TorrentFile tf : _torrentFiles)
{
long length = RAFfile[i].length();
if(RAFfile[i].exists() && length == lengths[i])
long length = tf.RAFfile.length();
if(tf.RAFfile.exists() && length == tf.length)
{
if (listener != null)
listener.storageAllocated(this, length);
@@ -789,27 +783,27 @@ public class Storage
}
else if (length == 0) {
changed = true;
synchronized(RAFlock[i]) {
allocateFile(i);
synchronized(tf) {
allocateFile(tf);
// close as we go so we don't run out of file descriptors
try {
closeRAF(i);
tf.closeRAF();
} catch (IOException ioe) {}
}
} else {
String msg = "File '" + names[i] + "' exists, but has wrong length (expected " +
lengths[i] + " but found " + length + ") - repairing corruption";
String msg = "File '" + tf.name + "' exists, but has wrong length (expected " +
tf.length + " but found " + length + ") - repairing corruption";
if (listener != null)
listener.addMessage(msg);
_log.error(msg);
changed = true;
resume = true;
_probablyComplete = false; // to force RW
synchronized(RAFlock[i]) {
checkRAF(i);
rafs[i].setLength(lengths[i]);
synchronized(tf) {
RandomAccessFile raf = tf.checkRAF();
raf.setLength(tf.length);
try {
closeRAF(i);
tf.closeRAF();
} catch (IOException ioe) {}
}
}
@@ -820,7 +814,7 @@ public class Storage
{
byte[] piece = new byte[piece_size];
int file = 0;
long fileEnd = lengths[0];
long fileEnd = _torrentFiles.get(0).length;
long pieceEnd = 0;
for (int i = 0; i < pieces; i++)
{
@@ -829,14 +823,15 @@ public class Storage
// close as we go so we don't run out of file descriptors
pieceEnd += length;
while (fileEnd <= pieceEnd) {
synchronized(RAFlock[file]) {
TorrentFile tf = _torrentFiles.get(file);
synchronized(tf) {
try {
closeRAF(file);
tf.closeRAF();
} catch (IOException ioe) {}
}
if (++file >= rafs.length)
if (++file >= _torrentFiles.size())
break;
fileEnd += lengths[file];
fileEnd += _torrentFiles.get(file).length;
}
if (correctHash)
{
@@ -882,59 +877,17 @@ public class Storage
* Sets isSparse[nr] = true. balloonFile(nr) should be called later to
* defrag the file.
*
* This calls openRAF(); caller must synchronize and call closeRAF().
* This calls OpenRAF(); caller must synchronize and call closeRAF().
*/
private void allocateFile(int nr) throws IOException
private void allocateFile(TorrentFile tf) throws IOException
{
// caller synchronized
openRAF(nr, false); // RW
long remaining = lengths[nr];
if (listener != null)
listener.storageCreateFile(this, names[nr], remaining);
rafs[nr].setLength(remaining);
// don't bother ballooning later on Windows since there is no sparse file support
// until JDK7 using the JSR-203 interface.
// RAF seeks/writes do not create sparse files.
// Windows will zero-fill up to the point of the write, which
// will make the file fairly unfragmented, on average, at least until
// near the end where it will get exponentially more fragmented.
if (!_isWindows)
isSparse[nr] = true;
// caller will close rafs[nr]
if (listener != null)
listener.storageAllocated(this, lengths[nr]);
}
/**
* This "balloons" the file with zeros to eliminate disk fragmentation.,
* Overwrites the entire file with zeros. Sets isSparse[nr] = false.
*
* Caller must synchronize and call checkRAF() or openRAF().
* @since 0.9.1
*/
private void balloonFile(int nr) throws IOException
{
if (_log.shouldLog(Log.INFO))
_log.info("Ballooning " + nr + ": " + RAFfile[nr]);
long remaining = lengths[nr];
final int ZEROBLOCKSIZE = (int) Math.min(remaining, 32*1024);
byte[] zeros = new byte[ZEROBLOCKSIZE];
rafs[nr].seek(0);
// don't bother setting flag for small files
if (remaining > 20*1024*1024)
_allocateCount.incrementAndGet();
try {
while (remaining > 0) {
int size = (int) Math.min(remaining, ZEROBLOCKSIZE);
rafs[nr].write(zeros, 0, size);
remaining -= size;
}
} finally {
remaining = lengths[nr];
if (remaining > 20*1024*1024)
_allocateCount.decrementAndGet();
tf.allocateFile();
if (listener != null) {
listener.storageCreateFile(this, tf.name, tf.length);
listener.storageAllocated(this, tf.length);
}
isSparse[nr] = false;
// caller will close rafs[nr]
}
@@ -944,18 +897,14 @@ public class Storage
*/
public void close() throws IOException
{
if (rafs == null) return;
for (int i = 0; i < rafs.length; i++)
for (TorrentFile tf : _torrentFiles)
{
// if we had an IOE in check(), the RAFlock may be null
if (RAFlock[i] == null)
continue;
try {
synchronized(RAFlock[i]) {
closeRAF(i);
synchronized(tf) {
tf.closeRAF();
}
} catch (IOException ioe) {
_log.error("Error closing " + RAFfile[i], ioe);
_log.error("Error closing " + tf, ioe);
// gobble gobble
}
}
@@ -1020,40 +969,50 @@ public class Storage
// Early typecast, avoid possibly overflowing a temp integer
long start = (long) piece * (long) piece_size;
int i = 0;
long raflen = lengths[i];
long raflen = _torrentFiles.get(i).length;
while (start > raflen) {
i++;
start -= raflen;
raflen = lengths[i];
raflen = _torrentFiles.get(i).length;
}
int written = 0;
int off = 0;
int length = metainfo.getPieceLength(piece);
while (written < length) {
int need = length - written;
int len = (start + need < raflen) ? need : (int)(raflen - start);
synchronized(RAFlock[i]) {
checkRAF(i);
if (isSparse[i]) {
// If the file is a newly created sparse file,
// AND we aren't skipping it, balloon it with all
// zeros to un-sparse it by allocating the space.
// Obviously this could take a while.
// Once we have written to it, it isn't empty/sparse any more.
if (priorities == null || priorities[i] >= 0)
balloonFile(i);
else
isSparse[i] = false;
TorrentFile tf = _torrentFiles.get(i);
synchronized(tf) {
try {
RandomAccessFile raf = tf.checkRAF();
if (tf.isSparse) {
// If the file is a newly created sparse file,
// AND we aren't skipping it, balloon it with all
// zeros to un-sparse it by allocating the space.
// Obviously this could take a while.
// Once we have written to it, it isn't empty/sparse any more.
if (tf.priority >= 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Ballooning " + tf);
tf.balloonFile();
} else {
tf.isSparse = false;
}
}
raf.seek(start);
//rafs[i].write(bs, off + written, len);
pp.write(raf, written, len);
} catch (IOException ioe) {
// get the file name in the logs
IOException ioe2 = new IOException("Error writing " + tf.RAFfile.getAbsolutePath());
ioe2.initCause(ioe);
throw ioe2;
}
rafs[i].seek(start);
//rafs[i].write(bs, off + written, len);
pp.write(rafs[i], off + written, len);
}
written += len;
if (need - len > 0) {
i++;
raflen = lengths[i];
raflen = _torrentFiles.get(i).length;
start = 0;
}
}
@@ -1130,12 +1089,12 @@ public class Storage
long start = ((long) piece * (long) piece_size) + off;
int i = 0;
long raflen = lengths[i];
long raflen = _torrentFiles.get(i).length;
while (start > raflen)
{
i++;
start -= raflen;
raflen = lengths[i];
raflen = _torrentFiles.get(i).length;
}
int read = 0;
@@ -1143,17 +1102,24 @@ public class Storage
{
int need = length - read;
int len = (start + need < raflen) ? need : (int)(raflen - start);
synchronized(RAFlock[i])
{
checkRAF(i);
rafs[i].seek(start);
rafs[i].readFully(bs, read, len);
}
TorrentFile tf = _torrentFiles.get(i);
synchronized(tf) {
try {
RandomAccessFile raf = tf.checkRAF();
raf.seek(start);
raf.readFully(bs, read, len);
} catch (IOException ioe) {
// get the file name in the logs
IOException ioe2 = new IOException("Error reading " + tf.RAFfile.getAbsolutePath());
ioe2.initCause(ioe);
throw ioe2;
}
}
read += len;
if (need - len > 0)
{
i++;
raflen = lengths[i];
raflen = _torrentFiles.get(i).length;
start = 0;
}
}
@@ -1161,58 +1127,191 @@ public class Storage
return length;
}
private static final long RAFCloseDelay = 4*60*1000;
/**
* Close unused RAFs - call periodically
*/
private static final long RAFCloseDelay = 4*60*1000;
public void cleanRAFs() {
long cutoff = System.currentTimeMillis() - RAFCloseDelay;
for (int i = 0; i < RAFlock.length; i++) {
synchronized(RAFlock[i]) {
if (RAFtime[i] > 0 && RAFtime[i] < cutoff) {
try {
closeRAF(i);
} catch (IOException ioe) {}
}
for (TorrentFile tf : _torrentFiles) {
synchronized(tf) {
tf.closeRAF(cutoff);
}
}
}
/*
* For each of the following,
* caller must synchronize on RAFlock[i]
* ... except at the beginning if you're careful
*/
/**
* This must be called before using the RAF to ensure it is open
* A single file in a torrent.
* @since 0.9.9
*/
private void checkRAF(int i) throws IOException {
if (RAFtime[i] > 0) {
RAFtime[i] = System.currentTimeMillis();
return;
}
openRAF(i);
}
private class TorrentFile implements Comparable<TorrentFile> {
public final long length;
public final String name;
public final File RAFfile;
/**
* when was RAF last accessed, or 0 if closed
* locking: this
*/
private long RAFtime;
/**
* null when closed
* locking: this
*/
private RandomAccessFile raf;
/**
* is the file empty and sparse?
* locking: this
*/
public boolean isSparse;
/** priority by file; default 0 */
public volatile int priority;
private void openRAF(int i) throws IOException {
openRAF(i, _probablyComplete);
}
/**
* For new metainfo from files;
* use base == f for single-file torrent
*/
public TorrentFile(File base, File f) {
this(base, f, f.length());
}
private void openRAF(int i, boolean readonly) throws IOException {
rafs[i] = new RandomAccessFile(RAFfile[i], (readonly || !RAFfile[i].canWrite()) ? "r" : "rw");
RAFtime[i] = System.currentTimeMillis();
}
/**
* For existing metainfo with specified file length;
* use base == f for single-file torrent
*/
public TorrentFile(File base, File f, long len) {
String n = f.getPath();
if (base.isDirectory() && n.startsWith(base.getPath()))
n = n.substring(base.getPath().length() + 1);
name = n;
length = len;
RAFfile = f;
}
/**
* Can be called even if not open
*/
private void closeRAF(int i) throws IOException {
RAFtime[i] = 0;
if (rafs[i] == null)
return;
rafs[i].close();
rafs[i] = null;
/*
* For each of the following,
* caller must synchronize on RAFlock[i]
* ... except at the beginning if you're careful
*/
/**
* This must be called before using the RAF to ensure it is open
* locking: this
*/
public synchronized RandomAccessFile checkRAF() throws IOException {
if (raf != null)
RAFtime = System.currentTimeMillis();
else
openRAF();
return raf;
}
/**
* locking: this
*/
private synchronized void openRAF() throws IOException {
openRAF(_probablyComplete);
}
/**
* locking: this
*/
private synchronized void openRAF(boolean readonly) throws IOException {
raf = new RandomAccessFile(RAFfile, (readonly || !RAFfile.canWrite()) ? "r" : "rw");
RAFtime = System.currentTimeMillis();
}
/**
* Close if last used time older than cutoff.
* locking: this
*/
public synchronized void closeRAF(long cutoff) {
if (RAFtime > 0 && RAFtime < cutoff) {
try {
closeRAF();
} catch (IOException ioe) {}
}
}
/**
* Can be called even if not open
* locking: this
*/
public synchronized void closeRAF() throws IOException {
RAFtime = 0;
if (raf == null)
return;
raf.close();
raf = null;
}
/**
* This creates a (presumably) sparse file so that reads won't fail with IOE.
* Sets isSparse[nr] = true. balloonFile(nr) should be called later to
* defrag the file.
*
* This calls openRAF(); caller must synchronize and call closeRAF().
*/
public synchronized void allocateFile() throws IOException {
// caller synchronized
openRAF(false); // RW
raf.setLength(length);
// don't bother ballooning later on Windows since there is no sparse file support
// until JDK7 using the JSR-203 interface.
// RAF seeks/writes do not create sparse files.
// Windows will zero-fill up to the point of the write, which
// will make the file fairly unfragmented, on average, at least until
// near the end where it will get exponentially more fragmented.
if (!_isWindows)
isSparse = true;
}
/**
* This "balloons" the file with zeros to eliminate disk fragmentation.,
* Overwrites the entire file with zeros. Sets isSparse[nr] = false.
*
* Caller must synchronize and call checkRAF() or openRAF().
* @since 0.9.1
*/
public synchronized void balloonFile() throws IOException
{
long remaining = length;
final int ZEROBLOCKSIZE = (int) Math.min(remaining, 32*1024);
byte[] zeros = new byte[ZEROBLOCKSIZE];
raf.seek(0);
// don't bother setting flag for small files
if (remaining > 20*1024*1024)
_allocateCount.incrementAndGet();
try {
while (remaining > 0) {
int size = (int) Math.min(remaining, ZEROBLOCKSIZE);
raf.write(zeros, 0, size);
remaining -= size;
}
} finally {
remaining = length;
if (remaining > 20*1024*1024)
_allocateCount.decrementAndGet();
}
isSparse = false;
}
public int compareTo(TorrentFile tf) {
return name.compareTo(tf.name);
}
@Override
public int hashCode() { return RAFfile.getAbsolutePath().hashCode(); }
@Override
public boolean equals(Object o) {
return (o instanceof TorrentFile) &&
RAFfile.getAbsolutePath().equals(((TorrentFile)o).RAFfile.getAbsolutePath());
}
@Override
public String toString() { return name; }
}
/**

View File

@@ -21,8 +21,6 @@
package org.klomp.snark;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
@@ -38,7 +36,6 @@ import java.util.Locale;
import java.util.Random;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.util.ConvertToHash;
@@ -86,6 +83,7 @@ public class TrackerClient implements Runnable {
private final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails
private final static long MIN_TRACKER_ANNOUNCE_INTERVAL = 15*60*1000;
private final static long MIN_DHT_ANNOUNCE_INTERVAL = 10*60*1000;
public static final int PORT = 6881;
private final I2PSnarkUtil _util;
private final MetaInfo meta;
@@ -113,6 +111,7 @@ public class TrackerClient implements Runnable {
private long lastDHTAnnounce;
private final List<TCTracker> trackers;
private final List<TCTracker> backupTrackers;
private long _startedOn;
/**
* Call start() to start it.
@@ -134,11 +133,11 @@ public class TrackerClient implements Runnable {
this.coordinator = coordinator;
this.snark = snark;
this.port = 6881; //(port == -1) ? 9 : port;
this.port = PORT; //(port == -1) ? 9 : port;
this.infoHash = urlencode(snark.getInfoHash());
this.peerID = urlencode(snark.getID());
this.trackers = new ArrayList(2);
this.backupTrackers = new ArrayList(2);
this.trackers = new ArrayList<TCTracker>(2);
this.backupTrackers = new ArrayList<TCTracker>(2);
}
public synchronized void start() {
@@ -272,7 +271,7 @@ public class TrackerClient implements Runnable {
primary = meta.getAnnounce();
else if (additionalTrackerURL != null)
primary = additionalTrackerURL;
Set<Hash> trackerHashes = new HashSet(8);
Set<Hash> trackerHashes = new HashSet<Hash>(8);
// primary tracker
if (primary != null) {
@@ -334,6 +333,7 @@ public class TrackerClient implements Runnable {
}
}
this.completed = coordinator.getLeft() == 0;
_startedOn = _util.getContext().clock().now();
}
/**
@@ -377,15 +377,24 @@ public class TrackerClient implements Runnable {
if (dht != null && (meta == null || !meta.isPrivate()))
dht.announce(snark.getInfoHash());
int oldSeenPeers = snark.getTrackerSeenPeers();
int maxSeenPeers = 0;
if (!trackers.isEmpty())
if (!trackers.isEmpty()) {
maxSeenPeers = getPeersFromTrackers(trackers);
// fast update for UI at startup
if (maxSeenPeers > oldSeenPeers)
snark.setTrackerSeenPeers(maxSeenPeers);
}
int p = getPeersFromPEX();
if (p > maxSeenPeers)
maxSeenPeers = p;
p = getPeersFromDHT();
if (p > maxSeenPeers)
if (p > maxSeenPeers) {
maxSeenPeers = p;
// fast update for UI at startup
if (maxSeenPeers > oldSeenPeers)
snark.setTrackerSeenPeers(maxSeenPeers);
}
// backup if DHT needs bootstrapping
if (trackers.isEmpty() && !backupTrackers.isEmpty() && dht != null && dht.size() < 16) {
p = getPeersFromTrackers(backupTrackers);
@@ -461,6 +470,9 @@ public class TrackerClient implements Runnable {
{
long uploaded = coordinator.getUploaded();
long downloaded = coordinator.getDownloaded();
long len = snark.getTotalLength();
if (len > 0 && downloaded > len)
downloaded = len;
left = coordinator.getLeft();
String event;
if (!tr.started) {
@@ -482,12 +494,31 @@ public class TrackerClient implements Runnable {
consecutiveFails = 0;
runStarted = true;
tr.started = true;
Set<Peer> peers = info.getPeers();
tr.seenPeers = info.getPeerCount();
if (snark.getTrackerSeenPeers() < tr.seenPeers) // update rising number quickly
snark.setTrackerSeenPeers(tr.seenPeers);
// auto stop
// These are very high thresholds for now, not configurable,
// just for update torrent
if (completed &&
tr.isPrimary &&
snark.isAutoStoppable() &&
!snark.isChecking() &&
info.getSeedCount() > 100 &&
coordinator.getPeerCount() <= 0 &&
_util.getContext().clock().now() > _startedOn + 2*60*60*1000 &&
snark.getTotalLength() > 0 &&
uploaded >= 2 * snark.getTotalLength()) {
if (_log.shouldLog(Log.WARN))
_log.warn("Auto stopping " + snark.getBaseName());
snark.setAutoStoppable(false);
snark.stopTorrent();
return tr.seenPeers;
}
Set<Peer> peers = info.getPeers();
// pass everybody over to our tracker
DHT dht = _util.getDHT();
if (dht != null) {
@@ -499,7 +530,7 @@ public class TrackerClient implements Runnable {
if (coordinator.needOutboundPeers()) {
// we only want to talk to new people if we need things
// from them (duh)
List<Peer> ordered = new ArrayList(peers);
List<Peer> ordered = new ArrayList<Peer>(peers);
Random r = _util.getContext().random();
Collections.shuffle(ordered, r);
Iterator<Peer> it = ordered.iterator();
@@ -564,7 +595,7 @@ public class TrackerClient implements Runnable {
if (!pids.isEmpty()) {
if (_log.shouldLog(Log.INFO))
_log.info("Got " + pids.size() + " from PEX");
List<Peer> peers = new ArrayList(pids.size());
List<Peer> peers = new ArrayList<Peer>(pids.size());
for (PeerID pID : pids) {
peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo()));
}
@@ -596,33 +627,29 @@ public class TrackerClient implements Runnable {
// FIXME this needs to be in its own thread
int rv = 0;
DHT dht = _util.getDHT();
if (dht != null && (meta == null || !meta.isPrivate()) && (!stop) &&
_util.getContext().clock().now() > lastDHTAnnounce + MIN_DHT_ANNOUNCE_INTERVAL) {
if (dht != null &&
(meta == null || !meta.isPrivate()) &&
(!stop) &&
(meta == null || _util.getContext().clock().now() > lastDHTAnnounce + MIN_DHT_ANNOUNCE_INTERVAL)) {
int numwant;
if (!coordinator.needOutboundPeers())
numwant = 1;
else
numwant = _util.getMaxConnections();
Collection<Hash> hashes = dht.getPeers(snark.getInfoHash(), numwant, 2*60*1000);
Collection<Hash> hashes = dht.getPeersAndAnnounce(snark.getInfoHash(), numwant, 5*60*1000, 1, 3*60*1000);
if (!hashes.isEmpty()) {
runStarted = true;
lastDHTAnnounce = _util.getContext().clock().now();
rv = hashes.size();
} else {
lastDHTAnnounce = 0;
}
if (_log.shouldLog(Log.INFO))
_log.info("Got " + hashes + " from DHT");
// announce ourselves while the token is still good
// FIXME this needs to be in its own thread
if (!stop) {
// announce only to the 1 closest
int good = dht.announce(snark.getInfoHash(), 1, 5*60*1000);
if (_log.shouldLog(Log.INFO))
_log.info("Sent " + good + " good announces to DHT");
}
// now try these peers
if ((!stop) && !hashes.isEmpty()) {
List<Peer> peers = new ArrayList(hashes.size());
List<Peer> peers = new ArrayList<Peer>(hashes.size());
for (Hash h : hashes) {
try {
PeerID pID = new PeerID(h.getData(), _util);
@@ -689,6 +716,9 @@ public class TrackerClient implements Runnable {
_log.debug("Running unannounce " + _threadName + " to " + tr.announce);
long uploaded = coordinator.getUploaded();
long downloaded = coordinator.getDownloaded();
long len = snark.getTotalLength();
if (len > 0 && downloaded > len)
downloaded = len;
long left = coordinator.getLeft();
try
{

View File

@@ -59,7 +59,7 @@ class TrackerInfo
this(be.bdecodeMap().getMap(), my_id, infohash, metainfo, util);
}
private TrackerInfo(Map m, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
private TrackerInfo(Map<String, BEValue> m, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
throws IOException
{
BEValue reason = (BEValue)m.get("failure reason");
@@ -80,7 +80,7 @@ class TrackerInfo
BEValue bePeers = (BEValue)m.get("peers");
if (bePeers == null) {
peers = Collections.EMPTY_SET;
peers = Collections.emptySet();
} else {
Set<Peer> p;
try {
@@ -127,7 +127,7 @@ class TrackerInfo
private static Set<Peer> getPeers(List<BEValue> l, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
throws IOException
{
Set<Peer> peers = new HashSet(l.size());
Set<Peer> peers = new HashSet<Peer>(l.size());
for (BEValue bev : l) {
PeerID peerID;
@@ -161,7 +161,7 @@ class TrackerInfo
throws IOException
{
int count = l.length / HASH_LENGTH;
Set<Peer> peers = new HashSet(count);
Set<Peer> peers = new HashSet<Peer>(count);
for (int i = 0; i < count; i++) {
PeerID peerID;
@@ -190,6 +190,12 @@ class TrackerInfo
return Math.max(pc, complete + incomplete - 1);
}
/** @since 0.9.9 */
public int getSeedCount()
{
return complete;
}
public String getFailureReason()
{
return failure_reason;

View File

@@ -42,10 +42,10 @@ class UpdateHandler implements Updater {
*/
public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources,
String id, String newVersion, long maxTime) {
if (type != UpdateType.ROUTER_SIGNED ||
if ((type != UpdateType.ROUTER_SIGNED && type != UpdateType.ROUTER_SIGNED_SU3) ||
method != UpdateMethod.TORRENT || updateSources.isEmpty())
return null;
UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, updateSources, newVersion);
UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, type, updateSources, newVersion);
_umgr.notifyProgress(update, "<b>" + _smgr.util().getString("Updating") + "</b>");
return update;
}

View File

@@ -6,11 +6,9 @@ import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.crypto.TrustedUpdate;
import net.i2p.data.DataHelper;
import net.i2p.update.*;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.VersionComparator;
/**
* The downloader for router signed updates.
@@ -22,6 +20,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
private final Log _log;
private final UpdateManager _umgr;
private final SnarkManager _smgr;
private final UpdateType _type;
private final List<URI> _urls;
private volatile boolean _isRunning;
private volatile boolean _hasMetaInfo;
@@ -36,11 +35,12 @@ class UpdateRunner implements UpdateTask, CompleteListener {
private static final long CHECK_INTERVAL = 3*60*1000;
public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr,
List<URI> uris, String newVersion) {
UpdateType type, List<URI> uris, String newVersion) {
_context = ctx;
_log = ctx.logManager().getLog(getClass());
_umgr = umgr;
_smgr = smgr;
_type = type;
_urls = uris;
_newVersion = newVersion;
}
@@ -56,7 +56,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
}
}
public UpdateType getType() { return UpdateType.ROUTER_SIGNED; }
public UpdateType getType() { return _type; }
public UpdateMethod getMethod() { return UpdateMethod.TORRENT; }
@@ -111,7 +111,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
}
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this);
if (_snark != null) {
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", updateURL) + "</b>");
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", linkify(updateURL)) + "</b>");
new Timeout();
break;
}
@@ -264,6 +264,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
}
_hasMetaInfo = true;
notifyProgress();
snark.setAutoStoppable(true);
return _smgr.gotMetaInfo(snark);
}
@@ -291,6 +292,12 @@ class UpdateRunner implements UpdateTask, CompleteListener {
//////// end CompleteListener methods
private static String linkify(String url) {
String durl = url.length() <= 28 ? url :
url.substring(0, 25) + "&hellip;";
return "<a target=\"_blank\" href=\"" + url + "\"/>" + durl + "</a>";
}
private void updateStatus(String s) {
_umgr.notifyProgress(this, s);
}

View File

@@ -60,7 +60,7 @@ public class BDecoder
private int indicator = 0;
// Used for ugly hack to get SHA hash over the metainfo info map
private final String special_map = "info";
private static final String special_map = "info";
private boolean in_special_map = false;
/** creation deferred until we encounter the special map, to make processing of announce replies more efficient */
private MessageDigest sha_digest;
@@ -281,7 +281,7 @@ public class BDecoder
+ (char)c + "'");
indicator = 0;
List result = new ArrayList();
List<BEValue> result = new ArrayList<BEValue>();
c = getNextIndicator();
while (c != 'e')
{
@@ -308,7 +308,7 @@ public class BDecoder
+ (char)c + "'");
indicator = 0;
Map result = new HashMap();
Map<String, BEValue> result = new HashMap<String, BEValue>();
c = getNextIndicator();
while (c != 'e')
{

View File

@@ -49,12 +49,12 @@ public class BEValue
this.value = value;
}
public BEValue(List value)
public BEValue(List<BEValue> value)
{
this.value = value;
}
public BEValue(Map value)
public BEValue(Map<String, BEValue> value)
{
this.value = value;
}
@@ -142,11 +142,12 @@ public class BEValue
* succeeds when the BEValue is actually a List, otherwise it will
* throw a InvalidBEncodingException.
*/
@SuppressWarnings("unchecked")
public List<BEValue> getList() throws InvalidBEncodingException
{
try
{
return (List)value;
return (List<BEValue>)value;
}
catch (ClassCastException cce)
{
@@ -159,11 +160,12 @@ public class BEValue
* values. This operation only succeeds when the BEValue is actually
* a Map, otherwise it will throw a InvalidBEncodingException.
*/
@SuppressWarnings("unchecked")
public Map<String, BEValue> getMap() throws InvalidBEncodingException
{
try
{
return (Map)value;
return (Map<String, BEValue>)value;
}
catch (ClassCastException cce)
{

View File

@@ -59,9 +59,9 @@ public class BEncoder
else if (o instanceof Number)
bencode((Number)o, out);
else if (o instanceof List)
bencode((List)o, out);
bencode((List<?>)o, out);
else if (o instanceof Map)
bencode((Map<String, Object>)o, out);
bencode((Map<?, ?>)o, out);
else if (o instanceof BEValue)
bencode(((BEValue)o).getValue(), out);
else
@@ -110,7 +110,7 @@ public class BEncoder
out.write('e');
}
public static byte[] bencode(List l)
public static byte[] bencode(List<?> l)
{
try
{
@@ -124,10 +124,10 @@ public class BEncoder
}
}
public static void bencode(List l, OutputStream out) throws IOException
public static void bencode(List<?> l, OutputStream out) throws IOException
{
out.write('l');
Iterator it = l.iterator();
Iterator<?> it = l.iterator();
while (it.hasNext())
bencode(it.next(), out);
out.write('e');
@@ -155,7 +155,7 @@ public class BEncoder
out.write(bs);
}
public static byte[] bencode(Map<String, Object> m)
public static byte[] bencode(Map<?, ?> m)
{
try
{
@@ -169,23 +169,29 @@ public class BEncoder
}
}
public static void bencode(Map<String, Object> m, OutputStream out) throws IOException
public static void bencode(Map<?, ?> m, OutputStream out)
throws IOException, IllegalArgumentException
{
out.write('d');
// Keys must be sorted. XXX - But is this the correct order?
Set<String> s = m.keySet();
List<String> l = new ArrayList(s);
Set<?> s = m.keySet();
List<String> l = new ArrayList<String>(s.size());
for (Object k : s) {
// Keys must be Strings.
if (String.class.isAssignableFrom(k.getClass()))
l.add((String) k);
else
throw new IllegalArgumentException("Cannot bencode map: contains non-String key of type " + k.getClass());
}
Collections.sort(l);
Iterator<String> it = l.iterator();
while(it.hasNext())
{
// Keys must be Strings.
String key = it.next();
Object value = m.get(key);
bencode(key, out);
bencode(value, out);
bencode(m.get(key), out);
}
out.write('e');

View File

@@ -36,16 +36,18 @@ public interface DHT {
public void ping(Destination dest, int port);
/**
* Get peers for a torrent.
* Get peers for a torrent, and announce to the closest node we find.
* Blocking!
* Caller should run in a thread.
*
* @param ih the Info Hash (torrent)
* @param max maximum number of peers to return
* @param maxWait the maximum time to wait (ms) must be > 0
* @param annMax the number of peers to announce to
* @param annMaxWait the maximum total time to wait for announces, may be 0 to return immediately without waiting for acks
* @return possibly empty (never null)
*/
public Collection<Hash> getPeers(byte[] ih, int max, long maxWait);
public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait, int annMax, long annMaxWait);
/**
* Announce to ourselves.

View File

@@ -5,11 +5,8 @@ package org.klomp.snark.dht;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.I2PAppContext;
@@ -53,8 +50,8 @@ class DHTNodes {
_context = ctx;
_expireTime = MAX_EXPIRE_TIME;
_log = _context.logManager().getLog(DHTNodes.class);
_nodeMap = new ConcurrentHashMap();
_kad = new KBucketSet(ctx, me, KAD_K, KAD_B, new KBTrimmer(ctx, KAD_K));
_nodeMap = new ConcurrentHashMap<NID, NodeInfo>();
_kad = new KBucketSet<NID>(ctx, me, KAD_K, KAD_B, new KBTrimmer(ctx, KAD_K));
}
public void start() {
@@ -120,7 +117,7 @@ class DHTNodes {
else
key = new NID(h.getData());
List<NID> keys = _kad.getClosest(key, numWant);
List<NodeInfo> rv = new ArrayList(keys.size());
List<NodeInfo> rv = new ArrayList<NodeInfo>(keys.size());
for (NID nid : keys) {
NodeInfo ninfo = _nodeMap.get(nid);
if (ninfo != null)

View File

@@ -104,10 +104,10 @@ class DHTTracker {
List<Hash> getPeers(InfoHash ih, int max) {
Peers peers = _torrents.get(ih);
if (peers == null)
return Collections.EMPTY_LIST;
return Collections.emptyList();
int size = peers.size();
List<Hash> rv = new ArrayList(peers.values());
List<Hash> rv = new ArrayList<Hash>(peers.values());
if (max < size) {
Collections.shuffle(rv, _context.random());
rv = rv.subList(0, max);

View File

@@ -10,7 +10,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -24,7 +23,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSessionMuxedListener;
@@ -32,17 +30,16 @@ import net.i2p.client.SendMessageOptions;
import net.i2p.client.datagram.I2PDatagramDissector;
import net.i2p.client.datagram.I2PDatagramMaker;
import net.i2p.client.datagram.I2PInvalidDatagramException;
import net.i2p.crypto.SHA1Hash;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.SimpleDataStructure;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
import org.klomp.snark.TrackerClient;
import org.klomp.snark.bencode.BDecoder;
import org.klomp.snark.bencode.BEncoder;
import org.klomp.snark.bencode.BEValue;
@@ -149,6 +146,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private static final long MAX_MSGID_AGE = 2*60*1000;
/** how long since sent do we wait for a reply */
private static final long DEFAULT_QUERY_TIMEOUT = 75*1000;
private static final long DEST_LOOKUP_TIMEOUT = 10*1000;
/** stagger with other cleaners */
private static final long CLEAN_TIME = 63*1000;
private static final long EXPLORE_TIME = 877*1000;
@@ -167,15 +165,15 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
_log = ctx.logManager().getLog(KRPC.class);
_tracker = new DHTTracker(ctx);
_sentQueries = new ConcurrentHashMap();
_outgoingTokens = new ConcurrentHashMap();
_incomingTokens = new ConcurrentHashMap();
_blacklist = new ConcurrentHashSet();
_sentQueries = new ConcurrentHashMap<MsgID, ReplyWaiter>();
_outgoingTokens = new ConcurrentHashMap<Token, NodeInfo>();
_incomingTokens = new ConcurrentHashMap<NID, Token>();
_blacklist = new ConcurrentHashSet<NID>();
// Construct my NodeInfo
// Pick ports over a big range to marginally increase security
// If we add a search DHT, adjust to stay out of each other's way
_qPort = 2555 + ctx.random().nextInt(61111);
_qPort = TrackerClient.PORT + 10 + ctx.random().nextInt(65535 - 20 - TrackerClient.PORT);
_rPort = _qPort + 1;
if (SECURE_NID) {
_myNID = NodeInfo.generateNID(session.getMyDestination().calculateHash(), _qPort, _context.random());
@@ -244,9 +242,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
_log.info("DHT is empty, cannot explore");
return;
}
SortedSet<NodeInfo> toTry = new TreeSet(new NodeInfoComparator(target));
SortedSet<NodeInfo> toTry = new TreeSet<NodeInfo>(new NodeInfoComparator(target));
toTry.addAll(nodes);
Set<NodeInfo> tried = new HashSet();
Set<NodeInfo> tried = new HashSet<NodeInfo>();
if (_log.shouldLog(Log.INFO))
_log.info("Starting explore of " + target);
@@ -307,7 +305,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
/**
* Get peers for a torrent.
* Get peers for a torrent, and announce to the closest node we find.
* This is an iterative lookup in the DHT.
* Blocking!
* Caller should run in a thread.
@@ -315,30 +313,38 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
* @param ih the Info Hash (torrent)
* @param max maximum number of peers to return
* @param maxWait the maximum time to wait (ms) must be > 0
* @param annMax the number of peers to announce to
* @param annMaxWait the maximum total time to wait for announces, may be 0 to return immediately without waiting for acks
* @return possibly empty (never null)
*/
public Collection<Hash> getPeers(byte[] ih, int max, long maxWait) {
public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait, int annMax, long annMaxWait) {
// check local tracker first
InfoHash iHash = new InfoHash(ih);
Collection<Hash> rv = _tracker.getPeers(iHash, max);
rv.remove(_myNodeInfo.getHash());
if (rv.size() >= max)
return rv;
rv = new HashSet(rv);
rv = new HashSet<Hash>(rv);
long endTime = _context.clock().now() + maxWait;
// needs to be much higher than log(size) since many lookups will fail
// at first and we will give up too early
int maxNodes = 30;
// Initial set to try, will get added to as we go
int maxNodes = 12;
List<NodeInfo> nodes = _knownNodes.findClosest(iHash, maxNodes);
SortedSet<NodeInfo> toTry = new TreeSet(new NodeInfoComparator(iHash));
NodeInfoComparator comp = new NodeInfoComparator(iHash);
SortedSet<NodeInfo> toTry = new TreeSet<NodeInfo>(comp);
SortedSet<NodeInfo> heardFrom = new TreeSet<NodeInfo>(comp);
toTry.addAll(nodes);
Set<NodeInfo> tried = new HashSet();
SortedSet<NodeInfo> tried = new TreeSet<NodeInfo>(comp);
if (_log.shouldLog(Log.INFO))
_log.info("Starting getPeers for " + iHash + " with " + nodes.size() + " to try");
_log.info("Starting getPeers for " + iHash + " (b64: " + new NID(ih) + ") " + " with " + nodes.size() + " to try");
for (int i = 0; i < maxNodes; i++) {
if (!_isRunning)
break;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Now to try: " + toTry);
NodeInfo nInfo;
try {
nInfo = toTry.first();
@@ -347,13 +353,15 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
toTry.remove(nInfo);
tried.add(nInfo);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Try " + i + ": " + nInfo);
ReplyWaiter waiter = sendGetPeers(nInfo, iHash);
if (waiter == null)
continue;
synchronized(waiter) {
try {
waiter.wait(Math.max(20*1000, (Math.min(40*1000, endTime - _context.clock().now()))));
waiter.wait(Math.max(30*1000, (Math.min(45*1000, endTime - _context.clock().now()))));
} catch (InterruptedException ie) {}
}
@@ -365,18 +373,24 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got pong");
} else if (replyType == REPLY_PEERS) {
heardFrom.add(waiter.getSentTo());
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got peers");
List<Hash> reply = (List<Hash>) waiter.getReplyObject();
// shouldn't send us an empty peers list but through
// 0.9.8.1 it will
if (!reply.isEmpty()) {
for (int j = 0; j < reply.size() && rv.size() < max; j++) {
rv.add(reply.get(j));
Hash h = reply.get(j);
if (!h.equals(_myNodeInfo.getHash()))
rv.add(h);
}
if (_log.shouldLog(Log.INFO))
_log.info("Finished get Peers, got " + rv.size() + " from DHT, returning " + reply.size());
return rv;
}
if (_log.shouldLog(Log.INFO))
_log.info("Finished get Peers, got " + reply.size() + " from DHT, returning " + rv.size());
break;
} else if (replyType == REPLY_NODES) {
heardFrom.add(waiter.getSentTo());
List<NodeInfo> reply = (List<NodeInfo>) waiter.getReplyObject();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got " + reply.size() + " nodes");
@@ -392,9 +406,45 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
if (_context.clock().now() > endTime)
break;
if (!toTry.isEmpty() && !heardFrom.isEmpty() &&
comp.compare(toTry.first(), heardFrom.first()) >= 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Finished get Peers, nothing closer to try after " + (i+1));
break;
}
}
// now announce
if (!heardFrom.isEmpty()) {
announce(ih);
// announce to the closest we've heard from
int annCnt = 0;
long start = _context.clock().now();
for (Iterator<NodeInfo> iter = heardFrom.iterator(); iter.hasNext() && annCnt < annMax && _isRunning; ) {
NodeInfo annTo = iter.next();
if (_log.shouldLog(Log.INFO))
_log.info("Announcing to closest from get peers: " + annTo);
long toWait = annMaxWait > 0 ? Math.min(annMaxWait, 60*1000) : 0;
if (announce(ih, annTo, toWait))
annCnt++;
if (annMaxWait > 0) {
annMaxWait -= _context.clock().now() - start;
if (annMaxWait < 1000)
break;
}
}
} else {
// spray it, but unlikely to work, we just went through the kbuckets,
// so this is essentially just a retry
if (_log.shouldLog(Log.INFO))
_log.info("Announcing to closest in kbuckets after get peers failed");
announce(ih, annMax, annMaxWait);
}
if (_log.shouldLog(Log.INFO)) {
_log.info("Finished get Peers, returning " + rv.size());
_log.info("Tried: " + tried);
_log.info("Heard from: " + heardFrom);
_log.info("Not tried: " + toTry);
}
if (_log.shouldLog(Log.INFO))
_log.info("Finished get Peers, " + rv.size() + " from local and none from DHT");
return rv;
}
@@ -436,13 +486,16 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
/**
* Not recommended - use getPeersAndAnnounce().
*
* Announce to the closest peers in the local DHT.
* This is NOT iterative - call getPeers() first to get the closest
* peers into the local DHT.
* Blocking unless maxWait <= 0
* Caller should run in a thread.
* This also automatically announces ourself to our local tracker.
* For best results do a getPeers() first so we have tokens.
* For best results do a getPeersAndAnnounce() instead, as this announces to
* the closest in the kbuckets, it does NOT sort through the known nodes hashmap.
*
* @param ih the Info Hash (torrent)
* @param max maximum number of peers to announce to
@@ -640,9 +693,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private ReplyWaiter sendPing(NodeInfo nInfo) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending ping to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("q", "ping");
Map<String, Object> args = new HashMap();
Map<String, Object> args = new HashMap<String, Object>();
map.put("a", args);
return sendQuery(nInfo, map, true);
}
@@ -657,9 +710,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private ReplyWaiter sendFindNode(NodeInfo nInfo, NID tID) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending find node of " + tID + " to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("q", "find_node");
Map<String, Object> args = new HashMap();
Map<String, Object> args = new HashMap<String, Object>();
args.put("target", tID.getData());
map.put("a", args);
return sendQuery(nInfo, map, true);
@@ -674,9 +727,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private ReplyWaiter sendGetPeers(NodeInfo nInfo, InfoHash ih) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending get peers of " + ih + " to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("q", "get_peers");
Map<String, Object> args = new HashMap();
Map<String, Object> args = new HashMap<String, Object>();
args.put("info_hash", ih.getData());
map.put("a", args);
ReplyWaiter rv = sendQuery(nInfo, map, true);
@@ -695,12 +748,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private ReplyWaiter sendAnnouncePeer(NodeInfo nInfo, InfoHash ih, Token token) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending announce of " + ih + " to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
map.put("q", "announce_peer");
Map<String, Object> args = new HashMap();
Map<String, Object> args = new HashMap<String, Object>();
args.put("info_hash", ih.getData());
// port ignored
args.put("port", Integer.valueOf(6881));
args.put("port", Integer.valueOf(TrackerClient.PORT));
args.put("token", token.getData());
map.put("a", args);
// an announce need not be signed, we have a token
@@ -718,8 +771,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private boolean sendPong(NodeInfo nInfo, MsgID msgID) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending pong to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> resps = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> resps = new HashMap<String, Object>();
map.put("r", resps);
return sendResponse(nInfo, msgID, map);
}
@@ -737,8 +790,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private boolean sendNodes(NodeInfo nInfo, MsgID msgID, Token token, byte[] ids) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending nodes to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> resps = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> resps = new HashMap<String, Object>();
map.put("r", resps);
if (token != null)
resps.put("token", token.getData());
@@ -750,8 +803,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private boolean sendPeers(NodeInfo nInfo, MsgID msgID, Token token, List<byte[]> peers) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending peers to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> resps = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> resps = new HashMap<String, Object>();
map.put("r", resps);
resps.put("token", token.getData());
resps.put("values", peers);
@@ -767,8 +820,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private boolean sendError(NodeInfo nInfo, MsgID msgID, int err, String msg) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending error " + msg + " to: " + nInfo);
Map<String, Object> map = new HashMap();
Map<String, Object> resps = new HashMap();
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> resps = new HashMap<String, Object>();
map.put("r", resps);
return sendResponse(nInfo, msgID, map);
}
@@ -800,8 +853,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
// Lookup the dest for the hash
// TODO spin off into thread or queue? We really don't want to block here
if (!lookupDest(nInfo)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Dropping repliable query, no dest for " + nInfo);
if (_log.shouldLog(Log.INFO))
_log.info("Dropping repliable query, no dest for " + nInfo);
timeout(nInfo);
return null;
}
@@ -891,7 +944,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
_log.info("looking up dest for " + nInfo);
try {
// use a short timeout for now
Destination dest = _session.lookupDest(nInfo.getHash(), 5*1000);
Destination dest = _session.lookupDest(nInfo.getHash(), DEST_LOOKUP_TIMEOUT);
if (dest != null) {
nInfo.setDestination(dest);
if (_log.shouldLog(Log.INFO))
@@ -1190,6 +1243,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
_log.info("Stored new OB token: " + token + " for: " + nInfo);
List<Hash> peers = _tracker.getPeers(ih, MAX_WANT);
peers.remove(nInfo.getHash()); // him
if (peers.isEmpty()) {
// similar to find node, but with token
// get closest from DHT
@@ -1202,11 +1256,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
sendNodes(nInfo, msgID, token, nodeArray);
} else {
List<byte[]> hashes = new ArrayList(peers.size());
Hash him = nInfo.getHash();
List<byte[]> hashes = new ArrayList<byte[]>(peers.size());
for (Hash peer : peers) {
if (!peer.equals(him))
hashes.add(peer.getData());
hashes.add(peer.getData());
}
sendPeers(nInfo, msgID, token, hashes);
}
@@ -1290,7 +1342,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
*/
private List<NodeInfo> receiveNodes(NodeInfo nInfo, byte[] ids) throws InvalidBEncodingException {
int max = Math.min(K, ids.length / NodeInfo.LENGTH);
List<NodeInfo> rv = new ArrayList(max);
List<NodeInfo> rv = new ArrayList<NodeInfo>(max);
for (int off = 0; off < ids.length && rv.size() < max; off += NodeInfo.LENGTH) {
NodeInfo nInf = new NodeInfo(ids, off);
if (_blacklist.contains(nInf.getNID())) {
@@ -1314,7 +1366,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
if (_log.shouldLog(Log.INFO))
_log.info("Rcvd peers from: " + nInfo);
int max = Math.min(MAX_WANT, peers.size());
List<Hash> rv = new ArrayList(max);
List<Hash> rv = new ArrayList<Hash>(max);
for (BEValue bev : peers) {
byte[] b = bev.getBytes();
//Hash h = new Hash(b);
@@ -1324,7 +1376,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
break;
}
if (_log.shouldLog(Log.INFO))
_log.info("Rcvd peers from: " + nInfo + ": " + DataHelper.toString(rv));
_log.info("Rcvd " + peers.size() + " peers from: " + nInfo + ": " + DataHelper.toString(rv));
return rv;
}

View File

@@ -37,10 +37,10 @@ abstract class PersistDHT {
public static synchronized void loadDHT(KRPC krpc, File file) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(PersistDHT.class);
int count = 0;
FileInputStream in = null;
BufferedReader br = null;
try {
in = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1"));
br = new BufferedReader(new InputStreamReader(
new FileInputStream(file), "ISO-8859-1"));
String line = null;
while ( (line = br.readLine()) != null) {
if (line.startsWith("#"))
@@ -61,7 +61,7 @@ abstract class PersistDHT {
if (log.shouldLog(Log.WARN) && file.exists())
log.warn("Error reading the DHT File", ioe);
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
if (br != null) try { br.close(); } catch (IOException ioe) {}
}
if (log.shouldLog(Log.INFO))
log.info("Loaded " + count + " nodes from " + file);

View File

@@ -7,7 +7,6 @@ import java.util.Date;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
/**
* Used for Both outgoing and incoming tokens

View File

@@ -27,7 +27,6 @@ import java.util.Enumeration;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
@@ -36,6 +35,7 @@ import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
@@ -66,9 +66,8 @@ import net.i2p.util.SystemVersion;
* The default servlet.
* This servlet, normally mapped to /, provides the handling for static
* content, OPTION and TRACE methods for the context.
* The following initParameters are supported, these can be set either
* on the servlet itself or as ServletContext initParameters with a prefix
* of org.mortbay.jetty.servlet.Default. :
* The following initParameters are supported, these can be set
* on the servlet itself:
* <PRE>
*
* resourceBase Set to replace the context resource base
@@ -325,7 +324,7 @@ class BasicServlet extends HttpServlet
long content_length = content.getContentLength();
// see if there are any range headers
Enumeration reqRanges = request.getHeaders("Range");
Enumeration<?> reqRanges = request.getHeaders("Range");
if (reqRanges == null || !reqRanges.hasMoreElements()) {
// if there were no ranges, send entire entity
@@ -469,7 +468,7 @@ class BasicServlet extends HttpServlet
{
String cpath = getServletContext().getContextPath();
// this won't work if we aren't at top level
String cname = cpath == "" ? "i2psnark" : cpath.substring(1).replace("/", "_");
String cname = "".equals(cpath) ? "i2psnark" : cpath.substring(1).replace("/", "_");
return (new File(_context.getBaseDir(), "webapps/" + cname + ".war")).lastModified();
}
@@ -578,7 +577,7 @@ class BasicServlet extends HttpServlet
byte[] buf = ba.getData();
try {
if (skip > 0)
in.skip(skip);
DataHelper.skip(in, skip);
int read = 0;
long tot = 0;
boolean done = false;

View File

@@ -13,11 +13,13 @@ import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocketEepGet;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.crypto.SHA1;
import net.i2p.data.DataHelper;
import net.i2p.util.EepGet;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SecureFile;
import org.klomp.snark.I2PSnarkUtil;
import org.klomp.snark.MetaInfo;
import org.klomp.snark.Snark;
import org.klomp.snark.SnarkManager;
@@ -95,7 +97,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
add(file);
} else {
_mgr.addMessage(_("Torrent was not retrieved from {0}", urlify(_url)) +
((_failCause != null) ? (": " + _failCause) : ""));
((_failCause != null) ? (": " + DataHelper.stripHTML(_failCause)) : ""));
}
if (file != null)
file.delete();
@@ -130,6 +132,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
return null;
_eepGet = new I2PSocketEepGet(_ctx, manager, RETRIES, out.getAbsolutePath(), _url);
_eepGet.addStatusListener(this);
_eepGet.addHeader("User-Agent", I2PSnarkUtil.EEPGET_USER_AGENT);
if (_eepGet.fetch()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Fetch successful [" + _url + "]: size=" + out.length());
@@ -160,8 +163,8 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
return;
}
name = Storage.filterName(name);
name = name + ".torrent";
String originalName = Storage.filterName(name);
name = originalName + ".torrent";
File torrentFile = new File(_mgr.getDataDir(), name);
String canonical = torrentFile.getCanonicalPath();
@@ -174,6 +177,8 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
} else {
// This may take a LONG time to create the storage.
_mgr.copyAndAddTorrent(file, canonical);
snark = _mgr.getTorrentByBaseName(originalName);
snark.startTorrent();
}
} catch (IOException ioe) {
_mgr.addMessage(_("Torrent at {0} was not valid", urlify(_url)) + ": " + ioe.getMessage());
@@ -196,7 +201,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
//_total = -1;
_transferred = 0;
_failCause = null;
_started = _ctx.clock().now();
_started = _util.getContext().clock().now();
_isRunning = true;
_active = false;
_thread = new I2PAppThread(this, "Torrent File EepGet", true);

View File

@@ -1,12 +1,8 @@
package org.klomp.snark.web;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.Collator;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
@@ -16,7 +12,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -26,14 +21,11 @@ import java.util.TreeSet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import org.klomp.snark.I2PSnarkUtil;
@@ -208,7 +200,8 @@ public class I2PSnarkServlet extends BasicServlet {
resp.sendError(404);
} else {
String base = addPaths(req.getRequestURI(), "/");
String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null);
@SuppressWarnings("unchecked") // TODO-Java6: Remove cast, return type is correct
String listing = getListHTML(resource, base, true, method.equals("POST") ? (Map<String, String[]>) req.getParameterMap() : null);
if (method.equals("POST")) {
// P-R-G
sendRedirect(req, resp, "");
@@ -509,7 +502,7 @@ public class I2PSnarkServlet extends BasicServlet {
// show startall too
out.write("<br>");
if (isDegraded)
out.write("<a href=\"/" + _contextPath + "/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
out.write("<a href=\"" + _contextPath + "/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action_StartAll\" value=\"foo\" title=\"");
out.write(_("Start all stopped torrents"));
@@ -523,7 +516,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
} else if ((!_manager.util().isConnecting()) && !snarks.isEmpty()) {
if (isDegraded)
out.write("<a href=\"/" + _contextPath + "/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
out.write("<a href=\"" + _contextPath + "/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action_StartAll\" value=\"foo\" title=\"");
out.write(_("Start all torrents and the I2P tunnel"));
@@ -684,7 +677,8 @@ public class I2PSnarkServlet extends BasicServlet {
String action = req.getParameter("action");
if (action == null) {
// http://www.onenaught.com/posts/382/firefox-4-change-input-type-image-only-submits-x-and-y-not-name
Map params = req.getParameterMap();
@SuppressWarnings("unchecked") // TODO-Java6: Remove cast, return type is correct
Map<String, String[]> params = req.getParameterMap();
for (Object o : params.keySet()) {
String key = (String) o;
if (key.startsWith("action_") && key.endsWith(".x")) {
@@ -758,8 +752,7 @@ public class I2PSnarkServlet extends BasicServlet {
if (torrent != null) {
byte infoHash[] = Base64.decode(torrent);
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
for (String name : _manager.listTorrentFiles() ) {
Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
_manager.stopTorrent(snark, false);
@@ -781,8 +774,7 @@ public class I2PSnarkServlet extends BasicServlet {
if (torrent != null) {
byte infoHash[] = Base64.decode(torrent);
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
for (String name : _manager.listTorrentFiles() ) {
Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
MetaInfo meta = snark.getMetaInfo();
@@ -809,8 +801,7 @@ public class I2PSnarkServlet extends BasicServlet {
if (torrent != null) {
byte infoHash[] = Base64.decode(torrent);
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
for (Iterator iter = _manager.listTorrentFiles().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
for (String name : _manager.listTorrentFiles() ) {
Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
MetaInfo meta = snark.getMetaInfo();
@@ -849,7 +840,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
}
// step 2 make Set of dirs with reverse sort
Set<File> dirs = new TreeSet(Collections.reverseOrder());
Set<File> dirs = new TreeSet<File>(Collections.reverseOrder());
for (List<String> list : files) {
for (int i = 1; i < list.size(); i++) {
dirs.add(Storage.getFileFromNames(f, list.subList(0, i)));
@@ -922,8 +913,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (announceURL.equals("none"))
announceURL = null;
_lastAnnounceURL = announceURL;
List<String> backupURLs = new ArrayList();
Enumeration e = req.getParameterNames();
List<String> backupURLs = new ArrayList<String>();
Enumeration<?> e = req.getParameterNames();
while (e.hasMoreElements()) {
Object o = e.nextElement();
if (!(o instanceof String))
@@ -946,7 +937,7 @@ public class I2PSnarkServlet extends BasicServlet {
boolean hasPrivate = false;
boolean hasPublic = false;
for (String url : backupURLs) {
if (_manager.getPrivateTrackers().contains(announceURL))
if (_manager.getPrivateTrackers().contains(url))
hasPrivate = true;
else
hasPublic = true;
@@ -955,7 +946,7 @@ public class I2PSnarkServlet extends BasicServlet {
_manager.addMessage(_("Error - Cannot mix private and public trackers in a torrent"));
return;
}
announceList = new ArrayList(backupURLs.size());
announceList = new ArrayList<List<String>>(backupURLs.size());
for (String url : backupURLs) {
announceList.add(Collections.singletonList(url));
}
@@ -976,7 +967,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (announceURL != null && !_manager.util().getOpenTrackers().contains(announceURL))
_manager.addMessage(_("Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\"", baseFile.getName()));
} catch (IOException ioe) {
_manager.addMessage(_("Error creating a torrent for \"{0}\"", baseFile.getAbsolutePath()) + ": " + ioe.getMessage());
_manager.addMessage(_("Error creating a torrent for \"{0}\"", baseFile.getAbsolutePath()) + ": " + ioe);
_log.error("Error creating a torrent", ioe);
}
} else {
_manager.addMessage(_("Cannot create a torrent for the nonexistent data: {0}", baseFile.getAbsolutePath()));
@@ -1016,10 +1008,10 @@ public class I2PSnarkServlet extends BasicServlet {
if (action.equals(_("Delete selected")) || action.equals(_("Save tracker configuration"))) {
boolean changed = false;
Map<String, Tracker> trackers = _manager.getTrackerMap();
List<String> removed = new ArrayList();
List<String> open = new ArrayList();
List<String> priv = new ArrayList();
Enumeration e = req.getParameterNames();
List<String> removed = new ArrayList<String>();
List<String> open = new ArrayList<String>();
List<String> priv = new ArrayList<String>();
Enumeration<?> e = req.getParameterNames();
while (e.hasMoreElements()) {
Object o = e.nextElement();
if (!(o instanceof String))
@@ -1044,7 +1036,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
open.removeAll(removed);
List<String> oldOpen = new ArrayList(_manager.util().getOpenTrackers());
List<String> oldOpen = new ArrayList<String>(_manager.util().getOpenTrackers());
Collections.sort(oldOpen);
Collections.sort(open);
if (!open.equals(oldOpen))
@@ -1053,7 +1045,7 @@ public class I2PSnarkServlet extends BasicServlet {
priv.removeAll(removed);
// open trumps private
priv.removeAll(open);
List<String> oldPriv = new ArrayList(_manager.getPrivateTrackers());
List<String> oldPriv = new ArrayList<String>(_manager.getPrivateTrackers());
Collections.sort(oldPriv);
Collections.sort(priv);
if (!priv.equals(oldPriv))
@@ -1073,11 +1065,11 @@ public class I2PSnarkServlet extends BasicServlet {
_manager.saveTrackerMap();
// open trumps private
if (req.getParameter("_add_open_") != null) {
List newOpen = new ArrayList(_manager.util().getOpenTrackers());
List<String> newOpen = new ArrayList<String>(_manager.util().getOpenTrackers());
newOpen.add(aurl);
_manager.saveOpenTrackers(newOpen);
} else if (req.getParameter("_add_private_") != null) {
List newPriv = new ArrayList(_manager.getPrivateTrackers());
List<String> newPriv = new ArrayList<String>(_manager.getPrivateTrackers());
newPriv.add(aurl);
_manager.savePrivateTrackers(newPriv);
}
@@ -1116,55 +1108,32 @@ public class I2PSnarkServlet extends BasicServlet {
/**
* Sort alphabetically in current locale, ignore case, ignore leading "the "
* (I guess this is worth it, a lot of torrents start with "The "
* These are full path names which makes it harder
* @since 0.7.14
*/
private class TorrentNameComparator implements Comparator<String> {
private static class TorrentNameComparator implements Comparator<Snark> {
private final Comparator collator = Collator.getInstance();
private final String skip;
public TorrentNameComparator() {
String s;
try {
s = _manager.getDataDir().getCanonicalPath();
} catch (IOException ioe) {
s = _manager.getDataDir().getAbsolutePath();
}
skip = s + File.separator;
}
public int compare(String l, String r) {
if (l.startsWith(skip))
l = l.substring(skip.length());
if (r.startsWith(skip))
r = r.substring(skip.length());
String llc = l.toLowerCase(Locale.US);
public int compare(Snark l, Snark r) {
// put downloads and magnets first
if (l.getStorage() == null && r.getStorage() != null)
return -1;
if (l.getStorage() != null && r.getStorage() == null)
return 1;
String ls = l.getBaseName();
String llc = ls.toLowerCase(Locale.US);
if (llc.startsWith("the ") || llc.startsWith("the.") || llc.startsWith("the_"))
l = l.substring(4);
String rlc = r.toLowerCase(Locale.US);
ls = ls.substring(4);
String rs = r.getBaseName();
String rlc = rs.toLowerCase(Locale.US);
if (rlc.startsWith("the ") || rlc.startsWith("the.") || rlc.startsWith("the_"))
r = r.substring(4);
return collator.compare(l, r);
rs = rs.substring(4);
return collator.compare(ls, rs);
}
}
private List<Snark> getSortedSnarks(HttpServletRequest req) {
Set<String> files = _manager.listTorrentFiles();
TreeSet<String> fileNames = new TreeSet(new TorrentNameComparator());
fileNames.addAll(files);
ArrayList<Snark> rv = new ArrayList(fileNames.size());
int magnet = 0;
for (Iterator iter = fileNames.iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
Snark snark = _manager.getTorrent(name);
if (snark != null) {
// put downloads and magnets first
if (snark.getStorage() == null)
rv.add(magnet++, snark);
else
rv.add(snark);
}
}
ArrayList<Snark> rv = new ArrayList<Snark>(_manager.getTorrents());
Collections.sort(rv, new TorrentNameComparator());
return rv;
}
@@ -1200,23 +1169,13 @@ public class I2PSnarkServlet extends BasicServlet {
if (statsOnly)
return;
String filename = snark.getName();
if (snark.getMetaInfo() != null) {
// Only do this if not a magnet or torrent download
// Strip full path down to the local name
File f = new File(filename);
filename = f.getName();
}
int i = filename.lastIndexOf(".torrent");
if (i > 0)
filename = filename.substring(0, i);
String fullFilename = filename;
if (filename.length() > MAX_DISPLAYED_FILENAME_LENGTH) {
String start = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH);
String basename = snark.getBaseName();
String fullBasename = basename;
if (basename.length() > MAX_DISPLAYED_FILENAME_LENGTH) {
String start = basename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH);
if (start.indexOf(" ") < 0 && start.indexOf("-") < 0) {
// browser has nowhere to break it
fullFilename = filename;
filename = start + "&hellip;";
basename = start + "&hellip;";
}
}
// includes skipped files, -1 for magnet mode
@@ -1245,10 +1204,10 @@ public class I2PSnarkServlet extends BasicServlet {
String statusString;
if (snark.isChecking()) {
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Checking") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Checking");
"<td class=\"snarkTorrentStatus\">" + _("Checking");
} else if (snark.isAllocating()) {
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Allocating") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Allocating");
"<td class=\"snarkTorrentStatus\">" + _("Allocating");
} else if (err != null && curPeers == 0) {
// Also don't show if seeding... but then we won't see the not-registered error
// && remaining != 0 && needed != 0) {
@@ -1262,18 +1221,18 @@ public class I2PSnarkServlet extends BasicServlet {
//else if (isRunning)
if (isRunning)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
"<td class=\"snarkTorrentStatus\">" + _("Tracker Error") +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else {
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "&hellip;";
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error");
"<td class=\"snarkTorrentStatus\">" + _("Tracker Error");
}
} else if (snark.isStarting()) {
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Starting") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Starting");
"<td class=\"snarkTorrentStatus\">" + _("Starting");
} else if (remaining == 0 || needed == 0) { // < 0 means no meta size yet
// partial complete or seeding
if (isRunning) {
@@ -1289,60 +1248,60 @@ public class I2PSnarkServlet extends BasicServlet {
}
if (curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + img + ".png\" title=\"" + txt + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + txt +
"<td class=\"snarkTorrentStatus\">" + txt +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + stParam + "\">" +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + img + ".png\" title=\"" + txt + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + txt +
"<td class=\"snarkTorrentStatus\">" + txt +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
} else {
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" title=\"" + _("Complete") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
"<td class=\"snarkTorrentStatus\">" + _("Complete");
}
} else {
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" title=\"" + _("OK") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
"<td class=\"snarkTorrentStatus\">" + _("OK") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + stParam + "\">" +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0 && downBps > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" title=\"" + _("OK") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
"<td class=\"snarkTorrentStatus\">" + _("OK") +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Stalled") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
"<td class=\"snarkTorrentStatus\">" + _("Stalled") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + stParam + "\">" +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Stalled") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
"<td class=\"snarkTorrentStatus\">" + _("Stalled") +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && knownPeers > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" title=\"" + _("No Peers") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers") +
"<td class=\"snarkTorrentStatus\">" + _("No Peers") +
": 0" + thinsp(noThinsp) + knownPeers ;
else if (isRunning)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" title=\"" + _("No Peers") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers");
"<td class=\"snarkTorrentStatus\">" + _("No Peers");
else
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stopped.png\" title=\"" + _("Stopped") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stopped");
"<td class=\"snarkTorrentStatus\">" + _("Stopped");
}
out.write("<tr class=\"" + rowClass + "\">");
out.write("<td class=\"center " + rowClass + "\">");
out.write("<td class=\"center\">");
out.write(statusString + "</td>\n\t");
// (i) icon column
out.write("<td class=\"" + rowClass + "\">");
out.write("<td>");
if (isValid && meta.getAnnounce() != null) {
// Link to local details page - note that trailing slash on a single-file torrent
// gets us to the details page instead of the file.
@@ -1359,9 +1318,9 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(trackerLink);
}
String encodedBaseName = urlEncode(snark.getBaseName());
String encodedBaseName = urlEncode(fullBasename);
// File type icon column
out.write("</td>\n<td class=\"" + rowClass + "\">");
out.write("</td>\n<td>");
if (isValid) {
// Link to local details page - note that trailing slash on a single-file torrent
// gets us to the details page instead of the file.
@@ -1388,7 +1347,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
// Torrent name column
out.write("</td><td class=\"snarkTorrentName " + rowClass + "\">");
out.write("</td><td class=\"snarkTorrentName\">");
if (remaining == 0 || isMultiFile) {
StringBuilder buf = new StringBuilder(128);
buf.append("<a href=\"").append(encodedBaseName);
@@ -1402,15 +1361,15 @@ public class I2PSnarkServlet extends BasicServlet {
buf.append("\">");
out.write(buf.toString());
}
out.write(filename);
out.write(basename);
if (remaining == 0 || isMultiFile)
out.write("</a>");
out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentETA\">");
if(isRunning && remainingSeconds > 0 && !snark.isChecking())
out.write(DataHelper.formatDuration2(Math.max(remainingSeconds, 10) * 1000)); // (eta 6h)
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded\">");
if (remaining > 0)
out.write(formatSize(total-remaining) + thinsp(noThinsp) + formatSize(total));
else if (remaining == 0)
@@ -1418,7 +1377,7 @@ public class I2PSnarkServlet extends BasicServlet {
//else
// out.write("??"); // no meta size yet
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentUploaded " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentUploaded\">");
if(isRunning && isValid)
out.write(formatSize(uploaded));
out.write("</td>\n\t");
@@ -1430,7 +1389,7 @@ public class I2PSnarkServlet extends BasicServlet {
if(isRunning && isValid)
out.write(formatSize(upBps) + "ps");
out.write("</td>\n\t");
out.write("<td align=\"center\" class=\"snarkTorrentAction " + rowClass + "\">");
out.write("<td align=\"center\" class=\"snarkTorrentAction\">");
String b64 = Base64.encode(snark.getInfoHash());
if (snark.isChecking()) {
// show no buttons
@@ -1451,7 +1410,7 @@ public class I2PSnarkServlet extends BasicServlet {
// Start Button
// This works in Opera but it's displayed a little differently, so use noThinsp here too so all 3 icons are consistent
if (noThinsp)
out.write("<a href=\"/" + _contextPath + "/?action=Start_" + b64 + "&amp;nonce=" + _nonce + stParam + "\"><img title=\"");
out.write("<a href=\"" + _contextPath + "/?action=Start_" + b64 + "&amp;nonce=" + _nonce + stParam + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action_Start_" + b64 + "\" value=\"foo\" title=\"");
out.write(_("Start the torrent"));
@@ -1473,7 +1432,7 @@ public class I2PSnarkServlet extends BasicServlet {
// 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 quote must be escaped
out.write(_("Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?", fullFilename));
out.write(_("Are you sure you want to delete the file \\''{0}\\'' (downloaded data will not be deleted) ?", snark.getName()));
out.write("')) { return false; }\"");
out.write(" src=\"" + _imgPath + "remove.png\" alt=\"");
out.write(_("Remove"));
@@ -1493,7 +1452,7 @@ public class I2PSnarkServlet extends BasicServlet {
// 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 quote must be escaped
out.write(_("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?", fullFilename));
out.write(_("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?", fullBasename));
out.write("')) { return false; }\"");
out.write(" src=\"" + _imgPath + "delete.png\" alt=\"");
out.write(_("Delete"));
@@ -1511,7 +1470,7 @@ public class I2PSnarkServlet extends BasicServlet {
if (!peer.isConnected())
continue;
out.write("<tr class=\"" + rowClass + "\"><td></td>");
out.write("<td colspan=\"4\" align=\"right\" class=\"" + rowClass + "\">");
out.write("<td colspan=\"4\" align=\"right\">");
String ch = peer.toString().substring(0, 4);
String client;
if ("AwMD".equals(ch))
@@ -1536,13 +1495,13 @@ public class I2PSnarkServlet extends BasicServlet {
if (showDebug)
out.write(" inactive " + (peer.getInactiveTime() / 1000) + "s");
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td class=\"snarkTorrentStatus\">");
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentStatus\">");
float pct;
if (isValid) {
pct = (float) (100.0 * peer.completed() / meta.getPieces());
if (pct == 100.0)
if (pct >= 100.0)
out.write(_("Seed"));
else {
String ps = String.valueOf(pct);
@@ -1556,9 +1515,9 @@ public class I2PSnarkServlet extends BasicServlet {
//out.write("??");
}
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td class=\"snarkTorrentStatus\">");
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentStatus\">");
if (needed > 0) {
if (peer.isInteresting() && !peer.isChoked()) {
out.write("<span class=\"unchoked\">");
@@ -1580,7 +1539,7 @@ public class I2PSnarkServlet extends BasicServlet {
//}
}
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentStatus\">");
if (isValid && pct < 100.0) {
if (peer.isInterested() && !peer.isChoking()) {
out.write("<span class=\"unchoked\">");
@@ -1596,10 +1555,10 @@ public class I2PSnarkServlet extends BasicServlet {
}
}
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td class=\"snarkTorrentStatus\">");
out.write("</td></tr>\n\t");
if (showDebug)
out.write("<tr class=\"" + rowClass + "\"><td></td><td colspan=\"10\" align=\"right\" class=\"" + rowClass + "\">" + peer.getSocket() + "</td></tr>");
out.write("<tr class=\"" + rowClass + "\"><td></td><td colspan=\"10\" align=\"right\">" + peer.getSocket() + "</td></tr>");
}
}
}
@@ -1948,7 +1907,7 @@ public class I2PSnarkServlet extends BasicServlet {
//out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
// + _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br>\n");
Map<String, String> options = new TreeMap(_manager.util().getI2CPOptions());
Map<String, String> options = new TreeMap<String, String>(_manager.util().getI2CPOptions());
out.write("<tr><td>");
out.write(_("Inbound Settings"));
out.write(":<td>");
@@ -2039,12 +1998,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (privateTrackers.contains(t.announceURL)) {
buf.append(" checked=\"checked\"");
} else {
for (int i = 1; i < SnarkManager.DEFAULT_TRACKERS.length; i += 2) {
if (SnarkManager.DEFAULT_TRACKERS[i].contains(t.announceURL)) {
buf.append(" disabled=\"disabled\"");
break;
}
}
if (SnarkManager.DEFAULT_TRACKER_ANNOUNCES.contains(t.announceURL))
buf.append(" disabled=\"disabled\"");
}
buf.append(">" +
"</td><td>").append(urlify(announceURL, 35))
@@ -2244,7 +2199,7 @@ public class I2PSnarkServlet extends BasicServlet {
* @return String of HTML or null if postParams != null
* @since 0.7.14
*/
private String getListHTML(File r, String base, boolean parent, Map postParams)
private String getListHTML(File r, String base, boolean parent, Map<String, String[]> postParams)
throws IOException
{
File[] ls = null;
@@ -2420,7 +2375,7 @@ public class I2PSnarkServlet extends BasicServlet {
.append(":</b> ")
.append(formatSize(needed));
if (meta != null) {
List files = meta.getFiles();
List<List<String>> files = meta.getFiles();
int fileCount = files != null ? files.size() : 1;
buf.append("&nbsp;<img alt=\"\" border=\"0\" src=\"" + _imgPath + "file.png\" >&nbsp;<b>")
.append(_("Files"))
@@ -2519,7 +2474,6 @@ public class I2PSnarkServlet extends BasicServlet {
Storage storage = snark.getStorage();
try {
File f = item;
if (f != null) {
long remaining = storage.remaining(f.getCanonicalPath());
if (remaining < 0) {
complete = true;
@@ -2539,9 +2493,6 @@ public class I2PSnarkServlet extends BasicServlet {
(100 * (length - remaining) / length) + "% " + _("complete") +
" (" + DataHelper.formatSize2(remaining) + "B " + _("remaining") + ")";
}
} else {
status = "Not a file?";
}
} catch (IOException ioe) {
status = "Not a file? " + ioe;
}
@@ -2553,8 +2504,7 @@ public class I2PSnarkServlet extends BasicServlet {
path=addPaths(path,"/");
String icon = toIcon(item);
buf.append("<TD class=\"snarkFileIcon ")
.append(rowClass).append("\">");
buf.append("<TD class=\"snarkFileIcon\">");
if (complete) {
buf.append("<a href=\"").append(path).append("\">");
// thumbnail ?
@@ -2569,24 +2519,23 @@ public class I2PSnarkServlet extends BasicServlet {
} else {
buf.append(toImg(icon));
}
buf.append("</TD><TD class=\"snarkFileName ")
.append(rowClass).append("\">");
buf.append("</TD><TD class=\"snarkFileName\">");
if (complete)
buf.append("<a href=\"").append(path).append("\">");
buf.append(item.getName());
if (complete)
buf.append("</a>");
buf.append("</TD><TD ALIGN=right class=\"").append(rowClass).append(" snarkFileSize\">");
buf.append("</TD><TD ALIGN=right class=\"snarkFileSize\">");
if (!item.isDirectory())
buf.append(DataHelper.formatSize2(length)).append('B');
buf.append("</TD><TD class=\"").append(rowClass).append(" snarkFileStatus\">");
buf.append("</TD><TD class=\"snarkFileStatus\">");
//buf.append(dfmt.format(new Date(item.lastModified())));
buf.append(status);
buf.append("</TD>");
if (showPriority) {
buf.append("<td class=\"priority\">");
File f = item;
if ((!complete) && (!item.isDirectory()) && f != null) {
if ((!complete) && (!item.isDirectory())) {
int pri = snark.getStorage().getPriority(f.getCanonicalPath());
buf.append("<input type=\"radio\" value=\"5\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
if (pri > 0)
@@ -2643,8 +2592,10 @@ public class I2PSnarkServlet extends BasicServlet {
if (mime.equals("text/html"))
icon = "html";
else if (mime.equals("text/plain") ||
mime.equals("text/x-sfv") ||
mime.equals("application/rtf") ||
mime.equals("application/epub+zip"))
mime.equals("application/epub+zip") ||
mime.equals("application/x-mobipocket-ebook"))
icon = "page";
else if (mime.equals("application/java-archive") ||
plc.endsWith(".deb"))
@@ -2684,17 +2635,16 @@ public class I2PSnarkServlet extends BasicServlet {
}
/** @since 0.8.1 */
private void savePriorities(Snark snark, Map postParams) {
private void savePriorities(Snark snark, Map<String, String[]> postParams) {
Storage storage = snark.getStorage();
if (storage == null)
return;
Set<Map.Entry> entries = postParams.entrySet();
for (Map.Entry entry : entries) {
String key = (String)entry.getKey();
for (Map.Entry<String, String[]> entry : postParams.entrySet()) {
String key = entry.getKey();
if (key.startsWith("pri.")) {
try {
String file = key.substring(4);
String val = ((String[])entry.getValue())[0]; // jetty arrays
String val = entry.getValue()[0]; // jetty arrays
int pri = Integer.parseInt(val);
storage.setPriority(file, pri);
//System.err.println("Priority now " + pri + " for " + file);

View File

@@ -73,7 +73,7 @@ public class InclusiveByteRange
* @param size Size of the resource.
* @return List of satisfiable ranges
*/
public static List<InclusiveByteRange> satisfiableRanges(Enumeration headers, long size)
public static List<InclusiveByteRange> satisfiableRanges(Enumeration<?> headers, long size)
{
List<InclusiveByteRange> satRanges = null;
@@ -128,7 +128,7 @@ public class InclusiveByteRange
if (first < size)
{
if (satRanges == null)
satRanges = new ArrayList(4);
satRanges = new ArrayList<InclusiveByteRange>(4);
InclusiveByteRange range = new InclusiveByteRange(first,last);
satRanges.add(range);
}

View File

@@ -21,8 +21,6 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
/* ------------------------------------------------------------ */
/**
@@ -48,7 +46,7 @@ class MimeTypes
private final Map<String, String> _mimeMap;
public MimeTypes() {
_mimeMap = new ConcurrentHashMap();
_mimeMap = new ConcurrentHashMap<String, String>();
}
/* ------------------------------------------------------------ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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