Compare commits

..

424 Commits

Author SHA1 Message Date
zzz
eafca84717 0.9.3 2012-10-27 13:03:14 +00:00
zzz
0bfe8ff41d * BuildHandler: Fix "too slow" rejections due to internal clock skew 2012-10-25 18:58:12 +00:00
str4d
804f0294bb Bumped router to -21 for previous commit 2012-10-25 02:51:18 +00:00
str4d
7a4430856d Tweaked default value of lastLine in susimail to make a no-response error clearer to users 2012-10-25 02:49:13 +00:00
str4d
6bd40e253a Bumped router to -20 for previous commit 2012-10-24 19:55:35 +00:00
str4d
c2d178efc3 Fixed a very stupid bug >_< 2012-10-24 19:51:54 +00:00
zzz
97da508df5 * I2PSnark:
- Fix (again) partial piece avoidance for seeds
   - Fix several partial piece (temp file) leaks,
     some uncovered by previous rarest-first fixes, some in end game
   - Don't lose all DHT peers if we stop quickly (backport from update branch)
   - Explore a kbucket if it's less than 3/4 full (backport from update branch)
2012-10-24 17:38:20 +00:00
str4d
211128f128 i2ptunnel: Truncate long client destinations (ticket #581) 2012-10-24 02:30:19 +00:00
meeh
fc461931bd Adding a new reseed host. 2012-10-23 14:08:12 +00:00
meeh
e5a8a6aba4 merge of '7ca37d4f5e443834de23ebd2cf306b6fe3aeca87'
and 'f9d82ac84936c56dc92691842757e8cc354511e2'
2012-10-22 20:24:53 +00:00
meeh
da835fbd6b h2ik don't have static ip anymore. 2012-10-22 19:52:21 +00:00
zzz
95870df45b * Watchdog: Don't dump threads too often (ticket #519) 2012-10-21 17:21:49 +00:00
zzz
e329742c8d * Transport: Back out CoDel for SSU PeerState and NTCP 2012-10-20 11:37:31 +00:00
zzz
5695d0e94a build fix 2012-10-20 03:38:54 +00:00
zzz
5a964dacbb * UDP: Fix peer test NPE (ticket # 748) 2012-10-19 22:03:41 +00:00
kytv
580c940d42 More pt trans updates from tx 2012-10-19 07:49:36 +00:00
kytv
7ea8cd4a09 Geoip update 2012-10-18 22:37:50 +00:00
kytv
a6ca962fcb Portuguese and Spanish updates from Transifex 2012-10-18 15:19:13 +00:00
kytv
b816ecc7e3 Italian and Swedish updates from Transifex 2012-10-15 18:05:38 +00:00
zzz
8df2a2d00a * i2psnark: Fix request tracking bug preventing piece requests 2012-10-14 16:38:36 +00:00
zzz
184220f4c5 minor optimization 2012-10-14 13:54:38 +00:00
zzz
5d6d27907d * Console: Use non-nio connector for Java 5 and JamVM/gij
(tickets #715 and #743)
 * SystemVersion: Centralize more methods here
2012-10-14 13:54:08 +00:00
kytv
cb56b76ef9 i2prouter: check /proc/1/comm for systemd (thanks k0e) 2012-10-13 12:45:25 +00:00
kytv
eff238e85c i2prouter: In Slackware, check for existence of /etc/rc.d/rc.i2p when installing as a daemon 2012-10-12 17:26:03 +00:00
kytv
a436e60fb8 Italian translation updates / updated EN po files 2012-10-12 00:52:09 +00:00
kytv
2c570f8d4e remove internel I2P link
Let's not direct people to see how to configure their browser at
http://www.i2p2.i2p/htproxyports when you need to have your proxy configured to go there!
2012-10-11 22:48:06 +00:00
kytv
6f23bdd331 remove another link to forum.i2p2.de 2012-10-11 22:43:51 +00:00
kytv
b797f9e26d remove link to forum.i2p2.de 2012-10-11 22:42:03 +00:00
kytv
2b13973eca debian: refresh patches 2012-10-10 23:32:27 +00:00
kytv
9331b229fe addressing a few concerns from #681 2012-10-10 23:32:04 +00:00
kytv
ccd0795a4e turn off executable bit 2012-10-10 23:31:07 +00:00
kytv
1f98493dbd i2prouter: add initscript support to Slackware 2012-10-10 22:44:42 +00:00
kytv
f20d906b67 i2prouter: Add systemd support for Arch Linux and SuSE Linux. 2012-10-10 21:33:05 +00:00
zzz
65757dee1c * ShellCommand: Fix launching all browsers at startup (ticket #453) 2012-10-10 19:12:30 +00:00
zzz
b259a3ac3d * stats.jsp: Sort groups by translated name 2012-10-10 19:11:18 +00:00
zzz
ca1f816ad9 remove colombo 2012-10-10 15:06:51 +00:00
zzz
1b154551a2 EventLog: add more events 2012-10-09 10:35:47 +00:00
zzz
c419016a12 * SSU:
- Add peer test throttling
   - Peer test packet count fixes
   - Adjust peer test timeouts and add backoff
   - Reject relays and peer tests from same /16
   - More peer test cleanup and log tweaks
 * Transports:
   - Enforce minimum peer port
   - Warn on low router ports
2012-10-09 10:20:45 +00:00
zzz
f10478ceef comment out test 2012-10-09 10:16:05 +00:00
zzz
d477773054 * NetDB: Increase floodfills again 2012-10-09 10:15:44 +00:00
zzz
8ed280ebf4 * RouterInfo: Exit 1 on error in main() 2012-10-09 10:14:56 +00:00
zzz
762e96b8a6 2 more for cache 2012-10-09 10:13:59 +00:00
zzz
23c77fbe4b * Console, i2ptunnel: Warn on low ports 2012-10-09 10:13:10 +00:00
zzz
e99dd72cb6 * SSU:
- Fix relay request handling bug from -10
   - Fix peer test reply handling bug from -10
   - Fix NPE from -6
2012-10-08 09:32:04 +00:00
zzz
b095b7e769 * i2ptunnel:
- Set default read timeout in standard server
   - Reduce header timeout, enforce total header timeout
     in IRC and HTTP servers (ticket #723)
 * Streaming: Don't ignore option or force connect timeout to 5 minutes
 * Streaming javadocs
 * SocketTimeout cleanup
2012-10-07 20:57:35 +00:00
zzz
6b97e1bfaf * Logs:
- Flush buffers in logs.jsp
   - Add dup message to buffers, was in file only
2012-10-07 20:50:26 +00:00
zzz
3ceb83d40e * I2PAppContext: Improved synching in constructor 2012-10-07 20:48:25 +00:00
zzz
d80340f0ae * UPnP: Workaround NPE (ticket #728)
root cause TBD
2012-10-07 20:47:22 +00:00
zzz
3acc2fb160 - Much improved peer test defenses
- Minor improvements to relay defenses
2012-10-06 22:47:17 +00:00
zzz
034db1a282 Validate port/IP in received peer tests 2012-10-06 14:58:42 +00:00
zzz
b07b9bf0b9 * SSU:
- Throttle outbound destroys on shutdown
   - Limit outbound introduction offers
2012-10-06 13:44:57 +00:00
zzz
97460e7d99 * configlogging.jsp: Fix IAE
* error500.jsp: Fix whitespace
2012-10-06 13:42:48 +00:00
zzz
ddc750469c * i2psnark:
- Add allocating and checking indications
   - Add bandwidth message at startup
   - More checks at torrent creation
2012-10-06 13:41:50 +00:00
zzz
0448537509 make inbound and exploratory settings final 2012-10-05 13:38:27 +00:00
zzz
583463ab42 * configservice.jsp: Add GC button 2012-10-05 13:09:34 +00:00
zzz
b20e298f6e * SSU:
- More synchronization fixes
   - Reduce chance of dup acks in a single message
   - Reduce max unsent acks to 50
   - Use last ack time in ping decision too
   - Reduce ack delay
2012-10-05 13:08:05 +00:00
zzz
090d59fcb7 * DataHelper: Sanity checks in storeProps(), use
storeProps() for router config again
2012-10-05 13:00:52 +00:00
zzz
1d174d6797 * TunnelPoolManager: Fix early NPE (ticket #724) 2012-10-05 12:59:30 +00:00
zzz
15a47b5612 import 2012-10-03 19:17:55 +00:00
zzz
4d1ea6e4cd * SSU:
- Increase max outbound establishments based on bandwidth
   - Synchronization fix for Java 5
   - Use multiple buffer sizes in OutboundMessageState to
     reduce memory usage
   - Adjust skew calculation, synchronize too
   - Ping loop improvements
2012-10-03 19:05:56 +00:00
zzz
13ef00cb2e add hasWrapper() 2012-10-03 17:41:33 +00:00
zzz
d2c1641569 * NTCP: Reduce conLock contention 2012-10-03 17:40:59 +00:00
zzz
a1873e74e5 cleanup 2012-10-03 17:40:31 +00:00
kytv
8be86fe80c debian: rework oom patch 2012-10-02 19:26:04 +00:00
zzz
4dc90ef5da * SSU:
- Fix memory leak in _peersByRemoteHost map caused by not
     removing peers that change IP or port
   - Send keepalives if firewalled
   - Handle peers that change ports on an established session
   - Synchronize adds and drops
   - Don't use peers with high RTTs in clock skew calculation
   - Reduce initial RTT/RTO
2012-10-02 18:36:06 +00:00
zzz
e130264254 * NTCP: Only set keepalive if firewalled 2012-10-02 12:41:31 +00:00
zzz
93039a6813 * OOMListener: Dump threads on OOM 2012-10-02 12:40:00 +00:00
zzz
07b3c8a7b4 * PRNG, LogWriter: Use I2PThread to catch OOM 2012-10-02 12:38:05 +00:00
zzz
83fe635438 * i2ptunnel: Fix log message 2012-10-02 12:37:16 +00:00
zzz
3ee96fb663 * i2psnark: Fix delete download message 2012-10-02 12:36:34 +00:00
zzz
6684ba1b1d * I2CP: Delay after sending disconnect message to
help it get through
2012-10-02 12:35:45 +00:00
zzz
466778875d * SimpleByteCache: Fix ABQ/LBQ selection 2012-10-02 12:34:29 +00:00
zzz
a71e8fae00 * i2psnark:
- Fix bugs in rarest-first tracking
   - Fix requesting of partial piece when there are multiple seeds
   - Synch fix in BitField
2012-09-28 19:25:31 +00:00
zzz
f58bf3028a javadoc 2012-09-28 19:08:00 +00:00
zzz
595556c39f * SessionKeyManager: Store original tagset size for debugging 2012-09-28 19:06:39 +00:00
zzz
eeaa4fbbb4 * peers.jsp: Remove SSU "Dev" column 2012-09-28 18:48:58 +00:00
zzz
49b11e1f84 * Streaming: Don't send RST on globally-blackisted conns 2012-09-28 18:48:16 +00:00
zzz
e3133d88d7 javadoc 2012-09-28 18:42:17 +00:00
zzz
1a50b6243d volatile 2012-09-28 18:41:19 +00:00
zzz
076558d4f5 * i2ptunnel: Fix wrong server IP in log message 2012-09-28 18:40:49 +00:00
zzz
fb5d0cd760 Boolean.valueOf(x).booleanValue() -> Boolean.parseBoolean(x) 2012-09-28 17:50:41 +00:00
zzz
7c8ba61f03 fix date 2012-09-26 20:03:10 +00:00
zzz
20e463e41b * Streaming:
- Implement changing connection limits on a running session
   - Implement global blacklist
2012-09-26 20:02:36 +00:00
zzz
5d3984e353 * Addresses: Reject numeric IPs of the form n, n.n, and n.n.n
* Console, i2ptunnel: More validation of address and port in forms
2012-09-26 20:00:59 +00:00
zzz
941aea80bb javadoc 2012-09-26 19:58:19 +00:00
zzz
0533aa7f6f * RFC822Date: Synchronization fix 2012-09-26 19:58:08 +00:00
zzz
568e2d5063 tweak to port field CSS 2012-09-26 19:57:37 +00:00
zzz
86c7aa8b8a * i2psnark: Enable DHT by default 2012-09-26 19:57:01 +00:00
zzz
f61e7a193f * ConvertToHash:
- Add support for b64hash.i2p (output in jetty logs)
   - Cleanup and use cache
2012-09-26 19:56:33 +00:00
str4d
567dae8ced merge of '6ccace0742effd1eaadcc151f428825fa3215e12'
and 'dc06981e777b7e1c191937d6d8190b26a8f6bbc7'
2012-09-25 22:26:47 +00:00
str4d
02f483a873 Modified susimail footer so <hr> is hidden as well 2012-09-25 21:57:22 +00:00
zzz
7051e1c5f6 * UPnP: Cleanup & final 2012-09-25 19:30:49 +00:00
zzz
87295b4bfd * URLLauncher: Add xdg-open (ticket #617); minor refactor 2012-09-25 19:25:01 +00:00
zzz
23ca6b4fac * SimpleByteCache: Concurrent fix 2012-09-25 19:24:11 +00:00
zzz
9e3559625c * OutboundEstablishState: Cleanup (ticket #671) 2012-09-25 19:22:36 +00:00
zzz
351d582c8f * Jetty: Add non-NIO selector option (ticket #715) 2012-09-25 19:21:28 +00:00
zzz
5b1ea6187f * EventLog: Fix IAE on portable 2012-09-25 19:20:15 +00:00
zzz
211782fae4 * Context: Make files final 2012-09-25 19:19:27 +00:00
str4d
44466aa769 Modified susidns footer so <hr> is hidden as well 2012-09-24 22:17:05 +00:00
str4d
d27d014eb0 Show susi footer on susimail and susidns when displayed standalone
Footer hidden when embedded because of margin issues, and out-of-place-ness.
Have confirmed that susi's opinion when the themes were initially updated was
"do what you want", so no legal problem.
2012-09-22 23:47:57 +00:00
zzz
e884ca54ef -1 2012-09-21 17:54:46 +00:00
zzz
336420cf50 propagate from branch 'i2p.i2p.zzz.test' (head 5dadb7923797a3e6d9ead4d4b17ab7e0e0201b2b)
to branch 'i2p.i2p' (head 703251aaf19111efe6fac5a4ae49f00a1aac1e9e)
2012-09-21 17:50:59 +00:00
zzz
f16e83f21b 0.9.2 2012-09-21 14:24:53 +00:00
zzz
0eedc3aa19 intern strings 2012-09-19 20:47:50 +00:00
zzz
f232775161 CoDel for build handler 2012-09-19 19:00:06 +00:00
zzz
bd57463d42 fix NTCP backlogged indication 2012-09-18 12:37:30 +00:00
zzz
2c4910e9e7 * ByteCache, ByteArray:
- Cleanups and javadocs
    - Prevent release of a wrong-sized array
2012-09-17 21:57:16 +00:00
zzz
2b14d32bea use ByteCache for chunks in/out 2012-09-17 21:32:05 +00:00
meeh
ee66747def Fix after review and install on fresh osx (lession learned: test clean installs) 2012-09-17 20:33:03 +00:00
zzz
259c28f8c1 startup/shutdown synchronization in several places 2012-09-16 15:47:36 +00:00
zzz
b6a5360390 log/stat tweaks 2012-09-16 15:46:36 +00:00
zzz
0b7b947786 increase flush interval 2012-09-16 15:43:36 +00:00
zzz
147e257cee comment out main() 2012-09-16 15:43:06 +00:00
zzz
ccb8483766 * Build: Fix unpack problem on Java 5: http://forum.i2p/viewtopic.php?t=7334 2012-09-15 13:12:00 +00:00
zzz
68ccb3a944 cleanup 2012-09-14 13:53:36 +00:00
zzz
b317eca5e3 * SSU: Fix shutdown NPE (ticket #709) 2012-09-14 13:50:06 +00:00
zzz
5ffacccdd7 update geoip license 2012-09-14 13:49:32 +00:00
zzz
a41936af94 typo 2012-09-14 13:49:09 +00:00
kytv
0991adc291 GeoIPdb update based on Maxmind GeoLite Country database from 2012-09-05 2012-09-13 16:15:09 +00:00
zzz
b9aceb895d * SSU:
- Increase initial and max RTO
    - Don't count ack-only packets in bandwidth allocation
    - Unused method cleanup
2012-09-12 21:55:15 +00:00
zzz
8633ef9513 * Streaming: Don't send a RST to an hour/day limited peer,
or blacklisted, or non-whitelisted, to not waste outbound bandwidth
2012-09-12 21:52:12 +00:00
kytv
7820cef60a Czech language translation updates from transifex
(and updated en po files)
2012-09-12 12:04:43 +00:00
zzz
4666454482 improve dup log message 2012-09-11 19:50:59 +00:00
zzz
db42d9ec37 * FortunaRandomSource:
- Fix bug that wasted entropy in nextInt()
    - Improved synchronization
2012-09-11 19:40:20 +00:00
zzz
d7b48a2256 change what we call imminent so we dont display ms 2012-09-10 22:40:21 +00:00
zzz
50ec279917 use partial match for dups; add config for dups 2012-09-10 22:38:18 +00:00
zzz
e8a8f3c210 * TunnelGateway: Implement pushback from a backlogged transport
queue to the pre-fragmentation queue
2012-09-10 21:30:54 +00:00
zzz
e0fc642fc3 reduce _jobLock contention 2012-09-10 17:27:18 +00:00
zzz
835ed6d9bb boost priority of shutdown thread 2012-09-10 17:25:00 +00:00
zzz
3781928693 logging cleanups 2012-09-10 17:22:51 +00:00
kytv
cb39006f6c minor corrections after review
The newly added OSX bits by meeh (thanks!) do not require Izpack to perform
substitutions, so I'm removing those files from the <parseable> tags.
2012-09-10 10:51:17 +00:00
meeh
52447096f2 Added a fix for a startup issue in newer versions of launchd. Setting Disabled
in configfile will only work on older launchd version. Ref manpage:
  (-w Overrides the Disabled key and sets it to false. In previous ver-
      sions, this option would modify the configuration file. Now the
      state of the Disabled key is stored elsewhere on-disk.)
2012-09-10 03:14:09 +00:00
zzz
2f98d05e7c * Clock: Synchronization, log large shifts to event log 2012-09-09 15:45:29 +00:00
zzz
74e753934c * SystemVersion: New util, to consolidate duplicate code,
and determine Java version on Android
2012-09-09 15:40:14 +00:00
zzz
9bc54f27cf * ClientManager:
- Concurrent client map for faster lookup
    - Add by-hash client map for faster lookup by hash
    - More cleanups
2012-09-08 21:56:05 +00:00
zzz
d9e6c06b22 * I2CP: Buffer output streams
* ClientConnectionRunner: More cleanups and edge cases
2012-09-08 20:45:11 +00:00
zzz
e02d82981a - Run HandleJob inline for speed
- Remove payload from message map if availability announce fails
- Cleanups
2012-09-08 15:10:27 +00:00
zzz
98da06cd83 limit queue size, make nonblocking 2012-09-08 14:25:04 +00:00
zzz
0d62266008 * ClientConnectionRunner: Run MessageReceivedJob inline for speed 2012-09-08 14:04:01 +00:00
zzz
1ae0c2e312 add -test 2012-09-08 13:15:58 +00:00
zzz
61629080b2 propagate from branch 'i2p.i2p' (head 86f3e7e668b7ec9f2ddf75be7586719944bbc37f)
to branch 'i2p.i2p.zzz.test' (head da9536c250bc4c0b7523ed748574de1cc97f3028)
2012-09-08 12:57:09 +00:00
zzz
4cf104720c * PumpedTunnelGateway:
- Move OBGW queue to CoDelPriority
    - Move IBGW queue to CoDel
    - Reduce max pumped per cycle for IBGW
2012-09-08 12:47:17 +00:00
zzz
2c866e205b * NTCP: Move NTCPConnection outbound queue to CoDelPriority
* SSU:
    - Separate PeerState outbound message list into a queue for unsent messages
      and a list for sent messages awaiting ack
    - Implement PeerState outbound queue as CoDelPriority
    - Implement backlogged indication like in NTCP
2012-09-08 12:40:27 +00:00
zzz
ca91ad3188 * SSU: Move MessageReceiver queue to CoDel 2012-09-08 12:34:34 +00:00
zzz
33de6beab3 * SSU: Move UDPSender and UDPReceiver queues to CoDel 2012-09-08 12:29:55 +00:00
zzz
871f046755 adjust target and interval, and backlogged indication 2012-09-08 12:23:43 +00:00
zzz
aef021dcd1 * I2CP: Limit router/client queue sizes and queue wait times 2012-09-07 22:49:24 +00:00
zzz
489f43529c booleanValue() -> parseBoolean() 2012-09-07 20:13:49 +00:00
zzz
78203aac9a * i2psnark:
- Implement blacklist for unreachable DHT peers
    - Reduce threshold for unreachable
    - Log tweaks
2012-09-07 20:10:01 +00:00
zzz
3c95f0b66b * LogWriter: Duplicate log message removal 2012-09-07 18:53:24 +00:00
zzz
3347788712 add isBacklogged() 2012-09-06 19:53:01 +00:00
zzz
0c5b4c05c6 minor cleanups 2012-09-06 19:25:31 +00:00
meeh
5056706742 Added command scripts for osx to install i2p as a daemon in launchd.
.command extension make it possible to double click on it like bat files
in windows. Daemon is runned as the user who executes the command file.
2012-09-05 21:36:24 +00:00
zzz
b8949eafe2 Non-codel version of priority blocking queue, so we can
implement priority queues without necessarily committing to codel.
2012-09-05 15:50:11 +00:00
zzz
9286d6a7b8 * IP Lookup:
- Add caching in RouterAddress with secondary caching
      in Addresses; use caches to speed up transport bids,
      blocklist checks, geoip lookups, and profile organizer checks
      (ticket #707)
    - Limit IP cache size in TransportImpl
    - Clear caches at shutdown
  * RouterAddress: Remove unused expiration field to save space
2012-09-04 20:33:04 +00:00
zzz
9fd2f1e6a7 SSU: Fix some issues with queueing outbound establishments 2012-09-04 13:51:55 +00:00
zzz
b98474880d OutNetMessage: Speedup after profiling (ticket #707 - thx dg, kytv, zab) 2012-09-04 13:50:24 +00:00
zzz
5347d296dc log tweak 2012-09-04 13:46:52 +00:00
zzz
666a387d1b log fix 2012-09-04 13:46:31 +00:00
zzz
bb66e16b69 I2PTunnelServer: Clean shutdown after session exception 2012-09-04 13:46:10 +00:00
zzz
2cddf1405f log tweaks 2012-09-04 00:27:04 +00:00
zzz
8575437626 * LHMCache: New util, replacing several private versions 2012-09-03 15:33:12 +00:00
zzz
c965a3dca0 add drainAllTo() 2012-09-02 14:41:21 +00:00
zzz
c48aca8d5c ByteCache: Move all 16/32 byte users to SimpleByteCache;
increase SimpleByteCache default size.
2012-09-02 12:31:08 +00:00
zzz
4360284355 stat and log tweaks 2012-09-02 00:45:58 +00:00
zzz
f44eeaf7dd TunnelGateway: Refactor TunnelGateway.Pending to its own file PendingGatewayMesasge 2012-09-01 21:39:14 +00:00
zzz
a0418bec59 OutNetMessage:
- Centralize priority definitions
  - Raise netdb store and reply priority
GarlicMessage:
  - Add notes about GarlicMessageHandler and HandleGarlicMessageJob
    being unused in practice
2012-09-01 20:47:22 +00:00
zzz
5eff26e40e add minimum priority check 2012-09-01 20:17:37 +00:00
zzz
4e78517651 TunnelGateway:
- Limit queue sizes
  - Add stat for overflow
  - Remove some stats
  - Change pumper to LinkedHashSet for efficiency
    (like NTCP Reader/Writer)
  - Limit messages pumped per cycle to increase
    round-robin fairness
  - Comment out some unused code
  - Javadoc
2012-09-01 17:20:52 +00:00
zzz
10d9eb70c8 CoDel:
- Add logging of drops
  - Set drop stat to delay of dropped item
  - Add no-drop priority
2012-09-01 16:30:12 +00:00
kytv
0ba3aad666 Disable i2jump.i2p from the tunnel wizard since it's been disabled elsewhere 2012-09-01 15:02:38 +00:00
zzz
8bfbe855a1 one last SimpleTimer 2012-09-01 13:40:38 +00:00
zzz
3fbf60ee21 Codel:
- Override poll() and drainTo()
  - Tweak stats
  - Add PriorityBlockingQueue version
2012-09-01 13:21:25 +00:00
zzz
6bfd916fef SimpleTimer (ticket #653):
- Move all remaining uses to SimpleTimer2
    - Deprecate
2012-09-01 13:14:15 +00:00
zzz
a5e4b15349 add irc.killyourtv.i2p 2012-08-31 14:47:14 +00:00
zzz
94f370e76c propagate from branch 'i2p.i2p' (head 871765966dc474b763ff0d5c017bed7535981c1e)
to branch 'i2p.i2p.zzz.test' (head 096242c22aa550274cb383a6a0c984cef07ae08c)
2012-08-31 14:41:18 +00:00
zzz
7cc353ab04 javadoc 2012-08-31 14:36:53 +00:00
zzz
506626d6b1 i2psnark: Remove * from magnet and download names 2012-08-31 13:58:37 +00:00
zzz
26898f38ad Startup: Don't complain about clients.config missing on Android 2012-08-31 13:57:24 +00:00
zzz
4fdff1bf13 Router: Lengthen shutdown spinner life 2012-08-31 13:56:24 +00:00
sponge
7d4a6e74d2 Report no bugs in Android BitSet 2012-08-31 03:53:19 +00:00
sponge
b33a01cf26 use index instead of upper and lower, it's the same thing, but makes more sense. 2012-08-31 02:37:15 +00:00
zzz
0689b03603 - Prevent crashes at update caused by event log starting timestamper thread 2012-08-30 15:29:35 +00:00
zzz
ee8cd29da9 New AQM blocking queue using CoDel reference implementation - untested. 2012-08-30 14:20:37 +00:00
zzz
c4a3159b33 Replace ident log with new, general-purpose event log.
Use for stops, starts, and updates, and others.
Mark all restarts on graphs using the event log.
2012-08-30 14:06:06 +00:00
kytv
a4511ca2ab typo fix 2012-08-29 19:17:40 +00:00
zzz
17b4ab6151 message cleanup 2012-08-29 14:16:19 +00:00
zzz
d2a7af2884 refactor trimmers to their own files 2012-08-29 14:05:02 +00:00
zzz
d05f1ca2c8 RandomIterator: Workaround for Android bug (ticket #703)
Include test case
2012-08-29 13:59:44 +00:00
zzz
832d66bfb9 NTCP: Reduce lock contention (ticket #697) 2012-08-29 13:47:05 +00:00
zzz
c8a46dac5d i2psnark:
- Add new flood-resistant KBucket trim policy
   - Limit received MsgID size
2012-08-29 13:45:29 +00:00
zzz
7005376061 - Fix NPE on destroy() if init() failed 2012-08-29 13:29:13 +00:00
zzz
ab213f45e2 cleanups 2012-08-29 13:28:03 +00:00
zzz
fa504ae8a3 - Fix cases where we weren't using the session for b32 lookup 2012-08-27 21:36:39 +00:00
zzz
d305eb6a9c * SSU:
- Limit UDPSender queue size
   - Increase UDPSender max packet lifetime
   - Clear UDPSender queue before sending destroys to all
   - Increase PeerState queue size so large streaming windows
     don't get dropped right away, especially at slow start
   - Various improvements on iterating over pending outbound
     messages in PeerState
2012-08-27 20:39:00 +00:00
zzz
f8bc6f8612 * Streaming: Limit amount of slow-start exponential growth 2012-08-27 20:36:24 +00:00
zzz
9099937119 * Reseed: Remove forum.i2p2.de 2012-08-27 20:35:02 +00:00
zzz
b827468e2f * i2psnark: Notify threads awaiting DHT replies at shutdown 2012-08-27 20:34:19 +00:00
zzz
587795552e Wrapper files for armv7.
Compiled on trimslice:
    gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) 
    java version "1.6.0_18"
    OpenJDK Runtime Environment (IcedTea6 1.8.13) (6b18-1.8.13-0ubuntu1~11.04.1)
    OpenJDK Zero VM (build 14.0-b16, mixed mode)
    Wrapper 3.5.15 GPLv2
    All binaries stripped.
2012-08-27 17:43:04 +00:00
kytv
0a1ff9b6bd Update Java Service Wrapper to v3.5.15.
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
   changed from Tanuki's default to Itoopie.
 - FreeBSD: Self-compiled in FreeBSD 7.4 to eliminate the dependency on the
   compat6x port.
 - Linux ARMv5 & PPC32: Self-compiled in Debian Squeeze
 - Linux x86, Linux x64, MacOSX & Solaris: Binares are from the "community
   edition" deltapack offered by Tanuki. The x86 and x64 binaries for Linux
   have been stripped.
2012-08-27 13:49:18 +00:00
zzz
b01cf32321 * SendMessageOptions: Increase tag fields to 4 bits and use
table lookup for more flexibility
 * Streaming: Use packet type and current window size to adjust
              number of tags sent and tag threshold, to improve
              efficiency and reliability
2012-08-26 13:02:11 +00:00
zzz
9ba6c293ed * DataHelper: Trim trailing whitespace when loading properties 2012-08-26 12:54:49 +00:00
zzz
99681e1d1e * NetDB: Increase floodfills, decrease flood redundancy 2012-08-26 12:47:31 +00:00
kytv
96775acf5a Dutch and German translation updates from TX 2012-08-25 19:43:25 +00:00
kytv
ba992067ad typo fixes (ticket #701), thanks vz 2012-08-25 19:05:45 +00:00
zzz
2552d99308 * Other object churn cleanups (ticket #699) 2012-08-25 14:48:39 +00:00
zzz
e99e25b3b9 minor cleanup 2012-08-25 14:45:31 +00:00
zzz
70820d7be6 * SDSCache: Reduce min and increase max size
* SimpleByteCache: Change from LBQ to ABQ to reduce object churn
2012-08-25 14:44:52 +00:00
zzz
38fda46d44 javadoc 2012-08-25 14:42:04 +00:00
zzz
9d383d6aef * i2psnark:
- Use extended I2CP options for datagrams
   - Fix timeout for sent datagrams
   - Reduce token timeout
   - Check token age before use
   - Limit incoming token size
2012-08-24 22:13:08 +00:00
zzz
ba0408a741 * I2CP:
- Add methods for sending a message with extended options
   - Fix cases where the efficient sendNoEffort() wasn't being used
 * OCMOSJ:
   - Implement per-message overrides for tag threshold,
     tags to send, and bundle leaseset
   - Fix bug adjusting timeouts
   - Warn on client expiration time bugs
2012-08-24 22:11:02 +00:00
zzz
07c21c3bfd - Add link for local torrent file on details page
- Show totals line even if only one torrent
2012-08-24 22:07:00 +00:00
zzz
5ffefd2a19 * Crypto: Rename bouncycastle HMAC libs so they don't conflict
with older Android versions which bundle them
2012-08-23 19:11:55 +00:00
zzz
e3e15850bb * SSU:
- Don't relay or introduce to/from privileged ports
   - Various spoof detections
2012-08-23 19:10:36 +00:00
zzz
54b367b153 * NTCP: Reduce lock contention 2012-08-23 19:08:45 +00:00
zzz
b61127270e * SSU:
- Fail establishment immediately on SessionCreated
     validation fail
   - Defer outbound DH generation until required
   - Validate address/port in RelayIntro messages
   - Throttle hole punches
   - More cleanups
2012-08-22 17:43:09 +00:00
zzz
1d41c2fd19 SSU: Workaround for Android ICS bug 2012-08-22 17:41:43 +00:00
zzz
7c7e131dc0 * SimpleTimer2: Synchronization improvements (ticket #653) 2012-08-22 17:40:47 +00:00
zzz
85fbbf8980 * NetDB: Add hash collision detection 2012-08-22 17:40:25 +00:00
zzz
612fab1b2a * SSU:
- Use external, not internal port to sign SessionCreated message.
     Together with previous fix to allow external port change, this
     should fix session establish fails when NAT changes our port
   - Track outbound establishments by both Hash and IP/port,
     to improve lookups of establishments in progress
   - Fix expiration of outbound establishments
   - Validate address/port in RelayResponse messages
   - Change RemoteHostID to store Hash instead of byte[] for the peer hash
   - Log tweaks
2012-08-21 19:53:08 +00:00
zzz
fbd8c69eea * NetDB: Decrease stat publish probability 2012-08-21 19:49:43 +00:00
zzz
8fcac04aad javadoc 2012-08-21 19:48:18 +00:00
zzz
7d902cca1e log tweak 2012-08-21 19:48:04 +00:00
meeh
ddc1d7c6bc disapproval of revision 'acc7942148f44d32fc600d2f5784d1a43496eada' 2012-08-20 21:26:12 +00:00
meeh
5bb90c6185 * Fixed the FIXME in createInstance where the method failed to ensures that there will be only one naming service instance. 2012-08-20 18:28:20 +00:00
zzz
9452547204 * SSU: Allow port change if firewalled
* UPnP:
   - Prep for UPnP returning different external port
   - Better logging of errors
2012-08-20 12:22:00 +00:00
zzz
34c09583b4 do not use 8887 default in UI 2012-08-20 12:14:43 +00:00
zzz
38b0927d01 * I2CP: MessageStatus cleanup 2012-08-20 12:13:26 +00:00
zzz
715bde5ecf * Streaming: Increase max connection timeout 2012-08-20 12:12:48 +00:00
zzz
6c2eb317fe * I2PTunnelRunner: Remove unnecessary lock (ticket #690) 2012-08-20 12:10:10 +00:00
zzz
05516f3260 * i2psnark: Add minimum tracker and DHT announce intervals 2012-08-20 12:09:20 +00:00
kytv
264df83943 fix hang during uninstallation (#656) 2012-08-18 13:06:07 +00:00
zzz
3a546612d9 * SSU:
- Use remote MTU when published (ticket #687)
   - Queue outbound msgs during inbound establish
   - IntroManager cleanups
   - More synchronization
   - More log tweaks
2012-08-17 14:15:01 +00:00
zzz
3cac01ff27 * i2psnark:
- Adjust DHT timeouts
   - Add max peers per-torrent in tracker
   - Remove duplicate clean task for nodes
   - Fix another DHT warning message
2012-08-17 14:09:49 +00:00
sponge
e01521618f BOB: just some cleanup 2012-08-17 05:39:02 +00:00
zzz
ee63f3b86d minor NTCP cleanup 2012-08-16 19:02:38 +00:00
zzz
a900511d5e * Utils: Drop unused BufferedRandomSource, PooledRandomSource,
EepGetScheduler, EepPost and HTTPSendData, moved to i2p.scripts
2012-08-16 18:25:49 +00:00
zzz
3fe092d788 tab cleanup 2012-08-16 18:24:59 +00:00
zzz
e2fe5004e7 javadoc fixes 2012-08-15 14:39:52 +00:00
zzz
442af031eb propagate from branch 'i2p.i2p.zzz.upnp' (head fbd68f812db1e891f96e212b3a5938beec0233b5)
to branch 'i2p.i2p' (head a8d4956565f7c58736c2a3001f2b08ecff59ab57)
2012-08-15 14:29:30 +00:00
zzz
e22882bd02 - More fixups from merge
- Remove local address from thread names for thread dump anonymity
2012-08-15 14:24:40 +00:00
zzz
523d39b3bb * i2psnark:
- Fix bug preventing completion announcement, broken in 0.9.1
   - Fix setting short retry time after initial announce failure
   - Fix DHT announce and getPeers
   - Fix DHT warning message
   - log tweaks
2012-08-15 12:44:46 +00:00
zzz
65efefb094 propagate from branch 'i2p.i2p' (head 51b3351f42e7ff6e2f2bd8512e4b4402e08631f4)
to branch 'i2p.i2p.zzz.upnp' (head d28cfe73c2741ea264f73a7317f8a9919e108170)
2012-08-14 13:50:15 +00:00
zzz
44edf70842 * SSU EstablishmentManager: Fix bug with OB establishment via introducers
- log tweaks
2012-08-13 23:06:07 +00:00
zzz
16a46b3211 * SSU EstablishmentManager:
- Remove use of outbound timers in EstablishmentManager; drive all events in Establisher thread
   - Don't change nonces when retransmitting intro packets
   - More synchronization in EstablishmentManager
   - Increase establishment timeouts and implement timeouts for individual phases (ticket #669)
   - Fix bug where InboundEstablishState.createdPacketSent() wasn't being called,
     so SessionCreated packets weren't retransmitted
   - Increase retransmission timeout for SessionCreated and implement backoff
   - Send destroy if establishment times out in the middle
   - Fix code that pulls outbound states off a deferred queue
   - Improve UDPPacket.toString() for debugging
   - More logging of packets dropped in EstablishmentManager
   - Change establish states to enums
2012-08-13 15:12:33 +00:00
zzz
e9cc85141c comparator cleanups 2012-08-13 15:08:06 +00:00
zzz
cfcafd2ba3 * SSU:
- Reject some packet types if they came in via fallback introKey
   - Increase retransmission timeout for SessionRequest, SessionConfirm,
     and RelayRequest; implement backoff
   - Move UDPFlooder to test
   - More volatiles, finals, cleanups, stat removals, log tweaks
2012-08-12 11:24:15 +00:00
zzz
e67dd15308 * PeerManager: Fix NPE on Android (ticket #687) 2012-08-12 11:19:49 +00:00
zzz
a76f840ff8 remove finalize 2012-08-12 11:18:24 +00:00
zzz
269a36c549 * Jetty: Don't use direct byte buffers that may be leaking (ticket #679) 2012-08-12 11:11:45 +00:00
str4d
36bf248385 Removed unnecessary <p></p> around <img> on /graph 2012-08-12 00:35:09 +00:00
kytv
046135f8e3 merge of '8027b8544962ebd34af3edfe73bbc8195f8c1e90'
and '871249c3be5c8d8ce83a539ba8c5409876ef3a44'
2012-08-11 14:47:43 +00:00
meeh
97e469da7b command safari does not exist. using command "open" instead. 2012-08-11 14:34:20 +00:00
zzz
01beb015dc merge of '52c0538bb3404f46ac4fde538794a547852d5d44'
and 'e40ee84836983c85a8985c0a76e9e5a7635002cd'
2012-08-11 13:55:55 +00:00
zzz
50d5692884 snark build fix sorry 2012-08-11 13:51:52 +00:00
meeh
0ea6513e9c Changed my reseed url to contain a subpath, /netDb/. also updated the certificate (forgot to copy out of conf folder when i changed webserver and deleted config). 2012-08-11 13:43:48 +00:00
zzz
e2b683556b merge of '15095538e7b5c72468863e969541571ade1796f9'
and '39af5d31a13c5d5b71107e2caa0c234b84827c03'
2012-08-11 12:26:32 +00:00
zzz
14587ebb59 dash six 2012-08-11 12:16:43 +00:00
zzz
be3cf44608 get rid of one more UnsupportedOperationException 2012-08-11 11:41:29 +00:00
zzz
1538cd84a9 * DataHelper: toString(byte[]) cleanup and javadoc 2012-08-11 11:40:41 +00:00
meeh
f5b808b997 OSX: Fixed a bug in OS_VER variable.
the old version (grep -o '[0-9]*\.[0-9]*\.[0-9]*') won't detect versions as 10.8, or 10.7
added cut -d: -f2 | sed -e 's/[^0-9]*//' , matching both 10.8, 10.7.4, etc.
2012-08-11 11:40:05 +00:00
zzz
f92d8aed3d make context list concurrent 2012-08-11 11:34:32 +00:00
zzz
f6c769187e fix 2012-08-11 11:33:43 +00:00
zzz
c70e3727be * SSU MTU (ticket #682):
- Use local MTU detection
   - i2np.udp.mtu now sets max MTU, not initial MTU
   - Put local MTU in netDb 
   - Fix receive MTU calculations
   - Track remote MTU based on actual received packet size
   - Display local MTU on peers page
2012-08-11 11:27:28 +00:00
zzz
a6a0228ef8 * i2psnark: Fix DHT nodes not being saved at shutdown
Log infohashes in hex
             Don't write out nodes if we don't have any
2012-08-11 11:23:27 +00:00
meeh
d2a5595df2 Added new reseed host, and a self signed certificate for that host. 2012-08-11 01:14:58 +00:00
kytv
e9c07a123a German and Greek translation updates from Transifex 2012-08-11 00:25:43 +00:00
meeh
1e8e2a197b A fix for ticket #684 2012-08-10 23:55:14 +00:00
zzz
39d9d3f5b6 * SAM: Don't use direct byte buffers for streams (ticket #679)
DatagramServer one stays as it is a singleton.
2012-08-09 15:12:17 +00:00
zzz
8bada7f882 merge of '01c1a5c0e70a460534e66dd487aa8676d666168d'
and '441b352d1cef1c64ee96f55692be67cfc4b4abf1'
2012-08-09 15:03:01 +00:00
kytv
a940062255 add ')' missing from str4d's checkins 2012-08-09 11:35:41 +00:00
str4d
93efd31a5b merge of '62c3f266fd9443e9d7b3f71be8f4b36b4952f96b'
and 'd71795fa9a3d5fa0349f46eef4062670755b2cff'
2012-08-09 02:37:19 +00:00
str4d
2e9fdc6d9f Updated history.txt 2012-08-09 02:36:39 +00:00
zzz
b9f5f230a2 stub out local MTU detection (ticket 682) 2012-08-08 23:36:11 +00:00
zzz
0a751a303f post-0.9 cleanup 2012-08-08 17:09:28 +00:00
zzz
b2da629034 * Datagrams: Remove static logs 2012-08-08 17:07:28 +00:00
zzz
37a542c009 NTCP stat cleanup 2012-08-08 17:06:33 +00:00
zzz
0451ee7f08 * SSU: More cleanups; don't send a packet that exceeds the MTU 2012-08-08 17:05:42 +00:00
zzz
d8dd76c6e0 * SAM: Volatiles and finals 2012-08-08 17:01:59 +00:00
zzz
9cee0ee504 * i2psnark:
- Remove static SnarkManager instance
   - Allow DHT-only torrents
   - DHT debugging
2012-08-08 17:00:33 +00:00
str4d
58a545d30c Snark: explicitly check if universal theme is "classic", and use "light" if so 2012-08-07 23:08:37 +00:00
str4d
dfb0b7801d Updates to classic console theme from dr|z3d 2012-08-07 23:03:34 +00:00
str4d
a21175d903 propagate from branch 'i2p.i2p' (head b1fe8f8037e6dd8a1f6be6e30151ad0ca92e6689)
to branch 'i2p.i2p.str4d.fux' (head 723929af49930ca764fe4befb3621a036a3f99b8)
2012-08-07 12:28:30 +00:00
str4d
9c7f4cc604 merge of '6014a9321bb2362ffc628a351c1db19922384f76'
and 'd68b6ad6b4308d8dbe27d1faac089cb15358bfa2'
2012-08-07 12:24:33 +00:00
str4d
3017e4f51a Fixed .mtn-ignore to ignore build dirs properly 2012-08-07 12:18:16 +00:00
str4d
5ed1ec681f Updates to classic console theme from dr|z3d 2012-08-07 11:42:22 +00:00
str4d
0a4031cd7b Updates to midnight console theme from dr|z3d 2012-08-07 06:03:35 +00:00
str4d
31ea4a7093 Changed universal theming prop key (so not mistaken as a theme name by routerconsole) 2012-08-07 04:29:50 +00:00
str4d
0ca2d33ee1 New midnight theme for susidns from dr|z3d 2012-08-07 04:24:41 +00:00
str4d
48bcd3a8c2 Updates to console and snark themes from dr|z3d 2012-08-07 04:22:40 +00:00
zzz
1ab8200c7f * Clone System properties before iterating to avoid
ConcurrentModificationException (ticket #680)
2012-08-06 14:45:37 +00:00
zzz
91e61dbd5c fix flag links so language selection returns to the same page 2012-08-06 14:13:15 +00:00
zzz
fb4ef57148 propagate from branch 'i2p.i2p.zzz.dhtsnark' (head d4f16babae7cb0156609b211f5bb0310b03aaf57)
to branch 'i2p.i2p' (head 7bcd2f192b0f571374cc9882eca407095eb97c17)
2012-08-06 14:05:09 +00:00
zzz
ced0129e03 * libjbigi.so for ARMv6
GMP 4.3.2
    Compiled on Raspberry Pi with gcc version: gcc (Debian 4.6.3-8+rpi1) 4.6.3
    java version "1.6.0_24"
    OpenJDK Runtime Environment (IcedTea6 1.11.3) (6b24-1.11.3-2+rpi1)
    OpenJDK Zero VM (build 20.0-b12, mixed mode)
    Stripped.
    Had a report that the ARMv5 jbigi worked on the RPi but it didn't for me.
    See NativeBigInteger for more info.
    /proc/cpuinfo:

Processor	: ARMv6-compatible processor rev 7 (v6l)
BogoMIPS	: 697.95
Features	: swp half thumb fastmult vfp edsp java tls 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xb76
CPU revision	: 7

Hardware	: BCM2708
Revision	: 0002
2012-08-06 14:04:32 +00:00
str4d
740b6501cd Updated history.txt 2012-08-06 12:38:00 +00:00
zzz
67f16b0de4 javadocs 2012-08-05 16:55:39 +00:00
zzz
fd3d92d3b2 merge of '1045fe48c576267959eae499a22776d9f9acafc3'
and 'bed1572eff55282ffcb5a2b92d02813eb04c0548'
2012-08-05 15:16:45 +00:00
zzz
5ba5d537b5 * UDP:
- Limit PacketHandler threads to 1 (ticket #660)
   - Limit queue sizes between UDPReceiver and PacketHandler,
     and between PacketHandler and MessageReceiver, to prevent OOMs
     and/or excessive queue delays
   - Increase UDPPacket cache size based on max mem
   - Remove more stats
2012-08-05 14:24:14 +00:00
zzz
4efa87d6bf * i2ptunnel, I2CP, EepGet: Buffer socket input streams (ticket #666)
* I2PSessionImpl: One more volatile (ticket #659)
2012-08-05 13:33:28 +00:00
str4d
442897ba5b merge of '48ea7675889a36bfb253833a66c22275abcee355'
and '925b1411e60b0e76e2421becd84d6c63832b69bb'
2012-08-05 07:40:05 +00:00
kytv
2b79da5c35 Debian: update patch to compensate for last commit
At the same time I'm making more Debian-specific changes, such as
 - not checking for Gentoo (this is obviously never going to be true :P)
 - not mentioning IzPack replacing variables (also not applicable)
 - inform about dpkg-reconfigure i2p in the event someone tries to remove or
   install an initscript with "i2prouter install|remove|uninstall"
 - remove the manual wrapper instructions
2012-08-04 17:44:09 +00:00
kytv
cc3a8e5d62 have izpack expand %USER_HOME in i2prouter
This will solve the issue of I2P_CONFIG_DIR being set incorrectly if another
user runs i2prouter once, such as when installing the initscript.
2012-08-04 17:32:11 +00:00
zzz
280a708afe - Change secure Node ID requirements again
- Protect against null DHT races
- Add message about restarting tunnel when DHT config changes
- Add DHT size to table totals
2012-08-04 17:11:11 +00:00
str4d
f5a348a863 propagate from branch 'i2p.i2p.str4d.test' (head 190d9be59620f8c6f80e0cb2fc4d9fa839edbb4f)
to branch 'i2p.i2p' (head c884db74f90a9d1c33deca6e2fd2e29f6c1ac8fa)
2012-08-03 21:30:29 +00:00
str4d
85a4e9cb5c Clarified purpose of the default IRC tunnel (it's not a "proxy") 2012-08-03 21:26:09 +00:00
zzz
4715dbdbd0 fixup after prop 2012-08-03 20:40:31 +00:00
zzz
afad77af19 propagate from branch 'i2p.i2p' (head d2198c4bc21a9d06194cdb2dce24945ebc9d1542)
to branch 'i2p.i2p.zzz.dhtsnark' (head 59fc0206608a5d1323a0acfbcb151d862fe95f95)
2012-08-03 20:29:31 +00:00
zzz
b4a50ed03a replace SimpleScheduler.getInstance() calls 2012-08-03 17:13:17 +00:00
zzz
00f9fea98c replace SimpleTimer2.getInstance() calls 2012-08-03 16:23:31 +00:00
zzz
501651125f * UDP:
- Catch some cases where UDPPackets were not returned to the cache (ticket #675)
   - Fix inverted logging logic (ticket #663)
   - Remove check in UDPPacket.getLifetime() (ticket #664)
   - RemoteHostID cleanup, cache hashcode
   - Remove udp.fetchRemoteSlow stat
   - Remove some time stamping in UDPPacket
   - Other cleanups - see http://zzz.i2p/topics/1198
2012-08-03 14:25:32 +00:00
zzz
18e8d35910 * LogManager: Add logger.logBufferSize and logger.dropOnOverflow options (ticket #662) 2012-08-03 13:42:40 +00:00
zzz
9e4d231285 final 2012-08-03 11:23:09 +00:00
zzz
2972e79f9e * OutNetMessage: Fix NPE when log level = INFO (ticket #676) 2012-08-03 11:22:48 +00:00
zzz
4d32eaa036 * JobQueue: Synch fix (ticket #670) 2012-08-03 11:21:28 +00:00
zzz
e4f141b94c * build.xml: Add buildI2PTunnelJar target for Android 2012-08-03 11:20:28 +00:00
zzz
ccf36abd30 * i2psnark: Finish migration to I2P logging to reduce object churn (ticket #673) 2012-08-03 11:19:52 +00:00
str4d
d147db3382 Only call SaveConfig once in ConfigUIHandler 2012-08-03 03:49:46 +00:00
str4d
9d29dc6b68 Fixed bugs introduced while reverting 2012-08-01 05:54:07 +00:00
str4d
6562b33bbc Removed readConfigFile and writeConfigFile from I2PAppContext (unnecessary now) 2012-08-01 03:05:18 +00:00
str4d
f58f297cdb Reverted susimail to storing theme itself, but checking routerconsole for universal theming 2012-08-01 03:00:23 +00:00
str4d
376b991b63 Reverted i2psnark to storing theme itself, but checking routerconsole for universal theming 2012-08-01 02:44:18 +00:00
str4d
120d31244e Reverted i2ptunnel to reading theme from routerconsole 2012-08-01 02:26:26 +00:00
str4d
679549cbf2 Reverted susidns to storing theme itself, but checking routerconsole for universal theming 2012-08-01 02:04:00 +00:00
str4d
a623d924fa Reverted routerconsole to storing theme itself, also store universal theming boolean 2012-08-01 01:50:59 +00:00
kytv
95fb141ad9 0.9.1 debian changelog 2012-08-01 00:34:17 +00:00
str4d
fad6f54794 propagate from branch 'i2p.i2p.unittests' (head 0c5ea65761d9127f160bccb3d1d157f8947ca050)
to branch 'i2p.i2p' (head e36d5669f32ad1a0f66ab84f7f9ff8fa2937680b)
2012-07-31 21:49:31 +00:00
str4d
e1525d98cd Fixed paths to JUnit tests in javadoc targets 2012-07-31 21:26:46 +00:00
str4d
3d69d2bf63 If the theme set for susidns doesn't exist, use the default instead 2012-07-31 12:56:23 +00:00
str4d
cb2dd03e77 Refactored writeConfigFile to use DataHelper.storeProps, tidied up logging 2012-07-31 12:52:31 +00:00
str4d
3253f82900 Added ScalaTest support to router build.xml 2012-07-31 00:06:28 +00:00
zzz
33a00efd82 * RoutingKeyGenerator: Cleanups (ticket #672) 2012-07-30 22:39:47 +00:00
zzz
8bcbf24713 propagate from branch 'i2p.i2p.zzz.test' (head 5474e1a513fc8144a3d855e9c85d8b235f7f9816)
to branch 'i2p.i2p' (head 5932d3923108572b22a8a7a600f0f9e62ecac347)
2012-07-30 22:29:02 +00:00
kytv
52ba727664 line ending fixes
These CSS files improperly contain a mixture of Windows *and* UNIX line
endings. Some lines had ^M after them but most didn't.
2012-07-30 17:01:12 +00:00
kytv
a1cfacd8da merge of '3347c631d86a2ccf634321b74e24b9a58e490a15'
and '95d885a94cdde7ad40bbef11ec76f86d1ea7b798'
2012-07-30 16:51:05 +00:00
str4d
5b6e7ba91d Added some skeleton Spec tests for various I2P data types in net.i2p.data 2012-07-30 14:50:51 +00:00
str4d
691ce6fec7 The first ScalaTest specification: a Hash must be 32 bytes long 2012-07-30 12:36:00 +00:00
str4d
618f214a4f Added ScalaTest support to core build.xml
The old JUnit tests are still present, but "ant test" and "ant fulltest" default
to the (pending) ScalaTest ones. To run the ScalaTest tests with Cobertura, execute
the following:

ant -Dscalatest.libs=./lib -Dwith.cobertura=/usr/share/java/cobertura.jar fulltest

The scalatest.libs property must point to a directory containing scala-compiler.jar,
scala-library.jar and scalatest.jar.
2012-07-30 12:26:35 +00:00
str4d
48df91f796 Moved existing JUnit tests to junittest/ in preparation for ScalaTest 2012-07-30 04:04:07 +00:00
str4d
d27d0bd2e4 A couple more specific excludes for JUnit tests 2012-07-30 04:03:02 +00:00
str4d
39d954d56a merge of '00209f1054786667de66adbd6038fccf8825260f'
and '180794b6e2aad94450e102b4ac346f8172811ba1'
2012-07-28 22:22:07 +00:00
str4d
639253e9bb Fixed a bug in a console_big.css override in light and dark themes 2012-07-28 13:45:12 +00:00
str4d
f8fe2a295f Fixed icon column width being too large in snark filemanager 2012-07-28 13:38:40 +00:00
zzz
4298958952 comment out tests 2012-07-27 15:49:46 +00:00
zzz
54a80d6bdc javadoc 2012-07-27 15:31:20 +00:00
zzz
aba655a9c7 move default properties from build.xml to build.properties 2012-07-27 15:30:11 +00:00
str4d
314817242b If the theme set for susimail doesn't exist, use the default instead 2012-07-23 11:01:39 +00:00
str4d
945a0f30aa If the theme set for snark doesn't exist, use the default instead 2012-07-23 10:39:11 +00:00
str4d
a7c8a7201a When fetching a theme, if theme config key is not found, write out the default
This is required in order to get the theme config keys of the various apps into
themes.config; this way, the routerconsole requires no knowledge of what apps
support universal theming, and can just blanket apply themes to all known keys.
2012-07-22 13:13:43 +00:00
str4d
6be94658a7 Use router console theme setting from themes.config in i2ptunnel 2012-07-22 11:33:20 +00:00
str4d
490dcc5020 Bugfix: update SnarkManager._theme each time getTheme() is called
FIXME: ensure that _theme is only read from the config file once per page load.
2012-07-22 06:59:43 +00:00
str4d
8e6bade42b Added checkbox to console to set theme universally across all apps 2012-07-22 06:53:43 +00:00
str4d
3c4f1b7814 Store susimail theme setting in themes.config 2012-07-21 12:33:42 +00:00
str4d
ce024ff006 Store susidns theme setting in themes.config 2012-07-21 11:39:13 +00:00
str4d
e603b120c3 Store snark theme setting in themes.config 2012-07-21 11:06:24 +00:00
str4d
b17af505c2 Replaced a hard-coded string that was missed in previous commit 2012-07-21 10:22:12 +00:00
str4d
5d5a3b80e5 Store router console theme setting in themes.config 2012-07-21 10:11:32 +00:00
str4d
c8a73b63fd Added methods to read and write properties in arbitrary config files 2012-07-21 10:07:04 +00:00
zzz
e2588a5379 move DecayingBloomFilter, DecayingHashSet, and xlattice filters from core to router 2012-07-02 19:22:33 +00:00
zzz
dba3fee477 - Concurrent PeerCoordinatorSet
- final infoHash in Snark
2012-06-25 18:20:18 +00:00
zzz
50fba8fc8d propagate from branch 'i2p.i2p' (head db152f1a9e08e80c7bd3b87735b51800e8f4c46f)
to branch 'i2p.i2p.zzz.dhtsnark' (head 9b08b2f47961167d0fee52b6481895c494d410d6)
2012-06-24 19:53:20 +00:00
zzz
5eab417134 propagate from branch 'i2p.i2p' (head db152f1a9e08e80c7bd3b87735b51800e8f4c46f)
to branch 'i2p.i2p.zzz.test' (head 5fd7a423338073ff81f5118cde74317b567846a6)
2012-06-24 19:53:08 +00:00
zzz
fe53501990 * GarlicMessage:
- Put data clove last to speed acks and leaseset store on far end
  - Change release target
  - Javadocs and cleanups
2012-06-24 14:41:50 +00:00
zzz
e497859587 * ElGamal/AES/SessionTag:
- Increase TX expire from 10 to 12 min, while keeping RX expire at 15 min.
    3 minutes should be plenty of clock skew + delay.
  - Move tags-to-send and low-threshold values to be per-SKM
  - New session config options crypto.tagsToSend and crypto.lowTagThreshold
  - Prep for per-packet override of tags and thresholds
  - Cleanups and Javadocs
* I2PTunnel: Add some defaults for the new session config options
* OCMOSJ:
  - Don't bundle LeaseSet just because we're requesting an ACK
  - Changed session config option shouldBundleReplyInfo to default to true
    and be used to disable bundling altogether when set to false.
    Was previously an undocumented option to force bundling with a certain probability.
  - Don't send tags unless we've already generated a reply token (race)
  - Cleanups and Javadocs
2012-06-24 13:17:52 +00:00
zzz
d5a1e0b1c6 - Add kad lib, from i2p.zzz.kademlia branch (without the history),
which is a rewrite of the netdb kad
- Drop now-unused SHA1Comparator
- Efficiency tweak to NodeInfoComparator
2012-06-22 17:39:41 +00:00
zzz
5883b7344e propagate from branch 'i2p.i2p' (head 80aed456e1c6e4b17906153c9ee6dc9bc45e0eec)
to branch 'i2p.i2p.zzz.dhtsnark' (head dbf88ff4c1429f26656ad34fe0b9ba94305d726a)
2012-06-22 15:13:04 +00:00
zzz
8522779df1 - Switch to real kad with lib from i2p.zzz.kademlia (not checked in yet)
- Bootstrap only once in explore thread
- Add exploring to explore thread
- Don't store default DHT setting in config file, so we can switch default to true later
- Add new enforce-protocol streaming config, sorry locks out < 0.7.1 peers
- Log tweaks
2012-06-22 15:12:43 +00:00
zzz
f8e470c7f4 propagate from branch 'i2p.i2p' (head a38c8874bc61e9bf11c4d43666ad72cd5eecbf8a)
to branch 'i2p.i2p.zzz.dhtsnark' (head 028e93195ce28c8b6fbe573e6c660d5c329df42a)
2012-06-20 01:19:25 +00:00
zzz
c6d1c552f8 propagate from branch 'i2p.i2p' (head 9ca94e960929c6af5dea1085105278d2f33217f2)
to branch 'i2p.i2p.zzz.dhtsnark' (head 1f23a71b0fa5169c220f3f21dd705e1fcfbb1b5d)
2012-06-19 23:31:53 +00:00
zzz
c2137a2a80 - Add explore thread
- More checks for stopping
- Add xor of port to secure NID
2012-06-12 21:38:25 +00:00
zzz
44da37f009 - Timeout if can't find b32
- Refactor ReplyWaiter
2012-06-12 19:22:31 +00:00
zzz
d0b967388a rework DHTNodes to hide the CHM implementation, in prep for real Kad 2012-06-12 18:30:58 +00:00
zzz
41096c7f23 - Add heardAbout() and call for receive peers
- Move last-seen tracking from NodeInfo to NID, add fail tracking
- Make NodeInfo fields final
- Remove nodes on consecutive failures
- Only persist nodes heard from recently
- Implement NID verification for security
2012-06-12 18:09:42 +00:00
zzz
fe2b97c941 propagate from branch 'i2p.i2p' (head 27fc588723d201c76ea9c18a6c715b11efcb5b0e)
to branch 'i2p.i2p.zzz.dhtsnark' (head cae6d265415ba9ed4242b3fc888ffcf2a1c1b2f2)
2012-06-11 20:29:19 +00:00
zzz
6a1b90f8f8 hash caching 2012-06-05 01:03:39 +00:00
zzz
3f40487c99 - Add persistent local DHT storage
- Shutdown now closes tunnel
- Delay after sending stop announces at shutdown
- Stub out using Hash cache
- Implement stop for all cleaners
- Log tweaks
2012-06-04 22:34:56 +00:00
zzz
a6f7761544 propagate from branch 'i2p.i2p' (head ab5f37b28e499d49e108e8e6869164d107c7049e)
to branch 'i2p.i2p.zzz.dhtsnark' (head afa1bbfb0882c9c1946ec32b87300e127c9928b2)
2012-06-04 14:26:10 +00:00
zzz
d5cb443925 - Switch back from storing NID to full NodeInfo for outgoing tokens so they don't get expired early
- Announce only to the single closest DHT peer
- Increase random port range
- Decrease max local tracker and DHT size
2012-06-04 14:15:38 +00:00
zzz
121491a3be - B32 lookup if required for non-announce queries only
- Token timeout tweaks
- Most classes package private
2012-06-03 16:05:38 +00:00
zzz
152b2152cb - Fix node ID / node info confusion
- Fix updating node ID when receiving pong
- Fix getting DHT enable setting from config file
- Fix handling of get_peers replies
- Fix sending and receiving announces without signing
- Fix incoming/outgoing token handling
- Set cleanup timer for all queries
- More debug logging
2012-06-03 15:25:51 +00:00
zzz
f8c185d09f prep for merging 2012-06-02 21:44:23 +00:00
zzz
558bb2f4f3 select proto on UDP send 2012-06-02 18:56:10 +00:00
zzz
7b07eb89a3 - Uncomment DHT
- Change DHT from option bit to extension message
- Add DHT start/stop code
- Add UI for DHT enabling
- Add raw datagram protocol type and use for response port
2012-06-02 18:52:46 +00:00
zzz
bec33cad87 propagate from branch 'i2p.i2p' (head f005cd64cce03cf3a301359f94380bc20eaa7c61)
to branch 'i2p.i2p.zzz.dhtsnark' (head 0562e4f429dcebf3f623d0975bd3a63d7645c0b7)
2012-06-02 15:16:14 +00:00
zzz
df00725077 compile fixup after merge 2012-05-25 20:30:06 +00:00
zzz
26846d592c merge of '10bd7656ab9a474e3bb2d405d50261f147690ce4'
and 'c3f96ef85962a5e9a3896e117036cc83b37fe3a8'
2012-05-25 20:11:28 +00:00
zzz
21466e017f explicit merge of 'dd3f93f7ec59e6a7f967945a75c5d4d7b53539ed'
and 'e99d32aef6da4112890ebe09c3f7d8fcb8b647e5'
2012-05-25 19:55:02 +00:00
zzz
b033db969c Revert all changes to the org/cybergarage library
in the 2009-08-11 whitespace cleanup at ef1c23821d433903124f7612cbc46ac096fc985b
to make merging with the newer library easier.
2012-05-25 19:52:39 +00:00
zzz
d18e4d430c explicit merge of '59eae97dbb470d8c4a1e4dba3a9763e134bb0c53'
and 'aeec86a504a5fd67dff12d6775411a9c865d42ad'


Merge to aeec86a504a5fd67dff12d6775411a9c865d42ad
which is just before the 2009-08-11 whitespace cleanup at ef1c23821d433903124f7612cbc46ac096fc985b
2012-05-25 19:36:22 +00:00
zzz
14ac5ac03e Cyberlink for Java v2.1 (2011-09-16) from SVN,
with extra parsers in xml/parsers removed.
Diverging from original v1.7 checkin in prep for merging.
2012-05-25 17:47:18 +00:00
zzz
b2846de94f propagate from branch 'i2p.i2p' (head 8066e0ff00b526c6971e77de44ff2d322f25069a)
to branch 'i2p.i2p.zzz.dhtsnark' (head f857dd921a7c806c85eb80419f4f9fdd3b6428a2)
2012-05-23 16:56:13 +00:00
str4d
c89e127d8a Added missing test classes to net.i2p.data.i2cp 2012-04-27 03:00:45 +00:00
str4d
104bfa8784 Exclude TestSuite classes from testing 2012-04-27 02:45:00 +00:00
str4d
e99749097a Moved tests for net.i2p.data.i2cp into the correct subdirectory 2012-04-26 12:08:14 +00:00
str4d
ce8cd91d72 propagate from branch 'i2p.i2p' (head 3002b47d5d20180f84fb6a4f161823bc751989be)
to branch 'i2p.i2p.unittests' (head 97dc8de19916c3d0c7ec42790800c1e23f9ce9e8)
2012-03-30 05:10:53 +00:00
str4d
0cefaba925 More excess whitespace removed 2012-03-30 04:40:56 +00:00
str4d
ba3bc9e2ed Uncommented two Datagram tests that currently throw NullPointerExceptions 2012-03-24 11:18:37 +00:00
str4d
f164951848 Actually test something in DatagramTest.testBadagram, remove excess whitespace 2012-03-24 08:04:49 +00:00
str4d
bfaf72a547 Added a couple of tests for net.i2p.client.naming 2012-03-24 05:09:31 +00:00
str4d
377aa9bca1 In core build.xml, tell junit to look for the hamcrest libraries
hamcrest-core.jar, hamcrest-library.jar and hamcrest-integration.jar should be
present in $ANT_HOME/lib/ (real or symlinked).
2012-03-20 00:29:14 +00:00
str4d
67da35ab35 Commented out test for net.i2p.data.Lease.getNumSuccess() / getNumFailure 2012-03-16 05:08:31 +00:00
str4d
136d77a8aa Fix YKGenerator test - methods no longer static 2012-03-16 04:51:55 +00:00
str4d
bf0b59b3b3 Remove DHSessionKeyBuilderTest from CryptoTestSuite 2012-03-16 03:18:53 +00:00
str4d
f19bc6a4b0 Moved DHSessionKeyBuilderTest to net.i2p.router.transport.crypto 2012-03-16 03:08:10 +00:00
str4d
79ab065500 propagate from branch 'i2p.i2p' (head e1c79060790ae24b2a96aff2857477d6528ae7c6)
to branch 'i2p.i2p.unittests' (head 357abd51672dd9950cbac6dd30ded117fe5695e0)
2012-03-16 02:30:42 +00:00
str4d
9d07bc241c Replace hostname included by junit in reports with "i2ptester"
The fake hostname can be overridden by setting the host.fakename property.
2012-03-16 01:41:23 +00:00
str4d
786a261a70 Fixed usage of assertEquals - should be assertEquals(expected, got) 2012-02-29 05:34:13 +00:00
str4d
a226d25dc6 Test getters etc. in RateStat 2012-02-29 05:01:21 +00:00
str4d
d436c846ac Temporarily exclude slow core tests for dev purposes 2012-02-27 03:29:13 +00:00
str4d
24268c5130 Exclude classes from code coverage report that aren't in net.i2p.*
The classes are specifically excluded rather than only including net.i2p.*
so that only classes we know we want to exclude get excluded.
2012-02-27 03:26:58 +00:00
str4d
22900a0d91 Fixed RouterAddressTest.testToString to actually test the returned String 2012-02-26 09:30:27 +00:00
str4d
e7922c4ded Added some tests of setOptions to RouterAddressTest 2012-02-26 04:57:31 +00:00
str4d
f19ef3e486 Fix test that would always pass 2012-02-26 03:01:48 +00:00
str4d
4148aa54f3 Need to run clean and prepareTest before test in router build.xml 2012-02-25 01:48:31 +00:00
str4d
204440b06b Run full test reports with fulltest target, not just junit report 2012-02-25 01:46:46 +00:00
str4d
6a26c0b621 Edited router build.xml to match core build.xml (inc. clover, cobertura stuff) 2012-02-25 01:43:15 +00:00
str4d
c955adf7f6 Set up report targets properly in main build.xml 2012-02-25 01:29:08 +00:00
str4d
c68d53faf3 Removed fullclovertest target from main build.xml
Clover usage is triggered by setting with.clover instead.
2012-02-25 01:23:17 +00:00
str4d
ceda7c9ca0 Fix jbigi.jar path in test target of router build.xml 2012-02-25 01:21:31 +00:00
str4d
849c407712 Added clover targets to core build.xml as well, so either will work
Pass in the absolute location of clover.jar as the with.clover property
to activate the clover targets.
2012-02-21 04:05:27 +00:00
str4d
a2217b2b36 Fiddle with cobertura definitions a bit in core build.xml
To run with cobertura, execute the following in "core/java/":
ant -Dwith.cobertura=/usr/share/java/cobertura.jar cobertura.report
2012-02-20 03:44:23 +00:00
str4d
c7d473a7eb Shuffle round mkdirs and deletes in router build.xml to match core build.xml
batchtest has a todir config option that makes manual copying unnecessary.
2012-02-18 02:13:46 +00:00
str4d
d1a03f500f Moved mkdir above delete in core build.xml and removed mkdir from base build.xml
mkdir does nothing if the directory exists, whereas delete fails by default
if the directory doesn't exist. Also, mkdir creates parent dirs as needed.
2012-02-16 02:58:25 +00:00
str4d
8a32aad6c3 Shuffled build targets around to group together ones related to unit tests 2012-02-16 00:08:27 +00:00
zzz
d8080278b3 initial DHT code, needs work 2011-02-06 00:12:54 +00:00
700 changed files with 50054 additions and 25102 deletions

View File

@@ -17,10 +17,10 @@ _jsp\.java$
\.war$
\.zip$
^\.
^build/
^build
^pkg-temp/
~$
/build/
/build
/classes/
^debian/copyright
override.properties

View File

@@ -10,6 +10,7 @@ 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.nl = apps/i2ptunnel/locale/messages_nl.po
trans.pt = apps/i2ptunnel/locale/messages_pt.po
trans.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
@@ -32,6 +33,7 @@ trans.hu = apps/routerconsole/locale/messages_hu.po
trans.it = apps/routerconsole/locale/messages_it.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.ru = apps/routerconsole/locale/messages_ru.po
trans.sv_SE = apps/routerconsole/locale/messages_sv.po
trans.uk_UA = apps/routerconsole/locale/messages_uk.po
@@ -70,6 +72,7 @@ trans.hu = apps/susidns/locale/messages_hu.po
trans.it = apps/susidns/locale/messages_it.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.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

View File

@@ -79,11 +79,13 @@ Public domain except as listed below:
From freenet
See licenses/LICENSE-GPLv2.txt
UPnP subsystem 1.7:
Copyright (C) 2003-2006 Satoshi Konno
UPnP subsystem (CyberLink) 2.1:
Copyright (C) 2003-2010 Satoshi Konno
See licenses/LICENSE-UPnP.txt
GeoIP data free to use, courtesy http://www.maxmind.com/
GeoIP: GeoLite databases are licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
http://creativecommons.org/licenses/by-sa/3.0/
This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/
Installer:

View File

@@ -41,7 +41,6 @@ public class I2Plistener implements Runnable {
private NamedDB info, database;
private Log _log;
// private int tgwatch;
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
private AtomicBoolean lives;
@@ -103,7 +102,7 @@ public class I2Plistener implements Runnable {
serverSocket.close();
} catch (I2PException ex) {
}
// System.out.println("I2Plistener: Close");
// System.out.println("I2Plistener: Close");
}
}
}

View File

@@ -108,16 +108,6 @@ public class MUXlisten implements Runnable {
this.listener = new ServerSocket(port, backlog, host);
}
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
// I2PException, IOException, RuntimeException
// To bad we can't just catch and enumerate....
// } catch (I2PException e) {
// Something went bad.
// this.database.getWriteLock();
// this.info.getWriteLock();
// this.info.add("STARTING", new Boolean(false));
// this.info.releaseWriteLock();
// this.database.releaseWriteLock();
// throw new I2PException(e);
} catch (IOException e) {
// Something went bad.
this.database.getWriteLock();
@@ -194,7 +184,6 @@ public class MUXlisten implements Runnable {
lock.set(false);
return;
}
// socketManager.addDisconnectListener(new DisconnectListener());
lives.set(true);
lock.set(false);
quit:
@@ -347,7 +336,6 @@ public class MUXlisten implements Runnable {
String boner = tg.getName();
// System.out.println("BOB: MUXlisten: Starting thread collection for: " + boner);
_log.warn("BOB: MUXlisten: Starting thread collection for: " + boner);
// tg.interrupt(); // give my stuff a small smack again.
if (tg.activeCount() + tg.activeGroupCount() != 0) {
// visit(tg, 0, boner);
int foo = tg.activeCount() + tg.activeGroupCount();

View File

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

View File

@@ -27,8 +27,6 @@ import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
// import net.i2p.client.I2PSession;
// import net.i2p.client.I2PSessionException;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;

View File

@@ -108,20 +108,18 @@ public class TCPtoI2P implements Runnable {
* @throws java.io.IOException
*/
private void Emsg(String e, OutputStream out) throws IOException {
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
out.write("ERROR ".concat(e).getBytes());
out.write(13);
out.write(10);
out.flush();
}
// private void rlock() throws Exception {
private void rlock() {
database.getReadLock();
info.getReadLock();
}
// private void runlock() throws Exception {
private void runlock() {
info.releaseReadLock();
database.releaseReadLock();

View File

@@ -111,7 +111,7 @@ public class UDPIOthread implements I2PSessionListener, Runnable {
* @param size
*/
public void messageAvailable(I2PSession session, int msgId, long size) {
// _log.debug("Message available: id = " + msgId + " size = " + size);
// _log.debug("Message available: id = " + msgId + " size = " + size);
try {
byte msg[] = session.receiveMessage(msgId);
out.write(msg);

View File

@@ -37,6 +37,7 @@ import java.util.Map;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SystemVersion;
/**
* Utility class providing methods to parse and write files in config file
@@ -49,7 +50,7 @@ import net.i2p.util.SecureFileOutputStream;
*/
class ConfigParser {
private static final boolean isWindows = System.getProperty("os.name").startsWith("Win");
private static final boolean isWindows = SystemVersion.isWindows();
/**
* Strip the comments from a String. Lines that begin with '#' and ';' are

View File

@@ -230,7 +230,7 @@ public class Daemon {
*/
public static void update(Map<String, String> settings, String home) {
File published = null;
boolean should_publish = Boolean.valueOf(settings.get("should_publish")).booleanValue();
boolean should_publish = Boolean.parseBoolean(settings.get("should_publish"));
if (should_publish)
published = new File(home, settings
.get("published_addressbook"));
@@ -261,7 +261,7 @@ public class Daemon {
// If false, add hosts via naming service; if true, write hosts.txt file directly
// Default false
if (Boolean.valueOf(settings.get("update_direct")).booleanValue()) {
if (Boolean.parseBoolean(settings.get("update_direct"))) {
// Direct hosts.txt access
File routerFile = new File(home, settings.get("router_addressbook"));
AddressBook master;

View File

@@ -0,0 +1,76 @@
package net.i2p.kademlia;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.util.Set;
import net.i2p.data.SimpleDataStructure;
/**
* Group, without inherent ordering, a set of keys a certain distance away from
* a local key, using XOR as the distance metric
*
* Refactored from net.i2p.router.networkdb.kademlia
* @since 0.9.2
*/
public interface KBucket<T extends SimpleDataStructure> {
/**
* Lowest order high bit for difference keys.
* The lower-bounds distance of this bucket is 2**begin.
* If begin == 0, this is the closest bucket.
*/
public int getRangeBegin();
/**
* Highest high bit for the difference keys.
* The upper-bounds distance of this bucket is (2**(end+1)) - 1.
* If begin == end, the bucket cannot be split further.
* If end == (numbits - 1), this is the furthest bucket.
*/
public int getRangeEnd();
/**
* Number of keys already contained in this kbucket
*/
public int getKeyCount();
/**
* Add the peer to the bucket
*
* @return true if added
*/
public boolean add(T key);
/**
* Remove the key from the bucket
* @return true if the key existed in the bucket before removing it, else false
*/
public boolean remove(T key);
/**
* Update the last-changed timestamp to now.
*/
public void setLastChanged();
/**
* The last-changed timestamp
*/
public long getLastChanged();
/**
* Retrieve all routing table entries stored in the bucket
* @return set of Hash structures
*/
public Set<T> getEntries();
public void getEntries(SelectionCollector<T> collector);
public void clear();
}

View File

@@ -0,0 +1,150 @@
package net.i2p.kademlia;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.util.Collections;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.data.SimpleDataStructure;
import net.i2p.util.ConcurrentHashSet;
/**
* A concurrent implementation using ConcurrentHashSet.
* The max size (K) may be temporarily exceeded due to concurrency,
* a pending split, or the behavior of the supplied trimmer,
* as explained below.
* The creator is responsible for splits.
*
* This class has no knowledge of the DHT base used for XORing,
* and thus there are no validity checks in add/remove.
*
* The begin and end values are immutable.
* All entries in this bucket will have at least one bit different
* from us in the range [begin, end] inclusive.
* Splits must be implemented by creating two new buckets
* and discarding this one.
*
* The keys are kept in a Set and are NOT sorted by last-seen.
* Per-key last-seen-time, failures, etc. must be tracked elsewhere.
*
* If this bucket is full (i.e. begin == end && size == max)
* then add() will call KBucketTrimmer.trim() do
* (possibly) remove older entries, and indicate whether
* to add the new entry. If the trimmer returns true without
* removing entries, this KBucket will exceed the max size.
*
* Refactored from net.i2p.router.networkdb.kademlia
* @since 0.9.2
*/
class KBucketImpl<T extends SimpleDataStructure> implements KBucket<T> {
/**
* set of Hash objects for the peers in the kbucket
*/
private final Set<T> _entries;
/** include if any bits equal or higher to this bit (in big endian order) */
private final int _begin;
/** include if no bits higher than this bit (inclusive) are set */
private final int _end;
private final int _max;
private final KBucketTrimmer _trimmer;
/** when did we last shake things up */
private long _lastChanged;
private final I2PAppContext _context;
/**
* All entries in this bucket will have at least one bit different
* from us in the range [begin, end] inclusive.
*/
public KBucketImpl(I2PAppContext context, int begin, int end, int max, KBucketTrimmer trimmer) {
if (begin > end)
throw new IllegalArgumentException(begin + " > " + end);
_context = context;
_entries = new ConcurrentHashSet(max + 4);
_begin = begin;
_end = end;
_max = max;
_trimmer = trimmer;
}
public int getRangeBegin() { return _begin; }
public int getRangeEnd() { return _end; }
public int getKeyCount() {
return _entries.size();
}
/**
* @return an unmodifiable view; not a copy
*/
public Set<T> getEntries() {
return Collections.unmodifiableSet(_entries);
}
public void getEntries(SelectionCollector<T> collector) {
for (T h : _entries) {
collector.add(h);
}
}
public void clear() {
_entries.clear();
}
/**
* Sets last-changed if rv is true OR if the peer is already present.
* Calls the trimmer if begin == end and we are full.
* If begin != end then add it and caller must do bucket splitting.
* @return true if added
*/
public boolean add(T peer) {
if (_begin != _end || _entries.size() < _max ||
_entries.contains(peer) || _trimmer.trim(this, peer)) {
// do this even if already contains, to call setLastChanged()
boolean rv = _entries.add(peer);
setLastChanged();
return rv;
}
return false;
}
/**
* @return if removed. Does NOT set lastChanged.
*/
public boolean remove(T peer) {
boolean rv = _entries.remove(peer);
//if (rv)
// setLastChanged();
return rv;
}
/**
* Update the last-changed timestamp to now.
*/
public void setLastChanged() {
_lastChanged = _context.clock().now();
}
/**
* The last-changed timestamp, which actually indicates last-added or last-seen.
*/
public long getLastChanged() {
return _lastChanged;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(1024);
buf.append(_entries.size());
buf.append(" entries in (").append(_begin).append(',').append(_end);
buf.append(") : ").append(_entries.toString());
return buf.toString();
}
}

View File

@@ -0,0 +1,777 @@
package net.i2p.kademlia;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.data.SimpleDataStructure;
import net.i2p.util.LHMCache;
import net.i2p.util.Log;
/**
* In-memory storage of buckets sorted by the XOR metric from the base (us)
* passed in via the constructor.
* This starts with one bucket covering the whole key space, and
* may eventually be split to a max of the number of bits in the data type
* (160 for SHA1Hash or 256 for Hash),
* times 2**(B-1) for Kademlia value B.
*
* Refactored from net.i2p.router.networkdb.kademlia
* @since 0.9.2
*/
public class KBucketSet<T extends SimpleDataStructure> {
private final Log _log;
private final I2PAppContext _context;
private final T _us;
/**
* The bucket list is locked by _bucketsLock, however the individual
* buckets are not locked. Users may see buckets that have more than
* the maximum k entries, or may have adds and removes silently fail
* when they appear to succeed.
*
* Closest values are in bucket 0, furthest are in the last bucket.
*/
private final List<KBucket> _buckets;
private final Range<T> _rangeCalc;
private final KBucketTrimmer _trimmer;
/**
* Locked for reading only when traversing all the buckets.
* Locked for writing only when splitting a bucket.
* Adds/removes/gets from individual buckets are not locked.
*/
private final ReentrantReadWriteLock _bucketsLock = new ReentrantReadWriteLock(false);
private final int KEYSIZE_BITS;
private final int NUM_BUCKETS;
private final int BUCKET_SIZE;
private final int B_VALUE;
private final int B_FACTOR;
/**
* Use the default trim strategy, which removes a random entry.
* @param us the local identity (typically a SHA1Hash or Hash)
* The class must have a zero-argument constructor.
* @param max the Kademlia value "k", the max per bucket, k >= 4
* @param b the Kademlia value "b", split buckets an extra 2**(b-1) times,
* b > 0, use 1 for bittorrent, Kademlia paper recommends 5
*/
public KBucketSet(I2PAppContext context, T us, int max, int b) {
this(context, us, max, b, new RandomTrimmer(context, max));
}
/**
* Use the supplied trim strategy.
*/
public KBucketSet(I2PAppContext context, T us, int max, int b, KBucketTrimmer trimmer) {
_us = us;
_context = context;
_log = context.logManager().getLog(KBucketSet.class);
_trimmer = trimmer;
if (max <= 4 || b <= 0 || b > 8)
throw new IllegalArgumentException();
KEYSIZE_BITS = us.length() * 8;
B_VALUE = b;
B_FACTOR = 1 << (b - 1);
NUM_BUCKETS = KEYSIZE_BITS * B_FACTOR;
BUCKET_SIZE = max;
_buckets = createBuckets();
_rangeCalc = new Range(us, B_VALUE);
// this verifies the zero-argument constructor
makeKey(new byte[us.length()]);
}
private void getReadLock() {
_bucketsLock.readLock().lock();
}
/**
* Get the lock if we can. Non-blocking.
* @return true if the lock was acquired
*/
private boolean tryReadLock() {
return _bucketsLock.readLock().tryLock();
}
private void releaseReadLock() {
_bucketsLock.readLock().unlock();
}
/** @return true if the lock was acquired */
private boolean getWriteLock() {
try {
boolean rv = _bucketsLock.writeLock().tryLock(3000, TimeUnit.MILLISECONDS);
if ((!rv) && _log.shouldLog(Log.WARN))
_log.warn("no lock, size is: " + _bucketsLock.getQueueLength(), new Exception("rats"));
return rv;
} catch (InterruptedException ie) {}
return false;
}
private void releaseWriteLock() {
_bucketsLock.writeLock().unlock();
}
/**
* @return true if the peer is new to the bucket it goes in, or false if it was
* already in it. Always returns false on an attempt to add ourselves.
*
*/
public boolean add(T peer) {
KBucket bucket;
getReadLock();
try {
bucket = getBucket(peer);
} finally { releaseReadLock(); }
if (bucket != null) {
if (bucket.add(peer)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer " + peer + " added to bucket " + bucket);
if (shouldSplit(bucket)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Splitting bucket " + bucket);
split(bucket.getRangeBegin());
//testAudit(this, _log);
}
return true;
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer " + peer + " NOT added to bucket " + bucket);
return false;
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Failed to add, probably us: " + peer);
return false;
}
}
/**
* No lock required.
* FIXME will split the closest buckets too far if B > 1 and K < 2**B
* Won't ever really happen and if it does it still works.
*/
private boolean shouldSplit(KBucket b) {
return
b.getRangeBegin() != b.getRangeEnd() &&
b.getKeyCount() > BUCKET_SIZE;
}
/**
* Grabs the write lock.
* Caller must NOT have the read lock.
* The bucket should be splittable (range start != range end).
* @param r the range start of the bucket to be split
*/
private void split(int r) {
if (!getWriteLock())
return;
try {
locked_split(r);
} finally { releaseWriteLock(); }
}
/**
* Creates two or more new buckets. The old bucket is replaced and discarded.
*
* Caller must hold write lock
* The bucket should be splittable (range start != range end).
* @param r the range start of the bucket to be split
*/
private void locked_split(int r) {
int b = pickBucket(r);
while (shouldSplit(_buckets.get(b))) {
KBucket<T> b0 = _buckets.get(b);
// Each bucket gets half the keyspace.
// When B_VALUE = 1, or the bucket is larger than B_FACTOR, then
// e.g. 0-159 => 0-158, 159-159
// When B_VALUE > 1, and the bucket is smaller than B_FACTOR, then
// e.g. 1020-1023 => 1020-1021, 1022-1023
int s1, e1, s2, e2;
s1 = b0.getRangeBegin();
e2 = b0.getRangeEnd();
if (B_FACTOR > 1 &&
(s1 & (B_FACTOR - 1)) == 0 &&
((e2 + 1) & (B_FACTOR - 1)) == 0 &&
e2 > s1 + B_FACTOR) {
// The bucket is a "whole" kbucket with a range > B_FACTOR,
// so it should be split into two "whole" kbuckets each with
// a range >= B_FACTOR.
// Log split
s2 = e2 + 1 - B_FACTOR;
} else {
// The bucket is the smallest "whole" kbucket with a range == B_FACTOR,
// or B_VALUE > 1 and the bucket has already been split.
// Start or continue splitting down to a depth B_VALUE.
// Linear split
s2 = s1 + ((1 + e2 - s1) / 2);
}
e1 = s2 - 1;
if (_log.shouldLog(Log.INFO))
_log.info("Splitting (" + s1 + ',' + e2 + ") -> (" + s1 + ',' + e1 + ") (" + s2 + ',' + e2 + ')');
KBucket<T> b1 = createBucket(s1, e1);
KBucket<T> b2 = createBucket(s2, e2);
for (T key : b0.getEntries()) {
if (getRange(key) < s2)
b1.add(key);
else
b2.add(key);
}
_buckets.set(b, b1);
_buckets.add(b + 1, b2);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Split bucket at idx " + b +
":\n" + b0 +
"\ninto: " + b1 +
"\nand: " + b2);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("State is now: " + toString());
if (b2.getKeyCount() > BUCKET_SIZE) {
// should be rare... too hard to call _trimmer from here
// (and definitely not from inside the write lock)
if (_log.shouldLog(Log.INFO))
_log.info("All went into 2nd bucket after split");
}
// loop if all the entries went in the first bucket
}
}
/**
* The current number of entries.
*/
public int size() {
int rv = 0;
getReadLock();
try {
for (KBucket b : _buckets) {
rv += b.getKeyCount();
}
} finally { releaseReadLock(); }
return rv;
}
public boolean remove(T entry) {
KBucket kbucket;
getReadLock();
try {
kbucket = getBucket(entry);
} finally { releaseReadLock(); }
boolean removed = kbucket.remove(entry);
return removed;
}
/** @since 0.8.8 */
public void clear() {
getReadLock();
try {
for (KBucket b : _buckets) {
b.clear();
}
} finally { releaseReadLock(); }
_rangeCalc.clear();
}
/**
* @return a copy in a new set
*/
public Set<T> getAll() {
Set<T> all = new HashSet(256);
getReadLock();
try {
for (KBucket b : _buckets) {
all.addAll(b.getEntries());
}
} finally { releaseReadLock(); }
return all;
}
/**
* @return a copy in a new set
*/
public Set<T> getAll(Set<T> toIgnore) {
Set<T> all = getAll();
all.removeAll(toIgnore);
return all;
}
public void getAll(SelectionCollector<T> collector) {
getReadLock();
try {
for (KBucket b : _buckets) {
b.getEntries(collector);
}
} finally { releaseReadLock(); }
}
/**
* The keys closest to us.
* Returned list will never contain us.
* @return non-null, closest first
*/
public List<T> getClosest(int max) {
return getClosest(max, Collections.EMPTY_SET);
}
/**
* The keys closest to us.
* Returned list will never contain us.
* @return non-null, closest first
*/
public List<T> getClosest(int max, Collection<T> toIgnore) {
List<T> rv = new ArrayList(max);
int count = 0;
getReadLock();
try {
// start at first (closest) bucket
for (int i = 0; i < _buckets.size() && count < max; i++) {
Set<T> entries = _buckets.get(i).getEntries();
// add the whole bucket except for ignores,
// extras will be trimmed after sorting
for (T e : entries) {
if (!toIgnore.contains(e)) {
rv.add(e);
count++;
}
}
}
} finally { releaseReadLock(); }
Comparator comp = new XORComparator(_us);
Collections.sort(rv, comp);
int sz = rv.size();
for (int i = sz - 1; i >= max; i--) {
rv.remove(i);
}
return rv;
}
/**
* The keys closest to the key.
* Returned list will never contain us.
* @return non-null, closest first
*/
public List<T> getClosest(T key, int max) {
return getClosest(key, max, Collections.EMPTY_SET);
}
/**
* The keys closest to the key.
* Returned list will never contain us.
* @return non-null, closest first
*/
public List<T> getClosest(T key, int max, Collection<T> toIgnore) {
if (key.equals(_us))
return getClosest(max, toIgnore);
List<T> rv = new ArrayList(max);
int count = 0;
getReadLock();
try {
int start = pickBucket(key);
// start at closest bucket, then to the smaller (closer to us) buckets
for (int i = start; i >= 0 && count < max; i--) {
Set<T> entries = _buckets.get(i).getEntries();
for (T e : entries) {
if (!toIgnore.contains(e)) {
rv.add(e);
count++;
}
}
}
// then the farther from us buckets if necessary
for (int i = start + 1; i < _buckets.size() && count < max; i++) {
Set<T> entries = _buckets.get(i).getEntries();
for (T e : entries) {
if (!toIgnore.contains(e)) {
rv.add(e);
count++;
}
}
}
} finally { releaseReadLock(); }
Comparator comp = new XORComparator(key);
Collections.sort(rv, comp);
int sz = rv.size();
for (int i = sz - 1; i >= max; i--) {
rv.remove(i);
}
return rv;
}
/**
* The bucket number (NOT the range number) that the xor of the key goes in
* Caller must hold read lock
* @return 0 to max-1 or -1 for us
*/
private int pickBucket(T key) {
int range = getRange(key);
if (range < 0)
return -1;
int rv = pickBucket(range);
if (rv >= 0) {
return rv;
}
_log.error("Key does not fit in any bucket?! WTF!\nKey : ["
+ DataHelper.toHexString(key.getData()) + "]"
+ "\nUs : " + _us
+ "\nDelta: ["
+ DataHelper.toHexString(DataHelper.xor(_us.getData(), key.getData()))
+ "]", new Exception("WTF"));
_log.error(toString());
throw new IllegalStateException("pickBucket returned " + rv);
//return -1;
}
/**
* Returned list is a copy of the bucket list, closest first,
* with the actual buckets (not a copy).
*
* Primarily for testing. You shouldn't ever need to get all the buckets.
* Use getClosest() or getAll() instead to get the keys.
*
* @return non-null
*/
List<KBucket<T>> getBuckets() {
getReadLock();
try {
return new ArrayList(_buckets);
} finally { releaseReadLock(); }
}
/**
* The bucket that the xor of the key goes in
* Caller must hold read lock
* @return null if key is us
*/
private KBucket getBucket(T key) {
int bucket = pickBucket(key);
if (bucket < 0)
return null;
return _buckets.get(bucket);
}
/**
* The bucket number that contains this range number
* Caller must hold read lock or write lock
* @return 0 to max-1 or -1 for us
*/
private int pickBucket(int range) {
// If B is small, a linear search from back to front
// is most efficient since most of the keys are at the end...
// If B is larger, there's a lot of sub-buckets
// of equal size to be checked so a binary search is better
if (B_VALUE <= 3) {
for (int i = _buckets.size() - 1; i >= 0; i--) {
KBucket b = _buckets.get(i);
if (range >= b.getRangeBegin() && range <= b.getRangeEnd())
return i;
}
return -1;
} else {
KBucket dummy = new DummyBucket(range);
return Collections.binarySearch(_buckets, dummy, new BucketComparator());
}
}
private List<KBucket> createBuckets() {
// just an initial size
List<KBucket> buckets = new ArrayList(4 * B_FACTOR);
buckets.add(createBucket(0, NUM_BUCKETS -1));
return buckets;
}
private KBucket createBucket(int start, int end) {
if (end - start >= B_FACTOR &&
(((end + 1) & B_FACTOR - 1) != 0 ||
(start & B_FACTOR - 1) != 0))
throw new IllegalArgumentException("Sub-bkt crosses K-bkt boundary: " + start + '-' + end);
KBucket bucket = new KBucketImpl(_context, start, end, BUCKET_SIZE, _trimmer);
return bucket;
}
/**
* The number of bits minus 1 (range number) for the xor of the key.
* Package private for testing only. Others shouldn't need this.
* @return 0 to max-1 or -1 for us
*/
int getRange(T key) {
return _rangeCalc.getRange(key);
}
/**
* For every bucket that hasn't been updated in this long,
* or isn't close to full,
* generate a random key that would be a member of that bucket.
* The returned keys may be searched for to "refresh" the buckets.
* @return non-null, closest first
*/
public List<T> getExploreKeys(long age) {
List<T> rv = new ArrayList(_buckets.size());
long old = _context.clock().now() - age;
getReadLock();
try {
for (KBucket b : _buckets) {
if (b.getLastChanged() < old || b.getKeyCount() < BUCKET_SIZE * 3 / 4)
rv.add(generateRandomKey(b));
}
} finally { releaseReadLock(); }
return rv;
}
/**
* Generate a random key to go within this bucket
* Package private for testing only. Others shouldn't need this.
*/
T generateRandomKey(KBucket bucket) {
int begin = bucket.getRangeBegin();
int end = bucket.getRangeEnd();
// number of fixed bits, out of B_VALUE - 1 bits
int fixed = 0;
int bsz = 1 + end - begin;
// compute fixed = B_VALUE - log2(bsz)
// e.g for B=4, B_FACTOR=8, sz 4-> fixed 1, sz 2->fixed 2, sz 1 -> fixed 3
while (bsz < B_FACTOR) {
fixed++;
bsz <<= 1;
}
int fixedBits = 0;
if (fixed > 0) {
// 0x01, 03, 07, 0f, ...
int mask = (1 << fixed) - 1;
// fixed bits masked from begin
fixedBits = (begin >> (B_VALUE - (fixed + 1))) & mask;
}
int obegin = begin;
int oend = end;
begin >>= (B_VALUE - 1);
end >>= (B_VALUE - 1);
// we need randomness for [0, begin) bits
BigInteger variance;
// 00000000rrrr
if (begin > 0)
variance = new BigInteger(begin - fixed, _context.random());
else
variance = BigInteger.ZERO;
// we need nonzero randomness for [begin, end] bits
int numNonZero = 1 + end - begin;
if (numNonZero == 1) {
// 00001000rrrr
variance = variance.setBit(begin);
// fixed bits as the 'main' bucket is split
// 00001fffrrrr
if (fixed > 0)
variance = variance.or(BigInteger.valueOf(fixedBits).shiftLeft(begin - fixed));
} else {
// dont span main bucket boundaries with depth > 1
if (fixed > 0)
throw new IllegalStateException("WTF " + bucket);
BigInteger nonz;
if (numNonZero <= 62) {
// add one to ensure nonzero
long nz = 1 + _context.random().nextLong((1l << numNonZero) - 1);
nonz = BigInteger.valueOf(nz);
} else {
// loop to ensure nonzero
do {
nonz = new BigInteger(numNonZero, _context.random());
} while (nonz.equals(BigInteger.ZERO));
}
// shift left and or-in the nonzero randomness
if (begin > 0)
nonz = nonz.shiftLeft(begin);
// 0000nnnnrrrr
variance = variance.or(nonz);
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("SB(" + obegin + ',' + oend + ") KB(" + begin + ',' + end + ") fixed=" + fixed + " fixedBits=" + fixedBits + " numNonZ=" + numNonZero);
byte data[] = variance.toByteArray();
T key = makeKey(data);
byte[] hash = DataHelper.xor(key.getData(), _us.getData());
T rv = makeKey(hash);
// DEBUG
//int range = getRange(rv);
//if (range < obegin || range > oend) {
// throw new IllegalStateException("Generate random key failed range=" + range + " for " + rv + " meant for bucket " + bucket);
//}
return rv;
}
/**
* Make a new SimpleDataStrucure from the data
* @param data size <= SDS length, else throws IAE
* Can be 1 bigger if top byte is zero
*/
private T makeKey(byte[] data) {
int len = _us.length();
int dlen = data.length;
if (dlen > len + 1 ||
(dlen == len + 1 && data[0] != 0))
throw new IllegalArgumentException("bad length " + dlen + " > " + len);
T rv;
try {
rv = (T) _us.getClass().newInstance();
} catch (Exception e) {
_log.error("fail", e);
throw new RuntimeException(e);
}
if (dlen == len) {
rv.setData(data);
} else {
byte[] ndata = new byte[len];
if (dlen == len + 1) {
// one bigger
System.arraycopy(data, 1, ndata, 0, len);
} else {
// smaller
System.arraycopy(data, 0, ndata, len - dlen, dlen);
}
rv.setData(ndata);
}
return rv;
}
private static class Range<T extends SimpleDataStructure> {
private final int _bValue;
private final BigInteger _bigUs;
private final Map<T, Integer> _distanceCache;
public Range(T us, int bValue) {
_bValue = bValue;
_bigUs = new BigInteger(1, us.getData());
_distanceCache = new LHMCache(256);
}
/** @return 0 to max-1 or -1 for us */
public int getRange(T key) {
Integer rv;
synchronized (_distanceCache) {
rv = _distanceCache.get(key);
if (rv == null) {
// easy way when _bValue == 1
//rv = Integer.valueOf(_bigUs.xor(new BigInteger(1, key.getData())).bitLength() - 1);
BigInteger xor = _bigUs.xor(new BigInteger(1, key.getData()));
int range = xor.bitLength() - 1;
if (_bValue > 1) {
int toShift = range + 1 - _bValue;
int highbit = range;
range <<= _bValue - 1;
if (toShift >= 0) {
int extra = xor.clearBit(highbit).shiftRight(toShift).intValue();
range += extra;
//Log log = I2PAppContext.getGlobalContext().logManager().getLog(KBucketSet.class);
//if (log.shouldLog(Log.DEBUG))
// log.debug("highbit " + highbit + " toshift " + toShift + " extra " + extra + " new " + range);
}
}
rv = Integer.valueOf(range);
_distanceCache.put(key, rv);
}
}
return rv.intValue();
}
public void clear() {
synchronized (_distanceCache) {
_distanceCache.clear();
}
}
}
/**
* For Collections.binarySearch.
* getRangeBegin == getRangeEnd.
*/
private static class DummyBucket<T extends SimpleDataStructure> implements KBucket<T> {
private final int r;
public DummyBucket(int range) {
r = range;
}
public int getRangeBegin() { return r; }
public int getRangeEnd() { return r; }
public int getKeyCount() {
return 0;
}
public Set<T> getEntries() {
throw new UnsupportedOperationException();
}
public void getEntries(SelectionCollector<T> collector) {
throw new UnsupportedOperationException();
}
public void clear() {}
public boolean add(T peer) {
throw new UnsupportedOperationException();
}
public boolean remove(T peer) {
return false;
}
public void setLastChanged() {}
public long getLastChanged() {
return 0;
}
}
/**
* For Collections.binarySearch.
* Returns equal for any overlap.
*/
private static class BucketComparator implements Comparator<KBucket> {
public int compare(KBucket l, KBucket r) {
if (l.getRangeEnd() < r.getRangeBegin())
return -1;
if (l.getRangeBegin() > r.getRangeEnd())
return 1;
return 0;
}
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(1024);
buf.append("Bucket set rooted on: ").append(_us.toString())
.append(" K= ").append(BUCKET_SIZE)
.append(" B= ").append(B_VALUE)
.append(" with ").append(size())
.append(" keys in ").append(_buckets.size()).append(" buckets:\n");
getReadLock();
try {
int len = _buckets.size();
for (int i = 0; i < len; i++) {
KBucket b = _buckets.get(i);
buf.append("* Bucket ").append(i).append("/").append(len).append(": ");
buf.append(b.toString()).append("\n");
}
} finally { releaseReadLock(); }
return buf.toString();
}
}

View File

@@ -0,0 +1,20 @@
package net.i2p.kademlia;
import net.i2p.data.SimpleDataStructure;
/**
* Called when a kbucket can no longer be split and is too big
* @since 0.9.2
*/
public interface KBucketTrimmer<K extends SimpleDataStructure> {
/**
* Called from add() just before adding the entry.
* You may call getEntries() and/or remove() from here.
* Do NOT call add().
* To always discard a newer entry, always return false.
*
* @param kbucket the kbucket that is now too big
* @return true to actually add the entry.
*/
public boolean trim(KBucket<K> kbucket, K toAdd);
}

View File

@@ -0,0 +1,21 @@
package net.i2p.kademlia;
import net.i2p.I2PAppContext;
import net.i2p.data.SimpleDataStructure;
/**
* Removes a random element, but only if the bucket hasn't changed in 5 minutes.
* @since 0.9.2
*/
public class RandomIfOldTrimmer<T extends SimpleDataStructure> extends RandomTrimmer<T> {
public RandomIfOldTrimmer(I2PAppContext ctx, int max) {
super(ctx, max);
}
public boolean trim(KBucket<T> kbucket, T toAdd) {
if (kbucket.getLastChanged() > _ctx.clock().now() - 5*60*1000)
return false;
return super.trim(kbucket, toAdd);
}
}

View File

@@ -0,0 +1,31 @@
package net.i2p.kademlia;
import java.util.ArrayList;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.data.SimpleDataStructure;
/**
* Removes a random element. Not resistant to flooding.
* @since 0.9.2
*/
public class RandomTrimmer<T extends SimpleDataStructure> implements KBucketTrimmer<T> {
protected final I2PAppContext _ctx;
private final int _max;
public RandomTrimmer(I2PAppContext ctx, int max) {
_ctx = ctx;
_max = max;
}
public boolean trim(KBucket<T> kbucket, T toAdd) {
List<T> e = new ArrayList(kbucket.getEntries());
int sz = e.size();
// concurrency
if (sz < _max)
return true;
T toRemove = e.get(_ctx.random().nextInt(sz));
return kbucket.remove(toRemove);
}
}

View File

@@ -0,0 +1,13 @@
package net.i2p.kademlia;
import net.i2p.data.SimpleDataStructure;
/**
* Removes nothing and always rejects the add. Flood resistant..
* @since 0.9.2
*/
public class RejectTrimmer<T extends SimpleDataStructure> implements KBucketTrimmer<T> {
public boolean trim(KBucket<T> kbucket, T toAdd) {
return false;
}
}

View File

@@ -0,0 +1,11 @@
package net.i2p.kademlia;
import net.i2p.data.SimpleDataStructure;
/**
* Visit kbuckets, gathering matches
* @since 0.9.2
*/
public interface SelectionCollector<T extends SimpleDataStructure> {
public void add(T entry);
}

View File

@@ -0,0 +1,28 @@
package net.i2p.kademlia;
import java.util.Comparator;
import net.i2p.data.DataHelper;
import net.i2p.data.SimpleDataStructure;
/**
* Help sort Hashes in relation to a base key using the XOR metric
*
* @since 0.9.2
*/
class XORComparator<T extends SimpleDataStructure> implements Comparator<T> {
private final byte[] _base;
/**
* @param target key to compare distances with
*/
public XORComparator(T target) {
_base = target.getData();
}
public int compare(T lhs, T rhs) {
byte lhsDelta[] = DataHelper.xor(lhs.getData(), _base);
byte rhsDelta[] = DataHelper.xor(rhs.getData(), _base);
return DataHelper.compareTo(lhsDelta, rhsDelta);
}
}

View File

@@ -0,0 +1,6 @@
<html><body><p>
This is a major rewrite of KBucket, KBucketSet, and KBucketImpl from net.i2p.router.networkdb.kademlia.
The classes are now generic to support SHA1. SHA256, or other key lengths.
The long-term goal is to prove out this new implementation in i2psnark,
then move it to core, then convert the network database to use it.
</p></body></html>

View File

@@ -39,7 +39,6 @@ public class BitField
this.size = size;
int arraysize = ((size-1)/8)+1;
bitfield = new byte[arraysize];
this.count = 0;
}
/**
@@ -99,9 +98,11 @@ public class BitField
throw new IndexOutOfBoundsException(Integer.toString(bit));
int index = bit/8;
int mask = 128 >> (bit % 8);
if ((bitfield[index] & mask) == 0) {
count++;
bitfield[index] |= mask;
synchronized(this) {
if ((bitfield[index] & mask) == 0) {
count++;
bitfield[index] |= mask;
}
}
}

View File

@@ -67,7 +67,7 @@ public class ConnectionAcceptor implements Runnable
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL);
_util.getContext().simpleScheduler().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL);
}
}
}
@@ -82,7 +82,7 @@ public class ConnectionAcceptor implements Runnable
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL);
_util.getContext().simpleScheduler().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL);
}
public void halt()
@@ -146,7 +146,7 @@ public class ConnectionAcceptor implements Runnable
}
} else {
if (socket.getPeerDestination().equals(_util.getMyDestination())) {
_util.debug("Incoming connection from myself", Snark.ERROR);
_log.error("Incoming connection from myself");
try { socket.close(); } catch (IOException ioe) {}
continue;
}
@@ -163,13 +163,13 @@ public class ConnectionAcceptor implements Runnable
catch (I2PException ioe)
{
if (!socketChanged) {
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
_log.error("Error while accepting", ioe);
stop = true;
}
}
catch (IOException ioe)
{
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
_log.error("Error while accepting", ioe);
stop = true;
}
// catch oom?

View File

@@ -40,4 +40,5 @@ interface CoordinatorListener
public boolean overUploadLimit(int uploaders);
public boolean overUpBWLimit();
public boolean overUpBWLimit(long total);
public void addMessage(String message);
}

View File

@@ -1,5 +1,7 @@
package org.klomp.snark;
import net.i2p.data.ByteArray;
/**
* Callback used to fetch data
* @since 0.8.2
@@ -10,5 +12,5 @@ interface DataLoader
* This is the callback that PeerConnectionOut calls to get the data from disk
* @return bytes or null for errors
*/
public byte[] loadData(int piece, int begin, int length);
public ByteArray loadData(int piece, int begin, int length);
}

View File

@@ -28,6 +28,9 @@ abstract class ExtensionHandler {
public static final int ID_PEX = 2;
/** not ut_pex since the compact format is different */
public static final String TYPE_PEX = "i2p_pex";
public static final int ID_DHT = 3;
/** not using the option bit since the compact format is different */
public static final String TYPE_DHT = "i2p_dht";
/** Pieces * SHA1 Hash length, + 25% extra for file names, benconding overhead, etc */
private static final int MAX_METADATA_SIZE = Storage.MAX_PIECES * 20 * 5 / 4;
private static final int PARALLEL_REQUESTS = 3;
@@ -36,9 +39,10 @@ abstract class ExtensionHandler {
/**
* @param metasize -1 if unknown
* @param pexAndMetadata advertise these capabilities
* @param dht advertise DHT capability
* @return bencoded outgoing handshake message
*/
public static byte[] getHandshake(int metasize, boolean pexAndMetadata) {
public static byte[] getHandshake(int metasize, boolean pexAndMetadata, boolean dht) {
Map<String, Object> handshake = new HashMap();
Map<String, Integer> m = new HashMap();
if (pexAndMetadata) {
@@ -47,6 +51,9 @@ abstract class ExtensionHandler {
if (metasize >= 0)
handshake.put("metadata_size", Integer.valueOf(metasize));
}
if (dht) {
m.put(TYPE_DHT, Integer.valueOf(ID_DHT));
}
// include the map even if empty so the far-end doesn't NPE
handshake.put("m", m);
handshake.put("p", Integer.valueOf(6881));
@@ -65,6 +72,8 @@ abstract class ExtensionHandler {
handleMetadata(peer, listener, bs, log);
else if (id == ID_PEX)
handlePEX(peer, listener, bs, log);
else if (id == ID_DHT)
handleDHT(peer, listener, bs, log);
else if (log.shouldLog(Log.INFO))
log.info("Unknown extension msg " + id + " from " + peer);
}
@@ -87,6 +96,12 @@ abstract class ExtensionHandler {
// peer state calls peer listener calls sendPEX()
}
if (msgmap.get(TYPE_DHT) != null) {
if (log.shouldLog(Log.DEBUG))
log.debug("Peer supports DHT extension: " + peer);
// peer state calls peer listener calls sendDHT()
}
MagnetState state = peer.getMagnetState();
if (msgmap.get(TYPE_METADATA) == null) {
@@ -323,7 +338,7 @@ abstract class ExtensionHandler {
System.arraycopy(ids, off, hash, 0, HASH_LENGTH);
if (DataHelper.eq(hash, peer.getPeerID().getDestHash()))
continue;
PeerID pID = new PeerID(hash);
PeerID pID = new PeerID(hash, listener.getUtil());
peers.add(pID);
}
// could include ourselves, listener must remove
@@ -335,6 +350,28 @@ abstract class ExtensionHandler {
}
}
/**
* Receive the DHT port numbers
* @since DHT
*/
private static void handleDHT(Peer peer, PeerListener listener, byte[] bs, Log log) {
if (log.shouldLog(Log.DEBUG))
log.debug("Got DHT msg from " + peer);
try {
InputStream is = new ByteArrayInputStream(bs);
BDecoder dec = new BDecoder(is);
BEValue bev = dec.bdecodeMap();
Map<String, BEValue> map = bev.getMap();
int qport = map.get("port").getInt();
int rport = map.get("rport").getInt();
listener.gotPort(peer, qport, rport);
} catch (Exception e) {
if (log.shouldLog(Log.INFO))
log.info("DHT msg exception from " + peer, e);
//peer.disconnect(false);
}
}
/**
* added.f and dropped unsupported
* @param pList non-null
@@ -362,4 +399,22 @@ abstract class ExtensionHandler {
}
}
/**
* Send the DHT port numbers
* @since DHT
*/
public static void sendDHT(Peer peer, int qport, int rport) {
Map<String, Object> map = new HashMap();
map.put("port", Integer.valueOf(qport));
map.put("rport", Integer.valueOf(rport));
byte[] payload = BEncoder.bencode(map);
try {
int hisMsgCode = peer.getHandshakeMap().get("m").getMap().get(TYPE_DHT).getInt();
peer.sendExtension(hisMsgCode, payload);
} catch (Exception e) {
// NPE, no DHT caps
//if (log.shouldLog(Log.INFO))
// log.info("DHT msg exception to " + peer, e);
}
}
}

View File

@@ -37,7 +37,7 @@ import net.i2p.util.SimpleTimer;
import net.i2p.util.Translate;
import org.klomp.snark.dht.DHT;
//import org.klomp.snark.dht.KRPC;
import org.klomp.snark.dht.KRPC;
/**
* I2P specific helpers for I2PSnark
@@ -65,6 +65,7 @@ public class I2PSnarkUtil {
private final File _tmpDir;
private int _startupDelay;
private boolean _shouldUseOT;
private boolean _shouldUseDHT;
private boolean _areFilesPublic;
private List<String> _openTrackers;
private DHT _dht;
@@ -77,7 +78,7 @@ public class I2PSnarkUtil {
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
public static final int MAX_CONNECTIONS = 16; // per torrent
public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
//private static final boolean ENABLE_DHT = true;
public static final boolean DEFAULT_USE_DHT = true;
public I2PSnarkUtil(I2PAppContext ctx) {
_context = ctx;
@@ -86,7 +87,6 @@ public class I2PSnarkUtil {
//setProxy("127.0.0.1", 4444);
setI2CPConfig("127.0.0.1", 7654, null);
_shitlist = new ConcurrentHashSet();
_configured = false;
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
_maxUpBW = DEFAULT_MAX_UP_BW;
_maxConnections = MAX_CONNECTIONS;
@@ -94,6 +94,7 @@ public class I2PSnarkUtil {
_shouldUseOT = DEFAULT_USE_OPENTRACKERS;
// FIXME split if default has more than one
_openTrackers = Collections.singletonList(DEFAULT_OPENTRACKERS);
_shouldUseDHT = DEFAULT_USE_DHT;
// This is used for both announce replies and .torrent file downloads,
// so it must be available even if not connected to I2CP.
// so much for multiple instances
@@ -241,12 +242,13 @@ public class I2PSnarkUtil {
opts.setProperty("i2p.streaming.maxTotalConnsPerMinute", "8");
if (opts.getProperty("i2p.streaming.maxConnsPerHour") == null)
opts.setProperty("i2p.streaming.maxConnsPerHour", "20");
if (opts.getProperty("i2p.streaming.enforceProtocol") == null)
opts.setProperty("i2p.streaming.enforceProtocol", "true");
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
_connecting = false;
}
// FIXME this only instantiates krpc once, left stuck with old manager
//if (ENABLE_DHT && _manager != null && _dht == null)
// _dht = new KRPC(_context, _manager.getSession());
if (_shouldUseDHT && _manager != null && _dht == null)
_dht = new KRPC(_context, _manager.getSession());
return (_manager != null);
}
@@ -273,7 +275,11 @@ public class I2PSnarkUtil {
/**
* Destroy the destination itself
*/
public void disconnect() {
public synchronized void disconnect() {
if (_dht != null) {
_dht.stop();
_dht = null;
}
I2PSocketManager mgr = _manager;
// FIXME this can cause race NPEs elsewhere
_manager = null;
@@ -309,7 +315,7 @@ public class I2PSnarkUtil {
return rv;
} catch (I2PException ie) {
_shitlist.add(dest);
SimpleScheduler.getInstance().addEvent(new Unshitlist(dest), 10*60*1000);
_context.simpleScheduler().addEvent(new Unshitlist(dest), 10*60*1000);
throw new IOException("Unable to reach the peer " + peer + ": " + ie.getMessage());
}
}
@@ -447,7 +453,8 @@ public class I2PSnarkUtil {
if (sess != null) {
byte[] b = Base32.decode(ip.substring(0, BASE32_HASH_LENGTH));
if (b != null) {
Hash h = new Hash(b);
//Hash h = new Hash(b);
Hash h = Hash.create(b);
if (_log.shouldLog(Log.INFO))
_log.info("Using existing session for lookup of " + ip);
try {
@@ -522,6 +529,22 @@ public class I2PSnarkUtil {
public boolean shouldUseOpenTrackers() {
return _shouldUseOT;
}
/** @since DHT */
public synchronized void setUseDHT(boolean yes) {
_shouldUseDHT = yes;
if (yes && _manager != null && _dht == null) {
_dht = new KRPC(_context, _manager.getSession());
} else if (!yes && _dht != null) {
_dht.stop();
_dht = null;
}
}
/** @since DHT */
public boolean shouldUseDHT() {
return _shouldUseDHT;
}
/**
* Like DataHelper.toHexString but ensures no loss of leading zero bytes
@@ -538,40 +561,6 @@ public class I2PSnarkUtil {
return buf.toString();
}
/** hook between snark's logger and an i2p log */
void debug(String msg, int snarkDebugLevel) {
debug(msg, snarkDebugLevel, null);
}
void debug(String msg, int snarkDebugLevel, Throwable t) {
if (t instanceof OutOfMemoryError) {
try { Thread.sleep(100); } catch (InterruptedException ie) {}
try {
t.printStackTrace();
} catch (Throwable tt) {}
try {
System.out.println("OOM thread: " + Thread.currentThread().getName());
} catch (Throwable tt) {}
}
switch (snarkDebugLevel) {
case 0:
case 1:
_log.error(msg, t);
break;
case 2:
_log.warn(msg, t);
break;
case 3:
case 4:
_log.info(msg, t);
break;
case 5:
case 6:
default:
_log.debug(msg, t);
break;
}
}
private static final String BUNDLE_NAME = "org.klomp.snark.web.messages";
/** lang in routerconsole.lang property, else current locale */

View File

@@ -23,8 +23,13 @@ package org.klomp.snark;
import java.io.DataOutputStream;
import java.io.IOException;
// Used to queue outgoing connections
// sendMessage() should be used to translate them to wire format.
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
/**
* Used to queue outgoing connections
* sendMessage() should be used to translate them to wire format.
*/
class Message
{
final static byte KEEP_ALIVE = -1;
@@ -69,6 +74,9 @@ class Message
// now unused
//SimpleTimer.TimedEvent expireEvent;
private static final int BUFSIZE = PeerState.PARTSIZE;
private static final ByteCache _cache = ByteCache.getInstance(16, BUFSIZE);
/** Utility method for sending a message through a DataStream. */
void sendMessage(DataOutputStream dos) throws IOException
{
@@ -79,11 +87,15 @@ class Message
return;
}
ByteArray ba;
// Get deferred data
if (data == null && dataLoader != null) {
data = dataLoader.loadData(piece, begin, length);
if (data == null)
ba = dataLoader.loadData(piece, begin, length);
if (ba == null)
return; // hmm will get retried, but shouldn't happen
data = ba.getData();
} else {
ba = null;
}
// Calculate the total length in bytes
@@ -139,6 +151,10 @@ class Message
// Send actual data
if (type == BITFIELD || type == PIECE || type == EXTENSION)
dos.write(data, off, len);
// Was pulled from cache in Storage.getPiece() via dataLoader
if (ba != null && ba.getData().length == BUFSIZE)
_cache.release(ba, false);
}
@Override

View File

@@ -9,6 +9,8 @@ import java.security.MessageDigest;
import net.i2p.I2PAppContext;
import net.i2p.crypto.SHA1;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SecureFile;
@@ -42,6 +44,9 @@ class PartialPiece implements Comparable {
private final int pclen;
private final File tempDir;
private static final int BUFSIZE = PeerState.PARTSIZE;
private static final ByteCache _cache = ByteCache.getInstance(16, BUFSIZE);
// Any bigger than this, use temp file instead of heap
private static final int MAX_IN_MEM = 128 * 1024;
// May be reduced on OOM
@@ -154,7 +159,16 @@ class PartialPiece implements Comparable {
sha1.update(bs);
} else {
int read = 0;
byte[] buf = new byte[Math.min(pclen, 16384)];
int buflen = Math.min(pclen, BUFSIZE);
ByteArray ba;
byte[] buf;
if (buflen == BUFSIZE) {
ba = _cache.acquire();
buf = ba.getData();
} else {
ba = null;
buf = new byte[buflen];
}
synchronized (this) {
if (raf == null)
throw new IOException();
@@ -167,6 +181,8 @@ class PartialPiece implements Comparable {
sha1.update(buf, 0, rd);
}
}
if (ba != null)
_cache.release(ba, false);
if (read < pclen)
throw new IOException();
}
@@ -182,7 +198,15 @@ class PartialPiece implements Comparable {
din.readFully(bs, off, len);
} else {
// read in fully before synching on raf
byte[] tmp = new byte[len];
ByteArray ba;
byte[] tmp;
if (len == BUFSIZE) {
ba = _cache.acquire();
tmp = ba.getData();
} else {
ba = null;
tmp = new byte[len];
}
din.readFully(tmp);
synchronized (this) {
if (raf == null)
@@ -190,6 +214,8 @@ class PartialPiece implements Comparable {
raf.seek(off);
raf.write(tmp);
}
if (ba != null)
_cache.release(ba, false);
}
}
@@ -208,7 +234,16 @@ class PartialPiece implements Comparable {
out.write(bs, offset, len);
} else {
int read = 0;
byte[] buf = new byte[Math.min(len, 16384)];
int buflen = Math.min(len, BUFSIZE);
ByteArray ba;
byte[] buf;
if (buflen == BUFSIZE) {
ba = _cache.acquire();
buf = ba.getData();
} else {
ba = null;
buf = new byte[buflen];
}
synchronized (this) {
if (raf == null)
throw new IOException();
@@ -220,6 +255,8 @@ class PartialPiece implements Comparable {
out.write(buf, 0, rd);
}
}
if (ba != null)
_cache.release(ba, false);
}
}

View File

@@ -80,7 +80,9 @@ public class Peer implements Comparable
static final long OPTION_FAST = 0x0000000000000004l;
static final long OPTION_DHT = 0x0000000000000001l;
/** we use a different bit since the compact format is different */
/* no, let's use an extension message
static final long OPTION_I2P_DHT = 0x0000000040000000l;
*/
static final long OPTION_AZMP = 0x1000000000000000l;
private long options;
@@ -269,15 +271,17 @@ public class Peer implements Comparable
_log.debug("Peer supports extensions, sending reply message");
int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1;
boolean pexAndMetadata = metainfo == null || !metainfo.isPrivate();
out.sendExtension(0, ExtensionHandler.getHandshake(metasize, pexAndMetadata));
boolean dht = util.getDHT() != null;
out.sendExtension(0, ExtensionHandler.getHandshake(metasize, pexAndMetadata, dht));
}
if ((options & OPTION_I2P_DHT) != 0 && util.getDHT() != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer supports DHT, sending PORT message");
int port = util.getDHT().getPort();
out.sendPort(port);
}
// Old DHT PORT message
//if ((options & OPTION_I2P_DHT) != 0 && util.getDHT() != null) {
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Peer supports DHT, sending PORT message");
// int port = util.getDHT().getPort();
// out.sendPort(port);
//}
// Send our bitmap
if (bitfield != null)

View File

@@ -117,9 +117,8 @@ public class PeerAcceptor
}
} else {
// multitorrent capable, so lets see what we can handle
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
PeerCoordinator cur = (PeerCoordinator)iter.next();
PeerCoordinator cur = coordinators.get(peerInfoHash);
if (cur != null) {
if (DataHelper.eq(cur.getInfoHash(), peerInfoHash)) {
if (cur.needPeers())
{

View File

@@ -28,6 +28,8 @@ import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import org.klomp.snark.dht.DHT;
/**
* TimerTask that checks for good/bad up/downloader. Works together
* with the PeerCoordinator to select which Peers get (un)choked.
@@ -74,6 +76,7 @@ class PeerCheckerTask implements Runnable
List<Peer> removed = new ArrayList();
int uploadLimit = coordinator.allowedUploaders();
boolean overBWLimit = coordinator.overUpBWLimit();
DHT dht = _util.getDHT();
for (Peer peer : peerList) {
// Remove dying peers
@@ -218,8 +221,8 @@ class PeerCheckerTask implements Runnable
if (coordinator.getNeededLength() > 0 || !peer.isCompleted())
peer.keepAlive();
// announce them to local tracker (TrackerClient does this too)
if (_util.getDHT() != null && (_runCount % 5) == 0) {
_util.getDHT().announce(coordinator.getInfoHash(), peer.getPeerID().getDestHash());
if (dht != null && (_runCount % 5) == 0) {
dht.announce(coordinator.getInfoHash(), peer.getPeerID().getDestHash());
}
}
@@ -267,8 +270,8 @@ class PeerCheckerTask implements Runnable
}
// announce ourselves to local tracker (TrackerClient does this too)
if (_util.getDHT() != null && (_runCount % 16) == 0) {
_util.getDHT().announce(coordinator.getInfoHash());
if (dht != null && (_runCount % 16) == 0) {
dht.announce(coordinator.getInfoHash());
}
}
}

View File

@@ -437,6 +437,7 @@ class PeerConnectionOut implements Runnable
*/
void sendPiece(int piece, int begin, int length, DataLoader loader)
{
/****
boolean sendNow = false;
// are there any cases where we should?
@@ -447,6 +448,7 @@ class PeerConnectionOut implements Runnable
sendPiece(piece, begin, length, bytes);
return;
}
****/
// queue a fake message... set everything up,
// except save the PeerState instead of the bytes.

View File

@@ -35,6 +35,7 @@ import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.ConcurrentHashSet;
@@ -160,7 +161,7 @@ class PeerCoordinator implements PeerListener
// Install a timer to check the uploaders.
// Randomize the first start time so multiple tasks are spread out,
// this will help the behavior with global limits
timer = new CheckEvent(new PeerCheckerTask(_util, this));
timer = new CheckEvent(_util.getContext(), new PeerCheckerTask(_util, this));
timer.schedule((CHECK_PERIOD / 2) + _random.nextInt((int) CHECK_PERIOD));
}
@@ -170,8 +171,8 @@ class PeerCoordinator implements PeerListener
*/
private static class CheckEvent extends SimpleTimer2.TimedEvent {
private final PeerCheckerTask _task;
public CheckEvent(PeerCheckerTask task) {
super(SimpleTimer2.getInstance());
public CheckEvent(I2PAppContext ctx, PeerCheckerTask task) {
super(ctx.simpleTimer2());
_task = task;
}
public void timeReached() {
@@ -214,7 +215,7 @@ class PeerCoordinator implements PeerListener
public Storage getStorage() { return storage; }
// for web page detailed stats
/** for web page detailed stats */
public List<Peer> peerList()
{
return new ArrayList(peers);
@@ -445,6 +446,12 @@ class PeerCoordinator implements PeerListener
synchronized (downloaded_old) {
Arrays.fill(downloaded_old, 0);
}
// failsafe
synchronized(wantedPieces) {
for (Piece pc : wantedPieces) {
pc.clear();
}
}
timer.schedule((CHECK_PERIOD / 2) + _random.nextInt((int) CHECK_PERIOD));
}
@@ -648,10 +655,15 @@ class PeerCoordinator implements PeerListener
if (listener != null)
listener.peerChange(this, peer);
synchronized(wantedPieces)
{
return wantedPieces.contains(new Piece(piece));
}
synchronized(wantedPieces) {
for (Piece pc : wantedPieces) {
if (pc.getId() == piece) {
pc.addPeer(peer);
return true;
}
}
return false;
}
}
/**
@@ -663,20 +675,17 @@ class PeerCoordinator implements PeerListener
if (listener != null)
listener.peerChange(this, peer);
synchronized(wantedPieces)
{
Iterator<Piece> it = wantedPieces.iterator();
while (it.hasNext())
{
Piece p = it.next();
boolean rv = false;
synchronized(wantedPieces) {
for (Piece p : wantedPieces) {
int i = p.getId();
if (bitfield.get(i)) {
p.addPeer(peer);
return true;
rv = true;
}
}
}
return false;
}
}
return rv;
}
/**
@@ -732,7 +741,19 @@ class PeerCoordinator implements PeerListener
break;
if (havePieces.get(p.getId()) && !p.isRequested())
{
piece = p;
// never ever choose one that's in partialPieces, or we
// will create a second one and leak
boolean hasPartial = false;
for (PartialPiece pp : partialPieces) {
if (pp.getPiece() == p.getId()) {
if (_log.shouldLog(Log.INFO))
_log.info("wantPiece() skipping partial for " + peer + ": piece = " + pp);
hasPartial = true;
break;
}
}
if (!hasPartial)
piece = p;
}
else if (p.isRequested())
{
@@ -747,8 +768,12 @@ class PeerCoordinator implements PeerListener
// AND if there are almost no wanted pieces left (real end game).
// If we do end game all the time, we generate lots of extra traffic
// when the seeder is super-slow and all the peers are "caught up"
if (wantedSize > END_GAME_THRESHOLD)
if (wantedSize > END_GAME_THRESHOLD) {
if (_log.shouldLog(Log.INFO))
_log.info("Nothing to request, " + requested.size() + " being requested and " +
wantedSize + " still wanted");
return null; // nothing to request and not in end game
}
// let's not all get on the same piece
// Even better would be to sort by number of requests
if (record)
@@ -784,7 +809,8 @@ class PeerCoordinator implements PeerListener
}
if (record) {
if (_log.shouldLog(Log.INFO))
_log.info(peer + " is now requesting: piece " + piece + " priority " + piece.getPriority());
_log.info("Now requesting from " + peer + ": piece " + piece + " priority " + piece.getPriority() +
" peers " + piece.getPeerCount() + '/' + peers.size());
piece.setRequested(peer, true);
}
return piece;
@@ -874,7 +900,7 @@ class PeerCoordinator implements PeerListener
*
* @throws RuntimeException on IOE getting the data
*/
public byte[] gotRequest(Peer peer, int piece, int off, int len)
public ByteArray gotRequest(Peer peer, int piece, int off, int len)
{
if (halted)
return null;
@@ -890,8 +916,10 @@ class PeerCoordinator implements PeerListener
snark.stopTorrent();
String msg = "Error reading the storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
_log.error(msg, ioe);
SnarkManager.instance().addMessage(msg);
SnarkManager.instance().addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
if (listener != null) {
listener.addMessage(msg);
listener.addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
}
throw new RuntimeException(msg, ioe);
}
}
@@ -927,11 +955,14 @@ class PeerCoordinator implements PeerListener
*/
public boolean gotPiece(Peer peer, PartialPiece pp)
{
if (metainfo == null || storage == null)
if (metainfo == null || storage == null) {
pp.release();
return true;
}
int piece = pp.getPiece();
if (halted) {
_log.info("Got while-halted piece " + piece + "/" + metainfo.getPieces() +" from " + peer + " for " + metainfo.getName());
pp.release();
return true; // We don't actually care anymore.
}
@@ -946,8 +977,10 @@ class PeerCoordinator implements PeerListener
// Assume we got a good piece, we don't really care anymore.
// Well, this could be caused by a change in priorities, so
// only return true if we already have it, otherwise might as well keep it.
if (storage.getBitField().get(piece))
if (storage.getBitField().get(piece)) {
pp.release();
return true;
}
}
try
@@ -970,8 +1003,10 @@ class PeerCoordinator implements PeerListener
snark.stopTorrent();
String msg = "Error writing storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
_log.error(msg, ioe);
SnarkManager.instance().addMessage(msg);
SnarkManager.instance().addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
if (listener != null) {
listener.addMessage(msg);
listener.addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
}
throw new RuntimeException(msg, ioe);
}
wantedPieces.remove(p);
@@ -1070,11 +1105,11 @@ class PeerCoordinator implements PeerListener
/** Called when a peer is removed, to prevent it from being used in
* rarest-first calculations.
*/
public void removePeerFromPieces(Peer peer) {
private void removePeerFromPieces(Peer peer) {
synchronized(wantedPieces) {
for(Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece piece = iter.next();
for (Piece piece : wantedPieces) {
piece.removePeer(peer);
piece.setRequested(peer, false);
}
}
}
@@ -1167,11 +1202,24 @@ class PeerCoordinator implements PeerListener
for(Piece piece : wantedPieces) {
if (piece.getId() == savedPiece) {
if (peer.isCompleted() && piece.getPeerCount() > 1) {
// Try to preserve rarest-first when we have only one seeder
// by not preferring a partial piece that others have too
// Try to preserve rarest-first
// by not requesting a partial piece that non-seeders also have
// from a seeder
skipped = true;
break;
boolean nonSeeds = false;
for (Peer pr : peers) {
PeerState state = pr.state;
if (state == null) continue;
BitField bf = state.bitfield;
if (bf == null) continue;
if (bf.get(savedPiece) && !pr.isCompleted()) {
nonSeeds = true;
break;
}
}
if (nonSeeds) {
skipped = true;
break;
}
}
iter.remove();
piece.setRequested(peer, true);
@@ -1246,6 +1294,7 @@ class PeerCoordinator implements PeerListener
PartialPiece pp = iter.next();
if (pp.getPiece() == piece) {
iter.remove();
pp.release();
// there should be only one but keep going to be sure
}
}
@@ -1287,6 +1336,7 @@ class PeerCoordinator implements PeerListener
}
} else if (id == ExtensionHandler.ID_HANDSHAKE) {
sendPeers(peer);
sendDHT(peer);
}
}
@@ -1315,6 +1365,26 @@ class PeerCoordinator implements PeerListener
} catch (InvalidBEncodingException ibee) {}
}
/**
* Send a DHT message to the peer, if we both support DHT.
* @since DHT
*/
void sendDHT(Peer peer) {
DHT dht = _util.getDHT();
if (dht == null)
return;
Map<String, BEValue> handshake = peer.getHandshakeMap();
if (handshake == null)
return;
BEValue bev = handshake.get("m");
if (bev == null)
return;
try {
if (bev.getMap().get(ExtensionHandler.TYPE_DHT) != null)
ExtensionHandler.sendDHT(peer, dht.getPort(), dht.getRPort());
} catch (InvalidBEncodingException ibee) {}
}
/**
* Sets the storage after transition out of magnet mode
* Snark calls this after we call gotMetaInfo()
@@ -1332,11 +1402,13 @@ class PeerCoordinator implements PeerListener
/**
* PeerListener callback
* Tell the DHT to ping it, this will get back the node info
* @param rport must be port + 1
* @since 0.8.4
*/
public void gotPort(Peer peer, int port) {
public void gotPort(Peer peer, int port, int rport) {
DHT dht = _util.getDHT();
if (dht != null)
if (dht != null &&
port > 0 && port < 65535 && rport == port + 1)
dht.ping(peer.getDestination(), port);
}
@@ -1408,5 +1480,13 @@ class PeerCoordinator implements PeerListener
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
return false;
}
/**
* Convenience
* @since 0.9.2
*/
public I2PSnarkUtil getUtil() {
return _util;
}
}

View File

@@ -1,9 +1,10 @@
package org.klomp.snark;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.crypto.SHA1Hash;
/**
* Hmm, any guesses as to what this is? Used by the multitorrent functionality
@@ -12,26 +13,28 @@ import java.util.Set;
* from it there too)
*/
public class PeerCoordinatorSet {
private final Set _coordinators;
private final Map<SHA1Hash, PeerCoordinator> _coordinators;
public PeerCoordinatorSet() {
_coordinators = new HashSet();
_coordinators = new ConcurrentHashMap();
}
public Iterator iterator() {
synchronized (_coordinators) {
return new ArrayList(_coordinators).iterator();
}
public Iterator<PeerCoordinator> iterator() {
return _coordinators.values().iterator();
}
public void add(PeerCoordinator coordinator) {
synchronized (_coordinators) {
_coordinators.add(coordinator);
}
_coordinators.put(new SHA1Hash(coordinator.getInfoHash()), coordinator);
}
public void remove(PeerCoordinator coordinator) {
synchronized (_coordinators) {
_coordinators.remove(coordinator);
}
_coordinators.remove(new SHA1Hash(coordinator.getInfoHash()));
}
/**
* @since 0.9.2
*/
public PeerCoordinator get(byte[] infoHash) {
return _coordinators.get(new SHA1Hash(infoHash));
}
}

View File

@@ -52,6 +52,7 @@ public class PeerID implements Comparable
/** whether we have tried to get the dest from the hash - only do once */
private boolean triedDestLookup;
private final int hash;
private final I2PSnarkUtil util;
public PeerID(byte[] id, Destination address)
{
@@ -60,6 +61,7 @@ public class PeerID implements Comparable
this.port = 6881;
this.destHash = address.calculateHash().getData();
hash = calculateHash();
util = null;
}
/**
@@ -93,13 +95,15 @@ public class PeerID implements Comparable
port = 6881;
this.destHash = address.calculateHash().getData();
hash = calculateHash();
util = null;
}
/**
* Creates a PeerID from a destHash
* @param util for eventual destination lookup
* @since 0.8.1
*/
public PeerID(byte[] dest_hash) throws InvalidBEncodingException
public PeerID(byte[] dest_hash, I2PSnarkUtil util) throws InvalidBEncodingException
{
// id and address remain null
port = 6881;
@@ -107,6 +111,7 @@ public class PeerID implements Comparable
throw new InvalidBEncodingException("bad hash length");
destHash = dest_hash;
hash = DataHelper.hashCode(dest_hash);
this.util = util;
}
public byte[] getID()
@@ -131,7 +136,7 @@ public class PeerID implements Comparable
{
if (address == null && destHash != null && !triedDestLookup) {
String b32 = Base32.encode(destHash) + ".b32.i2p";
address = I2PAppContext.getGlobalContext().namingService().lookup(b32);
address = util.getDestination(b32);
triedDestLookup = true;
}
return address;

View File

@@ -22,6 +22,8 @@ package org.klomp.snark;
import java.util.List;
import net.i2p.data.ByteArray;
/**
* Listener for Peer events.
*/
@@ -114,7 +116,7 @@ interface PeerListener
* @return a byte array containing the piece or null when the piece
* is not available (which is a protocol error).
*/
byte[] gotRequest(Peer peer, int piece, int off, int len);
ByteArray gotRequest(Peer peer, int piece, int off, int len);
/**
* Called when a (partial) piece has been downloaded from the peer.
@@ -190,13 +192,14 @@ interface PeerListener
void gotExtension(Peer peer, int id, byte[] bs);
/**
* Called when a port message is received.
* Called when a DHT port message is received.
*
* @param peer the Peer that got the message.
* @param port the port
* @param port the query port
* @param rport the response port
* @since 0.8.4
*/
void gotPort(Peer peer, int port);
void gotPort(Peer peer, int port, int rport);
/**
* Called when peers are received via PEX
@@ -206,4 +209,10 @@ interface PeerListener
* @since 0.8.4
*/
void gotPeers(Peer peer, List<PeerID> pIDList);
/**
* Convenience
* @since 0.9.2
*/
public I2PSnarkUtil getUtil();
}

View File

@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.util.Log;
class PeerState implements DataLoader
@@ -245,8 +246,8 @@ class PeerState implements DataLoader
* @return bytes or null for errors
* @since 0.8.2
*/
public byte[] loadData(int piece, int begin, int length) {
byte[] pieceBytes = listener.gotRequest(peer, piece, begin, length);
public ByteArray loadData(int piece, int begin, int length) {
ByteArray pieceBytes = listener.gotRequest(peer, piece, begin, length);
if (pieceBytes == null)
{
// XXX - Protocol error-> diconnect?
@@ -256,7 +257,7 @@ class PeerState implements DataLoader
}
// More sanity checks
if (length != pieceBytes.length)
if (length != pieceBytes.getData().length)
{
// XXX - Protocol error-> disconnect?
if (_log.shouldLog(Log.WARN))
@@ -526,10 +527,14 @@ class PeerState implements DataLoader
setInteresting(true);
}
/** @since 0.8.4 */
/**
* Unused
* @since 0.8.4
*/
void portMessage(int port)
{
listener.gotPort(peer, port);
// for compatibility with old DHT PORT message
listener.gotPort(peer, port, port + 1);
}
void unknownMessage(int type, byte[] bs)
@@ -587,6 +592,7 @@ class PeerState implements DataLoader
// Send cancel even when we are choked to make sure that it is
// really never ever send.
out.sendCancel(req);
req.getPartialPiece().release();
}
}
}
@@ -677,6 +683,7 @@ class PeerState implements DataLoader
_log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()");
return;
}
// huh? rv unused
more_pieces = requestNextPiece();
} else if (more_pieces) // We want something
{
@@ -706,6 +713,8 @@ class PeerState implements DataLoader
}
// failsafe
// However this is bad as it thrashes the peer when we change our mind
// Ticket 691 cause here?
if (interesting && lastRequest == null && outstandingRequests.isEmpty())
setInteresting(false);
@@ -733,6 +742,10 @@ class PeerState implements DataLoader
out.sendRequest(r);
lastRequest = r;
return true;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Got dup from coord: " + pp);
pp.release();
}
}
@@ -779,6 +792,8 @@ class PeerState implements DataLoader
}
// failsafe
// However this is bad as it thrashes the peer when we change our mind
// Ticket 691 cause here?
if (outstandingRequests.isEmpty())
lastRequest = null;

View File

@@ -12,13 +12,13 @@ class Piece implements Comparable {
private final int id;
private final Set<PeerID> peers;
/** @since 0.8.3 */
private Set<PeerID> requests;
private volatile Set<PeerID> requests;
/** @since 0.8.1 */
private int priority;
public Piece(int id) {
this.id = id;
this.peers = new HashSet(I2PSnarkUtil.MAX_CONNECTIONS);
this.peers = new HashSet(I2PSnarkUtil.MAX_CONNECTIONS / 2);
// defer creating requests to save memory
}
@@ -54,7 +54,10 @@ class Piece implements Comparable {
/** caller must synchronize */
public boolean addPeer(Peer peer) { return this.peers.add(peer.getPeerID()); }
/** caller must synchronize */
/**
* Caller must synchronize.
* @return true if removed
*/
public boolean removePeer(Peer peer) { return this.peers.remove(peer.getPeerID()); }
/**
@@ -104,6 +107,17 @@ class Piece implements Comparable {
public int getRequestCount() {
return this.requests == null ? 0 : this.requests.size();
}
/**
* Clear all knowledge of peers
* Caller must synchronize
* @since 0.9.3
*/
public void clear() {
peers.clear();
if (requests != null)
requests.clear();
}
/** @return default 0 @since 0.8.1 */
public int getPriority() { return this.priority; }

View File

@@ -35,6 +35,7 @@ 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;
/**
* Main Snark program startup class.
@@ -47,29 +48,6 @@ public class Snark
private final static int MIN_PORT = 6881;
private final static int MAX_PORT = 6889;
// Error messages (non-fatal)
public final static int ERROR = 1;
// Warning messages
public final static int WARNING = 2;
// Notices (peer level)
public final static int NOTICE = 3;
// Info messages (protocol policy level)
public final static int INFO = 4;
// Debug info (protocol level)
public final static int DEBUG = 5;
// Very low level stuff (network level)
public final static int ALL = 6;
/**
* What level of debug info to show.
*/
//public static int debug = NOTICE;
// Whether or not to ask the user for commands while sharing
//private static boolean command_interpreter = true;
@@ -252,9 +230,10 @@ public class Snark
private volatile boolean stopped;
private volatile boolean starting;
private byte[] id;
private byte[] infoHash;
private final byte[] infoHash;
private String additionalTrackerURL;
private final I2PSnarkUtil _util;
private final Log _log;
private final PeerCoordinatorSet _peerCoordinatorSet;
private String trackerProblems;
private int trackerSeenPeers;
@@ -308,6 +287,7 @@ public class Snark
completeListener = complistener;
_util = util;
_log = util.getContext().logManager().getLog(Snark.class);
_peerCoordinatorSet = peerCoordinatorSet;
acceptor = connectionAcceptor;
@@ -318,7 +298,8 @@ public class Snark
activity = "Network setup";
id = generateID();
debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("My peer id: " + PeerID.idencode(id));
/*
* Don't start a tunnel if the torrent isn't going to be started.
@@ -340,6 +321,7 @@ public class Snark
meta = null;
File f = null;
InputStream in = null;
byte[] x_infoHash = null;
try
{
f = new File(torrent);
@@ -362,7 +344,7 @@ public class Snark
throw new IOException("not found");
}
meta = new MetaInfo(in);
infoHash = meta.getInfoHash();
x_infoHash = meta.getInfoHash();
}
catch(IOException ioe)
{
@@ -403,7 +385,9 @@ public class Snark
try { in.close(); } catch (IOException ioe) {}
}
debug(meta.toString(), INFO);
infoHash = x_infoHash; // final
if (_log.shouldLog(Log.INFO))
_log.info(meta.toString());
// When the metainfo torrent was created from an existing file/dir
// it already exists.
@@ -464,6 +448,7 @@ public class Snark
{
completeListener = complistener;
_util = util;
_log = util.getContext().logManager().getLog(Snark.class);
_peerCoordinatorSet = peerCoordinatorSet;
acceptor = connectionAcceptor;
this.torrent = torrent;
@@ -531,9 +516,11 @@ public class Snark
fatal("Unable to listen for I2P connections");
else {
Destination d = serversocket.getManager().getSession().getMyDestination();
debug("Listening on I2P destination " + d.toBase64() + " / " + d.calculateHash().toBase64(), NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Listening on I2P destination " + d.toBase64() + " / " + d.calculateHash().toBase64());
}
debug("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient", NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient");
activity = "Collecting pieces";
coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this);
if (_peerCoordinatorSet != null) {
@@ -573,7 +560,8 @@ public class Snark
}
trackerclient.start();
} else {
debug("NOT starting TrackerClient???", NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("NOT starting TrackerClient???");
}
}
@@ -700,6 +688,22 @@ public class Snark
starting = true;
}
/**
* File checking in progress.
* @since 0.9.3
*/
public boolean isChecking() {
return storage != null && storage.isChecking();
}
/**
* Disk allocation (ballooning) in progress.
* @since 0.9.3
*/
public boolean isAllocating() {
return storage != null && storage.isAllocating();
}
/**
* @since 0.8.4
*/
@@ -1017,22 +1021,13 @@ public class Snark
private static void usage()
{
System.out.println
("Usage: snark [--debug [level]] [--no-commands] [--port <port>]");
("Usage: snark [--no-commands] [--port <port>]");
System.out.println
(" [--eepproxy hostname portnum]");
System.out.println
(" [--i2cp routerHost routerPort ['name=val name=val name=val']]");
System.out.println
(" (<url>|<file>)");
System.out.println
(" --debug\tShows some extra info and stacktraces");
System.out.println
(" level\tHow much debug details to show");
System.out.println
(" \t(defaults to "
+ NOTICE + ", with --debug to "
+ INFO + ", highest level is "
+ ALL + ").");
System.out.println
(" --no-commands\tDon't read interactive commands or show usage info.");
System.out.println
@@ -1071,7 +1066,7 @@ public class Snark
*/
private void fatal(String s, Throwable t)
{
_util.debug(s, ERROR, t);
_log.error(s, t);
//System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
//if (debug >= INFO && t != null)
// t.printStackTrace();
@@ -1083,14 +1078,6 @@ public class Snark
throw new RuntimeException(s, t);
}
/**
* Show debug info if debug is true.
*/
private void debug(String s, int level)
{
_util.debug(s, level, null);
}
/** CoordinatorListener - this does nothing */
public void peerChange(PeerCoordinator coordinator, Peer peer)
{
@@ -1168,9 +1155,10 @@ public class Snark
// + " pieces: ");
checking = true;
}
if (!checking)
debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
Snark.INFO);
if (!checking) {
if (_log.shouldLog(Log.INFO))
_log.info("Got " + (checked ? "" : "BAD ") + "piece: " + num);
}
}
public void storageAllChecked(Storage storage)
@@ -1186,7 +1174,8 @@ public class Snark
public void storageCompleted(Storage storage)
{
debug("Completely received " + torrent, Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("Completely received " + torrent);
//storage.close();
//System.out.println("Completely received: " + torrent);
if (completeListener != null)
@@ -1206,6 +1195,15 @@ public class Snark
//System.exit(0);
}
/**
* StorageListener and CoordinatorListener callback
* @since 0.9.2
*/
public void addMessage(String message) {
if (completeListener != null)
completeListener.addMessage(this, message);
}
public interface CompleteListener {
public void torrentComplete(Snark snark);
public void updateStatus(Snark snark);
@@ -1225,6 +1223,11 @@ public class Snark
*/
public void fatal(Snark snark, String error);
/**
* @since 0.9.2
*/
public void addMessage(Snark snark, String message);
// not really listeners but the easiest way to get back to an optional SnarkManager
public long getSavedTorrentTime(Snark snark);
public BitField getSavedTorrentBitField(Snark snark);
@@ -1239,8 +1242,8 @@ public class Snark
if (_peerCoordinatorSet == null || uploaders <= 0)
return false;
int totalUploaders = 0;
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next();
for (Iterator<PeerCoordinator> iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = iter.next();
if (!c.halted())
totalUploaders += c.uploaders;
}
@@ -1253,13 +1256,14 @@ public class Snark
if (_peerCoordinatorSet == null)
return false;
long total = 0;
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next();
for (Iterator<PeerCoordinator> iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = iter.next();
if (!c.halted())
total += c.getCurrentUploadRate();
}
long limit = 1024l * _util.getMaxUpBW();
debug("Total up bw: " + total + " Limit: " + limit, Snark.NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Total up bw: " + total + " Limit: " + limit);
return total > limit;
}

View File

@@ -37,6 +37,8 @@ import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import org.klomp.snark.dht.DHT;
/**
* Manage multiple snarks
*/
@@ -85,11 +87,14 @@ public class SnarkManager implements Snark.CompleteListener {
//public static final String DEFAULT_LINK_PREFIX = "file:///";
public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
public static final String PROP_REFRESH_DELAY = "i2psnark.refreshSeconds";
public static final String RC_PROP_THEME = "routerconsole.theme";
public static final String RC_PROP_UNIVERSAL_THEMING = "routerconsole.universal.theme";
public static final String PROP_THEME = "i2psnark.theme";
public static final String DEFAULT_THEME = "ubergine";
private static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
public static final String PROP_PRIVATETRACKERS = "i2psnark.privatetrackers";
private static final String PROP_USE_DHT = "i2psnark.enableDHT";
public static final int MIN_UP_BW = 2;
public static final int DEFAULT_MAX_UP_BW = 10;
@@ -120,15 +125,11 @@ public class SnarkManager implements Snark.CompleteListener {
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
public static final String PROP_TRACKERS = "i2psnark.trackers";
private static final SnarkManager _instance = new SnarkManager();
public static SnarkManager instance() { return _instance; }
private SnarkManager() {
public SnarkManager(I2PAppContext ctx) {
_snarks = new ConcurrentHashMap();
_magnets = new ConcurrentHashSet();
_addSnarkLock = new Object();
_context = I2PAppContext.getGlobalContext();
_context = ctx;
_log = _context.logManager().getLog(SnarkManager.class);
_messages = new LinkedBlockingQueue();
_util = new I2PSnarkUtil(_context);
@@ -199,11 +200,11 @@ public class SnarkManager implements Snark.CompleteListener {
* @since 0.8.9
*/
public boolean areFilesPublic() {
return Boolean.valueOf(_config.getProperty(PROP_FILES_PUBLIC)).booleanValue();
return Boolean.parseBoolean(_config.getProperty(PROP_FILES_PUBLIC));
}
public boolean shouldAutoStart() {
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START)).booleanValue();
return Boolean.parseBoolean(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START));
}
/****
@@ -288,6 +289,9 @@ public class SnarkManager implements Snark.CompleteListener {
_config.setProperty(PROP_STARTUP_DELAY, Integer.toString(DEFAULT_STARTUP_DELAY));
if (!_config.containsKey(PROP_THEME))
_config.setProperty(PROP_THEME, DEFAULT_THEME);
// no, so we can switch default to true later
//if (!_config.containsKey(PROP_USE_DHT))
// _config.setProperty(PROP_USE_DHT, Boolean.toString(I2PSnarkUtil.DEFAULT_USE_DHT));
updateConfig();
}
/**
@@ -296,6 +300,26 @@ public class SnarkManager implements Snark.CompleteListener {
*/
public String getTheme() {
String theme = _config.getProperty(PROP_THEME);
boolean universalTheming = _context.getBooleanProperty(RC_PROP_UNIVERSAL_THEMING);
if (universalTheming) {
// Fetch routerconsole theme (or use our default if it doesn't exist)
theme = _context.getProperty(RC_PROP_THEME, DEFAULT_THEME);
// Ensure that theme exists
String[] themes = getThemes();
boolean themeExists = false;
for (int i = 0; i < themes.length; i++) {
if (themes[i].equals(theme))
themeExists = true;
}
if (!themeExists) {
// Since the default is not "light", explicitly check if universal theme is "classic"
if (theme.equals("classic"))
theme = "light";
else
theme = DEFAULT_THEME;
_config.setProperty(PROP_THEME, DEFAULT_THEME);
}
}
return theme;
}
@@ -360,8 +384,11 @@ public class SnarkManager implements Snark.CompleteListener {
if (ot != null)
_util.setOpenTrackers(getOpenTrackers());
String useOT = _config.getProperty(PROP_USE_OPENTRACKERS);
boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
boolean bOT = useOT == null || Boolean.parseBoolean(useOT);
_util.setUseOpenTrackers(bOT);
// careful, so we can switch default to true later
_util.setUseDHT(Boolean.parseBoolean(_config.getProperty(PROP_USE_DHT,
Boolean.toString(I2PSnarkUtil.DEFAULT_USE_DHT))));
getDataDir().mkdirs();
initTrackerMap();
}
@@ -380,7 +407,7 @@ public class SnarkManager implements Snark.CompleteListener {
public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, String refreshDelay,
String startDelay, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, boolean useOpenTrackers, String theme) {
String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme) {
boolean changed = false;
//if (eepHost != null) {
// // unused, we use socket eepget
@@ -564,6 +591,17 @@ public class SnarkManager implements Snark.CompleteListener {
_util.setUseOpenTrackers(useOpenTrackers);
changed = true;
}
if (_util.shouldUseDHT() != useDHT) {
_config.setProperty(PROP_USE_DHT, Boolean.toString(useDHT));
if (useDHT)
addMessage(_("Enabled DHT."));
else
addMessage(_("Disabled DHT."));
if (_util.connected())
addMessage(_("DHT change requires tunnel shutdown and reopen"));
_util.setUseDHT(useDHT);
changed = true;
}
if (theme != null) {
if(!theme.equals(_config.getProperty(PROP_THEME))) {
_config.setProperty(PROP_THEME, theme);
@@ -669,7 +707,7 @@ public class SnarkManager implements Snark.CompleteListener {
public Properties getConfig() { return _config; }
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
private static final int MAX_FILES_PER_TORRENT = 512;
public static final int MAX_FILES_PER_TORRENT = 512;
/**
* Set of canonical .torrent filenames that we are dealing with.
@@ -787,14 +825,14 @@ public class SnarkManager implements Snark.CompleteListener {
if (!TrackerClient.isValidAnnounce(info.getAnnounce())) {
if (info.isPrivate()) {
addMessage(_("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName()));
} else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
//} else if (_util.getDHT() != null) {
// addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName()));
} else if (!_util.getOpenTrackers().isEmpty()) {
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
} else if (_util.shouldUseDHT()) {
addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName()));
} else {
//addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
addMessage(_("Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent.", info.getName()));
addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
//addMessage(_("Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent.", info.getName()));
dontAutoStart = true;
}
}
@@ -870,10 +908,13 @@ public class SnarkManager implements Snark.CompleteListener {
if (shouldAutoStart()) {
torrent.startTorrent();
addMessage(_("Fetching {0}", name));
boolean haveSavedPeers = false;
if ((_util.connected()) && !haveSavedPeers) {
addMessage(_("We have no saved peers and no other torrents are running. " +
"Fetch of {0} will not succeed until you start another torrent.", name));
DHT dht = _util.getDHT();
boolean shouldWarn = _util.connected() &&
_util.getOpenTrackers().isEmpty() &&
((!_util.shouldUseDHT()) || dht == null || dht.size() <= 0);
if (shouldWarn) {
addMessage(_("Open trackers are disabled and we have no DHT peers. " +
"Fetch of {0} may not succeed until you start another torrent, enable open trackers, or enable DHT.", name));
}
} else {
addMessage(_("Adding {0}", name));
@@ -1329,6 +1370,8 @@ public class SnarkManager implements Snark.CompleteListener {
} catch (Exception e) {
_log.error("Error in the DirectoryMonitor", e);
}
if (!_snarks.isEmpty())
addMessage(_("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
}
try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
}
@@ -1420,6 +1463,14 @@ public class SnarkManager implements Snark.CompleteListener {
addMessage(_("Error on torrent {0}", snark.getName()) + ": " + error);
}
/**
* A Snark.CompleteListener method.
* @since 0.9.2
*/
public void addMessage(Snark snark, String message) {
addMessage(message);
}
// End Snark.CompleteListeners
/**
@@ -1435,7 +1486,7 @@ public class SnarkManager implements Snark.CompleteListener {
byte[] ih = Base64.decode(b64);
// ignore value - TODO put tracker URL in value
if (ih != null && ih.length == 20)
addMagnet("* " + _("Magnet") + ' ' + I2PSnarkUtil.toHex(ih), ih, null, false);
addMagnet(_("Magnet") + ' ' + I2PSnarkUtil.toHex(ih), ih, null, false);
// else remove from config?
}
}
@@ -1708,9 +1759,12 @@ public class SnarkManager implements Snark.CompleteListener {
}
if (_util.connected()) {
if (count > 0) {
DHT dht = _util.getDHT();
if (dht != null)
dht.stop();
// Schedule this even for final shutdown, as there's a chance
// that it's just this webapp that is stopping.
SimpleScheduler.getInstance().addEvent(new Disconnector(), 60*1000);
_context.simpleScheduler().addEvent(new Disconnector(), 60*1000);
addMessage(_("Closing I2P tunnel after notifying trackers."));
if (finalShutdown) {
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}

View File

@@ -32,16 +32,21 @@ import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import net.i2p.crypto.SHA1;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SecureFile;
import net.i2p.util.SystemVersion;
/**
* Maintains pieces on disk. Can be used to store and retrieve pieces.
*/
public class Storage
{
private MetaInfo metainfo;
private final MetaInfo metainfo;
private long[] lengths;
private RandomAccessFile[] rafs;
private String[] names;
@@ -55,6 +60,7 @@ public class Storage
private final StorageListener listener;
private final I2PSnarkUtil _util;
private final Log _log;
private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces
private int needed; // Number of pieces needed
@@ -64,6 +70,8 @@ public class Storage
private final int pieces;
private final long total_length;
private boolean changed;
private volatile boolean _isChecking;
private final AtomicInteger _allocateCount = new AtomicInteger();
/** The default piece size. */
private static final int MIN_PIECE_SIZE = 256*1024;
@@ -75,22 +83,24 @@ public class Storage
private static final Map<String, String> _filterNameCache = new ConcurrentHashMap();
private static final boolean _isWindows = System.getProperty("os.name").startsWith("Win");
private static final boolean _isWindows = SystemVersion.isWindows();
private static final int BUFSIZE = PeerState.PARTSIZE;
private static final ByteCache _cache = ByteCache.getInstance(16, BUFSIZE);
/**
* Creates a new storage based on the supplied MetaInfo. This will
* try to create and/or check all needed files in the MetaInfo.
*
* @exception IOException when creating and/or checking files fails.
* Does not check storage. Caller MUST call check()
*/
public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener)
throws IOException
{
_util = util;
_log = util.getContext().logManager().getLog(Storage.class);
this.metainfo = metainfo;
this.listener = listener;
needed = metainfo.getPieces();
_probablyComplete = false;
bitfield = new BitField(needed);
piece_size = metainfo.getPieceLength(0);
pieces = needed;
@@ -98,18 +108,22 @@ public class Storage
}
/**
* Creates a storage from the existing file or directory together
* with an appropriate MetaInfo file as can be announced on the
* given announce String location.
* Creates a storage from the existing file or directory.
* Creates an in-memory metainfo but does not save it to
* a file, caller must do that.
*
* Creates the metainfo, this may take a LONG time. BLOCKING.
*
* @param announce may be null
* @param listener may be null
* @throws IOException when creating and/or checking files fails.
*/
public Storage(I2PSnarkUtil util, File baseFile, String announce,
boolean privateTorrent, StorageListener listener)
throws IOException
{
_util = util;
_log = util.getContext().logManager().getLog(Storage.class);
this.listener = listener;
// Create names, rafs and lengths arrays.
getFiles(baseFile);
@@ -125,6 +139,8 @@ public class Storage
if (total <= 0)
throw new IOException("Torrent contains no data");
if (total > MAX_TOTAL_SIZE)
throw new IOException("Torrent too big (" + total + " bytes), max is " + MAX_TOTAL_SIZE);
int pc_size = MIN_PIECE_SIZE;
int pcs = (int) ((total - 1)/pc_size) + 1;
@@ -160,6 +176,7 @@ public class Storage
lengthsList = null;
}
// TODO thread this so we can return and show something on the UI
byte[] piece_hashes = fast_digestCreate();
metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
lengthsList, piece_size, piece_hashes, total, privateTorrent);
@@ -195,6 +212,8 @@ public class Storage
private void getFiles(File base) throws IOException
{
if (base.getAbsolutePath().equals("/"))
throw new IOException("Don't seed root");
ArrayList files = new ArrayList();
addFiles(files, base);
@@ -223,17 +242,21 @@ public class Storage
}
}
private void addFiles(List l, File f)
{
if (!f.isDirectory())
l.add(f);
else
{
/**
* @throws IOException if too many total files
*/
private void addFiles(List 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?");
l.add(f);
} else {
File[] files = f.listFiles();
if (files == null)
{
_util.debug("WARNING: Skipping '" + f
+ "' not a normal file.", Snark.WARNING);
if (_log.shouldLog(Log.WARN))
_log.warn("WARNING: Skipping '" + f
+ "' not a normal file.");
return;
}
for (int i = 0; i < files.length; i++)
@@ -273,6 +296,23 @@ public class Storage
return changed;
}
/**
* File checking in progress.
* @since 0.9.3
*/
public boolean isChecking() {
return _isChecking;
}
/**
* Disk allocation (ballooning) in progress.
* Always false on Windows.
* @since 0.9.3
*/
public boolean isAllocating() {
return _allocateCount.get() > 0;
}
/**
* @param file canonical path (non-directory)
* @return number of bytes remaining; -1 if unknown file
@@ -457,7 +497,8 @@ public class Storage
if (files == null)
{
// Create base as file.
_util.debug("Creating/Checking file: " + base, Snark.NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Creating/Checking file: " + base);
if (!base.createNewFile() && !base.exists())
throw new IOException("Could not create file " + base);
@@ -481,7 +522,8 @@ public class Storage
else
{
// Create base as dir.
_util.debug("Creating/Checking directory: " + base, Snark.NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Creating/Checking directory: " + base);
if (!base.mkdir() && !base.isDirectory())
throw new IOException("Could not create directory " + base);
@@ -540,19 +582,22 @@ public class Storage
bitfield = savedBitField;
needed = metainfo.getPieces() - bitfield.count();
_probablyComplete = complete();
_util.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Found saved state and files unchanged, skipping check");
} else {
// the following sets the needed variable
changed = true;
checkCreateFiles(false);
}
if (complete()) {
_util.debug("Torrent is complete", Snark.NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Torrent is complete");
} else {
// fixme saved priorities
if (files != null)
priorities = new int[files.size()];
_util.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE);
if (_log.shouldLog(Log.INFO))
_log.info("Still need " + needed + " out of " + metainfo.getPieces() + " pieces");
}
}
@@ -687,11 +732,25 @@ public class Storage
* This is called at the beginning, and at presumed completion,
* so we have to be careful about locking.
*
* TODO thread the checking so we can return and display
* something on the UI
*
* @param recheck if true, this is a check after we downloaded the
* last piece, and we don't modify the global bitfield unless
* the check fails.
*/
private void checkCreateFiles(boolean recheck) throws IOException
private void checkCreateFiles(boolean recheck) throws IOException {
synchronized(this) {
_isChecking = true;
try {
locked_checkCreateFiles(recheck);
} finally {
_isChecking = false;
}
}
}
private void locked_checkCreateFiles(boolean recheck) throws IOException
{
// Whether we are resuming or not,
// if any of the files already exists we assume we are resuming.
@@ -730,8 +789,9 @@ public class Storage
} else {
String msg = "File '" + names[i] + "' exists, but has wrong length (expected " +
lengths[i] + " but found " + length + ") - repairing corruption";
SnarkManager.instance().addMessage(msg);
_util.debug(msg, Snark.ERROR);
if (listener != null)
listener.addMessage(msg);
_log.error(msg);
changed = true;
resume = true;
_probablyComplete = false; // to force RW
@@ -844,15 +904,25 @@ public class Storage
*/
private void balloonFile(int nr) throws IOException
{
_util.debug("Ballooning " + nr + ": " + RAFfile[nr], Snark.INFO);
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);
while (remaining > 0) {
int size = (int) Math.min(remaining, ZEROBLOCKSIZE);
rafs[nr].write(zeros, 0, size);
remaining -= size;
// 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();
}
isSparse[nr] = false;
}
@@ -875,7 +945,7 @@ public class Storage
closeRAF(i);
}
} catch (IOException ioe) {
_util.debug("Error closing " + RAFfile[i], Snark.ERROR, ioe);
_log.error("Error closing " + RAFfile[i], ioe);
// gobble gobble
}
}
@@ -886,21 +956,28 @@ public class Storage
* Returns a byte array containing a portion of the requested piece or null if
* the storage doesn't contain the piece yet.
*/
public byte[] getPiece(int piece, int off, int len) throws IOException
public ByteArray getPiece(int piece, int off, int len) throws IOException
{
if (!bitfield.get(piece))
return null;
//Catch a common place for OOMs esp. on 1MB pieces
ByteArray rv;
byte[] bs;
try {
bs = new byte[len];
// Will be restored to cache in Message.sendMessage()
if (len == BUFSIZE)
rv = _cache.acquire();
else
rv = new ByteArray(new byte[len]);
} catch (OutOfMemoryError oom) {
_util.debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
if (_log.shouldLog(Log.WARN))
_log.warn("Out of memory, can't honor request for piece " + piece, oom);
return null;
}
bs = rv.getData();
getUncheckedPiece(piece, bs, off, len);
return bs;
return rv;
}
/**
@@ -1000,8 +1077,9 @@ public class Storage
if (needed > 0) {
if (listener != null)
listener.setWantedPieces(this);
_util.debug("WARNING: Not really done, missing " + needed
+ " pieces", Snark.WARNING);
if (_log.shouldLog(Log.WARN))
_log.warn("WARNING: Not really done, missing " + needed
+ " pieces");
}
}

View File

@@ -61,4 +61,6 @@ interface StorageListener
*
*/
void setWantedPieces(Storage storage);
void addMessage(String message);
}

View File

@@ -27,6 +27,7 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
@@ -38,11 +39,12 @@ import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.util.Clock;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
import org.klomp.snark.dht.DHT;
/**
* Informs metainfo tracker of events and gets new peers for peer
* coordinator.
@@ -62,7 +64,7 @@ import net.i2p.util.SimpleTimer2;
* @author Mark Wielaard (mark@klomp.org)
*/
public class TrackerClient implements Runnable {
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(TrackerClient.class);
private final Log _log;
private static final String NO_EVENT = "";
private static final String STARTED_EVENT = "started";
private static final String COMPLETED_EVENT = "completed";
@@ -76,6 +78,8 @@ public class TrackerClient implements Runnable {
private final static int INITIAL_SLEEP = 90*1000;
private final static int MAX_CONSEC_FAILS = 5; // slow down after this
private final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails
private final static long MIN_TRACKER_ANNOUNCE_INTERVAL = 10*60*1000;
private final static long MIN_DHT_ANNOUNCE_INTERVAL = 10*60*1000;
private final I2PSnarkUtil _util;
private final MetaInfo meta;
@@ -98,8 +102,9 @@ public class TrackerClient implements Runnable {
// these 2 used in loop()
private volatile boolean runStarted;
private volatile int consecutiveFails;
private boolean completed;
private volatile boolean _fastUnannounce;
private long lastDHTAnnounce;
private final List<Tracker> trackers;
/**
@@ -116,6 +121,7 @@ public class TrackerClient implements Runnable {
String id = urlencode(snark.getID());
_threadName = "TrackerClient " + id.substring(id.length() - 12);
_util = util;
_log = util.getContext().logManager().getLog(TrackerClient.class);
this.meta = meta;
this.additionalTrackerURL = additionalTrackerURL;
this.coordinator = coordinator;
@@ -183,7 +189,7 @@ public class TrackerClient implements Runnable {
private class Runner extends SimpleTimer2.TimedEvent {
public Runner(long delay) {
super(SimpleTimer2.getInstance(), delay);
super(_util.getContext().simpleTimer2(), delay);
}
public void timeReached() {
@@ -209,17 +215,22 @@ public class TrackerClient implements Runnable {
* This will take several seconds to several minutes.
*/
public void run() {
long begin = Clock.getInstance().now();
long begin = _util.getContext().clock().now();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Start " + Thread.currentThread().getName());
try {
if (!_initialized) {
setup();
// FIXME dht
if (trackers.isEmpty()) {
stop = true;
return;
}
}
if (trackers.isEmpty() && _util.getDHT() == null) {
stop = true;
this.snark.addMessage(_util.getString("No valid trackers for {0} - enable opentrackers or DHT?",
this.snark.getBaseName()));
_log.error("No valid trackers for " + this.snark.getBaseName());
this.snark.stopTorrent();
return;
}
if (!_initialized) {
_initialized = true;
// FIXME only when starting everybody at once, not for a single torrent
long delay = I2PAppContext.getGlobalContext().random().nextInt(30*1000);
@@ -233,7 +244,7 @@ public class TrackerClient implements Runnable {
_thread = null;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Finish " + Thread.currentThread().getName() +
" after " + DataHelper.formatDuration(Clock.getInstance().now() - begin));
" after " + DataHelper.formatDuration(_util.getContext().clock().now() - begin));
}
}
@@ -293,16 +304,7 @@ public class TrackerClient implements Runnable {
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
}
}
if (trackers.isEmpty()) {
stop = true;
// FIXME translate
SnarkManager.instance().addMessage("No valid trackers for " + this.snark.getBaseName() + " - enable opentrackers?");
_log.error("No valid trackers for " + this.snark.getBaseName());
// FIXME keep going if DHT enabled
this.snark.stopTorrent();
return;
}
this.completed = coordinator.getLeft() == 0;
}
/**
@@ -322,13 +324,13 @@ public class TrackerClient implements Runnable {
}
// Local DHT tracker announce
if (_util.getDHT() != null)
_util.getDHT().announce(snark.getInfoHash());
DHT dht = _util.getDHT();
if (dht != null)
dht.announce(snark.getInfoHash());
long uploaded = coordinator.getUploaded();
long downloaded = coordinator.getDownloaded();
long left = coordinator.getLeft(); // -1 in magnet mode
boolean completed = (left == 0);
// First time we got a complete download?
String event;
@@ -342,8 +344,7 @@ public class TrackerClient implements Runnable {
// *** loop once for each tracker
int maxSeenPeers = 0;
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
Tracker tr = (Tracker)iter.next();
for (Tracker tr : trackers) {
if ((!stop) && (!tr.stop) &&
(completed || coordinator.needOutboundPeers() || !tr.started) &&
(event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
@@ -371,9 +372,10 @@ public class TrackerClient implements Runnable {
snark.setTrackerSeenPeers(tr.seenPeers);
// pass everybody over to our tracker
if (_util.getDHT() != null) {
dht = _util.getDHT();
if (dht != null) {
for (Peer peer : peers) {
_util.getDHT().announce(snark.getInfoHash(), peer.getPeerID().getDestHash());
dht.announce(snark.getInfoHash(), peer.getPeerID().getDestHash());
}
}
@@ -397,9 +399,10 @@ public class TrackerClient implements Runnable {
catch (IOException ioe)
{
// Probably not fatal (if it doesn't last to long...)
_util.debug
if (_log.shouldLog(Log.WARN))
_log.warn
("WARNING: Could not contact tracker at '"
+ tr.announce + "': " + ioe, Snark.WARNING);
+ tr.announce + "': " + ioe);
tr.trackerProblems = ioe.getMessage();
// don't show secondary tracker problems to the user
if (tr.isPrimary)
@@ -421,8 +424,9 @@ public class TrackerClient implements Runnable {
}
}
} else {
_util.debug("Not announcing to " + tr.announce + " last announce was " +
new Date(tr.lastRequestTime) + " interval is " + DataHelper.formatDuration(tr.interval), Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("Not announcing to " + tr.announce + " last announce was " +
new Date(tr.lastRequestTime) + " interval is " + DataHelper.formatDuration(tr.interval));
}
if ((!tr.stop) && maxSeenPeers < tr.seenPeers)
maxSeenPeers = tr.seenPeers;
@@ -432,7 +436,8 @@ public class TrackerClient implements Runnable {
if (coordinator.needOutboundPeers() && (meta == null || !meta.isPrivate()) && !stop) {
Set<PeerID> pids = coordinator.getPEXPeers();
if (!pids.isEmpty()) {
_util.debug("Got " + pids.size() + " from PEX", Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("Got " + pids.size() + " from PEX");
List<Peer> peers = new ArrayList(pids.size());
for (PeerID pID : pids) {
peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo()));
@@ -448,31 +453,41 @@ public class TrackerClient implements Runnable {
}
}
} else {
_util.debug("Not getting PEX peers", Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("Not getting PEX peers");
}
// Get peers from DHT
// FIXME this needs to be in its own thread
if (_util.getDHT() != null && (meta == null || !meta.isPrivate()) && !stop) {
dht = _util.getDHT();
if (dht != null && (meta == null || !meta.isPrivate()) && (!stop) &&
_util.getContext().clock().now() > lastDHTAnnounce + MIN_DHT_ANNOUNCE_INTERVAL) {
int numwant;
if (event.equals(STOPPED_EVENT) || !coordinator.needOutboundPeers())
numwant = 1;
else
numwant = _util.getMaxConnections();
List<Hash> hashes = _util.getDHT().getPeers(snark.getInfoHash(), numwant, 2*60*1000);
_util.debug("Got " + hashes + " from DHT", Snark.INFO);
Collection<Hash> hashes = dht.getPeers(snark.getInfoHash(), numwant, 2*60*1000);
if (!hashes.isEmpty()) {
runStarted = true;
lastDHTAnnounce = _util.getContext().clock().now();
}
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) {
int good = _util.getDHT().announce(snark.getInfoHash(), 8, 5*60*1000);
_util.debug("Sent " + good + " good announces to DHT", Snark.INFO);
// 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());
for (Hash h : hashes) {
PeerID pID = new PeerID(h.getData());
PeerID pID = new PeerID(h.getData(), _util);
peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo()));
}
Collections.shuffle(peers, r);
@@ -486,7 +501,8 @@ public class TrackerClient implements Runnable {
}
}
} else {
_util.debug("Not getting DHT peers", Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("Not getting DHT peers");
}
@@ -496,9 +512,6 @@ public class TrackerClient implements Runnable {
if (stop)
return;
if (!runStarted)
_util.debug(" Retrying in one minute...", Snark.DEBUG);
try {
// Sleep some minutes...
// Sleep the minimum interval for all the trackers, but 60s minimum
@@ -508,6 +521,8 @@ public class TrackerClient implements Runnable {
delay = 3*SLEEP*60*1000 + random;
else if (snark.getTrackerProblems() != null && ++consecutiveFails < MAX_CONSEC_FAILS)
delay = INITIAL_SLEEP;
else if ((!runStarted) && _runCount < MAX_CONSEC_FAILS)
delay = INITIAL_SLEEP;
else
// sleep a while, when we wake up we will contact only the trackers whose intervals have passed
delay = SLEEP*60*1000 + random;
@@ -526,7 +541,7 @@ public class TrackerClient implements Runnable {
} // try
catch (Throwable t)
{
_util.debug("TrackerClient: " + t, Snark.ERROR, t);
_log.error("TrackerClient: " + t, t);
if (t instanceof OutOfMemoryError)
throw (OutOfMemoryError)t;
}
@@ -538,8 +553,9 @@ public class TrackerClient implements Runnable {
*/
private void unannounce() {
// Local DHT tracker unannounce
if (_util.getDHT() != null)
_util.getDHT().unannounce(snark.getInfoHash());
DHT dht = _util.getDHT();
if (dht != null)
dht.unannounce(snark.getInfoHash());
int i = 0;
for (Tracker tr : trackers) {
if (_util.connected() &&
@@ -619,7 +635,8 @@ public class TrackerClient implements Runnable {
else
buf.append(_util.getMaxConnections());
String s = buf.toString();
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
if (_log.shouldLog(Log.INFO))
_log.info("Sending TrackerClient request: " + s);
tr.lastRequestTime = System.currentTimeMillis();
// Don't wait for a response to stopped when shutting down
@@ -634,14 +651,15 @@ public class TrackerClient implements Runnable {
in = new FileInputStream(fetched);
TrackerInfo info = new TrackerInfo(in, snark.getID(),
snark.getInfoHash(), snark.getMetaInfo());
_util.debug("TrackerClient response: " + info, Snark.INFO);
snark.getInfoHash(), snark.getMetaInfo(), _util);
if (_log.shouldLog(Log.INFO))
_log.info("TrackerClient response: " + info);
String failure = info.getFailureReason();
if (failure != null)
throw new IOException(failure);
tr.interval = info.getInterval() * 1000;
tr.interval = Math.max(MIN_TRACKER_ANNOUNCE_INTERVAL, info.getInterval() * 1000l);
return info;
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}

View File

@@ -38,7 +38,7 @@ import org.klomp.snark.bencode.InvalidBEncodingException;
* Compact format 1 - a list of hashes - early format for testing
* Compact format 2 - One big string of concatenated hashes - official format
*/
public class TrackerInfo
class TrackerInfo
{
private final String failure_reason;
private final int interval;
@@ -47,19 +47,19 @@ public class TrackerInfo
private int incomplete;
/** @param metainfo may be null */
public TrackerInfo(InputStream in, byte[] my_id, byte[] infohash, MetaInfo metainfo)
public TrackerInfo(InputStream in, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
throws IOException
{
this(new BDecoder(in), my_id, infohash, metainfo);
this(new BDecoder(in), my_id, infohash, metainfo, util);
}
private TrackerInfo(BDecoder be, byte[] my_id, byte[] infohash, MetaInfo metainfo)
private TrackerInfo(BDecoder be, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
throws IOException
{
this(be.bdecodeMap().getMap(), my_id, infohash, metainfo);
this(be.bdecodeMap().getMap(), my_id, infohash, metainfo, util);
}
private TrackerInfo(Map m, byte[] my_id, byte[] infohash, MetaInfo metainfo)
private TrackerInfo(Map m, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
throws IOException
{
BEValue reason = (BEValue)m.get("failure reason");
@@ -85,10 +85,10 @@ public class TrackerInfo
Set<Peer> p;
try {
// One big string (the official compact format)
p = getPeers(bePeers.getBytes(), my_id, infohash, metainfo);
p = getPeers(bePeers.getBytes(), my_id, infohash, metainfo, util);
} catch (InvalidBEncodingException ibe) {
// List of Dictionaries or List of Strings
p = getPeers(bePeers.getList(), my_id, infohash, metainfo);
p = getPeers(bePeers.getList(), my_id, infohash, metainfo, util);
}
peers = p;
}
@@ -124,7 +124,7 @@ public class TrackerInfo
******/
/** List of Dictionaries or List of Strings */
private static Set<Peer> getPeers(List<BEValue> l, byte[] my_id, byte[] infohash, MetaInfo metainfo)
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());
@@ -138,7 +138,7 @@ public class TrackerInfo
try {
// Case 2 - compact - A list of 32-byte binary strings (hashes)
// This was just for testing and is not the official format
peerID = new PeerID(bev.getBytes());
peerID = new PeerID(bev.getBytes(), util);
} catch (InvalidBEncodingException ibe2) {
// don't let one bad entry spoil the whole list
//Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
@@ -157,7 +157,7 @@ public class TrackerInfo
* One big string of concatenated 32-byte hashes
* @since 0.8.1
*/
private static Set<Peer> getPeers(byte[] l, byte[] my_id, byte[] infohash, MetaInfo metainfo)
private static Set<Peer> getPeers(byte[] l, byte[] my_id, byte[] infohash, MetaInfo metainfo, I2PSnarkUtil util)
throws IOException
{
int count = l.length / HASH_LENGTH;
@@ -168,7 +168,7 @@ public class TrackerInfo
byte[] hash = new byte[HASH_LENGTH];
System.arraycopy(l, i * HASH_LENGTH, hash, 0, HASH_LENGTH);
try {
peerID = new PeerID(hash);
peerID = new PeerID(hash, util);
} catch (InvalidBEncodingException ibe) {
// won't happen
continue;
@@ -195,6 +195,7 @@ public class TrackerInfo
return failure_reason;
}
/** in seconds */
public int getInterval()
{
return interval;

View File

@@ -4,7 +4,7 @@ package org.klomp.snark.dht;
* GPLv2
*/
import java.util.List;
import java.util.Collection;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
@@ -12,15 +12,21 @@ import net.i2p.data.Hash;
/**
* Stub for KRPC
* @since 0.8.4
*/
public interface DHT {
/**
* @return The UDP port that should be included in a PORT message.
* @return The UDP query port
*/
public int getPort();
/**
* @return The UDP response port
*/
public int getRPort();
/**
* Ping. We don't have a NID yet so the node is presumed
* to be absent from our DHT.
@@ -37,9 +43,9 @@ public interface 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
* @return list or empty list (never null)
* @return possibly empty (never null)
*/
public List<Hash> getPeers(byte[] ih, int max, long maxWait);
public Collection<Hash> getPeers(byte[] ih, int max, long maxWait);
/**
* Announce to ourselves.
@@ -79,4 +85,19 @@ public interface DHT {
* @return the number of successful announces, not counting ourselves.
*/
public int announce(byte[] ih, int max, long maxWait);
/**
* Stop everything.
*/
public void stop();
/**
* Known nodes, not estimated total network size.
*/
public int size();
/**
* Debug info, HTML formatted
*/
public String renderStatusHTML();
}

View File

@@ -0,0 +1,166 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
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;
import net.i2p.crypto.SHA1Hash;
import net.i2p.data.DataHelper;
import net.i2p.kademlia.KBucketSet;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
/**
* All the nodes we know about, stored as a mapping from
* node ID to a Destination and Port.
*
* And a real Kademlia routing table, which stores node IDs only.
*
* @since 0.9.2
* @author zzz
*/
class DHTNodes {
private final I2PAppContext _context;
private long _expireTime;
private final Log _log;
private final ConcurrentHashMap<NID, NodeInfo> _nodeMap;
private final KBucketSet<NID> _kad;
private volatile boolean _isRunning;
/** stagger with other cleaners */
private static final long CLEAN_TIME = 187*1000;
/** how long since last heard from do we delete - BEP 5 says 15 minutes */
private static final long MAX_EXPIRE_TIME = 30*60*1000;
private static final long MIN_EXPIRE_TIME = 10*60*1000;
private static final long DELTA_EXPIRE_TIME = 3*60*1000;
private static final int MAX_PEERS = 799;
/** Buckets older than this are refreshed - BEP 5 says 15 minutes */
private static final long MAX_BUCKET_AGE = 15*60*1000;
private static final int KAD_K = 8;
private static final int KAD_B = 1;
public DHTNodes(I2PAppContext ctx, NID me) {
_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));
}
public void start() {
_isRunning = true;
new Cleaner();
}
public void stop() {
clear();
_isRunning = false;
}
// begin ConcurrentHashMap methods
public int size() {
return _nodeMap.size();
}
public void clear() {
_kad.clear();
_nodeMap.clear();
}
public NodeInfo get(NID nid) {
return _nodeMap.get(nid);
}
/**
* @return the old value if present, else null
*/
public NodeInfo putIfAbsent(NodeInfo nInfo) {
_kad.add(nInfo.getNID());
return _nodeMap.putIfAbsent(nInfo.getNID(), nInfo);
}
public NodeInfo remove(NID nid) {
_kad.remove(nid);
return _nodeMap.remove(nid);
}
public Collection<NodeInfo> values() {
return _nodeMap.values();
}
// end ConcurrentHashMap methods
/**
* DHT
* @param h either a InfoHash or a NID
*/
public List<NodeInfo> findClosest(SHA1Hash h, int numWant) {
NID key;
if (h instanceof NID)
key = (NID) h;
else
key = new NID(h.getData());
List<NID> keys = _kad.getClosest(key, numWant);
List<NodeInfo> rv = new ArrayList(keys.size());
for (NID nid : keys) {
NodeInfo ninfo = _nodeMap.get(nid);
if (ninfo != null)
rv.add(ninfo);
}
return rv;
}
/**
* DHT - get random keys to explore
*/
public List<NID> getExploreKeys() {
return _kad.getExploreKeys(MAX_BUCKET_AGE);
}
/** */
private class Cleaner extends SimpleTimer2.TimedEvent {
public Cleaner() {
super(SimpleTimer2.getInstance(), CLEAN_TIME);
}
public void timeReached() {
if (!_isRunning)
return;
long now = _context.clock().now();
int peerCount = 0;
for (Iterator<NodeInfo> iter = DHTNodes.this.values().iterator(); iter.hasNext(); ) {
NodeInfo peer = iter.next();
if (peer.lastSeen() < now - _expireTime) {
iter.remove();
_kad.remove(peer.getNID());
} else {
peerCount++;
}
}
if (peerCount > MAX_PEERS)
_expireTime = Math.max(_expireTime - DELTA_EXPIRE_TIME, MIN_EXPIRE_TIME);
else
_expireTime = Math.min(_expireTime + DELTA_EXPIRE_TIME, MAX_EXPIRE_TIME);
if (_log.shouldLog(Log.DEBUG))
_log.debug("DHT storage cleaner done, now with " +
peerCount + " peers, " +
DataHelper.formatDuration(_expireTime) + " expiration");
schedule(CLEAN_TIME);
}
}
}

View File

@@ -0,0 +1,168 @@
package org.klomp.snark.dht;
/*
* From zzzot, relicensed to GPLv2
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
/**
* The tracker stores peers, i.e. Dest hashes (not nodes).
*
* @since 0.9.2
* @author zzz
*/
class DHTTracker {
private final I2PAppContext _context;
private final Torrents _torrents;
private long _expireTime;
private final Log _log;
private volatile boolean _isRunning;
/** not current, updated by cleaner */
private int _peerCount;
/** not current, updated by cleaner */
private int _torrentCount;
/** stagger with other cleaners */
private static final long CLEAN_TIME = 199*1000;
private static final long MAX_EXPIRE_TIME = 45*60*1000;
private static final long MIN_EXPIRE_TIME = 15*60*1000;
private static final long DELTA_EXPIRE_TIME = 3*60*1000;
private static final int MAX_PEERS = 2000;
private static final int MAX_PEERS_PER_TORRENT = 150;
DHTTracker(I2PAppContext ctx) {
_context = ctx;
_torrents = new Torrents();
_expireTime = MAX_EXPIRE_TIME;
_log = _context.logManager().getLog(DHTTracker.class);
}
public void start() {
_isRunning = true;
new Cleaner();
}
void stop() {
_torrents.clear();
_isRunning = false;
}
void announce(InfoHash ih, Hash hash) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Announce " + hash + " for " + ih);
Peers peers = _torrents.get(ih);
if (peers == null) {
peers = new Peers();
Peers peers2 = _torrents.putIfAbsent(ih, peers);
if (peers2 != null)
peers = peers2;
}
Peer peer = new Peer(hash.getData());
Peer peer2 = peers.putIfAbsent(peer, peer);
if (peer2 != null)
peer = peer2;
peer.setLastSeen(_context.clock().now());
}
void unannounce(InfoHash ih, Hash hash) {
Peers peers = _torrents.get(ih);
if (peers == null)
return;
Peer peer = new Peer(hash.getData());
peers.remove(peer);
}
/**
* Caller's responsibility to remove himself from the list
* @return list or empty list (never null)
*/
List<Hash> getPeers(InfoHash ih, int max) {
Peers peers = _torrents.get(ih);
if (peers == null)
return Collections.EMPTY_LIST;
int size = peers.size();
List<Hash> rv = new ArrayList(peers.values());
if (max < size) {
Collections.shuffle(rv, _context.random());
rv = rv.subList(0, max);
}
return rv;
}
/**
* Debug info, HTML formatted
*/
public void renderStatusHTML(StringBuilder buf) {
buf.append("DHT tracker: ").append(_torrentCount).append(" torrents ")
.append(_peerCount).append(" peers ")
.append(DataHelper.formatDuration(_expireTime)).append(" expiration<br>");
}
private class Cleaner extends SimpleTimer2.TimedEvent {
public Cleaner() {
super(SimpleTimer2.getInstance(), CLEAN_TIME);
}
public void timeReached() {
if (!_isRunning)
return;
long now = _context.clock().now();
int torrentCount = 0;
int peerCount = 0;
for (Iterator<Peers> iter = _torrents.values().iterator(); iter.hasNext(); ) {
Peers p = iter.next();
int recent = 0;
for (Iterator<Peer> iterp = p.values().iterator(); iterp.hasNext(); ) {
Peer peer = iterp.next();
if (peer.lastSeen() < now - _expireTime)
iterp.remove();
else {
recent++;
peerCount++;
}
}
if (recent > MAX_PEERS_PER_TORRENT) {
// too many, delete at random
// TODO per-torrent adjustable expiration?
for (Iterator<Peer> iterp = p.values().iterator(); iterp.hasNext() && p.size() > MAX_PEERS_PER_TORRENT; ) {
iterp.next();
iterp.remove();
peerCount--;
}
torrentCount++;
} else if (recent <= 0) {
iter.remove();
} else {
torrentCount++;
}
}
if (peerCount > MAX_PEERS)
_expireTime = Math.max(_expireTime - DELTA_EXPIRE_TIME, MIN_EXPIRE_TIME);
else
_expireTime = Math.min(_expireTime + DELTA_EXPIRE_TIME, MAX_EXPIRE_TIME);
if (_log.shouldLog(Log.DEBUG))
_log.debug("DHT tracker cleaner done, now with " +
torrentCount + " torrents, " +
peerCount + " peers, " +
DataHelper.formatDuration(_expireTime) + " expiration");
_peerCount = peerCount;
_torrentCount = torrentCount;
schedule(CLEAN_TIME);
}
}
}

View File

@@ -0,0 +1,29 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
import net.i2p.crypto.SHA1Hash;
import org.klomp.snark.I2PSnarkUtil;
/**
* A 20-byte SHA1 info hash
*
* @since 0.9.2
* @author zzz
*/
class InfoHash extends SHA1Hash {
public InfoHash(byte[] data) {
super(data);
}
@Override
public String toString() {
if (_data == null) {
return super.toString();
} else {
return "[InfoHash: " + I2PSnarkUtil.toHex(_data) + ']';
}
}
}

View File

@@ -0,0 +1,38 @@
package org.klomp.snark.dht;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.kademlia.KBucket;
import net.i2p.kademlia.KBucketTrimmer;
/**
* Removes an element older than 15 minutes, but only if the bucket hasn't changed in 5 minutes.
* @since 0.9.2
*/
class KBTrimmer implements KBucketTrimmer<NID> {
private final I2PAppContext _ctx;
private final int _max;
private static final long MIN_BUCKET_AGE = 5*60*1000;
private static final long MAX_NODE_AGE = 15*60*1000;
public KBTrimmer(I2PAppContext ctx, int max) {
_ctx = ctx;
_max = max;
}
public boolean trim(KBucket<NID> kbucket, NID toAdd) {
long now = _ctx.clock().now();
if (kbucket.getLastChanged() > now - MIN_BUCKET_AGE)
return false;
Set<NID> entries = kbucket.getEntries();
for (NID nid : entries) {
if (nid.lastSeen() < now - MAX_NODE_AGE) {
if (kbucket.remove(nid))
return true;
}
}
return entries.size() < _max;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
package org.klomp.snark.dht;
/*
* GPLv2
*/
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
/**
* Used for both incoming and outgoing message IDs
*
* @since 0.9.2
* @author zzz
*/
class MsgID extends ByteArray {
/** BEP 5: 2 bytes, incremented */
private static final int MY_TOK_LEN = 8;
private static final int MAX_TOK_LEN = 16;
/** outgoing - generate a random ID */
public MsgID(I2PAppContext ctx) {
super(null);
byte[] data = new byte[MY_TOK_LEN];
ctx.random().nextBytes(data);
setData(data);
setValid(MY_TOK_LEN);
}
/** incoming - save the ID (arbitrary length) */
public MsgID(byte[] data) {
super(data);
// lets not get carried away
if (data.length > MAX_TOK_LEN)
throw new IllegalArgumentException();
}
}

View File

@@ -0,0 +1,46 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
import net.i2p.crypto.SHA1Hash;
import net.i2p.util.Clock;
/**
* A 20-byte peer ID, used as a Map key in lots of places.
* Must be public for constructor in KBucketSet.generateRandomKey()
*
* @since 0.9.2
* @author zzz
*/
public class NID extends SHA1Hash {
private long lastSeen;
private int fails;
private static final int MAX_FAILS = 2;
public NID() {
super(null);
}
public NID(byte[] data) {
super(data);
}
public long lastSeen() {
return lastSeen;
}
public void setLastSeen() {
lastSeen = Clock.getInstance().now();
fails = 0;
}
/**
* @return if more than max timeouts
*/
public boolean timeout() {
return ++fails > MAX_FAILS;
}
}

View File

@@ -0,0 +1,253 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
import net.i2p.data.Base64;
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.RandomSource;
/*
* A Node ID, Hash, and port, and an optional Destination.
* This is what DHTNodes remembers. The DHT tracker just stores Hashes.
* getData() returns the 54 byte compact info (NID, Hash, port).
*
* Things are a little tricky in KRPC since we exchange Hashes and don't
* always have the Destination.
* The conpact info is immutable. The Destination may be added later.
*
* @since 0.9.2
* @author zzz
*/
class NodeInfo extends SimpleDataStructure {
private final NID nID;
private final Hash hash;
private Destination dest;
private final int port;
public static final int LENGTH = NID.HASH_LENGTH + Hash.HASH_LENGTH + 2;
/**
* With a fake NID used for pings
*/
public NodeInfo(Destination dest, int port) {
super();
this.nID = KRPC.FAKE_NID;
this.dest = dest;
this.hash = dest.calculateHash();
this.port = port;
initialize();
}
/**
* Use this if we have the full destination
* @throws IllegalArgumentException
*/
public NodeInfo(NID nID, Destination dest, int port) {
super();
this.nID = nID;
this.dest = dest;
this.hash = dest.calculateHash();
this.port = port;
initialize();
verify();
}
/**
* No Destination yet available
* @throws IllegalArgumentException
*/
public NodeInfo(NID nID, Hash hash, int port) {
super();
this.nID = nID;
this.hash = hash;
this.port = port;
initialize();
verify();
}
/**
* No Destination yet available
* @param compactInfo 20 byte node ID, 32 byte destHash, 2 byte port
* @param offset starting at this offset in compactInfo
* @throws IllegalArgumentException
* @throws AIOOBE
*/
public NodeInfo(byte[] compactInfo, int offset) {
super();
byte[] d = new byte[LENGTH];
System.arraycopy(compactInfo, offset, d, 0, LENGTH);
setData(d);
byte[] ndata = new byte[NID.HASH_LENGTH];
System.arraycopy(d, 0, ndata, 0, NID.HASH_LENGTH);
this.nID = new NID(ndata);
this.hash = Hash.create(d, NID.HASH_LENGTH);
this.port = (int) DataHelper.fromLong(d, NID.HASH_LENGTH + Hash.HASH_LENGTH, 2);
if (port <= 0 || port >= 65535)
throw new IllegalArgumentException("Bad port");
verify();
}
/**
* Create from persistent storage string.
* Format: NID:Hash:Destination:port
* First 3 in base 64; Destination may be empty string
* @throws IllegalArgumentException
*/
public NodeInfo(String s) throws DataFormatException {
super();
String[] parts = s.split(":", 4);
if (parts.length != 4)
throw new DataFormatException("Bad format");
byte[] nid = Base64.decode(parts[0]);
if (nid == null)
throw new DataFormatException("Bad NID");
nID = new NID(nid);
byte[] h = Base64.decode(parts[1]);
if (h == null)
throw new DataFormatException("Bad hash");
//hash = new Hash(h);
hash = Hash.create(h);
if (parts[2].length() > 0)
dest = new Destination(parts[2]);
try {
port = Integer.parseInt(parts[3]);
} catch (NumberFormatException nfe) {
throw new DataFormatException("Bad port", nfe);
}
initialize();
}
/**
* Creates 54-byte compact info
* @throws IllegalArgumentException
*/
private void initialize() {
if (port <= 0 || port >= 65535)
throw new IllegalArgumentException("Bad port");
byte[] compactInfo = new byte[LENGTH];
System.arraycopy(nID.getData(), 0, compactInfo, 0, NID.HASH_LENGTH);
System.arraycopy(hash.getData(), 0, compactInfo, NID.HASH_LENGTH, Hash.HASH_LENGTH);
DataHelper.toLong(compactInfo, NID.HASH_LENGTH + Hash.HASH_LENGTH, 2, port);
setData(compactInfo);
}
/**
* Generate a secure NID that matches the Hash and port.
* Rules: First 4 bytes must match Hash.
* Next 2 bytes must match Hash ^ port.
* Remaining bytes may be random.
*
* @throws IllegalArgumentException
*/
public static NID generateNID(Hash h, int p, RandomSource random) {
byte[] n = new byte[NID.HASH_LENGTH];
System.arraycopy(h.getData(), 0, n, 0, 6);
n[4] ^= (byte) (p >> 8);
n[5] ^= (byte) p;
random.nextBytes(n, 6, NID.HASH_LENGTH - 6);
return new NID(n);
}
/**
* Verify the NID matches the Hash.
* See generateNID() for requirements.
* @throws IllegalArgumentException on mismatch
*/
private void verify() {
if (!KRPC.SECURE_NID)
return;
byte[] nb = nID.getData();
byte[] hb = hash.getData();
if ((!DataHelper.eq(nb, 0, hb, 0, 4)) ||
((nb[4] ^ (port >> 8)) & 0xff) != (hb[4] & 0xff) ||
((nb[5] ^ port) & 0xff) != (hb[5] & 0xff))
throw new IllegalArgumentException("NID/Hash mismatch");
}
public int length() {
return LENGTH;
}
public NID getNID() {
return this.nID;
}
/** @return may be null if we don't have it */
public Destination getDestination() {
return this.dest;
}
public Hash getHash() {
return this.hash;
}
@Override
public Hash calculateHash() {
return this.hash;
}
/**
* This can come in later but the hash must match.
* @throws IllegalArgumentException if hash of dest doesn't match previous hash
*/
public void setDestination(Destination dest) throws IllegalArgumentException {
if (this.dest != null)
return;
if (!dest.calculateHash().equals(this.hash))
throw new IllegalArgumentException("Hash mismatch, was: " + this.hash + " new: " + dest.calculateHash());
this.dest = dest;
}
public int getPort() {
return this.port;
}
public long lastSeen() {
return nID.lastSeen();
}
@Override
public int hashCode() {
return super.hashCode() ^ nID.hashCode() ^ port;
}
@Override
public boolean equals(Object o) {
try {
NodeInfo ni = (NodeInfo) o;
// assume dest matches, ignore it
return this.hash.equals(ni.hash) && nID.equals(ni.nID) && port == ni.port;
} catch (Exception e) {
return false;
}
}
@Override
public String toString() {
return "NodeInfo: " + nID + ' ' + hash + " port: " + port + (dest != null ? " known dest" : " null dest");
}
/**
* To persistent storage string.
* Format: NID:Hash:Destination:port
* First 3 in base 64; Destination may be empty string
*/
public String toPersistentString() {
StringBuilder buf = new StringBuilder(650);
buf.append(nID.toBase64()).append(':');
buf.append(hash.toBase64()).append(':');
if (dest != null)
buf.append(dest.toBase64());
buf.append(':').append(port);
return buf.toString();
}
}

View File

@@ -0,0 +1,31 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
import java.util.Comparator;
import net.i2p.crypto.SHA1Hash;
import net.i2p.data.DataHelper;
/**
* Closest to a InfoHash or NID key.
* Use for NodeInfos.
*
* @since 0.9.2
* @author zzz
*/
class NodeInfoComparator implements Comparator<NodeInfo> {
private final byte[] _base;
public NodeInfoComparator(SHA1Hash h) {
_base = h.getData();
}
public int compare(NodeInfo lhs, NodeInfo rhs) {
byte lhsDelta[] = DataHelper.xor(lhs.getNID().getData(), _base);
byte rhsDelta[] = DataHelper.xor(rhs.getNID().getData(), _base);
return DataHelper.compareTo(lhsDelta, rhsDelta);
}
}

View File

@@ -0,0 +1,30 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
import net.i2p.data.Hash;
/**
* A single peer for a single torrent.
* This is what the DHT tracker remembers.
*
* @since 0.9.2
* @author zzz
*/
class Peer extends Hash {
private long lastSeen;
public Peer(byte[] data) {
super(data);
}
public long lastSeen() {
return lastSeen;
}
public void setLastSeen(long now) {
lastSeen = now;
}
}

View File

@@ -0,0 +1,21 @@
package org.klomp.snark.dht;
/*
* From zzzot, modded and relicensed to GPLv2
*/
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.data.Hash;
/**
* All the peers for a single torrent
*
* @since 0.9.2
* @author zzz
*/
class Peers extends ConcurrentHashMap<Hash, Peer> {
public Peers() {
super(8);
}
}

View File

@@ -0,0 +1,88 @@
package org.klomp.snark.dht;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import net.i2p.I2PAppContext;
import net.i2p.data.DataFormatException;
import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
/**
* Retrieve / Store the local DHT in a file
*
* @since 0.9.2
*/
abstract class PersistDHT {
private static final long MAX_AGE = 60*60*1000;
public static synchronized void loadDHT(KRPC krpc, File file) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(PersistDHT.class);
int count = 0;
FileInputStream in = null;
try {
in = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1"));
String line = null;
while ( (line = br.readLine()) != null) {
if (line.startsWith("#"))
continue;
try {
krpc.heardAbout(new NodeInfo(line));
count++;
// TODO limit number? this will flush the router's SDS caches
} catch (IllegalArgumentException iae) {
if (log.shouldLog(Log.WARN))
log.warn("Error reading DHT entry", iae);
} catch (DataFormatException dfe) {
if (log.shouldLog(Log.WARN))
log.warn("Error reading DHT entry", dfe);
}
}
} catch (IOException ioe) {
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 (log.shouldLog(Log.INFO))
log.info("Loaded " + count + " nodes from " + file);
}
/**
* @param saveAll if true, don't check last seen time
*/
public static synchronized void saveDHT(DHTNodes nodes, boolean saveAll, File file) {
if (nodes.size() <= 0)
return;
Log log = I2PAppContext.getGlobalContext().logManager().getLog(PersistDHT.class);
int count = 0;
long maxAge = saveAll ? 0 : I2PAppContext.getGlobalContext().clock().now() - MAX_AGE;
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(file), "ISO-8859-1")));
out.println("# DHT nodes, format is NID:Hash:Destination:port");
for (NodeInfo ni : nodes.values()) {
if (ni.lastSeen() < maxAge)
continue;
// DHTNodes shouldn't contain us, if that changes check here
out.println(ni.toPersistentString());
count++;
}
} catch (IOException ioe) {
if (log.shouldLog(Log.WARN))
log.warn("Error writing the DHT File", ioe);
} finally {
if (out != null) out.close();
}
if (log.shouldLog(Log.INFO))
log.info("Stored " + count + " nodes to " + file);
}
}

View File

@@ -0,0 +1,75 @@
package org.klomp.snark.dht;
/*
* GPLv2
*/
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
*
* @since 0.9.2
* @author zzz
*/
class Token extends ByteArray {
private static final int MY_TOK_LEN = 8;
private static final int MAX_TOK_LEN = 64;
private final long lastSeen;
/** outgoing - generate a random token */
public Token(I2PAppContext ctx) {
super(null);
byte[] data = new byte[MY_TOK_LEN];
ctx.random().nextBytes(data);
setData(data);
setValid(MY_TOK_LEN);
lastSeen = ctx.clock().now();
}
/** incoming - save the token (arbitrary length) */
public Token(I2PAppContext ctx, byte[] data) {
super(data);
// lets not get carried away
if (data.length > MAX_TOK_LEN)
throw new IllegalArgumentException();
lastSeen = ctx.clock().now();
}
/** incoming - for lookup only, not storage, lastSeen is 0 */
public Token(byte[] data) {
super(data);
lastSeen = 0;
}
public long lastSeen() {
return lastSeen;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(64);
buf.append("[Token: ");
byte[] bs = getData();
if (bs.length == 0) {
buf.append("0 bytes");
} else {
buf.append(bs.length).append(" bytes: 0x");
// backwards, but the same way BEValue does it
for (int i = 0; i < bs.length; i++) {
int b = bs[i] & 0xff;
if (b < 16)
buf.append('0');
buf.append(Integer.toHexString(b));
}
}
if (lastSeen > 0)
buf.append(" created ").append((new Date(lastSeen)).toString());
buf.append(']');
return buf.toString();
}
}

View File

@@ -0,0 +1,20 @@
package org.klomp.snark.dht;
/*
* GPLv2
*/
import net.i2p.crypto.SHA1Hash;
import net.i2p.data.DataHelper;
/**
* Used to index incoming Tokens
*
* @since 0.9.2
* @author zzz
*/
class TokenKey extends SHA1Hash {
public TokenKey(NID nID, InfoHash ih) {
super(DataHelper.xor(nID.getData(), ih.getData()));
}
}

View File

@@ -0,0 +1,19 @@
package org.klomp.snark.dht;
/*
* From zzzot, relicensed to GPLv2
*/
import java.util.concurrent.ConcurrentHashMap;
/**
* All the torrents
*
* @since 0.9.2
* @author zzz
*/
class Torrents extends ConcurrentHashMap<InfoHash, Peers> {
public Torrents() {
super();
}
}

View File

@@ -72,7 +72,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
_log = ctx.logManager().getLog(FetchAndAdd.class);
_mgr = mgr;
_url = url;
_name = "* " + _("Download torrent file from {0}", url);
_name = _("Download torrent file from {0}", url);
byte[] fake = null;
try {
fake = SHA1.getInstance().digest(url.getBytes("ISO-8859-1"));

View File

@@ -42,6 +42,7 @@ import org.klomp.snark.SnarkManager;
import org.klomp.snark.Storage;
import org.klomp.snark.Tracker;
import org.klomp.snark.TrackerClient;
import org.klomp.snark.dht.DHT;
import org.mortbay.jetty.servlet.DefaultServlet;
import org.mortbay.resource.Resource;
@@ -74,8 +75,7 @@ public class I2PSnarkServlet extends DefaultServlet {
_context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(I2PSnarkServlet.class);
_nonce = _context.random().nextLong();
// FIXME instantiate new one every time
_manager = SnarkManager.instance();
_manager = new SnarkManager(_context);
String configFile = _context.getProperty(PROP_CONFIG_FILE);
if ( (configFile == null) || (configFile.trim().length() <= 0) )
configFile = "i2psnark.config";
@@ -89,7 +89,8 @@ public class I2PSnarkServlet extends DefaultServlet {
@Override
public void destroy() {
_manager.stop();
if (_manager != null)
_manager.stop();
super.destroy();
}
@@ -448,9 +449,9 @@ public class I2PSnarkServlet extends DefaultServlet {
}
out.write("</th></tr></thead>\n");
String uri = "/i2psnark/";
boolean showDebug = "2".equals(peerParam);
for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i);
boolean showDebug = "2".equals(peerParam);
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.getInfoHash()).equals(peerParam);
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, noThinsp, showDebug);
}
@@ -461,7 +462,7 @@ public class I2PSnarkServlet extends DefaultServlet {
" colspan=\"11\"><i>");
out.write(_("No torrents loaded."));
out.write("</i></td></tr>\n");
} else if (snarks.size() > 1) {
} else /** if (snarks.size() > 1) */ {
out.write("<tfoot><tr>\n" +
" <th align=\"left\" colspan=\"6\">");
out.write(_("Totals"));
@@ -470,6 +471,16 @@ public class I2PSnarkServlet extends DefaultServlet {
out.write(", ");
out.write(DataHelper.formatSize2(stats[5]) + "B, ");
out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4]));
DHT dht = _manager.util().getDHT();
if (dht != null) {
int dhts = dht.size();
if (dhts > 0) {
out.write(", ");
out.write(ngettext("1 DHT peer", "{0} DHT peers", dhts));
}
if (showDebug)
out.write(dht.renderStatusHTML());
}
out.write("</th>\n");
if (_manager.util().connected()) {
out.write(" <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
@@ -598,6 +609,7 @@ public class I2PSnarkServlet extends DefaultServlet {
MetaInfo meta = snark.getMetaInfo();
if (meta == null) {
// magnet - remove and delete are the same thing
// Remove not shown on UI so we shouldn't get here
_manager.deleteMagnet(snark);
_manager.addMessage(_("Magnet deleted: {0}", name));
return;
@@ -626,7 +638,10 @@ public class I2PSnarkServlet extends DefaultServlet {
if (meta == null) {
// magnet - remove and delete are the same thing
_manager.deleteMagnet(snark);
_manager.addMessage(_("Magnet deleted: {0}", name));
if (snark instanceof FetchAndAdd)
_manager.addMessage(_("Download deleted: {0}", name));
else
_manager.addMessage(_("Magnet deleted: {0}", name));
return;
}
_manager.stopTorrent(snark, true);
@@ -699,11 +714,12 @@ public class I2PSnarkServlet extends DefaultServlet {
String refreshDel = req.getParameter("refreshDelay");
String startupDel = req.getParameter("startupDelay");
boolean useOpenTrackers = req.getParameter("useOpenTrackers") != null;
boolean useDHT = req.getParameter("useDHT") != null;
//String openTrackers = req.getParameter("openTrackers");
String theme = req.getParameter("theme");
_manager.updateConfig(dataDir, filesPublic, autoStart, refreshDel, startupDel,
seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
upLimit, upBW, useOpenTrackers, theme);
upLimit, upBW, useOpenTrackers, useDHT, theme);
} else if ("Save2".equals(action)) {
String taction = req.getParameter("taction");
if (taction != null)
@@ -727,6 +743,7 @@ public class I2PSnarkServlet extends DefaultServlet {
try {
// This may take a long time to check the storage, but since it already exists,
// it shouldn't be THAT bad, so keep it in this thread.
// TODO thread it for big torrents, perhaps a la FetchAndAdd
boolean isPrivate = _manager.getPrivateTrackers().contains(announceURL);
Storage s = new Storage(_manager.util(), baseFile, announceURL, isPrivate, null);
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
@@ -900,11 +917,17 @@ public class I2PSnarkServlet extends DefaultServlet {
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)
rv.add(snark);
if (snark != null) {
// put downloads and magnets first
if (snark.getStorage() == null)
rv.add(magnet++, snark);
else
rv.add(snark);
}
}
return rv;
}
@@ -970,7 +993,13 @@ public class I2PSnarkServlet extends DefaultServlet {
String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
String statusString;
if (err != null) {
if (snark.isChecking()) {
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Checking") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Checking");
} else if (snark.isAllocating()) {
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" title=\"" + _("Allocating") + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Allocating");
} else if (err != null) {
if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td>" +
"<td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
@@ -1152,7 +1181,9 @@ public class I2PSnarkServlet extends DefaultServlet {
String b64 = Base64.encode(snark.getInfoHash());
if (showPeers)
parameters = parameters + "&p=1";
if (isRunning) {
if (snark.isChecking()) {
// show no buttons
} else if (isRunning) {
// Stop Button
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
@@ -1492,6 +1523,7 @@ public class I2PSnarkServlet extends DefaultServlet {
boolean autoStart = _manager.shouldAutoStart();
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
//String openTrackers = _manager.util().getOpenTrackerString();
boolean useDHT = _manager.util().shouldUseDHT();
//int seedPct = 0;
out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n" +
@@ -1605,6 +1637,14 @@ public class I2PSnarkServlet extends DefaultServlet {
+ (useOpenTrackers ? "checked " : "")
+ "title=\"");
out.write(_("If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"));
out.write("\" ></td></tr>\n" +
"<tr><td>");
out.write(_("Enable DHT") + " (**BETA**)");
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"useDHT\" value=\"true\" "
+ (useDHT ? "checked " : "")
+ "title=\"");
out.write(_("If checked, use DHT"));
out.write("\" ></td></tr>\n");
// "<tr><td>");
@@ -1762,7 +1802,7 @@ public class I2PSnarkServlet extends DefaultServlet {
}
ihash = xt.substring("urn:btih:".length());
trackerURL = getTrackerParam(url);
name = "* " + _("Magnet") + ' ' + ihash;
name = _("Magnet") + ' ' + ihash;
String dn = getParam("dn", url);
if (dn != null)
name += " (" + Storage.filterName(dn) + ')';
@@ -1772,7 +1812,7 @@ public class I2PSnarkServlet extends DefaultServlet {
int col = ihash.indexOf(':');
if (col >= 0)
ihash = ihash.substring(0, col);
name = "* " + _("Magnet") + ' ' + ihash;
name = _("Magnet") + ' ' + ihash;
} else {
return;
}
@@ -2093,12 +2133,14 @@ public class I2PSnarkServlet extends DefaultServlet {
.append(snark.getBaseName())
.append("</th></tr>\n");
String fullPath = snark.getName();
String baseName = urlEncode((new File(fullPath)).getName());
buf.append("<tr><td>")
.append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "file.png\" >&nbsp;<b>")
.append(_("Torrent file"))
.append(":</b> ")
.append(snark.getName())
.append("</td></tr>\n");
.append(":</b> <a href=\"/i2psnark/").append(baseName).append("\">")
.append(fullPath)
.append("</a></td></tr>\n");
MetaInfo meta = snark.getMetaInfo();
if (meta != null) {

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

View File

@@ -694,7 +694,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
public void runClient(String args[], Logging l) {
boolean isShared = true;
if (args.length >= 3)
isShared = Boolean.valueOf(args[2].trim()).booleanValue();
isShared = Boolean.parseBoolean(args[2].trim());
if (args.length >= 2) {
int portNum = -1;
try {
@@ -717,7 +717,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
addtask(task);
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
String msg = "Invalid I2PTunnel configuration to create a standard client tunnel connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + portNum;
_log.error(getPrefix() + msg, iae);
l.log(msg);
@@ -766,7 +766,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
String proxy = "";
boolean isShared = true;
if (args.length > 1) {
if (Boolean.valueOf(args[1].trim()).booleanValue()) {
if (Boolean.parseBoolean(args[1].trim())) {
isShared = true;
if (args.length == 3)
proxy = args[2];
@@ -835,7 +835,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
String proxy = "";
boolean isShared = true;
if (args.length > 1) {
if (Boolean.valueOf(args[1].trim()).booleanValue()) {
if (Boolean.parseBoolean(args[1].trim())) {
isShared = true;
if (args.length == 3)
proxy = args[2];
@@ -906,7 +906,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
boolean isShared = true;
if (args.length > 2) {
if (Boolean.valueOf(args[2].trim()).booleanValue()) {
if (Boolean.parseBoolean(args[2].trim())) {
isShared = true;
} else if ("false".equalsIgnoreCase(args[2].trim())) {
_log.warn("args[2] == [" + args[2] + "] and rejected explicitly");
@@ -973,7 +973,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
boolean isShared = false;
if (args.length > 1)
isShared = Boolean.valueOf(args[1].trim()).booleanValue();
isShared = Boolean.parseBoolean(args[1].trim());
ownDest = !isShared;
try {
@@ -1017,7 +1017,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
boolean isShared = false;
if (args.length == 2)
isShared = Boolean.valueOf(args[1].trim()).booleanValue();
isShared = Boolean.parseBoolean(args[1].trim());
ownDest = !isShared;
String privateKeyFile = null;

View File

@@ -190,11 +190,11 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// no need to load the netDb with leaseSets for destinations that will never
// be looked up
boolean dccEnabled = (this instanceof I2PTunnelIRCClient) &&
Boolean.valueOf(tunnel.getClientOptions().getProperty(I2PTunnelIRCClient.PROP_DCC)).booleanValue();
Boolean.parseBoolean(tunnel.getClientOptions().getProperty(I2PTunnelIRCClient.PROP_DCC));
if (!dccEnabled)
tunnel.getClientOptions().setProperty("i2cp.dontPublishLeaseSet", "true");
boolean openNow = !Boolean.valueOf(tunnel.getClientOptions().getProperty("i2cp.delayOpen")).booleanValue();
boolean openNow = !Boolean.parseBoolean(tunnel.getClientOptions().getProperty("i2cp.delayOpen"));
if (openNow) {
while (sockMgr == null) {
verifySocketManager();
@@ -258,8 +258,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
if (sess == null) {
newManager = true;
} else if (sess.isClosed() &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")).booleanValue() &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume")).booleanValue()) {
Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")) &&
Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume"))) {
// build a new socket manager and a new dest if the session is closed.
getTunnel().removeSession(sess);
if (_log.shouldLog(Log.WARN))

View File

@@ -253,7 +253,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
line = null;
} else {
// Add Proxy-Authentication header for next hop (outproxy)
if (usingWWWProxy && Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH)).booleanValue()) {
if (usingWWWProxy && Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH))) {
// specific for this proxy
String user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER_PREFIX + currentProxy);
String pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW_PREFIX + currentProxy);

View File

@@ -521,7 +521,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
// Try to find an address helper in the query
String[] helperStrings = removeHelper(query);
if(helperStrings != null &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) {
query = helperStrings[0];
if(query.equals("")) {
query = null;
@@ -736,7 +736,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
} else if(lowercaseLine.startsWith("user-agent: ")) {
// save for deciding whether to offer address book form
userAgent = lowercaseLine.substring(12);
if(!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
line = null;
continue;
}
@@ -746,13 +746,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
line = null;
continue;
} else if(lowercaseLine.startsWith("referer: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_REFERER)).booleanValue()) {
!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_REFERER))) {
// Shouldn't we be more specific, like accepting in-site referers ?
//line = "Referer: i2p";
line = null;
continue; // completely strip the line
} else if(lowercaseLine.startsWith("via: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_VIA)).booleanValue()) {
!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_VIA))) {
//line = "Via: i2p";
line = null;
continue; // completely strip the line
@@ -786,7 +786,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
boolean gzip = DEFAULT_GZIP;
if(ok != null) {
gzip = Boolean.valueOf(ok).booleanValue();
gzip = Boolean.parseBoolean(ok);
}
if(gzip && !usingInternalServer) {
// according to rfc2616 s14.3, this *should* force identity, even if
@@ -796,7 +796,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
newRequest.append("X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n");
}
if(!shout) {
if(!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
// let's not advertise to external sites that we are from I2P
if(usingWWWProxy) {
newRequest.append("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6\r\n");
@@ -806,7 +806,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
}
}
// Add Proxy-Authentication header for next hop (outproxy)
if(usingWWWProxy && Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH)).booleanValue()) {
if(usingWWWProxy && Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH))) {
// specific for this proxy
String user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER_PREFIX + currentProxy);
String pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW_PREFIX + currentProxy);
@@ -869,7 +869,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
if(usingInternalServer) {
// disable the add form if address helper is disabled
if(internalPath.equals("/add") &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) {
out.write(ERR_HELPER_DISABLED);
} else {
LocalHTTPServer.serveLocalFile(out, method, internalPath, internalRawQuery, _proxyNonce);
@@ -949,7 +949,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
// Don't do this for eepget, which uses a user-agent of "Wget"
if(ahelperNew && "GET".equals(method) &&
(userAgent == null || !userAgent.startsWith("Wget")) &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) {
writeHelperSaveForm(out, destination, ahelperKey, targetRequest);
s.close();
return;

View File

@@ -100,7 +100,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
// Ref: RFC 2617
// If the socket is an InternalSocket, no auth required.
String authRequired = getTunnel().getClientOptions().getProperty(PROP_AUTH);
if (Boolean.valueOf(authRequired).booleanValue() ||
if (Boolean.parseBoolean(authRequired) ||
(authRequired != null && "basic".equals(authRequired.toLowerCase(Locale.US)))) {
if (s instanceof InternalSocket) {
if (_log.shouldLog(Log.INFO))

View File

@@ -3,6 +3,7 @@
*/
package net.i2p.i2ptunnel;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -44,7 +45,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
private static final String[] CLIENT_SKIPHEADERS = {HASH_HEADER, DEST64_HEADER, DEST32_HEADER};
private static final String SERVER_HEADER = "Server";
private static final String[] SERVER_SKIPHEADERS = {SERVER_HEADER};
private static final long HEADER_TIMEOUT = 60*1000;
private static final long HEADER_TIMEOUT = 15*1000;
private static final long TOTAL_HEADER_TIMEOUT = 2 * HEADER_TIMEOUT;
private static final long START_INTERVAL = (60 * 1000) * 3;
private long _startedOn = 0L;
@@ -153,7 +155,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
boolean allowGZIP = true;
if (opts != null) {
String val = opts.getProperty("i2ptunnel.gzip");
if ( (val != null) && (!Boolean.valueOf(val).booleanValue()) )
if ( (val != null) && (!Boolean.parseBoolean(val)) )
allowGZIP = false;
}
if (_log.shouldLog(Log.INFO))
@@ -219,6 +221,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
// shadows _log in super()
private final Log _log;
private static final int BUF_SIZE = 16*1024;
public CompressedRequestor(Socket webserver, I2PSocket browser, String headers, I2PAppContext ctx, Log log) {
_webserver = webserver;
_browser = browser;
@@ -259,7 +263,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
// at java.lang.Thread.run(Thread.java:619)
// at net.i2p.util.I2PThread.run(I2PThread.java:71)
try {
serverin = _webserver.getInputStream();
serverin = new BufferedInputStream(_webserver.getInputStream(), BUF_SIZE);
} catch (NullPointerException npe) {
throw new IOException("getInputStream NPE");
}
@@ -489,7 +493,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
protected static Map<String, List<String>> readHeaders(InputStream in, StringBuilder command, String[] skipHeaders, I2PAppContext ctx) throws IOException {
protected static Map<String, List<String>> readHeaders(InputStream in, StringBuilder command,
String[] skipHeaders, I2PAppContext ctx) throws IOException {
HashMap<String, List<String>> headers = new HashMap<String, List<String>>();
StringBuilder buf = new StringBuilder(128);
@@ -513,6 +518,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if (trimmed > 0)
ctx.statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
// slowloris / darkloris
long expire = ctx.clock().now() + TOTAL_HEADER_TIMEOUT;
int i = 0;
while (true) {
if (++i > MAX_HEADERS)
@@ -525,6 +532,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
// end of headers reached
return headers;
} else {
if (ctx.clock().now() > expire)
throw new IOException("Headers took too long [" + buf.toString() + "]");
int split = buf.indexOf(":");
if (split <= 0) throw new IOException("Invalid HTTP header, missing colon [" + buf.toString() + "]");
String name = buf.substring(0, split).trim();

View File

@@ -87,7 +87,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase {
setName("IRC Client on " + tunnel.listenHost + ':' + localPort);
_dccEnabled = Boolean.valueOf(tunnel.getClientOptions().getProperty(PROP_DCC)).booleanValue();
_dccEnabled = Boolean.parseBoolean(tunnel.getClientOptions().getProperty(PROP_DCC));
// TODO add some prudent tunnel options (or is it too late?)
startRunning();

View File

@@ -62,7 +62,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
public static final String PROP_WEBIRC_SPOOF_IP_DEFAULT="127.0.0.1";
public static final String PROP_HOSTNAME="ircserver.fakeHostname";
public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p";
private static final long HEADER_TIMEOUT = 60*1000;
private static final long HEADER_TIMEOUT = 15*1000;
private static final long TOTAL_HEADER_TIMEOUT = 2 * HEADER_TIMEOUT;
private final static byte[] ERR_UNAVAILABLE =
(":ircserver.i2p 499 you :" +
@@ -188,12 +189,16 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
StringBuilder buf = new StringBuilder(128);
int lineCount = 0;
// slowloris / darkloris
long expire = System.currentTimeMillis() + TOTAL_HEADER_TIMEOUT;
while (true) {
String s = DataHelper.readLine(in);
if (s == null)
throw new IOException("EOF reached before the end of the headers [" + buf.toString() + "]");
if (++lineCount > 10)
throw new IOException("Too many lines before USER or SERVER, giving up");
if (System.currentTimeMillis() > expire)
throw new IOException("Headers took too long [" + buf.toString() + "]");
s = s.trim();
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Got line: " + s);

View File

@@ -3,6 +3,7 @@
*/
package net.i2p.i2ptunnel;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
@@ -17,6 +18,7 @@ import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Clock;
import net.i2p.util.I2PAppThread;
import net.i2p.util.InternalSocket;
import net.i2p.util.Log;
public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErrorListener {
@@ -143,7 +145,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
OutputStream i2pout = i2ps.getOutputStream(); //new BufferedOutputStream(i2ps.getOutputStream(), MAX_PACKET_SIZE);
if (initialI2PData != null) {
// why synchronize this? we could be in here a LONG time for large initial data
synchronized (slock) {
//synchronized (slock) {
// this does not increment totalSent
i2pout.write(initialI2PData);
// do NOT flush here, it will block and then onTimeout.run() won't happen on fail.
@@ -157,7 +159,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
// only flush if it fits in one message.
if (initialI2PData.length <= 1730) // ConnectionOptions.DEFAULT_MAX_MESSAGE_SIZE
i2pout.flush();
}
//}
}
if (initialSocketData != null) {
// this does not increment totalReceived
@@ -167,6 +169,8 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
_log.debug("Initial data " + (initialI2PData != null ? initialI2PData.length : 0)
+ " written to I2P, " + (initialSocketData != null ? initialSocketData.length : 0)
+ " written to the socket, starting forwarders");
if (!(s instanceof InternalSocket))
in = new BufferedInputStream(in, 2*NETWORK_BUFFER_SIZE);
Thread t1 = new StreamForwarder(in, i2pout, true);
Thread t2 = new StreamForwarder(i2pin, out, false);
synchronized (finishLock) {

View File

@@ -49,8 +49,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
protected Logging l;
private static final long DEFAULT_READ_TIMEOUT = -1; // 3*60*1000;
/** default timeout to 3 minutes - override if desired */
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000;
/** default timeout to 5 minutes - override if desired */
protected long readTimeout = DEFAULT_READ_TIMEOUT;
/** do we use threads? default true (ignored for standard servers, always false) */
@@ -74,6 +74,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
protected int localPort = DEFAULT_LOCALPORT;
/**
* Warning, blocks in constructor while connecting to router and building tunnels;
* TODO move that to startRunning()
*
* @param privData Base64-encoded private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
@@ -87,6 +90,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
/**
* Warning, blocks in constructor while connecting to router and building tunnels;
* TODO move that to startRunning()
*
* @param privkey file containing the private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @param privkeyname the name of the privKey file, not clear why we need this too
@@ -111,6 +117,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
/**
* Warning, blocks in constructor while connecting to router and building tunnels;
* TODO move that to startRunning()
*
* @param privData stream containing the private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @param privkeyname the name of the privKey file, not clear why we need this too
@@ -124,6 +133,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
/**
* Non-blocking
*
* @param sktMgr the existing socket manager
* @since 0.8.9
*/
@@ -142,6 +153,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
private static final int MAX_RETRIES = 4;
/**
* Warning, blocks while connecting to router and building tunnels;
* TODO move that to startRunning()
*
* @param privData stream containing the private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @param privkeyname the name of the privKey file, not clear why we need this too
@@ -177,7 +191,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
if (_usePool) {
String usePool = getTunnel().getClientOptions().getProperty(PROP_USE_POOL);
if (usePool != null)
_usePool = Boolean.valueOf(usePool).booleanValue();
_usePool = Boolean.parseBoolean(usePool);
else
_usePool = DEFAULT_USE_POOL;
}
@@ -193,7 +207,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
if (sockMgr == null) {
// try to make this error sensible as it will happen...
String msg = "Unable to connect to the router at " + getTunnel().host + ':' + portNum +
" and build tunnels for the server at " + getTunnel().listenHost + ':' + port;
" and build tunnels for the server at " + host.getHostAddress() + ':' + port;
if (++retries < MAX_RETRIES) {
this.l.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
_log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
@@ -209,7 +223,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
sockMgr.setName("Server");
getTunnel().addSession(sockMgr.getSession());
l.log("Tunnels ready for server at " + getTunnel().listenHost + ':' + port);
l.log("Tunnels ready for server at " + host.getHostAddress() + ':' + port);
notifyEvent("openServerResult", "ok");
open = true;
}
@@ -236,6 +250,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
/**
* Start running the I2PTunnelServer.
*
* TODO: Wait to connect to router until here.
*/
public void startRunning() {
// prevent JVM exit when running outside the router
@@ -360,7 +375,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
return;
// TODO delay and loop if internal router is soft restarting?
open = false;
break;
} catch (ConnectException ce) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);

View File

@@ -15,7 +15,7 @@ public abstract class I2PTunnelTask extends EventDispatcherImpl {
private int id;
private String name;
protected boolean open;
protected volatile boolean open;
private I2PTunnel tunnel;
//protected I2PTunnelTask(String name) {

View File

@@ -156,8 +156,8 @@ public class TunnelController implements Logging {
}
String type = getType();
if ( (type == null) || (type.length() <= 0) ) {
if (_log.shouldLog(Log.WARN))
_log.warn("Cannot start the tunnel - no type specified");
if (_log.shouldLog(Log.ERROR))
_log.error("Cannot start the tunnel - no type specified");
return;
}
// Config options may have changed since instantiation, so do this again.
@@ -455,6 +455,25 @@ public class TunnelController implements Logging {
}
}
_config = props;
// Set up some per-type defaults
// This really isn't the best spot to do this but for servers in particular,
// it's hard to override settings in the subclass since the session connect
// is done in the I2PTunnelServer constructor.
String type = getType();
if (type != null) {
if (type.equals("httpserver") || type.equals("streamrserver")) {
if (!_config.containsKey("option.shouldBundleReplyInfo"))
_config.setProperty("option.shouldBundleReplyInfo", "false");
} else if (type.contains("irc") || type.equals("streamrclient")) {
// maybe a bad idea for ircclient if DCC is enabled
if (!_config.containsKey("option.crypto.tagsToSend"))
_config.setProperty("option.crypto.tagsToSend", "20");
if (!_config.containsKey("option.crypto.lowTagThreshold"))
_config.setProperty("option.crypto.lowTagThreshold", "14");
}
}
// tell i2ptunnel, who will tell the TunnelTask, who will tell the SocketManager
setSessionOptions();
if (_running && _sessions != null) {
@@ -467,6 +486,9 @@ public class TunnelController implements Logging {
}
}
/**
* @return a copy
*/
public Properties getConfig(String prefix) {
Properties rv = new Properties();
for (Map.Entry e : _config.entrySet()) {
@@ -514,8 +536,8 @@ public class TunnelController implements Logging {
/** default true */
public String getSharedClient() { return _config.getProperty("sharedClient", "true"); }
/** default true */
public boolean getStartOnLoad() { return Boolean.valueOf(_config.getProperty("startOnLoad", "true")).booleanValue(); }
public boolean getPersistentClientKey() { return Boolean.valueOf(_config.getProperty("option.persistentClientKey")).booleanValue(); }
public boolean getStartOnLoad() { return Boolean.parseBoolean(_config.getProperty("startOnLoad", "true")); }
public boolean getPersistentClientKey() { return Boolean.parseBoolean(_config.getProperty("option.persistentClientKey")); }
public String getMyDestination() {
if (_tunnel != null) {

View File

@@ -61,7 +61,7 @@ public class SOCKS5Server extends SOCKSServer {
this.clientSock = clientSock;
this.props = props;
this.authRequired =
Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_AUTH)).booleanValue() &&
Boolean.parseBoolean(props.getProperty(I2PTunnelHTTPClientBase.PROP_AUTH)) &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_USER) &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_PW);
}
@@ -181,7 +181,7 @@ public class SOCKS5Server extends SOCKSServer {
sendRequestReply(Reply.COMMAND_NOT_SUPPORTED, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
throw new SOCKSException("BIND command not supported");
case Command.UDP_ASSOCIATE:
/*** if(!Boolean.valueOf(tunnel.getOptions().getProperty("i2ptunnel.socks.allowUDP")).booleanValue()) {
/*** if(!Boolean.parseBoolean(tunnel.getOptions().getProperty("i2ptunnel.socks.allowUDP"))) {
_log.debug("UDP ASSOCIATE command is not supported!");
sendRequestReply(Reply.COMMAND_NOT_SUPPORTED, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
throw new SOCKSException("UDP ASSOCIATE command not supported");
@@ -463,7 +463,7 @@ public class SOCKS5Server extends SOCKSServer {
I2PSocket destSock = tun.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy), proxyOpts);
try {
DataOutputStream out = new DataOutputStream(destSock.getOutputStream());
boolean authAvail = Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH)).booleanValue();
boolean authAvail = Boolean.parseBoolean(props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH));
String configUser = null;
String configPW = null;
if (authAvail) {

View File

@@ -49,7 +49,7 @@ public class SOCKSServerFactory {
switch (socksVer) {
case 0x04:
// SOCKS version 4/4a
if (Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_AUTH)).booleanValue() &&
if (Boolean.parseBoolean(props.getProperty(I2PTunnelHTTPClientBase.PROP_AUTH)) &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_USER) &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_PW)) {
throw new SOCKSException("SOCKS 4/4a not supported when authorization is required");

View File

@@ -114,7 +114,7 @@ public class EditBean extends IndexBean {
public boolean isSharedClient(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
return Boolean.valueOf(tun.getSharedClient()).booleanValue();
return Boolean.parseBoolean(tun.getSharedClient());
else
return false;
}
@@ -312,7 +312,7 @@ public class EditBean extends IndexBean {
if (tun != null) {
Properties opts = getOptions(tun);
if (opts != null)
return Boolean.valueOf(opts.getProperty(prop)).booleanValue();
return Boolean.parseBoolean(opts.getProperty(prop));
}
return false;
}

View File

@@ -32,6 +32,7 @@ import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.util.Addresses;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
@@ -265,7 +266,7 @@ public class IndexBean {
}
// Only modify other shared tunnels
// if the current tunnel is shared, and of supported type
if (Boolean.valueOf(cur.getSharedClient()).booleanValue() && isClient(cur.getType())) {
if (Boolean.parseBoolean(cur.getSharedClient()) && isClient(cur.getType())) {
// all clients use the same I2CP session, and as such, use the same I2CP options
List controllers = _group.getControllers();
@@ -277,7 +278,7 @@ public class IndexBean {
// Only modify this non-current tunnel
// if it belongs to a shared destination, and is of supported type
if (Boolean.valueOf(c.getSharedClient()).booleanValue() && isClient(c.getType())) {
if (Boolean.parseBoolean(c.getSharedClient()) && isClient(c.getType())) {
Properties cOpt = c.getConfig("");
if (_tunnelQuantity != null) {
cOpt.setProperty("option.inbound.quantity", _tunnelQuantity);
@@ -393,8 +394,8 @@ public class IndexBean {
////
public String getTheme() {
String theme = _context.getProperty(PROP_THEME_NAME, DEFAULT_THEME);
return "/themes/console/" + theme + "/";
String theme = _context.getProperty(PROP_THEME_NAME, DEFAULT_THEME);
return "/themes/console/" + theme + "/";
}
public boolean allowCSS() {
@@ -436,6 +437,9 @@ public class IndexBean {
return _("New Tunnel");
}
/**
* No validation
*/
public String getClientPort(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null && tun.getListenPort() != null)
@@ -444,6 +448,28 @@ public class IndexBean {
return "";
}
/**
* Returns error message if blank or invalid
* @since 0.9.3
*/
public String getClientPort2(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null && tun.getListenPort() != null) {
String port = tun.getListenPort();
if (port.length() == 0)
return "<font color=\"red\">" + _("Port not set") + "</font>";
int iport = Addresses.getPort(port);
if (iport == 0)
return "<font color=\"red\">" + _("Invalid port") + ' ' + port + "</font>";
if (iport < 1024)
return "<font color=\"red\">" +
_("Warning - ports less than 1024 are not recommended") +
": " + port + "</font>";
return port;
}
return "<font color=\"red\">" + _("Port not set") + "</font>";
}
public String getTunnelType(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
@@ -551,12 +577,16 @@ public class IndexBean {
else
host = tun.getTargetHost();
String port = tun.getTargetPort();
if (host == null)
if (host == null || host.length() == 0)
host = "<font color=\"red\">" + _("Host not set") + "</font>";
else if (Addresses.getIP(host) == null)
host = "<font color=\"red\">" + _("Invalid address") + ' ' + host + "</font>";
else if (host.indexOf(':') >= 0)
host = '[' + host + ']';
if (port == null)
if (port == null || port.length() == 0)
port = "<font color=\"red\">" + _("Port not set") + "</font>";
else if (Addresses.getPort(port) == 0)
port = "<font color=\"red\">" + _("Invalid port") + ' ' + port + "</font>";
return host + ':' + port;
} else
return "";

View File

@@ -222,14 +222,8 @@
<label><%=intl._("Port")%>:</label>
<span class="text">
<%
String cPort= indexBean.getClientPort(curClient);
if ("".equals(cPort)) {
out.write("<font color=\"red\">");
out.write(intl._("Port not set"));
out.write("</font>");
} else {
out.write(cPort);
}
String cPort= indexBean.getClientPort2(curClient);
out.write(cPort);
%>
</span>
</div>
@@ -291,7 +285,9 @@
</label>
<div class="text">
<% String cdest = indexBean.getClientDestination(curClient);
if (cdest.length() > 0) {
if (cdest.length() > 70) { // Probably a B64 (a B32 is 60 chars) so truncate
%><%=cdest.substring(0, 45)%>&hellip;<%=cdest.substring(cdest.length() - 15, cdest.length())%><%
} else if (cdest.length() > 0) {
%><%=cdest%><%
} else {
%><i><%=intl._("none")%></i><%

View File

@@ -500,8 +500,7 @@
}
if ("httpclient".equals(tunnelType)) {
%><input type="hidden" name="jumpList" value="http://i2host.i2p/cgi-bin/i2hostjump?
http://stats.i2p/cgi-bin/jump.cgi?a=
http://i2jump.i2p/" /><%
http://stats.i2p/cgi-bin/jump.cgi?a=" /><%
} /* httpclient */
} else { /* Server-only defaults */
%><input type="hidden" name="privKeyFile" value="<%=editBean.getPrivateKeyFile(-1)%>" />

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-07-16 23:58+0000\n"
"POT-Creation-Date: 2012-10-12 00:38+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"
@@ -47,7 +47,7 @@ msgid "Base 32"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1031
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:374
msgid "Destination"
msgstr ""
@@ -131,94 +131,108 @@ msgstr ""
msgid "internal"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:174
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:175
msgid ""
"Invalid form submission, probably because you used the 'back' or 'reload' "
"button on your browser. Please resubmit."
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:221
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:222
msgid "Configuration reloaded for all tunnels"
msgstr ""
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:233
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:234
msgid "Starting tunnel"
msgstr ""
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:246
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:247
msgid "Stopping tunnel"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:314
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:315
msgid "Configuration changes saved"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:317
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:318
msgid "Failed to save configuration"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:436
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:437
msgid "New Tunnel"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:456
msgid "Standard client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:457
msgid "HTTP client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:458
msgid "IRC client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:459
msgid "Standard server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:460
msgid "HTTP server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:461
msgid "SOCKS 4/4a/5 proxy"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:462
msgid "SOCKS IRC proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:470
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:587
msgid "Port not set"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:463
msgid "CONNECT/SSL/HTTPS proxy"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:464
msgid "IRC server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:465
msgid "Streamr client"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:589
msgid "Invalid port"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:466
msgid "Warning - ports less than 1024 are not recommended"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:482
msgid "Standard client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:483
msgid "HTTP client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:484
msgid "IRC client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:485
msgid "Standard server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:486
msgid "HTTP server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:487
msgid "SOCKS 4/4a/5 proxy"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:488
msgid "SOCKS IRC proxy"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:489
msgid "CONNECT/SSL/HTTPS proxy"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:490
msgid "IRC server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:491
msgid "Streamr client"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:492
msgid "Streamr server"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:467
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:493
msgid "HTTP bidir"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:555
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:305
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:581
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
msgid "Host not set"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:559
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:287
msgid "Port not set"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:583
msgid "Invalid address"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:82
@@ -246,14 +260,14 @@ msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:127
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:127
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:261
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:294
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:288
msgid "Type"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:131
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:131
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:241
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:399
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:393
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:330
msgid "Description"
msgstr ""
@@ -798,7 +812,7 @@ msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:129
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:192
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:265
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:312
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306
msgid "Status"
msgstr ""
@@ -811,30 +825,30 @@ msgid "No Preview"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:199
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:319
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313
msgid "Starting..."
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:206
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:326
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:340
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:354
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348
msgid "Stop"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:213
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:347
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:341
msgid "Running"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:355
msgid "Stopped"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:368
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362
msgid "Start"
msgstr ""
@@ -843,7 +857,7 @@ msgid "New server tunnel"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:251
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:409
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:403
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:265
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:295
@@ -853,7 +867,7 @@ msgid "Standard"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:253
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:411
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:405
msgid "Create"
msgstr ""
@@ -862,23 +876,23 @@ msgid "I2P Client Tunnels"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:263
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:298
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:292
msgid "Interface"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:333
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327
msgid "Standby"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:371
msgid "Outproxy"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:394
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:388
msgid "none"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:407
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:401
msgid "New client tunnel"
msgstr ""

View File

@@ -2,10 +2,11 @@
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2ptunnel package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
#
# Translators:
# "blabla", 2011.
# <blabla@trash-mail.com>, 2011, 2012.
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2012.
# ducki2p <ducki2p@gmail.com>, 2011.
# foo <foo@bar>, 2009.
# <punkibastardo@gmail.com>, 2011, 2012.
@@ -13,17 +14,16 @@
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-07-26 19:45+0000\n"
"PO-Revision-Date: 2012-07-21 19:52+0000\n"
"Last-Translator: blabla <blabla@trash-mail.com>\n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/I2P/language/"
"es/)\n"
"Language: es\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2012-10-12 00:38+0000\n"
"PO-Revision-Date: 2012-10-18 08:55+0000\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/I2P/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:554
msgid "This seems to be a bad destination:"
@@ -36,13 +36,10 @@ msgstr "El ayudante de direcciones no te puede ayudar con un destino así."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:621
#, java-format
msgid ""
"To visit the destination in your host database, click <a href=\"{0}\">here</"
"a>. To visit the conflicting addresshelper destination, click <a href="
"\"{1}\">here</a>."
msgstr ""
"Para visitar el destino en la base de datos de hosts, ¡pincha <a href="
"\"{0}\">aquí</a>! Para visitar el destino del ayudante de direcciones en "
"conflicto, ¡pincha <a href=\"{1}\">aquí</a>!"
"To visit the destination in your host database, click <a "
"href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, "
"click <a href=\"{1}\">here</a>."
msgstr "Para visitar el destino en la base de datos de hosts, ¡pincha <a href=\"{0}\">aquí</a>! Para visitar el destino del ayudante de direcciones en conflicto, ¡pincha <a href=\"{1}\">aquí</a>!"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1023
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:403
@@ -57,7 +54,7 @@ msgid "Base 32"
msgstr "Base 32"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1031
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:374
msgid "Destination"
msgstr "Destino"
@@ -69,21 +66,18 @@ msgstr "Acceder a {0} sin guardar"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1042
#, java-format
msgid "Save {0} to router address book and continue to eepsite"
msgstr ""
"Guardar {0} a la libreta de direcciones del router y acceder al sitio i2p."
msgstr "Guardar {0} a la libreta de direcciones del router y acceder al sitio i2p."
#. only blockfile supports multiple books
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1045
#, java-format
msgid "Save {0} to master address book and continue to eepsite"
msgstr ""
"Guardar {0} a la libreta de direcciones principal y acceder al sitio i2p."
msgstr "Guardar {0} a la libreta de direcciones principal y acceder al sitio i2p."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1046
#, java-format
msgid "Save {0} to private address book and continue to eepsite"
msgstr ""
"Guardar {0} a la libreta de direcciones privada y acceder al sitio i2p."
msgstr "Guardar {0} a la libreta de direcciones privada y acceder al sitio i2p."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1211
msgid "HTTP Outproxy"
@@ -91,10 +85,9 @@ msgstr "Puerta de salida HTTP"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1216
msgid ""
"Click a link below to look for an address helper by using a \"jump\" service:"
msgstr ""
"Pincha en un enlace de debajo para buscar un ayudante de direcciones "
"mediante el uso de un servicio de \"salto\":"
"Click a link below to look for an address helper by using a \"jump\" "
"service:"
msgstr "Pincha en un enlace de debajo para buscar un ayudante de direcciones mediante el uso de un servicio de \"salto\":"
#. Translators: parameter is a host name
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1252
@@ -146,97 +139,109 @@ msgstr "¡Haz click aquí si no estás siendo enviado automáticamente!"
msgid "internal"
msgstr "interno"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:174
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:175
msgid ""
"Invalid form submission, probably because you used the 'back' or 'reload' "
"button on your browser. Please resubmit."
msgstr ""
"El formulario presentado es inválido, probablemente porque has utilizado el "
"botón 'atrás' o 'recargar' de tu navegador. Por favor, ¡vuelve a enviarlo!"
msgstr "El formulario presentado es inválido, probablemente porque has utilizado el botón 'atrás' o 'recargar' de tu navegador. Por favor, ¡vuelve a enviarlo!"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:221
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:222
msgid "Configuration reloaded for all tunnels"
msgstr "Configuración recargada para todos los túneles"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:233
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:234
msgid "Starting tunnel"
msgstr "Inicializando el túnel"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:246
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:247
msgid "Stopping tunnel"
msgstr "Deteniendo el túnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:314
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:315
msgid "Configuration changes saved"
msgstr "Cambios en la configuración guardados"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:317
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:318
msgid "Failed to save configuration"
msgstr "No se pudo guardar la configuración"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:436
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:437
msgid "New Tunnel"
msgstr "Nuevo túnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:456
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:460
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:470
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:587
msgid "Port not set"
msgstr "Puerto no establecido"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:463
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:589
msgid "Invalid port"
msgstr "Puerto no válido"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:466
msgid "Warning - ports less than 1024 are not recommended"
msgstr "Advertencia: no se recomienda usar puertos inferiores al 1024"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:482
msgid "Standard client"
msgstr "Cliente estándar"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:457
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:483
msgid "HTTP client"
msgstr "Cliente HTTP"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:458
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:484
msgid "IRC client"
msgstr "Cliente IRC"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:459
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:485
msgid "Standard server"
msgstr "Servidor estándar"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:460
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:486
msgid "HTTP server"
msgstr "Servidor HTTP"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:461
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:487
msgid "SOCKS 4/4a/5 proxy"
msgstr "Proxy SOCKS 4/4a/5"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:462
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:488
msgid "SOCKS IRC proxy"
msgstr "Proxy IRC SOCKS"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:463
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:489
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "Proxy CONNECT/SSL/HTTPS"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:464
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:490
msgid "IRC server"
msgstr "Servidor de IRC"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:465
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:491
msgid "Streamr client"
msgstr "Cliente Streamr"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:466
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:492
msgid "Streamr server"
msgstr "Servidor Streamr"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:467
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:493
msgid "HTTP bidir"
msgstr "HTTP bidir"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:555
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:305
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:581
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
msgid "Host not set"
msgstr "Host no establecido"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:559
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:287
msgid "Port not set"
msgstr "Puerto no establecido"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:583
msgid "Invalid address"
msgstr "Dirección no válida"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:82
msgid "I2P Tunnel Manager - Edit Client Tunnel"
@@ -263,14 +268,14 @@ msgstr "Nombre"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:127
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:127
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:261
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:294
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:288
msgid "Type"
msgstr "Tipo"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:131
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:131
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:241
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:399
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:393
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:330
msgid "Description"
msgstr "Descripción"
@@ -329,9 +334,7 @@ msgstr "Túnel Compartido"
msgid ""
"(Share tunnels with other clients and irc/httpclients? Change requires "
"restart of client proxy)"
msgstr ""
"(¿Compartir túneles con otros clientes y clientes de IRC/http? Cambiar esto "
"requiere reiniciar el proxy de cliente)"
msgstr "(¿Compartir túneles con otros clientes y clientes de IRC/http? Cambiar esto requiere reiniciar el proxy de cliente)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:225
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:135
@@ -359,9 +362,7 @@ msgstr "Opciones de red avanzadas"
msgid ""
"(NOTE: when this client proxy is configured to share tunnels, then these "
"options are for all the shared proxy clients!)"
msgstr ""
"(NOTA: Si este proxy de cliente está configurado para compartir túneles, "
"estas opciones se aplicarán a todos los proxys de cliente compartidos.)"
msgstr "(NOTA: Si este proxy de cliente está configurado para compartir túneles, estas opciones se aplicarán a todos los proxys de cliente compartidos.)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:245
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:255
@@ -412,23 +413,18 @@ msgstr "Variación de 0 saltos (sin aleatoriedad, rendimiento constante)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:300
msgid ""
"+ 0-1 hop variance (medium additive randomisation, subtractive performance)"
msgstr ""
"Variación de + 0-1 salto (aleatoriedad media aditiva, rendimiento "
"substractivo)"
msgstr "Variación de + 0-1 salto (aleatoriedad media aditiva, rendimiento substractivo)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:294
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:304
msgid ""
"+ 0-2 hop variance (high additive randomisation, subtractive performance)"
msgstr ""
"Variación de + 0-2 saltos (aleatoriedad alta aditiva, rendimiento "
"substractivo)"
msgstr "Variación de + 0-2 saltos (aleatoriedad alta aditiva, rendimiento substractivo)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:298
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:308
msgid "+/- 0-1 hop variance (standard randomisation, standard performance)"
msgstr ""
"Variación de +/- 0-1 salto (aleatoriedad estándar, rendimiento estándar)"
msgstr "Variación de +/- 0-1 salto (aleatoriedad estándar, rendimiento estándar)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:302
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:312
@@ -448,25 +444,20 @@ msgstr "Cantidad"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:325
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:335
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr ""
"1 túnel entrante, 1 de salida (bajo uso de ancho de banda, menos fiabilidad)"
msgstr "1 túnel entrante, 1 de salida (bajo uso de ancho de banda, menos fiabilidad)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:329
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:339
msgid ""
"2 inbound, 2 outbound tunnels (standard bandwidth usage, standard "
"reliability)"
msgstr ""
"2 túneles entrantes, 2 de salida (uso de ancho de banda estándar, fiabilidad "
"estándar)"
msgstr "2 túneles entrantes, 2 de salida (uso de ancho de banda estándar, fiabilidad estándar)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:333
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:343
msgid ""
"3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
msgstr ""
"3 túneles entrantes, 3 de salida (mayor uso de ancho de banda, mayor "
"fiabilidad)"
msgstr "3 túneles entrantes, 3 de salida (mayor uso de ancho de banda, mayor fiabilidad)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:341
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:351
@@ -486,24 +477,18 @@ msgstr "0 túneles de respaldo (redundancia 0, no aumenta el uso de recursos)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:357
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:367
msgid "1 backup tunnel each direction (low redundancy, low resource usage)"
msgstr ""
"1 túnel de respaldo en cada dirección (redundancia baja, uso bajo de "
"recursos)"
msgstr "1 túnel de respaldo en cada dirección (redundancia baja, uso bajo de recursos)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:371
msgid ""
"2 backup tunnels each direction (medium redundancy, medium resource usage)"
msgstr ""
"2 túneles de respaldo en cada dirección (redundancia media, uso de recursos "
"medio)"
msgstr "2 túneles de respaldo en cada dirección (redundancia media, uso de recursos medio)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:365
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:375
msgid "3 backup tunnels each direction (high redundancy, high resource usage)"
msgstr ""
"3 túneles de respaldo en cada dirección (alta redundancia, uso de recursos "
"alto)"
msgstr "3 túneles de respaldo en cada dirección (alta redundancia, uso de recursos alto)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:373
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
@@ -835,7 +820,7 @@ msgstr "Vista previa"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:129
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:192
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:265
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:312
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306
msgid "Status"
msgstr "Estado"
@@ -848,30 +833,30 @@ msgid "No Preview"
msgstr "Sin vista previa"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:199
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:319
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313
msgid "Starting..."
msgstr "Iniciando..."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:206
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:326
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:340
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:354
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348
msgid "Stop"
msgstr "Detener"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:213
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:347
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:341
msgid "Running"
msgstr "Ejecutándose"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:355
msgid "Stopped"
msgstr "Detenido"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:368
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362
msgid "Start"
msgstr "Iniciar"
@@ -880,7 +865,7 @@ msgid "New server tunnel"
msgstr "Nuevo servidor de túnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:251
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:409
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:403
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:265
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:295
@@ -890,7 +875,7 @@ msgid "Standard"
msgstr "Estándar"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:253
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:411
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:405
msgid "Create"
msgstr "Crear"
@@ -899,23 +884,23 @@ msgid "I2P Client Tunnels"
msgstr "Túneles de cliente I2P"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:263
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:298
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:292
msgid "Interface"
msgstr "Interfaz"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:333
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327
msgid "Standby"
msgstr "En espera"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:371
msgid "Outproxy"
msgstr "Puerta de salida"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:394
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:388
msgid "none"
msgstr "ninguno"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:407
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:401
msgid "New client tunnel"
msgstr "Nuevo túnel cliente"
@@ -959,35 +944,27 @@ msgstr "Asistente completado"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:189
msgid ""
"This wizard will take you through the various options available for creating "
"tunnels in I2P."
msgstr ""
"Este asistente le guiará a través de las distintas opciones disponibles para "
"la creación de túneles en I2P."
"This wizard will take you through the various options available for creating"
" tunnels in I2P."
msgstr "Este asistente le guiará a través de las distintas opciones disponibles para la creación de túneles en I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:191
msgid ""
"The first thing to decide is whether you want to create a server or a client "
"tunnel."
msgstr ""
"Lo primero que debe decidir es si se desea crear un túnel de servidor o de "
"cliente."
"The first thing to decide is whether you want to create a server or a client"
" tunnel."
msgstr "Lo primero que debe decidir es si se desea crear un túnel de servidor o de cliente."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:193
msgid ""
"If you need to connect to a remote service, such as an IRC server inside I2P "
"or a code repository, then you will require a CLIENT tunnel."
msgstr ""
"Si necesita conectarse a un servicio remoto, como un servidor de IRC dentro "
"de I2P o un repositorio de código, va a requerir un túnel CLIENTE."
"If you need to connect to a remote service, such as an IRC server inside I2P"
" or a code repository, then you will require a CLIENT tunnel."
msgstr "Si necesita conectarse a un servicio remoto, como un servidor de IRC dentro de I2P o un repositorio de código, va a requerir un túnel CLIENTE."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:195
msgid ""
"On the other hand, if you wish to host a service for others to connect to "
"you'll need to create a SERVER tunnel."
msgstr ""
"Por otro lado, si desea hospedar un servicio para que otros puedan "
"conectarse a usted, necesitará crear un túnel SERVIDOR."
msgstr "Por otro lado, si desea hospedar un servicio para que otros puedan conectarse a usted, necesitará crear un túnel SERVIDOR."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:197
msgid "Server Tunnel"
@@ -1010,9 +987,7 @@ msgstr "Túnel básico para la conexión a un servicio dentro de I2P."
msgid ""
"Try this if none of the tunnel types below fit your requirements, or you "
"don't know what type of tunnel you need."
msgstr ""
"Pruebe esto si ninguno de los tipos de túneles a continuación se ajustan a "
"sus requerimientos, o si no sabe qué tipo de túnel necesita."
msgstr "Pruebe esto si ninguno de los tipos de túneles a continuación se ajustan a sus requerimientos, o si no sabe qué tipo de túnel necesita."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:229
msgid "Tunnel that acts as an HTTP proxy for reaching eepsites inside I2P."
@@ -1021,20 +996,15 @@ msgstr "Túnel que actúa como un proxy HTTP para llegar a eepsites dentro I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:231
msgid ""
"Set your browser to use this tunnel as an http proxy, or set your "
"\"http_proxy\" environment variable for command-line applications in GNU/"
"Linux."
msgstr ""
"Configure su navegador para usar este túnel como un proxy HTTP, o configure "
"su variable de entorno \"http_proxy\" para aplicaciones de línea de comandos "
"en GNU / Linux."
"\"http_proxy\" environment variable for command-line applications in "
"GNU/Linux."
msgstr "Configure su navegador para usar este túnel como un proxy HTTP, o configure su variable de entorno \"http_proxy\" para aplicaciones de línea de comandos en GNU / Linux."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:233
msgid ""
"Websites outside I2P can also be reached if an HTTP proxy within I2P is "
"known."
msgstr ""
"También es posible llegar a sitios web de fuera de I2P si se conoce algún "
"proxy HTTP dentro de I2P."
msgstr "También es posible llegar a sitios web de fuera de I2P si se conoce algún proxy HTTP dentro de I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:235
msgid "Customised client tunnel specific for IRC connections."
@@ -1044,17 +1014,13 @@ msgstr "Túnel de cliente personalizado específicamente para conexiones de IRC.
msgid ""
"With this tunnel type, your IRC client will be able to connect to an IRC "
"network inside I2P."
msgstr ""
"Con este tipo de túnel, su cliente de IRC será capaz de conectarse a una red "
"de IRC dentro de I2P."
msgstr "Con este tipo de túnel, su cliente de IRC será capaz de conectarse a una red de IRC dentro de I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:239
msgid ""
"Each IRC network in I2P that you wish to connect to will require its own "
"tunnel. (See Also, SOCKS IRC)"
msgstr ""
"Cada red IRC en I2P a la que desee conectarse requerirá su propio túnel. "
"(Véase también, SOCKS IRC)"
msgstr "Cada red IRC en I2P a la que desee conectarse requerirá su propio túnel. (Véase también, SOCKS IRC)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:241
msgid "A tunnel that implements the SOCKS protocol."
@@ -1064,45 +1030,33 @@ msgstr "Un túnel que implementa el protocolo SOCKS."
msgid ""
"This enables both TCP and UDP connections to be made through a SOCKS "
"outproxy within I2P."
msgstr ""
"Esto permite que las conexiones TCP y UDP se hagan a través de un outproxy "
"SOCKS que esté dentro de I2P."
msgstr "Esto permite que las conexiones TCP y UDP se hagan a través de un outproxy SOCKS que esté dentro de I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:245
msgid ""
"A client tunnel implementing the SOCKS protocol, which is customised for "
"connecting to IRC networks."
msgstr ""
"Un túnel de cliente que implementa el protocolo SOCKS, personalizado para la "
"conexión con redes IRC."
msgstr "Un túnel de cliente que implementa el protocolo SOCKS, personalizado para la conexión con redes IRC."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:247
msgid ""
"With this tunnel type, IRC networks in I2P can be reached by typing the I2P "
"address into your IRC client, and configuring the IRC client to use this "
"SOCKS tunnel."
msgstr ""
"Con este tipo de túnel, las redes IRC de I2P pueden ser alcanzadas "
"escribiendo directamente la dirección I2P en el cliente de IRC, y "
"configurando el cliente de IRC para utilizar este túnel SOCKS."
msgstr "Con este tipo de túnel, las redes IRC de I2P pueden ser alcanzadas escribiendo directamente la dirección I2P en el cliente de IRC, y configurando el cliente de IRC para utilizar este túnel SOCKS."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:249
msgid ""
"This means that only one I2P tunnel is required rather than a separate "
"tunnel per IRC network."
msgstr ""
"Esto significa que sólo es necesario un único túnel I2P en lugar de un túnel "
"distinto por cada red IRC."
msgstr "Esto significa que sólo es necesario un único túnel I2P en lugar de un túnel distinto por cada red IRC."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:251
msgid ""
"IRC networks outside I2P can also be reached if a SOCKS outproxy within I2P "
"is known, though it depends on whether or not the outproxy has been blocked "
"by the IRC network."
msgstr ""
"También se puede llegar a redes IRC de fuera de I2P si se conoce un outproxy "
"SOCKS en I2P, aunque depende de si el outproxy ha sido bloqueado por la red "
"IRC."
msgstr "También se puede llegar a redes IRC de fuera de I2P si se conoce un outproxy SOCKS en I2P, aunque depende de si el outproxy ha sido bloqueado por la red IRC."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:253
msgid "A client tunnel that implements the HTTP CONNECT command."
@@ -1112,9 +1066,7 @@ msgstr "Un túnel de cliente que implementa el comando HTTP CONNECT."
msgid ""
"This enables TCP connections to be made through an HTTP outproxy, assuming "
"the proxy supports the CONNECT command."
msgstr ""
"Esto permite hacer conexiones TCP a través de un outproxy HTTP, suponiendo "
"que el servidor proxy admita el comando CONNECT."
msgstr "Esto permite hacer conexiones TCP a través de un outproxy HTTP, suponiendo que el servidor proxy admita el comando CONNECT."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:257
msgid "A customised client tunnel for Streamr."
@@ -1122,8 +1074,7 @@ msgstr "Un túnel de cliente personalizado para Streamr."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:267
msgid "A basic server tunnel for hosting a generic service inside I2P."
msgstr ""
"Un túnel básico de servidor para alojar un servicio genérico dentro de I2P."
msgstr "Un túnel básico de servidor para alojar un servicio genérico dentro de I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:271
msgid "A server tunnel that is customised for HTTP connections."
@@ -1137,28 +1088,21 @@ msgstr "Utilice este tipo de túnel si desea alojar una eepsite."
msgid ""
"A customised server tunnel that can both serve HTTP data and connect to "
"other server tunnels."
msgstr ""
"Un túnel de servidor personalizado que puede servir tanto datos HTTP como "
"conectar a otros túneles de servidor."
msgstr "Un túnel de servidor personalizado que puede servir tanto datos HTTP como conectar a otros túneles de servidor."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:277
msgid "This tunnel type is predominantly used when running a Seedless server."
msgstr ""
"Este tipo de túnel se utiliza principalmente cuando se ejecuta un servidor "
"sin semillas (Seedless)."
msgstr "Este tipo de túnel se utiliza principalmente cuando se ejecuta un servidor sin semillas (Seedless)."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:279
msgid "A customised server tunnel for hosting IRC networks inside I2P."
msgstr ""
"Un túnel de servidor personalizado para alojar redes IRC dentro de I2P."
msgstr "Un túnel de servidor personalizado para alojar redes IRC dentro de I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:281
msgid ""
"Usually, a separate tunnel needs to be created for each IRC server that is "
"to be accessible inside I2P."
msgstr ""
"Normalmente, se debe crear un túnel por separado para cada servidor IRC, que "
"será accesible dentro de I2P."
msgstr "Normalmente, se debe crear un túnel por separado para cada servidor IRC, que será accesible dentro de I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:283
msgid "A customised server tunnel for Streamr."
@@ -1172,17 +1116,13 @@ msgstr "Elegir un nombre y una descripción para su túnel."
msgid ""
"These can be anything you want - they are just for ease of identifying the "
"tunnel in the routerconsole."
msgstr ""
"Estos pueden ser lo que se quiera - son sólo para facilitar la "
"identificación del túnel en la consola del router."
msgstr "Estos pueden ser lo que se quiera - son sólo para facilitar la identificación del túnel en la consola del router."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:354
msgid ""
"If you know of any outproxies for this type of tunnel (either HTTP or "
"SOCKS), fill them in below."
msgstr ""
"Si conoce algún outproxie para este tipo de túnel (HTTP o SOCKS), rellénelo "
"a continuación."
msgstr "Si conoce algún outproxie para este tipo de túnel (HTTP o SOCKS), rellénelo a continuación."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:356
msgid "Separate multiple proxies with commas."
@@ -1192,35 +1132,27 @@ msgstr "Separe múltiples servidores proxy con comas."
msgid ""
"Type in the I2P destination of the service that this client tunnel should "
"connect to."
msgstr ""
"Introduzca el destino de I2P del servicio al que este túnel de cliente debe "
"conectarse."
msgstr "Introduzca el destino de I2P del servicio al que este túnel de cliente debe conectarse."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:376
msgid ""
"This could be the full base 64 destination key, or an I2P URL from your "
"address book."
msgstr ""
"Este puede ser la clave de destino en base 64 o una dirección URL I2P de su "
"libreta de direcciones."
msgstr "Este puede ser la clave de destino en base 64 o una dirección URL I2P de su libreta de direcciones."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:406
msgid ""
"This is the IP that your service is running on, this is usually on the same "
"machine so 127.0.0.1 is autofilled."
msgstr ""
"Esta es la IP en la que el servicio se está ejecutando, esto suele ser en la "
"misma máquina, por lo que se ha auto-rellenado con 127.0.0.1 "
msgstr "Esta es la IP en la que el servicio se está ejecutando, esto suele ser en la misma máquina, por lo que se ha auto-rellenado con 127.0.0.1 "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:429
msgid "This is the port that the service is accepting connections on."
msgstr ""
"Este es el puerto por el que el servicio está aceptando conexiones entrantes."
msgstr "Este es el puerto por el que el servicio está aceptando conexiones entrantes."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:450
msgid "This is the port that the client tunnel will be accessed from locally."
msgstr ""
"Este es el puerto por el que se accederá al túnel de cliente localmente."
msgstr "Este es el puerto por el que se accederá al túnel de cliente localmente."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:452
msgid "This is also the client port for the HTTPBidir server tunnel."
@@ -1230,9 +1162,7 @@ msgstr "También es el puerto de cliente para el túnel de servidor HTTPBidir."
msgid ""
"How do you want this tunnel to be accessed? By just this machine, your "
"entire subnet, or external internet?"
msgstr ""
"¿Cómo quiere que se acceda a este túnel? ¿Sólo esta máquina, su subred "
"entera, o todo el internet externo?"
msgstr "¿Cómo quiere que se acceda a este túnel? ¿Sólo esta máquina, su subred entera, o todo el internet externo?"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:473
msgid "You will most likely want to just allow 127.0.0.1"
@@ -1242,41 +1172,30 @@ msgstr "Lo más probable es que desee permitir sólo 127.0.0.1"
msgid ""
"The I2P router can automatically start this tunnel for you when the router "
"is started."
msgstr ""
"El router I2P puede activar automáticamente este túnel cuando el router se "
"inicie"
msgstr "El router I2P puede activar automáticamente este túnel cuando el router se inicie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:517
msgid ""
"This can be useful for frequently-used tunnels (especially server tunnels), "
"but for tunnels that are only used occassionally it would mean that the I2P "
"router is creating and maintaining unnecessary tunnels."
msgstr ""
"Esto puede ser útil para los túneles de uso frecuente (especialmente en los "
"túneles de servidor), pero para los túneles que sólo se utilizan "
"ocasionalmente, significaría que el router I2P está creando y manteniendo "
"túneles innecesarios."
msgstr "Esto puede ser útil para los túneles de uso frecuente (especialmente en los túneles de servidor), pero para los túneles que sólo se utilizan ocasionalmente, significaría que el router I2P está creando y manteniendo túneles innecesarios."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:543
msgid "The wizard has now collected enough information to create your tunnel."
msgstr ""
"El asistente ya ha recogido suficiente información para crear el túnel."
msgstr "El asistente ya ha recogido suficiente información para crear el túnel."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:545
msgid ""
"Upon clicking the Save button below, the wizard will set up the tunnel, and "
"take you back to the main I2PTunnel page."
msgstr ""
"Al hacer clic en el botón Guardar a continuación, el asistente creará el "
"túnel, y le llevará de vuelta a la página principal de túneles I2P."
msgstr "Al hacer clic en el botón Guardar a continuación, el asistente creará el túnel, y le llevará de vuelta a la página principal de túneles I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:550
msgid ""
"Because you chose to automatically start the tunnel when the router starts, "
"you don't have to do anything further."
msgstr ""
"Como ha decidido iniciar automáticamente el túnel cuando el router se "
"inicie, no tiene que hacer nada más."
msgstr "Como ha decidido iniciar automáticamente el túnel cuando el router se inicie, no tiene que hacer nada más."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:552
msgid "The router will start the tunnel once it has been set up."
@@ -1286,17 +1205,13 @@ msgstr "El router iniciará el túnel una vez haya sido establecido."
msgid ""
"Because you chose not to automatically start the tunnel, you will have to "
"manually start it."
msgstr ""
"Como usted ha decidido no iniciar automáticamente el túnel, tendrá que "
"iniciarlo de forma manual."
msgstr "Como usted ha decidido no iniciar automáticamente el túnel, tendrá que iniciarlo de forma manual."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:558
msgid ""
"You can do this by clicking the Start button on the main page which "
"corresponds to the new tunnel."
msgstr ""
"Esto se puede hacer haciendo clic en el botón Iniciar en la página principal "
"que corresponde al nuevo túnel."
msgstr "Esto se puede hacer haciendo clic en el botón Iniciar en la página principal que corresponde al nuevo túnel."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:562
msgid "Below is a summary of the options you chose:"
@@ -1306,19 +1221,14 @@ msgstr "A continuación se muestra un resumen de las opciones que ha elegido:"
msgid ""
"Alongside these basic settings, there are a number of advanced options for "
"tunnel configuration."
msgstr ""
"Junto a estos valores básicos, hay una serie de opciones avanzadas para la "
"configuración de túneles."
msgstr "Junto a estos valores básicos, hay una serie de opciones avanzadas para la configuración de túneles."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:662
msgid ""
"The wizard will set reasonably sensible default values for these, but you "
"can view and/or edit these by clicking on the tunnel's name in the main "
"I2PTunnel page."
msgstr ""
"El asistente establecerá valores razonablemente sensibles para ellos por "
"defecto, pero se pueden ver y/o editar haciendo clic en el nombre del túnel "
"en la página de túneles I2P principal."
msgstr "El asistente establecerá valores razonablemente sensibles para ellos por defecto, pero se pueden ver y/o editar haciendo clic en el nombre del túnel en la página de túneles I2P principal."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:704
msgid "Previous"

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

View File

@@ -2,23 +2,22 @@
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2ptunnel package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
#
# Translators:
# Martin Svensson <digitalmannen@gmail.com>, 2011, 2012.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-07-26 19:10+0000\n"
"PO-Revision-Date: 2012-07-23 16:31+0000\n"
"Last-Translator: Martin Svensson <digitalmannen@gmail.com>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/"
"language/sv_SE/)\n"
"Language: sv_SE\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2012-10-12 00:38+0000\n"
"PO-Revision-Date: 2012-10-12 00:40+0000\n"
"Last-Translator: kytv <killyourtv@i2pmail.org>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/language/sv_SE/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"Language: sv_SE\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:554
msgid "This seems to be a bad destination:"
@@ -31,13 +30,10 @@ msgstr "i2padresshjälp kan inte hjälpa dig med ett sådant mål!"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:621
#, java-format
msgid ""
"To visit the destination in your host database, click <a href=\"{0}\">here</"
"a>. To visit the conflicting addresshelper destination, click <a href="
"\"{1}\">here</a>."
msgstr ""
"För att besöka målet i din värd databas href=\"{0}\"> klicka <a här </ a>. "
"För att besöka de motstridiga hjälpaddresserna,<a href=\"{1}\"> klicka <a "
"här </ a>."
"To visit the destination in your host database, click <a "
"href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, "
"click <a href=\"{1}\">here</a>."
msgstr "För att besöka målet i din värd databas href=\"{0}\"> klicka <a här </ a>. För att besöka de motstridiga hjälpaddresserna,<a href=\"{1}\"> klicka <a här </ a>."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1023
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:403
@@ -52,7 +48,7 @@ msgid "Base 32"
msgstr "Bas 32"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1031
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:374
msgid "Destination"
msgstr "Mål"
@@ -83,10 +79,9 @@ msgstr "HTTP Utproxy"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1216
msgid ""
"Click a link below to look for an address helper by using a \"jump\" service:"
msgstr ""
"Klicka på en länk nedan för att söka efter en hjälpaddress genom att använda "
"en \"hopp\" tjänst"
"Click a link below to look for an address helper by using a \"jump\" "
"service:"
msgstr "Klicka på en länk nedan för att söka efter en hjälpaddress genom att använda en \"hopp\" tjänst"
#. Translators: parameter is a host name
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1252
@@ -138,97 +133,109 @@ msgstr "Klicka här om du inte omdirigeras automatiskt "
msgid "internal"
msgstr "Intern "
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:174
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:175
msgid ""
"Invalid form submission, probably because you used the 'back' or 'reload' "
"button on your browser. Please resubmit."
msgstr ""
"Ogiltigt formulärbegäran, beror troligtvis på attt du använde 'tillbaka' "
"eller 'uppdatera' knappen. Försök att skicka igen"
msgstr "Ogiltigt formulärbegäran, beror troligtvis på attt du använde 'tillbaka' eller 'uppdatera' knappen. Försök att skicka igen"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:221
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:222
msgid "Configuration reloaded for all tunnels"
msgstr "Konfigurationen uppdateras för alla tunnlar"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:233
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:234
msgid "Starting tunnel"
msgstr "Startar tunnel"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:246
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:247
msgid "Stopping tunnel"
msgstr "Stannar tunnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:314
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:315
msgid "Configuration changes saved"
msgstr "Konfigurationsändringar sparas"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:317
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:318
msgid "Failed to save configuration"
msgstr "Det gick inte att spara konfigurationen"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:436
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:437
msgid "New Tunnel"
msgstr "Ny tunnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:456
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:460
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:470
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:587
msgid "Port not set"
msgstr "Ingen port angiven"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:463
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:589
msgid "Invalid port"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:466
msgid "Warning - ports less than 1024 are not recommended"
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:482
msgid "Standard client"
msgstr "Standard klient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:457
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:483
msgid "HTTP client"
msgstr "HTTP-klient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:458
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:484
msgid "IRC client"
msgstr "IRC-klient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:459
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:485
msgid "Standard server"
msgstr "Standard server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:460
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:486
msgid "HTTP server"
msgstr "HTTP server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:461
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:487
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS 4/4a/5 proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:462
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:488
msgid "SOCKS IRC proxy"
msgstr "SOCKS IRC proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:463
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:489
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:464
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:490
msgid "IRC server"
msgstr "IRC-server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:465
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:491
msgid "Streamr client"
msgstr "Klient för Streamr "
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:466
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:492
msgid "Streamr server"
msgstr "Server för Streamr"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:467
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:493
msgid "HTTP bidir"
msgstr "HTTP bidir"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:555
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:305
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:581
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
msgid "Host not set"
msgstr "Ingen värd angiven"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:559
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:287
msgid "Port not set"
msgstr "Ingen port angiven"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:583
msgid "Invalid address"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:82
msgid "I2P Tunnel Manager - Edit Client Tunnel"
@@ -255,14 +262,14 @@ msgstr "Namn"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:127
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:127
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:261
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:294
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:288
msgid "Type"
msgstr "Typ"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:131
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:131
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:241
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:399
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:393
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:330
msgid "Description"
msgstr "Beskrivning"
@@ -321,9 +328,7 @@ msgstr "Delad klient"
msgid ""
"(Share tunnels with other clients and irc/httpclients? Change requires "
"restart of client proxy)"
msgstr ""
"(Dela tunnlarna med andra klienter och irc/HTTP-klienter? Ändring kräver "
"omstart av klientproxyn)"
msgstr "(Dela tunnlarna med andra klienter och irc/HTTP-klienter? Ändring kräver omstart av klientproxyn)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:225
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:135
@@ -351,9 +356,7 @@ msgstr "Avancerade nätverks instälningar"
msgid ""
"(NOTE: when this client proxy is configured to share tunnels, then these "
"options are for all the shared proxy clients!)"
msgstr ""
"(OBS: när denna klientproxyn är konfigurerad för att dela tunnlar, då gäller "
"dessa alternativ för alla delade proxyklienter!)"
msgstr "(OBS: när denna klientproxyn är konfigurerad för att dela tunnlar, då gäller dessa alternativ för alla delade proxyklienter!)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:245
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:255
@@ -435,26 +438,20 @@ msgstr "Antal"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:325
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:335
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr ""
"1 inkommande, 1 utgående tunnlar (låg bandbreddsanvändning, låg "
"tillförlitlighet)"
msgstr "1 inkommande, 1 utgående tunnlar (låg bandbreddsanvändning, låg tillförlitlighet)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:329
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:339
msgid ""
"2 inbound, 2 outbound tunnels (standard bandwidth usage, standard "
"reliability)"
msgstr ""
"2 inkommande, 2 utgående tunnlar (normal bandbreddsanvändning, normal "
"tillförlitlighet)"
msgstr "2 inkommande, 2 utgående tunnlar (normal bandbreddsanvändning, normal tillförlitlighet)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:333
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:343
msgid ""
"3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
msgstr ""
"3 inkommande, 3 utgående tunnlar (Högre bandbreddsanvändning, högre "
"tillförlitlighet)"
msgstr "3 inkommande, 3 utgående tunnlar (Högre bandbreddsanvändning, högre tillförlitlighet)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:341
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:351
@@ -469,8 +466,7 @@ msgstr "Antal reserver"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:353
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:363
msgid "0 backup tunnels (0 redundancy, no added resource usage)"
msgstr ""
"0 reserv tunnlar i varje riktning (ingen redundans, ingen resursanvändning)"
msgstr "0 reserv tunnlar i varje riktning (ingen redundans, ingen resursanvändning)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:357
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:367
@@ -481,15 +477,12 @@ msgstr "1 reserv tunnel i varje riktning (låg redundans, låg resursanvändning
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:371
msgid ""
"2 backup tunnels each direction (medium redundancy, medium resource usage)"
msgstr ""
"2 reserv tunnlar i varje riktning (medel hög redundans, medel hög "
"resursanvändning)"
msgstr "2 reserv tunnlar i varje riktning (medel hög redundans, medel hög resursanvändning)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:365
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:375
msgid "3 backup tunnels each direction (high redundancy, high resource usage)"
msgstr ""
"3 reserv tunnlar i varje riktning (hög redundans, hög resursanvändning)"
msgstr "3 reserv tunnlar i varje riktning (hög redundans, hög resursanvändning)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:373
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
@@ -821,7 +814,7 @@ msgstr "förhandsvisning"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:129
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:192
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:265
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:312
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306
msgid "Status"
msgstr "Status"
@@ -834,30 +827,30 @@ msgid "No Preview"
msgstr "Ingen förhandsvisning"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:199
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:319
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313
msgid "Starting..."
msgstr "Startar..."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:206
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:326
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:340
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:354
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348
msgid "Stop"
msgstr "Stopp"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:213
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:347
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:341
msgid "Running"
msgstr "Kör"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:355
msgid "Stopped"
msgstr "Stoppad"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:368
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362
msgid "Start"
msgstr "Start"
@@ -866,7 +859,7 @@ msgid "New server tunnel"
msgstr "Ny severtunnel "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:251
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:409
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:403
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:265
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:295
@@ -876,7 +869,7 @@ msgid "Standard"
msgstr "Standard"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:253
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:411
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:405
msgid "Create"
msgstr "Skapa"
@@ -885,23 +878,23 @@ msgid "I2P Client Tunnels"
msgstr "I2P Klienttunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:263
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:298
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:292
msgid "Interface"
msgstr "Gränssnitt "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:333
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327
msgid "Standby"
msgstr "Standby"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:371
msgid "Outproxy"
msgstr "Utproxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:394
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:388
msgid "none"
msgstr "Ingen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:407
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:401
msgid "New client tunnel"
msgstr "Ny klienttunnel"
@@ -945,33 +938,27 @@ msgstr "Guiden färdig "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:189
msgid ""
"This wizard will take you through the various options available for creating "
"tunnels in I2P."
msgstr ""
"Guiden tar dig igenom de olika inställningsmöjligheterna för att skapa "
"tunnlar."
"This wizard will take you through the various options available for creating"
" tunnels in I2P."
msgstr "Guiden tar dig igenom de olika inställningsmöjligheterna för att skapa tunnlar."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:191
msgid ""
"The first thing to decide is whether you want to create a server or a client "
"tunnel."
msgstr ""
"Det första är att bestämma om det skall vara en server- eller klient-tunnel. "
"The first thing to decide is whether you want to create a server or a client"
" tunnel."
msgstr "Det första är att bestämma om det skall vara en server- eller klient-tunnel. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:193
msgid ""
"If you need to connect to a remote service, such as an IRC server inside I2P "
"or a code repository, then you will require a CLIENT tunnel."
msgstr ""
"Om du ansluter till en fjärrtjänst så som tex en IRC-server inom I2P, behövs "
"en KLIENT-tunnel. "
"If you need to connect to a remote service, such as an IRC server inside I2P"
" or a code repository, then you will require a CLIENT tunnel."
msgstr "Om du ansluter till en fjärrtjänst så som tex en IRC-server inom I2P, behövs en KLIENT-tunnel. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:195
msgid ""
"On the other hand, if you wish to host a service for others to connect to "
"you'll need to create a SERVER tunnel."
msgstr ""
"Men om du vill göra en tjänst tillgänglig för andra behövs en SERVER-tunnel."
msgstr "Men om du vill göra en tjänst tillgänglig för andra behövs en SERVER-tunnel."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:197
msgid "Server Tunnel"
@@ -987,32 +974,25 @@ msgstr "Det finns flera typer av tunnlar att välja på:"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:225
msgid "Basic tunnel for connecting to a single service inside I2P."
msgstr ""
"Grundläggande tunnel för anslutning till en snigel tjänst innanför I2P. "
msgstr "Grundläggande tunnel för anslutning till en snigel tjänst innanför I2P. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:269
msgid ""
"Try this if none of the tunnel types below fit your requirements, or you "
"don't know what type of tunnel you need."
msgstr ""
"Prova detta om ingen av valen passar eller du inte vet vilken typ av tunnel "
"som behövs."
msgstr "Prova detta om ingen av valen passar eller du inte vet vilken typ av tunnel som behövs."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:229
msgid "Tunnel that acts as an HTTP proxy for reaching eepsites inside I2P."
msgstr ""
"Tunneln agerar som en HTTP-proxy för att komma åt eepsites innanför I2P. "
msgstr "Tunneln agerar som en HTTP-proxy för att komma åt eepsites innanför I2P. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:231
msgid ""
"Set your browser to use this tunnel as an http proxy, or set your "
"\"http_proxy\" environment variable for command-line applications in GNU/"
"Linux."
msgstr ""
"Peka din webbläsare på denna tunnel som en http-proxy eller ställ in "
"miljövariabeln \"http_proxy\" för terminal baserade applikationer i GNU/"
"Linux."
"\"http_proxy\" environment variable for command-line applications in "
"GNU/Linux."
msgstr "Peka din webbläsare på denna tunnel som en http-proxy eller ställ in miljövariabeln \"http_proxy\" för terminal baserade applikationer i GNU/Linux."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:233
msgid ""
@@ -1034,9 +1014,7 @@ msgstr "Med denna tunneltyp kan IRC-klienter ansluta till IRC-nät inom I2P "
msgid ""
"Each IRC network in I2P that you wish to connect to will require its own "
"tunnel. (See Also, SOCKS IRC)"
msgstr ""
"Varje IRC-nät inom I2P som du vill ansluta till kräver en egen tunnel (Se "
"även: SOCKS IRC) "
msgstr "Varje IRC-nät inom I2P som du vill ansluta till kräver en egen tunnel (Se även: SOCKS IRC) "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:241
msgid "A tunnel that implements the SOCKS protocol."
@@ -1046,9 +1024,7 @@ msgstr "En tunnel som implementerar SOCKS protokollet."
msgid ""
"This enables both TCP and UDP connections to be made through a SOCKS "
"outproxy within I2P."
msgstr ""
"Detta möjliggör både TCP och UDP anslutningar genom SOCKS utgående-proxy "
"innanför I2P "
msgstr "Detta möjliggör både TCP och UDP anslutningar genom SOCKS utgående-proxy innanför I2P "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:245
msgid ""
@@ -1061,27 +1037,20 @@ msgid ""
"With this tunnel type, IRC networks in I2P can be reached by typing the I2P "
"address into your IRC client, and configuring the IRC client to use this "
"SOCKS tunnel."
msgstr ""
"Med denna tunnel typen kan IRC-nät inom I2P nås genom att skriva in I2P "
"adressen i IRC-klienten och konfigurera IRC-klienten att använda denna SOCKS-"
"tunneln."
msgstr "Med denna tunnel typen kan IRC-nät inom I2P nås genom att skriva in I2P adressen i IRC-klienten och konfigurera IRC-klienten att använda denna SOCKS-tunneln."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:249
msgid ""
"This means that only one I2P tunnel is required rather than a separate "
"tunnel per IRC network."
msgstr ""
"Detta innebär att enbart en I2P-tunnel behövs istället för en tunnel per IRC-"
"nät."
msgstr "Detta innebär att enbart en I2P-tunnel behövs istället för en tunnel per IRC-nät."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:251
msgid ""
"IRC networks outside I2P can also be reached if a SOCKS outproxy within I2P "
"is known, though it depends on whether or not the outproxy has been blocked "
"by the IRC network."
msgstr ""
"IRC-nät utanför I2P kan nås om en SOCKS-proxy innanför I2P är känd, men det "
"bror på om utgående-proxy har blockerats av IRC-nätet."
msgstr "IRC-nät utanför I2P kan nås om en SOCKS-proxy innanför I2P är känd, men det bror på om utgående-proxy har blockerats av IRC-nätet."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:253
msgid "A client tunnel that implements the HTTP CONNECT command."
@@ -1091,9 +1060,7 @@ msgstr "En klient-tunnel som implementerar HTTP CONNECT kommandot. "
msgid ""
"This enables TCP connections to be made through an HTTP outproxy, assuming "
"the proxy supports the CONNECT command."
msgstr ""
"Detta möjliggör TCP anslutningar genom en HTTP utgående-proxy om proxyn "
"stödjer CONNECT kommandot"
msgstr "Detta möjliggör TCP anslutningar genom en HTTP utgående-proxy om proxyn stödjer CONNECT kommandot"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:257
msgid "A customised client tunnel for Streamr."
@@ -1115,9 +1082,7 @@ msgstr "Använd denna denna typ av tunnel om du vill köra en eepsite."
msgid ""
"A customised server tunnel that can both serve HTTP data and connect to "
"other server tunnels."
msgstr ""
"En anpassad server tunnel som hanterar både HTTP data och anslutningar till "
"andra server-tunnlar."
msgstr "En anpassad server tunnel som hanterar både HTTP data och anslutningar till andra server-tunnlar."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:277
msgid "This tunnel type is predominantly used when running a Seedless server."
@@ -1131,9 +1096,7 @@ msgstr "En server-tunnel för IRC-Nät innanför I2P."
msgid ""
"Usually, a separate tunnel needs to be created for each IRC server that is "
"to be accessible inside I2P."
msgstr ""
"Vanligtvis behövs en separat tunnel för varje IRC-server som skall anslutas "
"till innanför I2P."
msgstr "Vanligtvis behövs en separat tunnel för varje IRC-server som skall anslutas till innanför I2P."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:283
msgid "A customised server tunnel for Streamr."
@@ -1147,17 +1110,13 @@ msgstr "Välj namn och beskrivning av tunneln."
msgid ""
"These can be anything you want - they are just for ease of identifying the "
"tunnel in the routerconsole."
msgstr ""
"Kan vad som helst, används enbart för att enkelt identifiera tunneln i "
"routerkonsolen "
msgstr "Kan vad som helst, används enbart för att enkelt identifiera tunneln i routerkonsolen "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:354
msgid ""
"If you know of any outproxies for this type of tunnel (either HTTP or "
"SOCKS), fill them in below."
msgstr ""
"Om du känner till några utgående proxies för denna typen av tunnlar (HTTP "
"eller SOCKS), fyll i dem nedan. "
msgstr "Om du känner till några utgående proxies för denna typen av tunnlar (HTTP eller SOCKS), fyll i dem nedan. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:356
msgid "Separate multiple proxies with commas."
@@ -1179,9 +1138,7 @@ msgstr "Kan vara hela base 64 målsnyckeln eller en I2P URL från adressboken."
msgid ""
"This is the IP that your service is running on, this is usually on the same "
"machine so 127.0.0.1 is autofilled."
msgstr ""
"Detta är IP-adressen som tjänsten körs på, detta är vanligtvis på samma "
"maskin så 127.0.0.1 fylls i automatiskt. "
msgstr "Detta är IP-adressen som tjänsten körs på, detta är vanligtvis på samma maskin så 127.0.0.1 fylls i automatiskt. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:429
msgid "This is the port that the service is accepting connections on."
@@ -1199,9 +1156,7 @@ msgstr "Detta är också en klient-port för HTTPBidir server-tunneln."
msgid ""
"How do you want this tunnel to be accessed? By just this machine, your "
"entire subnet, or external internet?"
msgstr ""
"Hur du vill att tunneln ska nås? Enbart denna maskinen, ditt lokala nät "
"eller hela internet? "
msgstr "Hur du vill att tunneln ska nås? Enbart denna maskinen, ditt lokala nät eller hela internet? "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:473
msgid "You will most likely want to just allow 127.0.0.1"
@@ -1218,10 +1173,7 @@ msgid ""
"This can be useful for frequently-used tunnels (especially server tunnels), "
"but for tunnels that are only used occassionally it would mean that the I2P "
"router is creating and maintaining unnecessary tunnels."
msgstr ""
"Detta kan vara användbart för tunnlar som används ofta (tex server-tunnlar) "
"men för tunnlar som används sällan innebär det att onödiga tunnlar "
"upprättas. "
msgstr "Detta kan vara användbart för tunnlar som används ofta (tex server-tunnlar) men för tunnlar som används sällan innebär det att onödiga tunnlar upprättas. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:543
msgid "The wizard has now collected enough information to create your tunnel."
@@ -1231,17 +1183,13 @@ msgstr "Guiden hat samlat tillräckligt med information för att skapa tunneln.
msgid ""
"Upon clicking the Save button below, the wizard will set up the tunnel, and "
"take you back to the main I2PTunnel page."
msgstr ""
"När du klickar på \"spara\" kommer guiden att skapa tunneln och sedan ta dig "
"till sidan för tunnlar."
msgstr "När du klickar på \"spara\" kommer guiden att skapa tunneln och sedan ta dig till sidan för tunnlar."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:550
msgid ""
"Because you chose to automatically start the tunnel when the router starts, "
"you don't have to do anything further."
msgstr ""
"Efter som du valt att starta tunneln samtidigt som routern startas behövs "
"inget mer göras. "
msgstr "Efter som du valt att starta tunneln samtidigt som routern startas behövs inget mer göras. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:552
msgid "The router will start the tunnel once it has been set up."
@@ -1251,9 +1199,7 @@ msgstr "Routern starta tunneln när den skapats. "
msgid ""
"Because you chose not to automatically start the tunnel, you will have to "
"manually start it."
msgstr ""
"Efter som du valt att inte starta tunneln samtidigt som routern startas, "
"behövs den startas manuellt."
msgstr "Efter som du valt att inte starta tunneln samtidigt som routern startas, behövs den startas manuellt."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:558
msgid ""
@@ -1269,18 +1215,14 @@ msgstr "Nedan är en sammanfattning över valen du kan göra:"
msgid ""
"Alongside these basic settings, there are a number of advanced options for "
"tunnel configuration."
msgstr ""
"Vid sidan om dessa grundägande inställningar finns att par avancerade val "
"för tunneln. "
msgstr "Vid sidan om dessa grundägande inställningar finns att par avancerade val för tunneln. "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:662
msgid ""
"The wizard will set reasonably sensible default values for these, but you "
"can view and/or edit these by clicking on the tunnel's name in the main "
"I2PTunnel page."
msgstr ""
"Guiden väljer lämpliga värden för dessa. Men du kan ändra/se värdena på "
"huvudsidan för I2P-tunnlar."
msgstr "Guiden väljer lämpliga värden för dessa. Men du kan ändra/se värdena på huvudsidan för I2P-tunnlar."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:704
msgid "Previous"

View File

@@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import net.i2p.I2PAppContext;
@@ -36,7 +37,7 @@ public class I2PSocketManagerFactory {
* @return the newly created socket manager, or null if there were errors
*/
public static I2PSocketManager createManager() {
return createManager(getHost(), getPort(), System.getProperties());
return createManager(getHost(), getPort(), (Properties) System.getProperties().clone());
}
/**
@@ -59,7 +60,7 @@ public class I2PSocketManagerFactory {
* @return the newly created socket manager, or null if there were errors
*/
public static I2PSocketManager createManager(String host, int port) {
return createManager(host, port, System.getProperties());
return createManager(host, port, (Properties) System.getProperties().clone());
}
/**
@@ -95,7 +96,7 @@ public class I2PSocketManagerFactory {
* @return the newly created socket manager, or null if there were errors
*/
public static I2PSocketManager createManager(InputStream myPrivateKeyStream) {
return createManager(myPrivateKeyStream, getHost(), getPort(), System.getProperties());
return createManager(myPrivateKeyStream, getHost(), getPort(), (Properties) System.getProperties().clone());
}
/**
@@ -126,10 +127,11 @@ public class I2PSocketManagerFactory {
I2PClient client = I2PClientFactory.createClient();
if (opts == null)
opts = new Properties();
for (Iterator iter = System.getProperties().keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
Properties syscopy = (Properties) System.getProperties().clone();
for (Map.Entry e : syscopy.entrySet()) {
String name = (String) e.getKey();
if (!opts.containsKey(name))
opts.setProperty(name, System.getProperty(name));
opts.setProperty(name, (String) e.getValue());
}
//boolean oldLib = DEFAULT_MANAGER.equals(opts.getProperty(PROP_MANAGER, DEFAULT_MANAGER));
//if (oldLib && false) {

View File

@@ -17,6 +17,9 @@ public interface I2PSocketOptions {
/**
* How long we will wait for the ACK from a SYN, in milliseconds.
*
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
* and it also interprets <= 0 as default.
*
* @return milliseconds to wait, or -1 if we will wait indefinitely
*/
public long getConnectTimeout();
@@ -24,6 +27,9 @@ public interface I2PSocketOptions {
/**
* Define how long we will wait for the ACK from a SYN, in milliseconds.
*
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
* and it also interprets <= 0 as default.
*
* @param ms timeout in ms
*/
public void setConnectTimeout(long ms);
@@ -32,6 +38,9 @@ public interface I2PSocketOptions {
* What is the longest we'll block on the input stream while waiting
* for more data. If this value is exceeded, the read() throws
* InterruptedIOException
*
* WARNING: Default -1 (unlimited), which is probably not what you want.
*
* @return timeout in ms
*/
public long getReadTimeout();
@@ -40,6 +49,9 @@ public interface I2PSocketOptions {
* What is the longest we'll block on the input stream while waiting
* for more data. If this value is exceeded, the read() throws
* InterruptedIOException
*
* WARNING: Default -1 (unlimited), which is probably not what you want.
*
* @param ms timeout in ms
*/
public void setReadTimeout(long ms);
@@ -50,6 +62,8 @@ public interface I2PSocketOptions {
* either some data is removed or the connection is closed. If this is
* less than or equal to zero, there is no limit (warning: can eat ram)
*
* Default 64 KB
*
* @return buffer size limit, in bytes
*/
public int getMaxBufferSize();
@@ -60,6 +74,8 @@ public interface I2PSocketOptions {
* either some data is removed or the connection is closed. If this is
* less than or equal to zero, there is no limit (warning: can eat ram)
*
* Default 64 KB
*
* @param numBytes How much data will we accept that hasn't been written out yet.
*/
public void setMaxBufferSize(int numBytes);
@@ -69,6 +85,9 @@ public interface I2PSocketOptions {
* for the data to flush. If this value is exceeded, the write() throws
* InterruptedIOException. If this is less than or equal to zero, there
* is no timeout.
*
* Default -1 (unlimited)
*
* @return wait time to block on the output stream while waiting for the data to flush.
*/
public long getWriteTimeout();
@@ -78,6 +97,9 @@ public interface I2PSocketOptions {
* for the data to flush. If this value is exceeded, the write() throws
* InterruptedIOException. If this is less than or equal to zero, there
* is no timeout.
*
* Default -1 (unlimited)
*
* @param ms wait time to block on the output stream while waiting for the data to flush.
*/
public void setWriteTimeout(long ms);

View File

@@ -96,6 +96,9 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
/**
* How long we will wait for the ACK from a SYN, in milliseconds.
*
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
* and it also interprets <= 0 as default.
*
* @return milliseconds to wait, or -1 if we will wait indefinitely
*/
public long getConnectTimeout() {
@@ -105,6 +108,9 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
/**
* Define how long we will wait for the ACK from a SYN, in milliseconds.
*
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
* and it also interprets <= 0 as default.
*
*/
public void setConnectTimeout(long ms) {
_connectTimeout = ms;
@@ -114,6 +120,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
* What is the longest we'll block on the input stream while waiting
* for more data. If this value is exceeded, the read() throws
* InterruptedIOException
*
* WARNING: Default -1 (unlimited), which is probably not what you want.
*/
public long getReadTimeout() {
return _readTimeout;
@@ -123,6 +131,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
* What is the longest we'll block on the input stream while waiting
* for more data. If this value is exceeded, the read() throws
* InterruptedIOException
*
* WARNING: Default -1 (unlimited), which is probably not what you want.
*/
public void setReadTimeout(long ms) {
_readTimeout = ms;
@@ -134,6 +144,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
* either some data is removed or the connection is closed. If this is
* less than or equal to zero, there is no limit (warning: can eat ram)
*
* Default 64 KB
*
* @return buffer size limit, in bytes
*/
public int getMaxBufferSize() {
@@ -146,6 +158,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
* either some data is removed or the connection is closed. If this is
* less than or equal to zero, there is no limit (warning: can eat ram)
*
* Default 64 KB
*
*/
public void setMaxBufferSize(int numBytes) {
_maxBufferSize = numBytes;
@@ -156,6 +170,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
* for the data to flush. If this value is exceeded, the write() throws
* InterruptedIOException. If this is less than or equal to zero, there
* is no timeout.
*
* Default -1 (unlimited)
*/
public long getWriteTimeout() {
return _writeTimeout;
@@ -166,6 +182,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
* for the data to flush. If this value is exceeded, the write() throws
* InterruptedIOException. If this is less than or equal to zero, there
* is no timeout.
*
* Default -1 (unlimited)
*/
public void setWriteTimeout(long ms) {
_writeTimeout = ms;

View File

@@ -44,6 +44,7 @@ fi
# list specific files in core/ and router/ here, so we don't scan the whole tree
ROUTERFILES="\
../../../core/java/src/net/i2p/data/DataHelper.java \
../../../core/java/src/net/i2p/util/LogWriter.java \
../../../router/java/src/net/i2p/router/tasks/CoalesceStatsEvent.java \
../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \
../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \

View File

@@ -12,7 +12,8 @@ public class CSSHelper extends HelperBase {
private static final Map<String, Boolean> _UACache = new ConcurrentHashMap();
public CSSHelper() {}
public static final String PROP_UNIVERSAL_THEMING = "routerconsole.universal.theme";
public static final String PROP_THEME_NAME = "routerconsole.theme";
public static final String DEFAULT_THEME = "light";
public static final String BASE_THEME_PATH = "/themes/console/";

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