Compare commits

...

730 Commits

Author SHA1 Message Date
idk
1c67f06ffc Since service installs always have an i2p.dir.config set, they don't need to have a default in WorkingDir.java around line 110. However, since user installs do not have an i2p.dir.config set, at around line 80-110 we have to determine whether to use the legacy config in AppData/Roaming or the new default in AppData/Local. Use programdata environment variable becaue it is consistent with the actual path that we should be using. 2022-09-16 14:06:41 -04:00
idk
0ce816acd1 change path validation for service installs when install location contains system32 2022-09-13 11:06:43 -04:00
idk
2fd01c8390 add correct programdata path to default eepsite 2022-09-10 11:16:35 -04:00
idk
16eb1577f9 remove extraneous logging 2022-09-10 11:12:19 -04:00
idk
ecd58a833c If default computed path contains %programdata% or system32 we're running as a daemon on Windows, and %programdata%/Application Data/ does not exist anymore(since ~Win7?). Don't append /Application Data/ in default, command, or shortcut, that should all go directly into %programdata%/i2p now 2022-09-10 10:26:06 -04:00
idk
b533ccaabd remove Application Data from path to I2P service config on Windows 2022-09-08 17:03:39 -04:00
zzz
0f560139f3 unused field 2022-09-07 10:11:39 -04:00
zzz
b610b7a695 Transports: Don't rekey noise params on testnet 2022-09-07 10:09:05 -04:00
zzz
26f882edd5 SSU: Fallback processing for MTU detection
take the minimum of all interfaces if specific interface not found
Update CLI to support address args for testing
2022-09-07 10:01:32 -04:00
idk
f00e020f2b Fix unexpanded styles on addressbook pages #365 2022-09-06 18:09:58 -04:00
idk
edd0dd0b0d fix padding on expanded elements in SusiDNS 2022-09-06 15:54:44 -04:00
idk
031fa45eb8 fix incorrect background color on expanding element in SusiDNS 2022-09-06 15:39:45 -04:00
zzz
a2eee5a673 NetDB: Fix reseeding when clock is skewed
reported, fixed, and tested by zlatinb
2022-09-06 11:56:33 -04:00
zzz
45c160f27a Data: Cache SSU2 string 2022-09-06 09:39:14 -04:00
zzz
7ba59b4338 SSU2: Don't publish or connect if our MTU becomes too small
after initial check in constructor
Don't rectify 1280 IPv4 MTU down to 1276
Add note about replay detector
2022-09-06 09:35:29 -04:00
zzz
554b17fe9a SusiDNS: Fix adding to empty address book
by doing form processing even if book is empty.
Do all form processing before displays so the
displays reflect any form add/delete.
Broken in 0.9.50 when form processing call was moved.
Hide replace and add alternate buttons if book is empty.
Ref: https://www.reddit.com/r/i2p/comments/wu7nac/how_do_i_add_to_the_private_address_book/
2022-09-04 08:14:19 -04:00
zzz
64632eed4a UPnP: Fix opening IPv6 ports 2022-09-03 12:01:59 -04:00
zzz
49299f3f28 NetDB: Query connected peers for their RI directly
Negative cache router hash when expiring RI
Log tweaks
2022-09-03 11:59:39 -04:00
zzz
00774590b0 SSU2: Fix ISE after sending retry for clock skew in session request
log tweaks
2022-09-01 12:21:33 -04:00
zzz
52b640b582 Router: Ensure database store message is processed before reply job (Gitlab #364)
by processing DSM inline in InNetMessagePool.
Caused random lookup failures of RI and LS.
Made worse by previous change removing duplicate store from reply job.
thanks obscuratus and drzed
2022-09-01 11:55:00 -04:00
zzz
911e69e3ae Emphasize checklist step to try Maven jars build before release
to not break Android build
ref: Gitlab MR !64
2022-08-31 07:56:13 -04:00
zzz
d809d6653d SSU2: Implement ack-immediate flag
Use a single ack timer for each session rather than
creating a new one for every ack
Log tweaks
2022-08-29 16:47:19 -04:00
idk
8df81fc0a1 Merge branch '1.9.0-java7-classpath-fix' into 'master'
explicitly set types of some objects so that the code can be compiled with a Java 7 bootclasspth

See merge request i2p-hackers/i2p.i2p!64
2022-08-29 15:45:55 +00:00
zzz
ed76829562 Console: Don't lookup RI if banned 2022-08-28 15:28:17 -04:00
zzz
4f4044c3f0 Console: Add notification and summary bar info on deadlock
Check for deadlock more frequently
2022-08-28 15:24:34 -04:00
zzz
3a4bfc9c07 Util: Add option to gzip router logs
Primarily for devs. No UI.
remove shutdown hook ID
2022-08-28 15:07:30 -04:00
zzz
b25c207e9a Console: Linkify router hash even if not in netdb
as the console will do the lookup if not
2022-08-28 11:22:31 -04:00
idk
fcae43547b explicitly set types of some objects so that the code can be compiled with a Java 7 bootclasspth 2022-08-27 19:26:03 -04:00
zzz
b34b0cc399 SSU2: Fix packets exceeding MTU by up to 3 bytes 2022-08-25 10:58:14 -04:00
zzz
f4875d12fa SSU2: Immediately fail session request containing zero token
i2pd will send this after retry with zero token and termination
2022-08-25 10:56:34 -04:00
zzz
2f06e9bebf SSU2: Implement path challenge and connection migration
mark session dead after receiving destroy
log tweaks
2022-08-25 08:57:02 -04:00
zzz
9b6dde008d Router: Hopefully fix deadlock via rebuildRouterAddress() and UDPTransport 2022-08-25 08:46:25 -04:00
zzz
6ddaa72a86 Add deadlocks to event log 2022-08-23 13:01:32 -04:00
zzz
d064de1913 Debian files for 1.9.0 2022-08-23 11:36:06 -04:00
zzz
97013f8874 blocklist update 2022-08-22 15:15:20 -04:00
zzz
39954032d2 1.9.0 2022-08-22 10:16:29 -04:00
zzz
44f0acead5 Refresh debian patches 2022-08-21 07:28:57 -04:00
zzz
6d024b49a9 Fix encoding of getopt translations az and es_AR 2022-08-21 06:36:20 -04:00
zzz
8a379d5394 Pull translations from Transifex 2022-08-19 12:54:48 -04:00
zzz
972adde7eb Router: Add SSU2 keys to the killKeys() list 2022-08-16 18:13:02 -04:00
zzz
f3dd06ad1e Bump build time 2022-08-13 13:32:26 -04:00
zzz
55603782bb New translation: Spanish (Argentina) 2022-08-13 13:31:53 -04:00
zzz
3d65f93277 i2psnark: CSS fix for disabled edit torrent button 2022-08-12 09:42:22 -04:00
zzz
e35d173982 SSU2: Enable for Android, ARM, and 2% of others 2022-08-10 08:11:11 -04:00
zzz
ec6e9b1bfb Router: Hopefully fix clock/job queue deadlock after clock shift
ref: i2p.i2p/-#6
2022-08-06 11:00:09 -04:00
zzz
ca6046f821 GeoIP 2022-08 2022-08-06 10:57:36 -04:00
zzz
c81b4645a8 SSU: Try to keep a mix of v1/v2 introducers 2022-08-05 10:51:08 -04:00
zzz
0687ef8364 SSU2: Block bob's IP in relay response from charlie
(i2pd bug, fixed today)
2022-08-04 17:33:31 -04:00
zzz
8d149136fe SSU2: Remove unused ECN variable
Add RTTdev to logging
2022-08-04 08:40:18 -04:00
zzz
2a83c8f6ee i2ptunnel: New outproxy (new installs only) 2022-08-04 05:58:30 -04:00
zzz
689016f48e SSU2: Pass source ip/port to path challenge/response callbacks
(more prep for connection migration)
2022-08-02 09:38:11 -04:00
zzz
146bbf67f8 SSU2: Add state lookup by conn ID
As fallback for failed lookup by RemoteHostId.
This will eventually be the primary lookup after most traffic is SSU2.
For now, only used to receive traffic from a peer that changed IP/port.
SSU 1/2 send destroy when replacing old session with new.
Prep for full SSU2 connection migration.
2022-07-31 11:34:55 -04:00
zzz
b606c2084b LogManager: Prevent hangs at shutdown on Mac after dock right-click-quit (Gitlab #363) 2022-07-29 12:23:34 -04:00
idk
c1efe6daab Merge pull request #27 from mehdie79/master
Fix errors in HACKING.md
2022-07-28 14:23:49 -04:00
zzz
4bdb7d752f SSU2: Send response to path challenge 2022-07-27 11:48:27 -04:00
zzz
6d9aca9d9b SSU2: Path challenge/response block types 2022-07-27 11:43:00 -04:00
zzz
e250531174 SSU2: Stub out path challenge/response 2022-07-27 10:56:18 -04:00
zzz
5948a7dec3 SSU: Only decrease MTU if the retransmitted packet was large 2022-07-27 10:30:56 -04:00
zzz
4e4718b3b1 NetDB: Publish ff stats based on current caps, not previous
Comment out unused contact property
2022-07-27 09:34:02 -04:00
zzz
d94ff6ad86 Router: Log warning if no family keys loaded 2022-07-27 09:16:01 -04:00
zzz
e4a8a6492d SSU2: Send termination in response to termination 2022-07-26 09:51:41 -04:00
zzz
17695915fa SSU2: Fix bitfield shifts of 256 or more 2022-07-25 13:17:56 -04:00
zzz
69adf84363 Console: Fix saving flat clients.config file
when in portable configuration and changing the
launch browser on startup setting on /configservice
ref: http://zzz.i2p/topics/3347
2022-07-21 09:19:25 -04:00
zzz
af8272b970 SSU: Reduce max establishment time 2022-07-19 12:08:26 -04:00
zzz
5355ee7740 SSU2: Shorten token expiration based on cache size 2022-07-19 11:55:59 -04:00
zzz
02cd83187b GeoIP: Don't lookup route48 addresses 2022-07-19 11:21:12 -04:00
zzz
f5ca15c28d SSU2: Retransmit session confirmed after receiving apparent retransmitted session created
Retransmit handshake messages faster and expire faster (SSU 1/2)
log tweaks
2022-07-19 11:17:54 -04:00
zzz
b7db6ae77c SSU2: Fix storage/checking of local firewalled IP address/port in token file 2022-07-19 11:15:24 -04:00
idk
4aa6ee2308 Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2022-07-17 15:34:48 -04:00
idk
21dc07bf5a add note about possible need for Java 17 options to startapp.sh 2022-07-17 15:34:25 -04:00
idk
4a6fe9b291 Merge branch 'docker_updates' into 'master'
Switch to OpenJDK17

See merge request i2p-hackers/i2p.i2p!61
2022-07-17 19:33:23 +00:00
zzz
8aef6ce292 SSU2: MTU and other fixes
Use minimum MTU for IPv6 session confirmed to avoid PMTU issues
Set default MTU for known IPv6 tunnel brokers
Check for s mismatch in session confirmed RI
Don't put DateTime block after Termination block
Fix first message failed check
Log sent data packet size
Log tweaks
2022-07-17 11:28:00 -04:00
c9cf208de7 Fix errors in HACKING.md 2022-07-17 01:45:55 -07:00
zzz
097fa34e91 SSU2: Send retry with termination block on clock skew 2022-07-15 15:03:22 -04:00
zzz
c2ffcb8512 SSU2: Don't rectify MTUs to mod 16 in SSU2 addresses
Set max MTU for range48.org brokered addresses
Limit MTU for brokered addresses in UDPAddress also
2022-07-15 08:51:43 -04:00
zzz
2432680ed3 SSU2: Fail session if first outbound message fails
Reduce max consecutive message failures to fail session (SSU 1/2)
Set peer as unreachable for these failures
Reduce max consectutive session confirmed retransmissions
Fix session confirmed retransmission timing
Respond to relay tag request in data phase
Log tweaks
2022-07-12 07:29:20 -04:00
zzz
8e985eb951 SSU2: Fix NACK handling when higher than previous highest acked
was treating them as acks
2022-07-10 13:01:56 -04:00
zzz
a18a5136b7 Console: Only display news if a new entry is found
not simply when a new file is downloaded
2022-07-09 09:41:13 -04:00
zzz
73c8ee826e SSU2: Support other reason codes in destroy message 2022-07-09 07:31:46 -04:00
zzz
2a4ab118de SSU2: Persist SSU2 tokens
Move establisher and packet handler initialization
to after the address initialization
2022-07-08 14:12:31 -04:00
zzz
70596d0548 SSU: Initialize MTUs
SSU2: Don't log MTU warning at startup
Remove unused dropPeerCapacities()
2022-07-08 11:13:58 -04:00
zzz
6ede06cfdf SSU2: Send termination before dropping session after failure to get Session Confirmed ack 2022-07-08 11:09:58 -04:00
zzz
8818c78cbd Transport: Don't lookup RI in wasUnreachable()
to reduce netdb lookups
2022-07-08 10:00:04 -04:00
zzz
9489b41cb7 Util: Fix UnmodifiableSortedSet compiler warnings 2022-07-05 12:02:28 -04:00
zzz
9a9722dd3e SSU2: Fix peer test throttling
Only throttle messages 1 and 2
Send limit response on throttle
Throttle IPv6 based on first 8 bytes only
2022-07-05 07:37:51 -04:00
zzz
ec3a88dc34 Console: Add cancel button to netdb search form 2022-07-04 08:32:16 -04:00
zzz
4e21fe74e5 NetDB: Lookup handling cleanups
Allow lookups of our RI even when hidden
Consolidate routerHash() calls
Remove unused router.publishUnreachableRouters option, was default true
2022-07-04 08:30:21 -04:00
9dc8ca4edb Merge branch 'jbigi-apple-silicon' into 'master'
jbigi for Apple silicon

See merge request i2p-hackers/i2p.i2p!63
2022-07-03 12:46:31 +00:00
efc3b847ac jbigi for Apple silicon 2022-07-03 13:43:29 +01:00
3701cf9782 Merge branch 'gmp-patch-x18' into 'master'
Add ability to apply patches to GMP.  Apply fix for x18 register.  Run GMP tests after build.

See merge request i2p-hackers/i2p.i2p!62
2022-07-03 11:48:36 +00:00
a171d71bbe Add ability to apply patches to GMP. Apply fix for x18 register. Run GMP tests after build. 2022-07-03 11:09:01 +01:00
a6ef362ad7 Switch to OpenJDK17 2022-07-02 16:31:35 +00:00
c2f3732469 Merge branch 'jbigi-mac-arm64' into 'master'
JBigi build changes for M1

See merge request i2p-hackers/i2p.i2p!60
2022-07-02 13:11:54 +00:00
454cd6bda6 JavaVM framework isn't a thing anymore 2022-07-02 13:22:28 +01:00
zzz
740c7fad4d SSU: Remove copy of peers in idle timeout checker
Just iterate through the main map.
Log tweaks
2022-06-30 18:22:53 -04:00
zzz
c875f1d105 SSU2: Fix last check of local RI for relay
Expire relay token quickly
Log tweaks
2022-06-30 17:15:33 -04:00
idk
43945dcbbf fix dark them address book css. closes #343 2022-06-26 12:28:03 -04:00
zzz
3c7659277d SSU: MTU fixes for IPv6 and SSU2
Fix setting local IPv6 MTU when firewalled
Fix publishing MTU when firewalled or hidden
Save local MTU when changing addresses, not when publishing
Add SSU2 MTU methods (no mod 16 required)
Allow MTU up to 1500 for SSU2 transport style
Disable SSU2 at startup if local MTU too low
2022-06-25 13:14:59 -04:00
zzz
26cffabf86 Build: Update GMP download script to 6.2.1 2022-06-25 08:33:32 -04:00
zzz
897338b790 SSU2: Add checks of peer test msg 1 IP/port 2022-06-24 16:56:47 -04:00
zzz
ac3fc6a0d8 JBigI: Drop 32-bit OSX libs 2022-06-23 12:29:46 -04:00
zzz
20acd7cf61 Debian: Update apparmor profile
see gitlab MR !59
2022-06-23 09:20:35 -04:00
zzz
08e95655c1 SSU2: More MTU checks
Add code for bob rejecting alice peer test address
Don't allow MTU to exceed his MTU
Don't use a token about to expire
Send token with termination message
Add internal type to termination message
log tweaks
2022-06-22 11:00:56 -04:00
zzz
5d27ce3f8d SSU: Rewrite adjustMTU()
to make it more responsive to conditions and a more effective PMTU algorithm.
Move MTU up and down in increments rather than simply shift between min and max
Increase or decrease based on success or failure of each message
Only increase if the successful message was almost as large as current MTU
Clear increase/decrease counters when changing MTU the other way
Don't wait for 10 packets to increase MTU
Reduce max retransmissions from 30% to 10%
2022-06-22 08:07:13 -04:00
zzz
1e95c123e5 Console: Fix SSU TX/RX sorters on /peers 2022-06-21 12:41:47 -04:00
zzz
a6536ea48a Crypto: Fix equality checking of ECParameterSpecs for private keys too
see earlier checkin for public keys
2022-06-21 09:43:16 -04:00
zzz
9aa9f7a714 SSU2: Fix swapped dest/src conn IDs for peer test 2022-06-20 15:19:09 -04:00
zzz
723257d6ef SSU2: First fragments can be 5 bytes larger than followon fragments 2022-06-20 12:05:45 -04:00
zzz
c5323a8d36 SSU2: Fix overhead calculation for followon fragments
so as not to exceed MTU
2022-06-20 07:37:05 -04:00
zzz
67082463e4 Util: HostTxtParser CLI improvements 2022-06-19 12:07:23 -04:00
zzz
b3072d9ef3 SSU: PeerState _remotePeer cannot be null 2022-06-19 12:05:39 -04:00
zzz
3c4956f0c3 SSU2: Add delayed lookup of RI for relay and peer test
Prefer SSU2 introducers for slots 1 and 2
log tweaks
2022-06-19 12:04:10 -04:00
zzz
d69a65605d SSU2: Don't delete empty ipv6 address at startup
Needed for SSU2 handshakes
2022-06-19 12:01:44 -04:00
zzz
2bf7d5ddea Util: New UnmodifiableSortedSet based on ArraySet
use in OrderedProperties
2022-06-17 13:07:22 -04:00
zzz
c2edd7e926 SusiDNS: Fix classloading on Java 11+
Caused SusiDNS and addressbook to be in a different context
addressbook config would be stored in base dir
and subscriptions would not load because it couldn't find i2ptunnel
2022-06-17 12:52:36 -04:00
zzz
ed1e705d35 Crypto: Fix equality checking of ECParameterSpecs
in SigUtil.fromJavaKey()
as the class does not define equals().
Affects Android family key loading where the class does not match our class.
Tested via unit test to compare provider class sun.security.util.NamedCurve
to our class java.security.spec.ECParameterSpec, untested on Android.
Add conversion test to CertUtil loadcert CLI.
ref: http://zzz.i2p/topics/3328
ref: i2p.android.base gitlab ticket #47
2022-06-17 10:34:34 -04:00
zzz
fa145ff7c5 Util: ArraySet improvements
Was never used; prep for actual usage
Move from router to core
Add Set constructors that are more efficient
Add addUnique() method
Allow size of set passed in constructors
Prepare for extension
javadocs
2022-06-17 10:21:15 -04:00
zzz
7610b3842f SSU2: Hole punch processing
Validate and process hole punch payload
Send session request immediately after receiving hole punch
Remove some unused code
Log tweaks
2022-06-16 08:22:55 -04:00
zzz
d812f82e92 SSU2: Fixes
Fix conn ids on hole punch
Fix min size on relay response
2022-06-16 08:16:12 -04:00
zzz
0a87559ba2 SSU2: Add per-introducer relay state machine
Enable relay
Set session created token to 0 as per spec
Log tweaks
2022-06-14 12:48:00 -04:00
zzz
c248279a03 Console: Minor fix for dark theme /logs version section 2022-06-13 07:11:31 -04:00
zzz
22efde37e3 SSU2: Relay WIP part 15
Fix sending charlie's address in relay response
Fix sending session request after introduction
Send 0-length endpoint in relay response on failure
Log tweaks
2022-06-12 16:08:23 -04:00
zzz
c976b86b6e SSU2: Fix peer test msg 1 signature 2022-06-12 13:20:37 -04:00
zzz
3ef06f88c9 SSU2: Relay WIP part 14
Fixes after testnet testing:
Fix NPE in OES2 constructor
Fix relay request signature
Fix relay response signature verification bugs
Fix unhandled state OB_STATE_INTRODUCED
Refactor state handling to switch
Remove dup copy in SSU2Util.sign()
Log tweaks
2022-06-12 12:54:52 -04:00
zzz
2ec0894c35 SSU2: Relay WIP part 13
Reject SSU1/SSU2 relay request mismatch as Bob
2022-06-11 13:06:29 -04:00
zzz
d85d501291 SSU2: Relay WIP part 12
Don't send SSU1 relay request to SSU2-connected introducers
and vice versa
Log tweaks
2022-06-11 09:13:36 -04:00
zzz
e4996a2db6 SSU: No need to validate Bob IP/port on relay intro as Charlie
as it is received in-session only
Log tweaks all over
2022-06-10 16:50:46 -04:00
zzz
ffc4520382 Transport: Remove mtn port from invalid list 2022-06-10 16:03:48 -04:00
zzz
386b259666 SSU: Reduce level of SSU 1 relay logging
to make it easier to debug SSU2 relay
2022-06-10 15:09:23 -04:00
idk
ee5e3a97ed Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2022-06-10 13:39:54 -04:00
idk
a70c988a07 Automatically configure clients and client tunnels to listen on the container network address instead of the localhost. Closes #358 2022-06-10 13:39:27 -04:00
zzz
788babeaa0 SSU2: Relay WIP part 11
prevent dup SSU2 introducers take 2
2022-06-10 13:29:42 -04:00
zzz
3befe90007 i2ptunnel: Add tunnel name to offline expiration log messages 2022-06-10 09:53:55 -04:00
zzz
bfdf75f45b SSU2: Fix test/relay response code for banned IP 2022-06-10 09:08:08 -04:00
zzz
9de618d644 SSU2: Catch errors on bad ack blocks
so rest of payload can be processed
Improve debug output on errors
2022-06-10 07:50:43 -04:00
zzz
cdf778514c SSU2: Don't attempt SSU1 fallback validation on a SSU2 peer
This should actually fix the HMAC NPE
2022-06-10 07:35:53 -04:00
zzz
03f315fc1c SSU2: Relay WIP part 10
Fix OES2 initial state when pending intro
Handle relay response as Alice
Check relay request and relay response sigs as Bob
Remove unused method OES2.reset()
Fix javadoc for one OES state
2022-06-10 07:32:54 -04:00
zzz
379227592c hosts.txt update 2022-06-09 15:08:01 -04:00
zzz
3d9ded4ab1 SSU2: Relay WIP part 9
Alice side:
check for valid v2 introducers,
fetch Bob RIs if not found,
connect if not connected,
then send relay request
2022-06-09 12:24:29 -04:00
zzz
29c827c076 SSU2: Ignore dup session confirmed 2022-06-09 11:54:52 -04:00
zzz
5582814d7c Noise: Add state info to debug output 2022-06-09 09:49:06 -04:00
zzz
43a5998cfd SSU2: Set timer to remove peer test state
Reduce SSU 1/2 max test time as Bob
2022-06-08 11:31:42 -04:00
zzz
d1633938db NetDb: Bypass checks on lookups of our router hash 2022-06-08 11:04:33 -04:00
zzz
5129665256 SSU: Request RI from introducer if we don't have it 2022-06-08 10:58:16 -04:00
zzz
0d51b2d25f Transport: Don't requeue message after multiple failures
Change failed transports from a Set to a List for efficiency
Check fail count before getting bids
Don't remove from netdb after a failure
Other minor tweaks
2022-06-07 14:22:27 -04:00
zzz
ba7b154a09 SSU: Ban IP on bad handshake signature 2022-06-07 14:15:00 -04:00
zzz
52bb2aea94 SSU2: Peer test fixes
per spec, Alice hash not included in msg 1/2 sig
Add sig checks of msgs 1/3 at Bob
Fix checking of 'B' cap in peer selection
2022-06-07 14:08:53 -04:00
zzz
265804a750 Console: Add deadlock detector 2022-06-06 17:01:15 -04:00
zzz
74795a83d6 SSU2: Relay WIP part 8
prevent dup SSU2 introducers
2022-06-06 16:25:30 -04:00
zzz
0fe437f649 SSU2: Check for missing address block in peer test msg 7 2022-06-06 16:24:19 -04:00
zzz
a2ec81eaec Util: Cache new SSU2 properties 2022-06-06 16:21:44 -04:00
zzz
df4be26878 SSU: Don't allow android to be introducers 2022-06-06 16:20:44 -04:00
zzz
06456fb318 SSU2: Peer test fix message 7
Put source address of msg 6 into address block for msg 7
Use msg 7 address block for received address
2022-06-06 11:41:31 -04:00
zzz
d9c932ac2e Compile fix previous checkin 2022-06-06 11:40:24 -04:00
zzz
d680cfd80c SSU2: Relay WIP part 7
Add SSU2 parameter support to UDPAddress
Count SSU2 introducers in UDPAddress
Fix reuse of SSU2 introducers
Don't immediately remove introducer for idle time
2022-06-06 11:07:45 -04:00
zzz
4a9f8240db SSU2: Relay WIP part 6
Fix saving relay tag as Bob
Select introducers by newest connection instead of random
Ping introducers more often
Check and set ping time when pinging introducers
Remove unused nextCipherKey
Debug: Prefer selecting SSU2 introducers
Log tweaks
2022-06-05 11:21:04 -04:00
zzz
266dc09384 Transports: Periodically send RI to connected peers (Gitlab ticket #356) 2022-06-03 08:15:01 -04:00
zzz
4dd5e7737b SSU: Make cipher/MAC keys final
Possible fix for HMAC NPE
2022-06-03 08:07:29 -04:00
zzz
af6722c57b SSU2: Relay WIP part 5
Publish SSU2 introducers
2022-06-02 11:39:30 -04:00
zzz
2ff0a13990 SSU2: Relay WIP part 4
Decrypt and handle hole punch as alice
2022-06-02 10:14:37 -04:00
zzz
cfdc2203fb SSU2: Relay WIP part 3
Put alice hash in relay intro as Bob
Fix relay intro/response generation and signing
Add token to relay response as Charlie
Store relay nonce as Bob
Handle relay response as Bob and forward to Alice
Stub out handling relay response as Alice
2022-06-02 08:43:50 -04:00
zzz
2c53424210 SSU2: Relay WIP part 2
Handle relay request as bob
Send relay intro as bob
Send relay response rejection as bob
Check for valid time in relay request and relay intro
2022-06-01 13:59:15 -04:00
zzz
8b0edde290 SSU2: Relay WIP part 1
Pass relay data from PS2 to Intro manager
Handle relay intro as charlie
Send hole punch as charlie
Send relay response as charlie
Update hole punch format to match spec
2022-06-01 13:12:35 -04:00
zzz
a4d3bf285d SSU2: Enable peer test 2022-06-01 09:01:50 -04:00
zzz
3acc4b754a SSLEepGet: Send Host header to HTTPS proxy
ref: RFC 2617 sec. 5.2
2022-05-30 10:39:38 -04:00
zzz
ef08dfad55 SSU2: Remove role field from peer test block
to match spec change
2022-05-29 10:18:19 -04:00
zzz
b9099fbd99 i2psnark: Fix scrollbar hiding X box on Firefox 100 2022-05-28 15:54:02 -04:00
zzz
c9a6950550 Crypto: Handle conversion from Java JCA 15+ EdEC keys
Change from unchecked to checked exception on unknown keys
2022-05-28 15:14:29 -04:00
zzz
80f76e38b4 i2psnark: Fix DHT not restarting after router restart
cancel DHT cleaner and explorer on stop
2022-05-28 13:00:32 -04:00
zzz
7ea3c430aa Util: FileLogWriter minor optimization 2022-05-28 12:32:39 -04:00
zzz
d467dc28b9 I2CP: Only send one notification to each session listener
for reportAbuse(), disconnected(), and errorOccurred(),
because a single listener may be registered for multiple ports/protocols
2022-05-28 12:02:52 -04:00
zzz
8ac78af293 Console: Require full restart on transport enable/disable
Don't do soft restart if full restart required
2022-05-28 11:58:02 -04:00
zzz
e44eeaf5ae Router: Don't fail to start up on unchecked family key errors 2022-05-28 10:53:25 -04:00
zzz
17cc514bb1 Console: Add TODOs for country variants of readme files
Clean up language selection code in ResourceHelper
2022-05-27 11:59:49 -04:00
zzz
86996dde28 UPnP: Don't bind HTTP listen sockets to all addresses at startup
The lib was binding to all addresses, and then our
UPnP.updateInterfaces() was closing most of them on first run.
Fix the lib to only bind to the non-public and non-deprecated ones,
using the same getLocalAddresses() method as in our code.
2022-05-27 11:18:48 -04:00
zzz
34789fdb30 Streaming: Improve error message on unsupported sig type
Fallback to Ed25519 on error
2022-05-27 09:29:49 -04:00
zzz
a74f36358f i2psnark standalone: Skip browser launch if so configured 2022-05-26 12:29:35 -04:00
zzz
a6ad525197 Addressbook: Add CLI 2022-05-26 11:57:34 -04:00
zzz
0826b1e228 Crypto: Throw checked exception
for unimplemented ElG import, so CertUtil.loadPrivateKey() will
continue processing and then
fail with the correct exception and error message on bad input.
Pull constant KeySpec out of loop.
2022-05-25 09:12:12 -04:00
zzz
5d3c29fb27 Debian files for 1.8.0 2022-05-24 12:29:31 -04:00
zzz
8256f61d56 1.8.0 / 0.9.54 2022-05-23 09:25:37 -04:00
zzz
ffc5ed8dc2 i2psnark standalone: Add hint to disable browser launch on windows 2022-05-23 09:10:48 -04:00
zzz
860eb22af7 refresh Debian patch 2022-05-23 08:47:56 -04:00
zzz
1a050303fa bump for review 2022-05-20 13:30:19 -04:00
idk
ce0c84c5d9 make SAMException class public so that it can easily be used by SAM implementers/embedders. Looks like it should have been public, all the constructors are public but the public keyword is missing on the class itself. Make tabs and spacing consistent in that file. 2022-05-19 14:37:17 -04:00
zzz
b537bd18b0 bump -20-rc 2022-05-19 13:40:25 -04:00
zzz
de79f52c81 New zh_TW translations 2022-05-19 13:35:28 -04:00
zzz
a5bc80da09 i2ptunnel: Improve message on filter file error 2022-05-19 13:15:16 -04:00
zzz
5f4ad87d10 Bump build time 2022-05-19 13:13:16 -04:00
zzz
cc56c4b506 Rebuild updated man page translations 2022-05-19 13:12:39 -04:00
zzz
13efc59916 Pull translations from Transifex 2022-05-19 13:10:57 -04:00
zzz
515a9b8d0d i2psnark: Fix 'left' amount in announce exceeding size
and causing tracker error on initial announce
2022-05-17 09:51:34 -04:00
zzz
52958b95d5 i2ptunnel: Add log message on reconnect 2022-05-14 08:58:58 -04:00
zzz
b36ed7de1a SSU2: Method scope 2022-05-14 08:52:15 -04:00
zzz
693aefe83a javadoc 2022-05-14 08:50:37 -04:00
zzz
ed30da0f0f NetDB: Remove dup now() calls 2022-05-14 08:48:13 -04:00
zzz
81255e19ae Transport: Fix thrashing of UPnP IPv6 listen sockets
Strip % suffixes from addresses before comparing
Fix HTTPMUSocket.getLocalAddress() to return the correct bound address
Throw exception on multicast socket bind failures, don't attempt
further operations on failed sockets
Add toString() to sockets for debugging
Log tweaks
2022-05-11 11:54:25 -04:00
zzz
07dbab9f02 Util: Rename modified apache classes (Gitlab ticket #353)
to avoid conflict in applications linking to apache jars
As requested by 'mesh' project
Remove with-libhttpclient-java build option
No known external uses other than obsolete i2pcontrol plugin
2022-05-11 07:54:56 -04:00
zzz
bf27bf140d poupdate-source 2022-05-10 12:41:09 -04:00
idk
3a906a6ce5 Merge branch 'sam-secure-session' into 'master'
Interactive SAM Authentication Interface

See merge request i2p-hackers/i2p.i2p!58
2022-05-07 16:36:39 +00:00
idk
47e02f7930 Interactive SAM Authentication Interface 2022-05-07 16:36:38 +00:00
zzz
75b808fcf6 DoH Server list update 2022-05-06 08:50:13 -04:00
zzz
5cbdb7d806 Tomcat 9.0.62 2022-05-02 11:31:45 -04:00
zzz
2c8428d85e GeoIP 2022-05-01 2022-05-02 10:15:06 -04:00
zzz
8fe9d7ac06 SSU2 minor updates
Send ack for peer test and relay blocks
Add SSU2 pending inbound states to establisher check
Remove unused PacketBuilder2 method
2022-04-30 11:44:52 -04:00
zzz
db8a843e82 SSU: Enforce peer test message 4 in-session
for routers 0.9.52 or higher
2022-04-29 09:41:10 -04:00
zzz
a730c1acea SSU2: Handle RI block in Data and Peer Test messages
Don't process out-of-session Peer Test message unless enabled
2022-04-28 10:52:01 -04:00
zzz
d6aaf3ee3a NTCP: Don't flood RI block unless newer
Don't accept store of our RI in RI block
2022-04-28 10:49:13 -04:00
zzz
9e4063a161 NetDB: Don't flood RIs banlisted forever 2022-04-28 10:47:01 -04:00
zzz
008943f699 SSU2: Peer Test fixes part 6
Change size/ip/port fields to match changes in proposal 159
2022-04-27 08:30:22 -04:00
zzz
71a58cb1bf Crypto: Destroy ChaCha/Poly after one-time-use 2022-04-25 10:05:16 -04:00
zzz
4a6f6f8647 SSU2: Peer Test fixes part 5
Fix extraction of Charlie address after receiving message 4
for use in message 6
2022-04-25 07:38:48 -04:00
zzz
32bba60bed SSU2: Peer Test fixes part 4
Fix NPE sending message 6
2022-04-24 15:46:57 -04:00
zzz
0f3abf0c9e SSU: Publish empty IPv6 address when missing introducers 2022-04-24 10:23:33 -04:00
zzz
5c1b6ba703 SSU2: Add properties to address when missing introducers 2022-04-24 09:36:23 -04:00
zzz
5e6ec442a7 SSU2: Fix PacketPusher NPE 2022-04-24 09:35:00 -04:00
zzz
cdf5bec155 SSU2: Peer Test fixes part 3
Reject if alice/charlie already connected
Do not retransmit msg 1 after receiving msg 4
Log tweaks
2022-04-24 08:57:20 -04:00
zzz
281bf68098 SSU2: Peer Test fixes part 2
Don't send message 5 unless we sent accept in message 3
Fix packet length for messages 5-7
Pass messages 5-7 from PacketHandler to PeerTestManager
Decrypt and process messages 5-7
Handle messages 4 and 5 in either order
Don't set test complete after message 5
Build data block for message 6
Log tweaks
2022-04-23 15:57:00 -04:00
zzz
ce2b5639b5 SSU2: Peer Test fixes part 1
Store our IP/port in PeerState2
Send our IP/port in message 1
Fix signature validation of message 4
Check for 0 status in messages 1 and 2
Fail on nonzero status in message 4
Log tweaks
2022-04-23 12:13:03 -04:00
zzz
4c10b414c4 InNetMessagePool: Remove some low-level logging 2022-04-17 10:13:46 -04:00
zzz
4c15a0e1c4 i2psnark: Make PeerCoordinatorSet and ConnectionAcceptor final 2022-04-17 10:11:19 -04:00
zzz
203fbdaa9f Console: Usage formatting on /tunnels 2022-04-17 10:10:18 -04:00
zzz
9431b9cfdc i2psnark: Soft restart fixes part 5
Do not stop the ConnectionAcceptor after RouterRestartException,
delay and reconnect instead.
Fix restart() to actually restart after stopped.
2022-04-17 09:56:07 -04:00
zzz
2bec84dd88 Streaming: Soft restart fixes part 4
Do not clear the DisconnectListeners after notification
2022-04-17 09:51:30 -04:00
zzz
cf7efcada8 I2CP: Soft restart fixes part 3
Remove low-level I2CP reconnector
as it may result in duplicate destinations after
higher-level (i2ptunnel) or application-layer reconnections
Root cause identified by BiglyBT
Gitlab issue #350
2022-04-17 09:45:40 -04:00
zzz
dda25bf1ed Router: Restart fixes part 2
Don't set our RI loaded from disk if too old
Rekeying was prevented by previous checkin,
but this fixes root cause
2022-04-14 08:25:16 -04:00
zzz
04b1bdb453 Router: Soft restart fixes part 1
Reset uptime on soft restart
Don't rekey after failure to store our RI due to clock skew
Change comm system state during soft restart
Restarter log tweaks
2022-04-13 10:28:43 -04:00
zzz
e04d31eb04 Update: Log full path to update file 2022-04-12 09:33:06 -04:00
zzz
706ed2ced2 javadoc 2022-04-12 09:33:06 -04:00
zzz
bb7278c5f6 Transport: Remove unnecessary isEmpty() check 2022-04-12 09:33:06 -04:00
zzz
3edc235104 SSU2: Minor updates
send timeout code in termination
remove unused intro key block handling
log tweaks
2022-04-12 09:33:06 -04:00
zzz
806046df64 One more ihost to itag change, missed in earlier checkin 2022-04-12 09:33:06 -04:00
zzz
345c64ebaf Tunnels: Don't build client tunnels less than min length
even if we don't have enough peers
2022-04-12 09:33:05 -04:00
zzz
53eb6ba7e0 Console: Fix Sybil closest hash tabs 2022-04-12 09:33:05 -04:00
zzz
eaa526583d Transport: Fix UPnP deadlock 2022-04-12 09:33:05 -04:00
idk
c0b8fe94a8 fix margins on dark theme bandwidth config table and info div 2022-04-11 13:59:26 -04:00
idk
6e5049c1db remove remaining absolute tags from xhr's on wizard page 2022-04-11 13:56:11 -04:00
idk
949f619ecc fix margin on bandwidth configuration page, fix alignment on bandwidth configuration page, align informational text to language start 2022-04-11 13:35:13 -04:00
zzz
f7c3e06db5 I2CP: Fix external I2CP broken when session ID is 0
one chance in 64K, broken since 2005
don't revert previous attempted fix using synching,
that's still a good idea
2022-04-11 10:30:29 -04:00
idk
1a26e1789c remove the startup wizard images themselves from the source tree 2022-04-08 16:55:31 -04:00
idk
e40bbc9f18 Overhaul CSS n New Install Wizard in order to make it less dependent on absolute positioning. Remove confusing M-Lab measurement table since the meaningful results are already populated in the configuration table. Adjust postioning of some elements on the bandwidth config pages. remove the old images from both themes. 2022-04-08 16:53:36 -04:00
idk
ec72f3cdf6 disable high-contrast mode on browsers where it is possible 2022-04-07 22:36:09 -04:00
zzz
b19998c072 Console: Change sidebar netdb tooltip 2022-04-06 08:37:41 -04:00
zzz
66e1c94bee Console: Use full hash for links to RI
for efficient lookup and to prevent display of dup prefixes
2022-04-06 08:22:12 -04:00
zzz
0449589406 SSU2: Fix hashcode function to detect dup acks
Arrays.hashCode() interacted badly with it,
causing numerous false positives
2022-04-05 14:13:23 -04:00
zzz
cc85df19aa SSU2: Fragmented Session Confirmed
Revert related parts of "Prep for fragmented RI",
we are now fragmenting Session Confirmed instead.
Fragment and send multiple Session Confirmed packets if required
Reassemble Session Confirmed packets

Don't process ack block identical to previous received
Log tweaks
bump -12
2022-04-05 09:26:42 -04:00
zzz
8418bda5a5 Console: Add netdb search options for v1 or v2 only transports 2022-04-05 08:22:26 -04:00
zzz
75492514ca SSU: Fix packet-too-large check in UDPSender 2022-04-05 07:55:28 -04:00
zzz
e43810f182 SSU2: Don't send our RI after outbound handshake, it's in the handshake already 2022-04-05 07:49:43 -04:00
zzz
9d49dc7af7 SSU2: Fix NPE in PeerState.loadFrom() 2022-04-05 07:47:56 -04:00
zzz
680320dede SSU2: Add termination reason codes 2022-04-05 07:45:02 -04:00
zzz
b2d6a091d1 Add more family certs 2022-03-31 06:05:57 -04:00
zzz
5d22a2152a Data: Add cached X25519/Ed25519 key cert, now common 2022-03-28 08:30:36 -04:00
zzz
acbf849b44 Crypto: Micro-optimize AES encrypt loop 2022-03-28 08:08:22 -04:00
zzz
7cf9895908 Transport: Add util methods for AddressType
WIP, not hooked in
2022-03-28 06:38:18 -04:00
zzz
d41c39a4d0 Debian: Add Java 18 2022-03-28 06:24:08 -04:00
zzz
b1852c127b SSU2: Prep for fragmented RI (WIP)
Fix IES2 not being removed from pending after complete
Don't send DSM after handshake
Validate conn ID before pkt type for data pkts
More log tweaks

SSU: Increase min pending establish states limit (unless slow)
Reduce IB establish timeout to 15s
Log pending inbound establish states when limit exceeded
Log tweaks to add establish state lifetime
Bump -11
2022-03-27 12:36:12 -04:00
zzz
8c59c514b2 Router: Validate family sig at startup
when loaded from router.info, and discard if invalid or when family changed.
This fixes some routers out there with bad sigs.
Don't loop forever through LoadRouterInfoJob.
2022-03-27 08:21:22 -04:00
zzz
93493a6d15 Crypto: Add provider in CertUtil so we can load EdDSA certs
Check cert sigs when loading, and log warning on failure
2022-03-27 08:00:08 -04:00
zzz
03e5c6c13c Crypto: Add official EdDSA OIDs to provider 2022-03-26 13:05:28 -04:00
zzz
826bf3c24f SSU2: Hook in IMF Bloom filter to detect dups
Call messagePartiallyReceived() even for dups or expired messages
so an ack is generated.
2022-03-26 11:39:10 -04:00
zzz
68273cd256 SSU2: Reduce ack delay, see MR !57
See previous checkin for SSU 1.
This change dramatically reduces the measured RTT to get it much closer to the real RTT by reducing the ack delay.
With the ack delay dependent on the measured RTT, the measured RTT will increase.

Simulation results: For a denominator D in the ack delay calculation (currently 2) and a true RTT = TRTT:
For D <= about 2, measured RTT -> TRTT + 2 * TRTT/D For D >= about 4, measured RTT -> TRTT + TRTT/D

In other words, for D == 2, measured RTT -> 2 * TRTT. For a TRTT of 50, the measured RTT is 100.
D == 2 is too small. It's been like that since 2005.
Testnet results: measured RTT 80-90

This changes D to 6. measured RTT -> 6/5 * TRTT.
Simulation results: For a TRTT of 50, the measured RTT is 58.
Testnet results: measured RTT 60
2022-03-26 07:04:49 -04:00
zzz
e130f85a65 Merge branch 'ssuackdelay' into 'master'
SSU: Reduce ack delay to minimize addition to measured RTT

See merge request i2p-hackers/i2p.i2p!57
2022-03-26 10:53:49 +00:00
zzz
9385ce7080 Console: Prevent creating a family that another router is using 2022-03-25 08:47:19 -04:00
zzz
da190cc24f SSU2 cleanups
Remove padding and unknown block callbacks
Remove handshake state logging in IES2 now that i2pd works
2022-03-25 08:27:53 -04:00
zzz
2a6dc58659 SSU: Reduce ack delay to minimize addition to measured RTT 2022-03-25 05:59:33 -04:00
zzz
f4eda0551d Router: Change quick address check for introducers
from ihost0 to itag0, because SSU2 probably won't use ihost
2022-03-24 17:31:48 -04:00
zzz
0560b3221d SSU2: Flush tokens on ip/port change
both inbound and outbound
2022-03-24 05:21:58 -04:00
zzz
631a6dd2b2 I2CP: Synch fixes
Synch fields in the data messages both directions,
after one report of zero session ID in MessagePayloadMessage
to an external client on fast hardware with Java 18.
Add new constructors for efficiency.
Deprecated setters, unit tests not changed, TODO.
Should fix all the other messages also, TODO.
2022-03-23 07:25:01 -04:00
zzz
0154a87cbf SSU2: Refactor tokens
Store OB tokens by IP/port
Centralize token generation and expiration in Establishment Manager
Add methods to flush OB tokens on IP/port change
Log tweaks
Javadoc fix
2022-03-23 06:46:01 -04:00
zzz
4f8ad3b6cb Router family fixes
Don't overwrite an existing family keystore file
Don't allow starting a new family with an existing family keystore file
Don't add family to RI until we have restarted and have a keystore file
Don't fail a netdb store for no family sig
Don't ever fail our own netdb store for family errors, to avoid rekey/restart
2022-03-22 08:03:18 -04:00
zzz
458e980e2f bump -10, javadoc typo 2022-03-20 07:59:32 -04:00
zzz
e08d2f354a File missed in previous netdb checkin 2022-03-20 07:57:43 -04:00
zzz
037e6940a9 SSU2: More work on peer test
generate msgs 1,5-7
handle msgs 5-7
log tweaks
2022-03-20 07:53:41 -04:00
zzz
b3055feff6 NetDB: Remove duplicate store in FloodOnlyLookupMatchJob
which bypassed all the checks in HandleFloodfillDatabaseStoreMessageJob
Don't store an entry which is older
2022-03-20 07:45:33 -04:00
zzz
c520dcb0f6 NetDB: Refactor family validation
Return a result code from verify()
Load all known certs at startup rather than continually reloading them
Only give full verified status to known keys
Enforce signatures in netdb store when key is available
Show family verification status on /netdb
Export our cert to disk if missing
Add stormycloud family cert
Bypass /24 Sybil penalty
2022-03-20 07:41:49 -04:00
zzz
fc88d672c5 Console: Fix rare IAE on destination sort 2022-03-18 11:40:09 -04:00
zzz
c62884ef85 SSU2: Implement peer test state machine
msgs 5-7 still TODO
WIP, untested
2022-03-18 10:21:30 -04:00
zzz
d9c629a6b1 SSU2: Log tweaks 2022-03-17 16:45:16 -04:00
zzz
70b7d1204b SSU2: Still more prep for Peer Test (WIP) 2022-03-17 16:43:24 -04:00
zzz
a90bbc3554 SSU2: More prep for Peer Test (WIP) 2022-03-17 16:10:26 -04:00
zzz
c2ec6cdeff SSU2: Set _lastACKSend 2022-03-17 16:08:15 -04:00
zzz
f57abe84bd SSU: Peer Test refactor
to store Bob's PeerState directly in PeerTestState
prep for SSU2
2022-03-17 16:04:28 -04:00
zzz
a1ee8220bb SSU2: Relay and Peer Test WIP
Packet building, fix peer test block
Not hooked in
2022-03-17 10:48:10 -04:00
zzz
ce73b9e8da Console: Remove CSS for hidden text on /graph 2022-03-16 07:59:55 -04:00
zzz
e6c3c097b5 Console: Remove UTC text already hidden by CSS 2022-03-16 07:47:26 -04:00
zzz
8961009292 SSU2: Minor cleanups
Add min packet size constants and notes
Don't attempt to decrypt a packet as a new inbound session if too small
Remove unused payload[] in IES2, now decrypted in-place
Log level tweaks in Establisher
2022-03-16 07:28:22 -04:00
zzz
de27cb1a46 Util: Increase min log file size limit
Rotate the log before we hit the limit, not after
2022-03-16 07:22:00 -04:00
zzz
e8afbc5b92 Transport: Don't use HE addresses for GeoIP
Limit max MTU for HE addresses
2022-03-15 14:30:04 -04:00
zzz
587409daa7 SSU2: Compress large RIs in Session Confirmed
even if they would fit in the MTU uncompressed,
to save bandwidth and room for other blocks
2022-03-15 07:23:53 -04:00
zzz
af5019c8dd SSU2: Fixes part 11
Save data messages received before or immediately after session confirmed
by queueing them for processing after the PeerState2 is created.
The fragments for the first I2NP message from Alice to Bob are frequently lost,
this will hopefully fix it.
Not fully tested, needs wider network testing.
2022-03-15 07:20:23 -04:00
zzz
46bba0fe71 SSU2: Fixes part 10
Avoid relaying until it's implemented:
Don't use SSU2 for an SSU address with introducers (fixes NPE)
Don't connect to SSU2 address without host/port
Don't ask for relay tag
Log tweaks
2022-03-15 07:12:25 -04:00
zzz
049456493f SSU2: Stubs for relay and peer test (phase 2) 2022-03-13 12:42:13 -04:00
zzz
2f63762c80 SSU2: Fixes part 9
Fix length calculation to see if new token block will fit in session confirmed
Extend timeout after sending retry
Fix retx timer for sess req after sending token req
Remove dup call to confirmedPacketsSent()
Cancel ack timer when sending acks
Include intro key in firewalled addresses too
Use SSU2 version of ping packet for SSU2 peers
Reduce max padding
Log tweaks
2022-03-13 07:33:36 -04:00
zzz
ca0d9f5a26 Tunnels: Reduce build reply timeout 2022-03-12 11:37:29 -05:00
zzz
aa620f5ed3 SSU2: Fixes part 8
Fix packet length for retransmitted handshake messages
Expire pending acks
2022-03-12 11:08:20 -05:00
zzz
15bb157126 NTCP: Encrypt handshake options in-place
round timestamp in Session Created
2022-03-12 09:48:33 -05:00
zzz
7e3e42ce42 i2psnark standalone: Add DTG and notifications 2022-03-11 07:23:46 -05:00
zzz
981c5e3878 i2psnark: Don't js-reload CSS on first click 2022-03-11 07:13:09 -05:00
zzz
393ee71ad9 SSU2: Fixes part 7
Clean up and optimize ack handling
Log tweaks and javadocs
2022-03-10 10:27:19 -05:00
zzz
97736cef1c SSU2: Fixes part 6
MTU and related fixes:
Fix max fragment size
Fix max space for acks
Fix max packet size
Pull MTU from best address in Session Confirmed
Pass MTU from establish state to peer state
Use SSU2 min/default/max MTU in PeerState
Stop looping when out of space in OMF (SSU 1 too)
2022-03-09 13:53:16 -05:00
zzz
25af51faf9 SSU2: Fixes part 5
Correctly calculate skew after retry in establish state
Pass calculated skew from establish state to peer state
Round time in DateTime block
Periodically send DateTime block
Handle DateTime block in peer state
2022-03-09 07:04:31 -05:00
zzz
a717dfb923 DTG: Add new ExternalMain class for app context use
that does not require router.jar
and rework other classes as necessary
2022-03-09 05:21:58 -05:00
zzz
e594b9532c SSU2: Track dup packets received
Log tweaks
2022-03-09 04:37:36 -05:00
zzz
a7a5b06b5c I2NP: Fix TunnelGatewayMessage.calculateWrittenLength()
so it doesn't null out the contained message.
Required for SSU2.
Unrelated TunnelDispatcher cleanup done while trying to find the problem.
2022-03-08 05:39:47 -05:00
zzz
eb72e97c03 SSU2: Fixes part 4
Fix deadlock in AckTimer
Enforce token in IES2
Increase bitfield sizes in PS2
Log tweaks
2022-03-07 10:44:17 -05:00
zzz
25cdc988e1 SSU2: Fixes part 3
Handle acks
Set ack timer
Retransmit session confirmed
Fix bitfield constructor when no ranges
2022-03-07 09:55:10 -05:00
zzz
3ce669575f SSU2: Fixes part 2
Add method to put additional blocks in data messages
Send and handle termination blocks
2022-03-06 07:31:16 -05:00
zzz
63aa64f8bb Console: Improve class selection on /configlogging 2022-03-06 06:16:59 -05:00
zzz
a6f61d2bf6 SSU2: Fixes part 1
after initial testnet testing

Use correct intro key for Session/Token request
Fix state management in EstablishmentManager, OES2, IES2
Fix next send time during handshake
Fix header decryption in PacketHandler
Add additional packet checks in IES2 handling
Remove expired IES immediately (SSU1 also)
Failsafe sleep in EstablishmentManager on exception
Remove dup requestSent() calls
Don't release packet in PS2
Log tweaks and javadocs
2022-03-06 06:15:23 -05:00
zzz
9457271ce6 Transport: Fix wasUnreachable() for transports with alt style
Only affects NTCP for now.
This bug had little impact when both transports were enabled,
but significantly harmed connectivity and tunnel building for NTCP2-only.
Decrease unreachable cache time in testnet
Make cache cleaner a little more efficient
2022-03-04 09:17:26 -05:00
zzz
22512d3889 i2psnark standalone: Add more CLI messages
Increase memory
2022-03-04 07:15:16 -05:00
zzz
a7115263f0 i2psnark: Reduce log level 2022-03-04 05:57:27 -05:00
zzz
c4b167b845 i2psnark: Fix css icon link 2022-03-04 05:52:44 -05:00
zzz
5e09245234 i2psnark: Add js theme preview 2022-03-04 05:47:18 -05:00
zzz
fee38c1c32 Console: Add SSU version column to /peers 2022-03-04 05:36:18 -05:00
zzz
a1ced67bad Transport: Fix port selection for NTCP-only 2022-03-04 05:06:01 -05:00
zzz
87f7d470a6 bump -3 2022-03-03 13:38:37 -05:00
zzz
32d60858da NTCP: Start out reachable if SSU disabled
So peers will attempt to connect
2022-03-03 13:37:28 -05:00
zzz
be4ad7eba9 NetDB: Load reseed RI if newer than that in-memory
previously, was only loaded if not known at all
2022-03-03 13:11:08 -05:00
zzz
7f8fa825ac SSU2: More debug logging additions/fixes 2022-03-02 11:08:57 -05:00
zzz
1cd5926f6c SSU2: Debug logging additions/fixes 2022-03-02 11:04:19 -05:00
zzz
9c31be66e6 SSU2: Data phase updates
Send immediate ack of Session Confirmed
Process I2NP messages and fragments in Session Confirmed
2022-03-02 10:47:47 -05:00
zzz
0e89b07ae8 SSU2: Data phase fix
Fix initialization of IMS when receiving last fragment first
2022-03-02 09:37:10 -05:00
zzz
7b6e6270ba SSU2: Data phase more fixes
Fix writing follow-on fragment block
Call messageFullyReceived() for I2NP block
Override messageFullyReceived() to avoid NPE
2022-03-02 09:05:09 -05:00
zzz
9d9310a726 SSU2: Data phase fixes
Fix receiver CipherState key
Override clearWantedACKSendSince() to avoid NPE
Add/tweak debug logging
2022-03-02 08:32:22 -05:00
zzz
0f26baf114 SSU2: Implement split()
Use socket address in PacketBuilder2
Decrypt session confirmed in-place
Check for RI in session confirmed
Copy session confirmed to PeerState2 for retx
RTT calculation fixes
State transitions
Javadoc fixes
WIP, untested
2022-03-01 13:52:16 -05:00
zzz
5ef93f11a9 Util: Add Addresses.getConnectedAddressTypes()
method to efficiently get all types in one pass
2022-03-01 07:25:49 -05:00
zzz
ce53714ba1 Util: Add AddressType enum 2022-03-01 05:48:20 -05:00
zzz
50ce3c2856 NetDB: New reseeds 2022-03-01 05:15:49 -05:00
zzz
21c1f89249 SSU2: Validate DateTime block in handshake messages 2022-02-28 16:50:41 -05:00
zzz
46ef49f2cf SSU2: Token Req. and Retry fixes
Fix Token Request and Retry payload generation
Implement Token Request and Retry payload decryption
Decrypt payloads in-place
Change from numbers to constants
2022-02-28 16:24:59 -05:00
zzz
e53a59b4ac SSU2: fix PS2 packet numbering 2022-02-28 13:36:19 -05:00
zzz
a13f2b9768 SSU2 more fixes
Fix OES2 MTU
Fix Token Request header encryption
2022-02-28 12:32:36 -05:00
zzz
44c30e78fc SSU2 fixes
Fix NPE in PS2
Fix Token Request message type
2022-02-28 10:01:05 -05:00
zzz
ec63f41b27 SSU2: Handle handshake messages
Decrypt handshake headers in Packet Handler
Pass handshake messages to Establishment Manager
SSU 1 and 2: Pass establish state to Establishment Manager
so it doesn't have to look it up again
Add notes about causes of decrypt failures
WIP, untested
2022-02-28 09:18:06 -05:00
zzz
c19944384e SSU2: Fix packet numbering to match spec 2022-02-27 14:50:13 -05:00
zzz
0c08a05bce SSU2: Hook in new classes to EstablishmentManager
Implement handshake retransmissions
Fix up calls to IES2/OES2
split() TODO
not hooked in to PacketHandler yet
WIP, untested
2022-02-27 12:03:28 -05:00
zzz
7eda9c77af SSU: Don't use SSU2 for peer test or relay
Add getAltStyle() so getTargetAddresses() will return SSU2
Add getSSUVersion()
2022-02-27 06:38:43 -05:00
zzz
66045cebc2 SSU2: Store RI in IES2 2022-02-27 05:41:48 -05:00
zzz
2b93dbbf48 SSU2: Add token support to EstablishmentManager 2022-02-27 05:26:04 -05:00
zzz
759f6968f6 Add SSU2 support to OMF 2022-02-26 17:15:07 -05:00
zzz
e3db28542c SSU2: Fix overhead calculations 2022-02-26 16:33:35 -05:00
zzz
e7f98e9243 SSU2: Add acks to data messages
implement buildPing() and buildACK()
2022-02-26 15:39:50 -05:00
zzz
4908f760d9 SSU2: PeerState2 I2NP handling
Handle complete messages and fragments in PeerState2
Send complete messages to transport
Add SSU2 constructor and reader in IMS
Change fragment callback to avoid an extra copy
Fix checks of fragment blocks
MessageReader cleanups for SSU1
Other cleanups

WIP, untested, not hooked in
2022-02-26 11:31:04 -05:00
zzz
6bb3657de2 SSU2: Start of packet handling
Store CipherStates in PeerState2
Add missing getVersion() overrides
2022-02-26 08:25:55 -05:00
zzz
dc40755e7c Sybil: Improve family analysis
Increase credit if family sig is verified
Speed up analysis by only looping through RIs once
Add link to all family members
Add SUNYSB certificate
bump -2
2022-02-25 10:36:17 -05:00
zzz
140ab47354 Fix SSU2 enable logic 2022-02-24 14:42:33 -05:00
zzz
da887f7c6c SSU2: Publish keys and version in address when enabled 2022-02-24 08:49:57 -05:00
zzz
f4be99ecd0 SSU: Add SSU2 class extensions and packet builder
Pass XDH key builder to UDPTransport
Add SSU2 static keygen when enabled
WIP, not hooked in
2022-02-24 06:13:28 -05:00
zzz
b8407a261e SSU2: ACK bitfield support and conversion to ACK block
WIP, not hooked in
2022-02-23 15:55:03 -05:00
zzz
969a8a5d8a SSU: Add support for SSU2 fragmentation to OMS 2022-02-23 15:22:40 -05:00
zzz
b57d9f2f7e SSU: More prep of classes for SSU2 extension 2022-02-23 11:57:03 -05:00
zzz
c9a97d889b SSU: Prep classes for SSU2 extension
add SSU2 states
2022-02-23 10:55:51 -05:00
zzz
51bdd9a283 SSU: Add getVersion() methods (prep for SSU2) 2022-02-23 09:25:21 -05:00
zzz
04dd18615c i2psnark: Load sytem mime types if available 2022-02-23 08:12:39 -05:00
zzz
265f5ee5df Util, i2ptunnel: Update firefox user-agent 2022-02-23 07:08:34 -05:00
zzz
9c3f8602da i2psnark standalone: Add startup message
update readme
2022-02-23 06:28:42 -05:00
zzz
74dedcf7f0 SSU2: More WIP 2022-02-23 06:12:35 -05:00
zzz
ae2b99b1c6 Build: Fix it 2022-02-22 14:53:41 -05:00
zzz
818ecc3563 Build: Fix testscripts target 2022-02-22 14:52:35 -05:00
zzz
5ccbeca676 bump -1 2022-02-22 10:34:31 -05:00
zzz
a621f56c33 Console: Add search for SSU2 transport 2022-02-22 10:32:25 -05:00
zzz
1513695768 Update: Add notification for new version
remove old Java 7 check
2022-02-22 10:30:41 -05:00
zzz
63e202f8f0 SSU: Start of SSU2 support
WIP, not hooked in
2022-02-22 10:27:42 -05:00
zzz
80535875ad SSU: PacketHandler cleanup (prep for SSU2) 2022-02-22 10:22:16 -05:00
zzz
f0ad921fd2 NetDB: Prevent rare deadlock via FloodfillMonitorJob at startup 2022-02-22 10:06:07 -05:00
zzz
63f3d88f78 Util: Speed up PRNG nextInt() and nextLong()
Add signedNextInt()
2022-02-22 09:57:35 -05:00
zzz
9f7f1bbcab Crypto: Prep for SSU2
- ChaCha20: Add ivOffset param
- ChaCha20/Poly1305: Add adOffset/adLength params
- Noise: Add XK-SSU2 initializer
- Noise: Add notes about handshake offsets
2022-02-22 09:45:22 -05:00
zzz
edc9d6fec5 NTCP: Reduce max writer threads 2022-02-22 09:07:58 -05:00
zzz
a089156afc Remove BOB source 2022-02-22 08:58:56 -05:00
zzz
767a5043ab Debian files for 1.7.0 2022-02-22 08:04:03 -05:00
zzz
3b9c26fe8a 1.7.0 2022-02-21 09:12:59 -05:00
zzz
961936f8d5 bump for review 2022-02-18 13:58:02 -05:00
zzz
7ea31835c2 more translations from Transifex 2022-02-18 13:44:08 -05:00
zzz
bf1f2e4635 pull translations from Transifex 2022-02-18 13:39:24 -05:00
zzz
198008472a i2psnark standalone: Raise open files ulimit
copied from i2prouter script
2022-02-17 13:58:10 -05:00
91e9d95df7 Merge branch 'docker-host-networking' into 'master'
Make Docker host networking safer

See merge request i2p-hackers/i2p.i2p!54
2022-02-16 15:53:32 +00:00
1b5feda517 generic advice for cloud deployments 2022-02-16 15:51:28 +00:00
29f74ba72a change interfaces 0.0.0.0->127.0.0.1 and update documentation 2022-02-16 11:14:10 +00:00
zzz
d6684403a2 Add new Japanese man pages 2022-02-12 13:47:52 -05:00
zzz
388aa233e0 Add new Slovenian translated resources 2022-02-12 13:30:33 -05:00
idk
ea92b79340 set table-width to fixed on console dark theme, and run the auto-indenter on the console light theme to fix it's inconsistent tabs. Merge the chrome-overrides rules on the console light theme CSS. Changes to light theme are entirely cosmetic, except that they improve the reliability of my CSS linter. 2022-02-11 23:01:51 -05:00
idk
3ba754d723 Merge branch 'master' of github.com:i2p/i2p.i2p 2022-02-11 15:34:41 -05:00
idk
d651d25de6 Merge pull request #26 from zlatinb/github-actions
Use GitHub Actions to publish installer.jar on each push
2022-02-11 15:32:37 -05:00
idk
00ea32938e set .wizardimg css to display: none on the dark theme so the light-theme background images don't show up. Normalize the wildly inconsistent tabs tabs in console.css 2022-02-11 15:27:50 -05:00
37002822b3 install.jar fix name 2022-02-11 19:50:40 +00:00
50d56ccbe8 gettext 2022-02-11 19:46:27 +00:00
48cb6f79ef Use GitHub Actions to publish installer.jar on each push 2022-02-11 19:38:04 +00:00
idk
a325e63426 use updateType instead of key for error message in ConsoleUpdateManager with custom UPP 2022-02-10 12:42:50 -05:00
zzz
309e306337 javadoc fixes 2022-02-10 09:02:39 -05:00
zzz
2ba56a5e17 Bump build time 2022-02-10 08:39:46 -05:00
zzz
c949ad5205 Update Manager: Add an UpdateType for the API version 2022-02-10 08:37:52 -05:00
zzz
5621b4bf97 GeoIP 2022-02 2022-02-10 08:28:19 -05:00
idk
dbfe8d24a8 log not-found key should an UPP error occur 2022-02-09 21:33:32 -05:00
zzz
548c0994a7 poupdate-source 2022-02-09 14:25:09 -05:00
zzz
d0ca1d38ca NTCP: Fixes for SSU disabled
Update RI reachability after first inbound connection
Allow local address in test mode
2022-02-09 06:39:18 -05:00
idk
96560e8590 Increase size of unicode links on proxy.css 2022-02-07 00:26:18 -05:00
zzz
19712cfd95 SSU: Fix race NPE in debug logging 2022-02-06 09:51:46 -05:00
idk
3dcc954341 Put description of jump link function on newline in proxy.css 2022-02-04 17:26:27 -05:00
zzz
568b5e303f Tunnels: Avoid buggy routers
SSU: Don't bid on connection to buggy routers
2022-02-03 10:36:03 -05:00
idk
73d90ed5c4 Don't add os-arch to pluginname if it's already correct 2022-02-03 01:51:33 -05:00
idk
b2fe36b0d3 Revise ShellService.name to match ShellService directory if the directory includes -SystemVersion.getOS or -SystemVersion.getArch 2022-02-02 17:37:02 -05:00
idk
632a1578a2 Check executable status of shellservice plugins in start. If the ShellService plugin name doesn't correspond to a directory, check plugin name+-$OS-$ARCH and name+$OS. 2022-02-02 15:18:25 -05:00
idk
e28f4be46b Merge branch 'plugin-config-redux' into 'master'
Adds the ability to use `$OS`  and `$ARCH`  variables in clients.config and plugins.config(updateURL.* only)

Closes #340

See merge request i2p-hackers/i2p.i2p!52
2022-02-02 18:57:30 +00:00
idk
73e34b3941 Adds the ability to use $OS and $ARCH variables in clients.config and plugins.config(updateURL.* only) 2022-02-02 18:57:30 +00:00
b4e2366458 Merge branch 'filefilter-fix' into 'master'
Fix for FileFilterDefinitionElement.  Issue #349

See merge request i2p-hackers/i2p.i2p!50
2022-01-31 13:22:44 +00:00
1389e89f6d Merge branch 'junit-deprecations' into 'master'
fix junit deprecations, issue #339

See merge request i2p-hackers/i2p.i2p!51
2022-01-31 13:11:17 +00:00
c3abe7b3d4 Do not use forEach 2022-01-31 13:10:26 +00:00
042c1e88aa fix junit deprecations, issue #339 2022-01-31 11:39:57 +00:00
899ce0f959 Fix for FileFilterDefinitionElement. Issue #349 2022-01-31 04:38:48 +00:00
zzz
5dd8139aad Reseed, DoH: Fixes for IPv6-only 2022-01-30 11:25:36 -05:00
zzz
13ee324d36 NTCP2: Clock skew handling improvements
as discussed in #ls2 meeting
- Bob replies with Session Created even if skewed,
  so that Alice finds out what the skew is
- Alice handles Session Created timestamp and drops if skewed,
  bans Bob, and updates clock if NTP failed
- If Alice does reply with SessionConfirmed, Bob will send a
  destroy with a skew error code
- Don't change skew error code if netdb store failed
- Fix skew adjustment for RTT by Bob
- Call setLastBadSkew() in the right places
- Fix ntcp.invalidInboundSkew and ntcp.invalidOutboundSkew stats
2022-01-26 07:28:43 -05:00
zzz
afa7278080 NTCP: Ban IP if RI signature fails 2022-01-25 12:22:57 -05:00
zzz
b6be2d7e65 bump -9 2022-01-25 09:42:33 -05:00
zzz
78ba3d1f68 Console: CSS tweak for messages 2022-01-25 09:41:12 -05:00
zzz
d930f0a64a Console: Set encoding for CSS 2022-01-25 09:40:02 -05:00
zzz
c1dc3c8275 Data: Remove dup check for negative tunnel ID 2022-01-25 09:37:26 -05:00
zzz
8bf87da4b1 Transport: BW limiter log and javadoc improvements
Portion of gitlab MR !49
2022-01-25 09:35:33 -05:00
zzz
8812e822f9 Util: CDPQ stat description tweak 2022-01-25 09:29:43 -05:00
zzz
f17cd24dc8 UDP: Pass message priority through to the packets
Change UDP-Sender queue from CoDel to CoDelPriority
No change to CoDel params

UDP msg priorities:
High priority: ack-only, session request/created/confirmed, relay request, hole punch, injected
Low priority: ping, destroy, peer test, relay intro/response
2022-01-25 09:27:49 -05:00
zzz
b9f53069bb Tunnels: Reimplement, re-enable using tunnel builds as a tunnel test,
but without ooming
disabled in 2009 because of ooms
2022-01-25 09:10:00 -05:00
zzz
21f5f7c148 Tunnels: Enable tunnel testing by default
disabled since 2011
2022-01-25 09:03:14 -05:00
idk
3057103875 tweak light proxy.css on non-mobile screens 2022-01-23 11:02:47 -05:00
idk
2752015b6e Simplify, add better logging, correctly mark state change in ShellService 2022-01-22 21:26:59 -05:00
idk
f2e0aacbf0 use Arrays.toString to convert trimmed process args to application args in ShellService. 2022-01-22 14:56:04 -05:00
idk
3e8f8a2bd3 add null check to isProcessRunning() in new ShellService 2022-01-22 00:12:37 -05:00
zzz
77e30e246d Util: Fix leak of SimpleTimer2 shutdown task 2022-01-21 09:09:32 -05:00
idk
5e7a00ede4 Merge branch 'fix-docker-configs-support' into 'master'
Allow chown to fail so files can be managed via docker configs and secrets

See merge request i2p-hackers/i2p.i2p!48
2022-01-16 16:45:56 +00:00
ba55ec09ed Allow chown to fail so files can be managed via docker configs and secrets 2022-01-16 16:45:56 +00:00
zzz
0b058c0ffd i2psnark: Add UDPTrackerClient
WIP - not hooked in, untested - target 1.8.0 / 0.9.54
Requires significant changes to TrackerClient
Adapted from mtn branch i2p.i2p.zzz.udpsnark (2014)
Ref: Proposal 160
2022-01-16 08:58:03 -05:00
idk
61422d9f7f Merge branch 'docker_update' into 'master'
Upgrade base image to latest version of Alpine

See merge request i2p-hackers/i2p.i2p!47
2022-01-15 20:32:48 +00:00
zzz
b63a2e41be i2psnark: html fix 2022-01-15 11:52:13 -05:00
zzz
606961c788 Console: Add ban counts to headers 2022-01-15 06:59:52 -05:00
9573c6ed0f Upgrade base image to latest version of Alpine 2022-01-14 20:17:52 +00:00
idk
70bb63e8ab Make the buttons on the save host form look like the links on the jump host form 2022-01-10 17:16:30 -05:00
idk
b96255a65b Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2022-01-10 14:44:45 -05:00
idk
e15dae5c5f Turn jump button-links back into regular-looking hyperlinks when resolution indicates we are not on a mobile device 2022-01-10 14:28:40 -05:00
zzz
695cf8796d javadoc: Add API version 2022-01-10 09:07:07 -05:00
zzz
175f043819 javadoc: Add message flow chart 2022-01-10 08:57:01 -05:00
zzz
662ea995c1 javadoc note 2022-01-07 10:48:48 -05:00
zzz
b8670e1e5b hosts.txt update 2022-01-07 05:53:50 -05:00
zzz
7f4441078d Router: Prevent deadlock at startup
in the transports through PLRIJ via FNDF.publish()
2022-01-06 07:18:42 -05:00
zzz
150248d8d7 Plugins: Fix webapp classpath setting when the webapp name does not match the plugin name 2022-01-05 16:50:33 -05:00
zzz
aaa1da4c66 Plugins: console-icon path is relative to consoleLinkURL if specified,
otherwise relative to plugin name, as before
2022-01-05 15:08:35 -05:00
zzz
8167f5184d hosts.txt update 2022-01-05 06:25:01 -05:00
zzz
034a5acd37 i2pcontrol: Send translated tunnel status string 2022-01-04 13:09:34 -05:00
idk
7249f21602 redirect output and error from process builder to files within the plugin directory 2022-01-03 14:26:27 -05:00
idk
d1192f74f2 Remove platform-specific workarounds from Java 8+ version of ShellService 2022-01-03 14:18:16 -05:00
zzz
13f910be70 i2ptunnel: Add hooks to get the session from the contoller 2022-01-02 11:23:23 -05:00
zzz
2d42541b79 i2pcontrol: Handle more router states mapping to i2pcontrol states
Linkify start/stop webapp on password page
2022-01-02 11:13:15 -05:00
zzz
131da9bdb9 javadoc fixes 2021-12-30 09:59:26 -05:00
zzz
bc97e955e2 bump -7 2021-12-28 12:24:37 -05:00
zzz
faa1bf117a i2ptunnel: Add IRC filter support for IRCv3 message tags
Required for irc.ilita.i2p
2021-12-28 12:07:07 -05:00
zzz
aa386f3bdc bump -6 2021-12-28 10:02:27 -05:00
zzz
f1170b948f NetDB: StoreJob reliability improvements
- Always use a lease as the reply tunnel when publishing LS through a client tunnel
  This ensures we're not using about-to-expire tunnels for the reply,
  and ensures the ff is able pick an alternate
- Don't count skipped peers as attempted in FloodfillVerify
- Pass failed and skipped peers to FloodfillVerify job to be skipped there also
- Pass failed and skipped peers from FloodfillVerify job to the next StoreJob on failure
- Consolidate common reply token generation code in StoreJob
- Ensure tunnel diversity in StoreJob retries by only
  using tunnels closest to the target for the first request.
  This increases reliability by not reusing the same tunnels for all retries.
- Refactor StoreState to rework inefficient methods and unused data
- Clean up commented-out code in StoreState
- Log tweaks
2021-12-28 09:57:42 -05:00
zzz
59ab40779c NetDB: RepublishLeaseSetJob
Don't requeue on failure if there is a newer LS, KNDF will have already done that.
Log tweaks and cleanups
2021-12-28 09:44:39 -05:00
zzz
85b9862b64 NetDB: Ensure tunnel diversity in ISJ retries
by only using tunnels closest to the target for the first request.
This increases reliability by not reusing the same tunnels for all retries.
2021-12-28 09:24:35 -05:00
zzz
132d76a06b NetDB: SearchJob minor cleanup, only call getHash() once 2021-12-28 09:15:48 -05:00
zzz
c4b4b2d4b2 NetDB: Increase lookup throttle time
This reduces the max lookup rate
2021-12-28 09:12:29 -05:00
zzz
db6914f555 NetDB: Use same dbResponseTime rate in ff peer selector as in KNDF.getPeerTimeout()
10 minute rate is too short
Change to getAvgOrLifetimeAvg()
Reduce max time
2021-12-28 09:02:40 -05:00
zzz
bef729463d NetDB: Fix usage of dbResponseTime stat
Actually update the stat for stores in dbStoreSent();
we are generally storing to different ffs than lookups, so we need the
stat for stores as well, since we use it as the timeout in StoreJob.

Change from 1-day to 1-hour stat.
Switch to avgOrLifetimeAvg() so the rate is always valid.
Reduce max time used for timeout.
This allows more peers to be tried before total timeout
Previously, the per-peer timeout was almost always the max.
Make sendStore() package private.
Javadocs and cleanups.
2021-12-28 08:56:47 -05:00
zzz
d0e72aca66 Console: Partial string case-insensitive match for netdb family search 2021-12-28 08:55:29 -05:00
zzz
46ee8be9c6 i2psnark standalone: Add version number to header 2021-12-27 12:40:33 -05:00
zzz
cc3d2cf67b bump -5 2021-12-27 09:00:11 -05:00
zzz
57c997730f Console: Fix display of ip lookup param with netmask in netdb search 2021-12-27 08:55:49 -05:00
zzz
0826f431ef i2psnark standalone: Fixes for router startup and shutdown
so that torrents stop when the router stops and restart when the router restarts.

- Use BWLimits from the DirMonitor as a periodic test that the router is there
- DirMonitor does not attempt to autostart torrents if BWLimits test fails
- DirMonitor does autostart existing torrents when BWLimits test passes again
- Register disconnect listener with socket manger and stop all torrents on disconnect
- Use stopTorrent(true) on router errors to prevent changing the persisted torrent running status
- Change autostart default to true for standalone

Possibly more todo for corner cases or other start/stop/fail scenarios.
2021-12-27 08:52:56 -05:00
zzz
c63cb378e8 I2CP: Send DestroySession message when destroying session
in client-side AppContext SimpleSession, to prevent router-side
error message when closing socket, e.g. for BW limits check
2021-12-27 08:32:04 -05:00
zzz
242dc92397 Banlist: Increase ban time again for routers without netID
it's not a i2pd bug at startup that fixes itself.
2021-12-27 08:27:11 -05:00
zzz
26f34d6985 Debian: Update URL in watch file 2021-12-23 15:28:07 -05:00
idk
e002d3f558 Move ShellService into net.i2p.router.web 2021-12-23 15:10:24 -05:00
zzz
3d5dd639e3 i2psnark standalone: Use previously translated I2CP connect error 2021-12-23 13:49:18 -05:00
zzz
2bfedfbc74 i2psnark standalone: Translate I2CP connect error 2021-12-23 13:06:58 -05:00
zzz
70131c6b25 i2psnark standalone: Pass ctx to logger 2021-12-23 12:02:19 -05:00
zzz
e946040ddd i2psnark standalone: Redirect jetty logging to i2p log 2021-12-23 11:54:51 -05:00
zzz
bab37e57fe i2psnark: Add note for translators 2021-12-23 11:23:00 -05:00
zzz
70e06de846 i2psnark: Translate theme names, translated sort 2021-12-23 11:01:05 -05:00
zzz
11f60a7192 i2psnark standalone: Set launch-i2psnark +x 2021-12-23 09:47:48 -05:00
zzz
6282c365bb i2psnark standalone: Update readme 2021-12-23 09:12:57 -05:00
zzz
621ea49621 i2psnark standalone: Add da, el, and fa to language menu 2021-12-23 08:16:32 -05:00
zzz
e51738d180 i2psnark standalone: Add jbigi.jar
as requested by R4SAS
2021-12-21 06:51:06 -05:00
zzz
811442f9cb Transport: Async NTCP writes (MR !43)
- Write directly from writer threads, except for during establishment and when write doesn't complete; throw those to the pumper as usual
- New NTCPCon writelock, readlock, and statlock (formerly all on NTCPCon.this) to prevent deadlocks
- NTCPCon chan and key now volatile, remove synch to prevent deadlocks
- All interestOps changes now lock on the key via setInterest() and clearInterest() since changes may now happen in multiple threads
- Set _paddingConfig at initialization to avoid NPE

Greatly reduces pumper loops and CPU

As proposed by jogger
Reviewed by zlatinb
Ref: http://zzz.i2p/topics/3192
2021-12-21 06:37:10 -05:00
zzz
464a39b939 MaskedIPSet: More efficient string generation
and don't IAE on 8 byte negative value
2021-12-19 10:53:50 -05:00
zzz
1a05083ed0 Tunnels: Double mask value for IPv6
rather than using a fixed value of 6
so IPv6 default is now 4
2021-12-19 08:38:13 -05:00
zzz
937b6120ff i2psnark standalone: Add notes about changing browser and port 2021-12-18 07:52:30 -05:00
zzz
2a451cdb97 bump -3 2021-12-18 06:34:21 -05:00
zzz
ccba4a197d Tunnels: Do not allow failed tunnels to be rebuilt 2021-12-18 06:33:36 -05:00
zzz
feaff690a3 Debian build doc update 2021-12-18 06:28:19 -05:00
zzz
098ef9a0ff Tunnels: remove log in test timeout job 2021-12-18 06:27:18 -05:00
zzz
f317d29dd5 javadoc fix 2021-12-18 06:25:04 -05:00
zzz
f17b568f19 Tunnels: Remove old NTCP cost=2 check in MaskedIPSet 2021-12-18 06:22:54 -05:00
zzz
5029516087 i2ptunnel: Use defined SOCKS constants 2021-12-18 06:21:25 -05:00
zzz
69699638ae i2psnark: Add avif mime type 2021-12-18 06:19:49 -05:00
zzz
e6c76fa5ae Console: CSS tweak for update status box 2021-12-18 06:18:49 -05:00
zzz
b8435f5e9e Tunnels: Cleanup settings for IP restriction
Check bounds at initialization
Remove unused setIPRestriction()
2021-12-18 06:17:41 -05:00
zzz
5995b0b7a7 Tunnels: Restore support for IP restriction in client tunnels (MR !45)
Removed in May 2011 when we added fast tier slices
Also add support in exploratory tunnels
Create MaskedIPSet in peer selectors, pass to ProfileOrganizer.selectXXX() for each call.
Not required for one-hop tunnels.
Disable for test networks (i2np.allowLocal)
Reported by 'vulnerability_reports' http://zzz.i2p/topics/3215
2021-12-18 06:14:09 -05:00
zzz
80237a57bd Reseed: Renew SSL cert 2021-12-13 07:01:41 -05:00
idk
c4cfe420a6 disable any chance of JNDI lookups in log4j.properties file by setting %m{nolookups}. I don't think we're actually vulnerable to CVE-2021-44228 if I'm understanding correctly, by default it doesn't seem like we actually use log4j for much of anything and we don't do much logging of arbitrarily crafted remote inputs, but also it seems like this JNDI lookups thing is way more trouble than it could possibly be worth to us. Maybe it's a good idea to make sure it's turned off by default. 2021-12-10 21:01:37 -05:00
zzz
14c5d54f0e Reseed: Server list update 2021-12-10 07:58:08 -05:00
zzz
b1a4a8517e i2ptunnel: Refactor UDPTunnel, Streamr, and SOCKS UDP for I2CP ports
- Add fromPort and toPort to Sink interface (breaking API change)
- Change cache maps from Destination to I2PSocketAddress to include port
- Accept host:port for destination in Streamr Client, use port
  as toPort in pinger
- Change to muxed listener in I2PSource, only listen for
  specified protocols
- Eliminate thread and queue in I2PSource, process messages inline
  in the listener
- Add support for handling both repliable and raw datagrams in
  a single I2PSource instance
- Remove verify option from I2PSource and I2PTunnelUDPServerBase,
  always verify repliable datagrams
- Add getPort() method to UDPSource
- Add a constructor to UDPSink to pass in an existing DatagramSocket
- Change I2PTunnelUDPClientBase to receive both repliable and raw
- Change SOCKSUDPTunnel reply handling strategy to key on I2CP toPort;
  remove ReplyTracker; the tunnel would not have worked before, because
  it expected raw replies only but MultiSink required a destination
  to look up where to forward the reply.
- Mark SOCKSUDPTunnel as preliminary; note lack of support
  for raw replies; untested
- Change Streamr Client Pinger to support fromPort
- Change Streamr Server to remember fromPort in subscriptions
  and use it as toPort in data stream
- Move fields to top of classes for sanity
- Cleanups and log tweaks
2021-12-08 13:05:27 -05:00
zzz
22ff40bc84 Build: Add missing @Override annotations (dep-ann lint) 2021-12-07 15:33:41 -05:00
zzz
b5d7dffb08 Debian: Add explicit dependency on libservlet3.1-java (Debian #997213)
libjetty9-java used to depend on libservlet3.1-java
but now in sid it doesn't.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=997213
2021-12-07 14:14:32 -05:00
zzz
a59cad0066 Router: Tweak shutdown messages
Change one from CRIT to WARN
Translate one of them
Attempt to translate class name in notifications
2021-12-05 07:21:57 -05:00
zzz
cbb6a6db65 DTG: Add menu items to control notifications
Fix check for successful configuration save
2021-12-05 06:38:28 -05:00
zzz
730b9790d9 Console: Remove job queue link on /configservice 2021-12-04 16:54:12 -05:00
zzz
ebf6ca5b34 Console: Case-insensitive sort of jobs on /jobs 2021-12-04 16:03:53 -05:00
zzz
0422134a86 SusiMail: Notify new messages on DTG
experimental
2021-12-04 12:47:47 -05:00
zzz
1a77352fa7 i2psnark: Notify completed downloads on DTG
experimental
2021-12-04 11:59:39 -05:00
zzz
cc971eb34f Build: Fix minimum Java version in installer config 2021-12-04 10:56:45 -05:00
zzz
fa0e59435e DTG: Change icon from white to black on Windows by default
Will be set to the opposite of the console theme.
2021-12-04 10:48:11 -05:00
zzz
962cc31f31 DTG: Show all CRIT messages on DTG.
Experimental, may add a separate config or disable later.
Show I2P starting message in DTG
2021-12-04 09:50:08 -05:00
zzz
87362fd68b i2psnark: Edit torrent page cleanup - remove unneeded info 2021-12-04 08:02:37 -05:00
zzz
51f6bef5dc i2psnark: Respect newlines in torrent comments 2021-12-04 07:38:24 -05:00
idk
a1ea48e2b6 Fix the very first ShellService bug, the long pid should be parsed from the pidString from the wrapper output, or it won't be available 2021-12-03 22:44:46 -05:00
zzz
e9aa3a55cc Add file missing from previous checkin to fix build 2021-12-03 16:51:51 -05:00
zzz
d03c690724 Tunnels: Immediately fail outbound tunnels when
we can't connect to the first hop
by attaching an onSendFailJob in OutboundSender.
Check if failed in isValidTunnel()
2021-12-03 12:51:01 -05:00
zzz
2a900a8c5b i2psnark: Add torrent edit page
Additional UI cleanup to follow
2021-12-03 06:26:14 -05:00
zzz
de995761db Tunnels: Change tunnel test failure count to AtomicInteger 2021-12-03 06:15:37 -05:00
zzz
cfbdf8385d Tunnels: Count consecutive build timeouts per-pool
Use exploratory paired tunnel after too many timeouts
2021-12-03 06:10:21 -05:00
zzz
83b959c4a1 Tunnels: Remove 2nd arg on TestJob failure stats 2021-12-03 05:51:56 -05:00
zzz
e66ec208a8 Tunnels: Refactor build completion handling
- Add result code to BuildExecutor.buildComplete() and TunnelPool.buildComplete()
- Remove BuildExecutor.buildSuccessful(), move to buildComplete()
- Move ExpireJob creation to buildComplete()
- TunnelPool.buildComplete() now calls addTunnel()
- Eliminate some now() calls
2021-12-03 05:48:27 -05:00
zzz
cf22186182 Router: Shorter ban time for localhost addresses 2021-12-01 15:51:44 -05:00
zzz
890a8927a5 DTG: Add notification service to display popup messages
unused for now
2021-12-01 08:37:51 -05:00
zzz
dd439bc9be Transport: Add NTCPConnection.getRemoteIP()
to match SSU PeerState method
2021-11-30 11:24:24 -05:00
zzz
537a8bf19b Console: Linkify router hashes on Sybil analysis 2021-11-30 11:14:51 -05:00
zzz
bd0c696b84 CLI: Allow empty blocklist when signing news feed 2021-11-30 11:11:30 -05:00
zzz
5c56884d7f bump -1 2021-11-30 10:51:33 -05:00
zzz
b53707074f DTG: Add classpath to jar, add early check for support when called by CLI
for ease of command-line testing
2021-11-30 10:26:52 -05:00
zzz
6cb8d2eeb7 i2ptunnel: Increase default priority for IRC and standard tunnels 2021-11-30 10:23:14 -05:00
zzz
3895cd1068 Console: NetDB search form improvements 2021-11-30 09:53:44 -05:00
zzz
5b2fbc4ec4 Build: Add bumpBuildTime target 2021-11-30 09:35:06 -05:00
zzz
87654e2f4f Build: Remove BOB from installer, updater, and clients.config
Source remains for now and may still be built with ant buildBOB.
Existing non-package installs will continue to work.
2021-11-30 09:31:06 -05:00
zzz
9c29f8c8ff Debian files for 1.6.1
fix a lintian warning about compare-versions
update launchpad doc for git
2021-11-30 08:53:49 -05:00
zzz
619c36d18d 1.6.1 2021-11-29 12:21:54 -05:00
zzz
cf10a2d5b6 Tunnels: Fix NPE in BuildHandler 2021-11-29 12:19:02 -05:00
zzz
56fdc244d4 1.6.0 2021-11-29 10:41:18 -05:00
zzz
adc69c0d9a Refresh Debian patch 2021-11-29 10:31:55 -05:00
zzz
dd9a5548a8 Man pages: Update bug reporting URL 2021-11-27 08:52:30 -05:00
zzz
ab88f86954 ShellService: More import cleanup 2021-11-27 08:05:57 -05:00
zzz
9466b225b6 blocklist update 2021-11-26 12:47:35 -05:00
zzz
ef1e2b02de Build: Fix the tagged string with '75%'
which causes gettext to add a java-printf-format directive,
then the testscript fails if the translated
string doesn't have a '%' in it; strip out the directive
Bump for review
2021-11-26 11:13:41 -05:00
zzz
ee68aec647 Pull translations 2021-11-26 11:06:29 -05:00
zzz
3dfeb92b63 Update bug report links 2021-11-24 10:33:30 -05:00
zzz
ee5288ebb1 i2ptunnel: AccessFilter findbugs 2021-11-24 09:08:18 -05:00
zzz
488acdfd98 Util: ShellService findbugs and cleanups 2021-11-24 08:59:08 -05:00
idk
ee2e7ec30d Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2021-11-23 14:08:19 -05:00
idk
40466bc602 Tweak location of dark theme animation. Closes #335 2021-11-23 14:06:41 -05:00
zzz
d8d6954ef0 BuildTime update 2021-11-23 09:57:59 -05:00
zzz
0aa4550bbe Add Hungarian man pages 2021-11-23 07:51:47 -05:00
zzz
ad82946fd3 Tunnels: Drop request if hop throttle exceeded by 50%
Revert banning peer in throttles
2021-11-23 07:25:53 -05:00
zzz
77b48a48ab Console: Remove tinhat from home page at op's request 2021-11-22 09:38:35 -05:00
zzz
d948fa8db3 Update: Fix registered version of feed blocklist after update 2021-11-21 08:50:10 -05:00
zzz
31393c2bef Update: Add message about pack200 plugins 2021-11-21 08:32:09 -05:00
zzz
e3fc34ef1f Tunnels: Ban peer on excessive build requests
Drop requests if previous or next peer is banned
Console: Drop peer when manually banned
Update: Drop peer when banlisted
2021-11-21 08:17:43 -05:00
idk
d7fdd6d9dc Merge pull request #24 from kfeoktistoff/debian_mkdir_log_on_startup
debian: create a log dir on startup if absent
2021-11-20 21:53:06 +00:00
idk
5a3a7b843a Merge pull request #23 from shisheng-1/Modify_GRADLE_1
Improve GRADLE build Performance
2021-11-20 21:22:01 +00:00
e06f8961b4 debian: create a log dir on startup if absent 2021-11-20 17:35:28 +00:00
idk
9d1aa5b762 Merge branch 'shellservice' into 'master'
Manage Fork-and-Exec Plugins by Monitoring them by PID

See merge request i2p-hackers/i2p.i2p!39
2021-11-17 17:42:50 +00:00
idk
2e71a0b36a Manage Fork-and-Exec Plugins by Monitoring them by PID 2021-11-17 17:42:45 +00:00
zzz
b072f40ed1 Initial Slovenian translations for a few resources
not added to menu yet
2021-11-17 09:00:00 -05:00
zzz
35d2f118ce poupdate-source 2021-11-17 08:30:23 -05:00
idk
3f7f315951 Place .wizardnotice at bottom right of screen above the buttons on both dark and light themes(#335) 2021-11-16 12:21:40 -05:00
zzz
6ef4c74d97 NTCP: Move wantsWrite(byte[]) from EventPumper to NTCPConnection
for sanity in following the write code path, rather than
going from con to pumper to con, keep the code in con.
Prep for possible write-side improvements in a future release,
ref: http://zzz.i2p/topics/3192
2021-11-16 11:09:05 -05:00
zzz
0e4d684e7d NetDB: Add new reseed 2021-11-16 10:58:38 -05:00
zzz
e3be6b50ce Tunnels: Use connected peer for closest inbound hop when
approaching conn limits to increase tunnel build success

This should reduce chances of tunnel builds pushing us over conn limits,
and reduce build failures and watchdog warnings when at conn limits.
2021-11-12 07:21:27 -05:00
zzz
dad2bed334 GeoIP 2021-11-01 2021-11-09 08:35:11 -05:00
zzz
bbe66f0e18 Util: DoH server list update 2021-11-08 13:04:01 -05:00
27bf65c1a4 Improve GRADLE build Performance 2021-11-06 00:13:26 +08:00
zzz
9c7b415d62 Util: Don't warn for new SU3 file types 2021-11-03 08:11:05 -04:00
zzz
78e4572a8c CSS button and checkbox spacing,
NTCP table fixes
2021-10-28 09:08:52 -04:00
zzz
4507ecd5f2 javadoc PKF clarification 2021-10-28 09:06:54 -04:00
zzz
721d39c01d Remove UDPPacketReader logging 2021-10-28 08:25:43 -04:00
zzz
427fc1c1ca More javadocs on getLibDir() 2021-10-27 10:02:45 -04:00
idk
33f1b3be87 Merge branch 'add-libdir' into 'master'
Add an i2p.dir.lib property

See merge request i2p-hackers/i2p.i2p!40
2021-10-26 16:22:37 +00:00
idk
7e1c8c7983 Add an i2p.dir.lib property 2021-10-26 16:22:36 +00:00
idk
aa6b27d829 Merge branch 'backup-locale-conf' into 'master'
This adds inclusion of /etc/locale.conf to i2prouter i2p.init, per backup's...

Closes #326

See merge request i2p-hackers/i2p.i2p!41
2021-10-26 16:06:13 +00:00
idk
999e2615c3 This adds inclusion of /etc/locale.conf to i2prouter i2p.init, per backup's... 2021-10-26 16:06:12 +00:00
zzz
807b7d672f Debian: Update JRE dependencies 2021-10-23 12:03:49 -04:00
idk
685a2f1e39 4217a05ae9 and 1e70849bde were mis-tagged, cannot rewrite history on master, they apply to #335 and not #338 2021-10-21 13:53:48 -04:00
idk
4217a05ae9 Make the background images closer to exactly the same size on /welcome, #338 2021-10-21 13:40:28 -04:00
idk
1e70849bde Checkin consistency fixes for wizard themes, should address remaining issues with #338 2021-10-21 12:53:01 -04:00
zzz
1ab3e9b310 SSU: Send Bob-to-Alice Peer Test message in-session
Matches what i2pd does.
More checks to require in-session for
Alice/Bob and Bob/Charlie Peer Test messages.
2021-10-20 09:37:32 -04:00
zzz
fd2cf972bf Javadoc typos 2021-10-14 07:49:02 -04:00
zzz
d9eed6446e Util: Add more Intel processors to CPUID 2021-10-13 08:51:12 -04:00
zzz
6b823e6381 Tomcat 9.0.54 2021-10-11 10:46:26 -04:00
zzz
917b7e615e javadoc fix 2021-10-11 07:43:15 -04:00
zzz
af97381461 Jetty 9.3.30.v20211001
Remove patched SslConnection.java for Jetty #6072, fix included in this release
2021-10-10 12:09:12 -04:00
idk
4975bb1482 Fix positioning of options on welcome page between instructional text and progression buttons 2021-10-06 11:43:21 -04:00
zzz
83e2246195 Console: eepProxy -> proxy 2021-10-05 10:32:20 -04:00
zzz
3632070e3f i2ptunnel: Move the "(0 = unlimited)" text from section headers to tooltips 2021-10-05 09:56:55 -04:00
zzz
0cb30a085c i2ptunnel: Save access list as B64 to save space
Convert access list to B32 and sort in UI
Remove blank lines in get/set
2021-10-05 09:34:57 -04:00
zzz
a7a59a2b1b NetDB: Reduce ban time for routers without netId
Don't ban routers with bad netId before RI validation,
unless that router sent the RI
2021-10-05 08:40:30 -04:00
zzz
bf7155b935 NetDB: Consolidate getKBucketSetSize() calls
reported by jogger
fix javadoc
2021-10-03 10:13:04 -04:00
zzz
62fb294f54 Console: Replace n/a with -- on floodfills page for readability 2021-10-03 09:46:18 -04:00
zzz
b7e710b28f Wizard: Add theme picker page
Clean up configui.js
CSS cleanups for new page TODO
Gitlab #335
2021-10-03 09:05:26 -04:00
zzz
4a8534e4e6 SSU: Downgrade fragmentation log errors to warn
reported by drzed
2021-10-02 13:40:23 -04:00
zzz
aa4e2f5c95 Console: ConfigUIHelper minor refactor (prep for wizard) 2021-10-02 09:06:50 -04:00
zzz
fe4fbce7bd Wizard: Add a simple progress ticker to bw test status 2021-10-02 08:10:40 -04:00
idk
33374eacaa add input:disabled and button:disabled to dark theme css 2021-10-01 13:12:21 -04:00
zzz
cea76ed9d5 i2ptunnel: Fix enc type configuration logic 2021-10-01 08:18:07 -04:00
zzz
f41db2685e i2ptunnel: Center text in buttons (light) 2021-10-01 07:40:31 -04:00
zzz
95bf068b0a i2ptunnel: Remove experts-only label for X25519-only option 2021-10-01 07:39:09 -04:00
idk
e2caa246f2 Line up the columns on results page of the bandwidth wizard. Remove some unnecessary box-shadows which are causing optboxes to appear blurry in some cases. 2021-09-30 16:36:46 -04:00
idk
bed013d858 hide notification div when bandwidth test is complete, switch back to green icon for slide messages 2021-09-30 14:14:10 -04:00
zzz
282460cb3f Console: Add js to /configui to preview themes
Save theme change before form processing so no refresh required
Enable/disable reset and apply buttons on config clicks
Prep for theme picker in wizard
2021-09-30 09:55:35 -04:00
idk
f015d1f490 Merge branch 'master' of 127.0.0.1:i2p-hackers/i2p.i2p 2021-09-29 17:56:48 -04:00
idk
f0758ee36f Adjust alignment of notifications and increase contrast on dark theme /welcome, progress on #335 2021-09-29 17:55:49 -04:00
idk
c77e9537ae Adjust alignment of notifications and increase contrast on dark theme /welcome, progress on #337 2021-09-29 17:54:08 -04:00
zzz
b7de63e922 Console: Wizard HTML fixes 2021-09-28 12:15:01 -04:00
zzz
13ade14289 Console: Refactor wizard progress indicator 2021-09-28 09:52:07 -04:00
zzz
2b43e4e4b5 Router: Rekey all Android/ARM routers 2021-09-27 10:26:03 -04:00
idk
571986a78b Add transparent channel to wizardlogo.png s and blend with exclusion instead to improve appearance of logo on dark theme. 2021-09-26 02:24:42 -04:00
zzz
d7c89be9a2 Tunnels: Implement Bloom filter for short TBM
Reduce TBM Bloom filter size and interval for EC routers
2021-09-25 09:12:15 -04:00
zzz
d466fd6799 UDP: Use a single PacketBuilder everywhere 2021-09-22 12:44:28 -04:00
zzz
116ec88f56 UDP: Replace ACKSender thread with per-PeerState delayed ack timers
(low latency improvements part 2)

Timer is created in PeerState messageFullyReceived() and messagePartiallyReceived().
Don't send a delayed ack-only packet if acks are sent in a data packet first.

Reviewed and tested by zlatinb.
Related MRs: !36 !37 !38
2021-09-22 12:12:16 -04:00
346372e002 Merge branch 'ssu-low-latency-2' into 'master'
SSU low-latency changes pt1

See merge request i2p-hackers/i2p.i2p!37
2021-09-17 16:36:42 +00:00
f14b7d53a3 reduce the delay in ACKs to the minimum of rtt/2 and the constant 2021-09-17 17:32:37 +01:00
3355daa334 introduce a lock just for _sendWindowBytesRemaining field 2021-09-17 17:31:45 +01:00
zzz
67fea26638 Wizard: remove 'Tcpbw100' from test status messages 2021-09-16 11:50:44 -04:00
zzz
b1c367777d Console: Add constants for wizard page numbers
to make it easier to add/remove/reorder pages later
2021-09-16 10:50:57 -04:00
zzz
3917dc6d2f I2CP: Don't call listener.readError() after external client disconnect via destroySocketManager()
prevents log error on normal client shutdown
reported and tested by zlatinb
2021-09-10 13:43:26 -04:00
zzz
2d239edf34 Update: Get backup URLs from news feed
Remove hardcoded backup URLs
Parse i2p, clearnet, and clearnet-ssl URLs from news
Write i2p, clearnet, and clearnet-ssl URLs to old news format
Clearnet and clearnet-ssl URLs currently unused; no handler is registered
2021-09-05 10:47:10 -04:00
1fbe084b74 Update build.xml 2021-09-03 07:16:57 +00:00
7a37f09334 Merge branch 'choking-retransmission-fix' into 'master'
Prevent the sender from sending too far ahead of an unacked packet

See merge request i2p-hackers/i2p.i2p!35
2021-09-02 17:26:54 +00:00
1ae05103e4 Prevent the sender from sending too far ahead of an unacked packet 2021-09-02 18:22:12 +01:00
zzz
a66422fa3c Console: Catch error checking systray availability (gitlab issue !331) 2021-08-28 09:05:38 -04:00
zzz
dabc29f8a5 Build: Always echo JDK version 2021-08-27 09:51:32 -04:00
zzz
132da4a35a Debian: Add copyright file to apparmor list 2021-08-27 09:42:28 -04:00
zzz
ea1eac2343 Tunnels: Enable sending short tunnel build messages,
remove debug settings
2021-08-26 10:23:13 -04:00
zzz
569e035bfd Router: Increase rekey probability to 1 in 4 2021-08-26 09:57:16 -04:00
zzz
8b1b5d4eb3 Debian files for 1.5.0
Fix build error dh_installdocs linking from the libjbigi-jni arch package
to an arch:all package, this is an error for compat level 10.
2021-08-26 09:52:40 -04:00
zzz
33f64f7913 build checklists and windows scripts updates for 1.x 2021-08-24 09:58:17 -04:00
zzz
e340fc885d 1.5.0 / API 0.9.51 release 2021-08-23 10:34:39 -04:00
zzz
63b3da265b javadoc fix 2021-08-23 09:21:24 -04:00
zzz
03f2cbfc89 bump -10 for review 2021-08-20 13:58:51 -04:00
zzz
7f5e7e54c0 Add Hungarian readme
fix routerconsole po files failing testscript
2021-08-20 13:19:42 -04:00
zzz
30aab77047 Pull translations from Transifex 2021-08-20 12:56:07 -04:00
zzz
367a35e531 refresh Debian patches 2021-08-20 09:28:29 -04:00
zzz
76a48f5983 GeoIP 2021-08-01
BuildTime update
2021-08-20 09:08:43 -04:00
idk
6a1ad6bef5 line up margin for unordered list on susidns.css 2021-08-18 16:50:08 -04:00
zzz
ef947e2dbc spelling fix 2021-08-14 09:38:42 -04:00
zzz
de73dec4b8 Crypto: Fix corruption of EC and DSA private keys on Java 17
Update test to try all key types
2021-08-13 10:15:24 -04:00
zzz
4938e13f0e poupdate-source 2021-08-11 11:38:49 -04:00
zzz
dc48afe89d Remove dead links 2021-08-11 08:18:40 -04:00
idk
15cfa147a6 Add descriptions of the address book section to the front page in susidns. This is the last string change I intend to check in for this cycle. 2021-08-10 16:10:07 -04:00
zzz
7d1656c20f UPnP: Fix construction of absolute URLs
where the service relative URL is an absolute path
and the location absolute URL is below the top level.
Fixes communication with "Freebox" UPnP routers.
ref: http://zzz.i2p/topics/3157
2021-08-07 08:39:05 -04:00
zzz
2cb0650980 javadoc fix 2021-08-03 08:37:41 -04:00
zzz
cf38697774 Update: Show restart button after an update is handled by a post-processor 2021-08-02 11:36:38 -04:00
zzz
f2b878d02a Data: Remove unused static field deprecated long ago 2021-07-30 12:17:15 -04:00
zzz
877b1f5f56 Build: Add resources to dependencies
remove unused systray icons
2021-07-30 10:35:12 -04:00
zzz
a634a9e3cf Util: DoH server list update 2021-07-30 10:12:59 -04:00
zzz
c652d597c9 Tunnels: Prop. 157 updates
- Enable handling
- Remove option to disable garlic reply
- Add option to enable sending
2021-07-29 09:51:21 -04:00
zzz
9db50256a8 Console: whitespace fix 2021-07-28 11:11:46 -04:00
zzz
2edac95be9 Tunnels: Updates for proposal 157
- Fix compatibility check for OB tunnels
- Add test code to send STBM to explicit peers
- Skip too-many-tunnels check when in test mode
- Cleanups and Log tweaks
2021-07-28 11:09:51 -04:00
idk
d246689242 Address some font size, section size, and spacing issues on proxy.css 2021-07-23 17:01:52 -04:00
zzz
6eb1510324 Transport: Fix UPnP IPv6 NPE
ref: http://zzz.i2p/topics/3153
2021-07-23 11:07:59 -04:00
zzz
24ef2b5189 Prop. 157 fix for ChaCha20 IV
after testing with i2pd
2021-07-22 15:15:26 -04:00
zzz
2b3a0f0232 bump -5 2021-07-20 10:52:33 -04:00
zzz
cd7c2efda8 build doc update 2021-07-20 10:50:13 -04:00
zzz
ca879f04e3 javadoc 2021-07-20 10:49:14 -04:00
zzz
369c40322e Make method static 2021-07-20 10:47:50 -04:00
zzz
3244fe1b0f Tunnels: Add check for prop. 157 layer enc. type 2021-07-20 10:44:38 -04:00
zzz
6b2a4a8fda Streaming: remove unneeded returns 2021-07-20 10:39:59 -04:00
zzz
83e67ad9d8 Sybil: Increase min display points 2021-07-20 10:37:08 -04:00
zzz
9f0d6c302f Router: New blocklist entries
as reported by drzed
2021-07-20 10:34:57 -04:00
zzz
d42d41ce0a Util: Check java versions up to 17 2021-07-20 10:33:53 -04:00
zzz
7ff6373d0c Output stream to string optimizations 2021-07-20 10:31:52 -04:00
zzz
3bf3a4ff9d NetDB: Increase min ff version to 0.9.38
previously was .38 for LS2 stores/lookups only
2021-07-20 10:26:17 -04:00
idk
4c5823ecb7 remove console.css lines from build.xml 2021-07-20 09:22:36 -04:00
idk
8b95aa9652 Merge branch 'proxy-css' into 'master'
Proxy Error Page CSS

Closes #330

See merge request i2p-hackers/i2p.i2p!34
2021-07-19 18:30:52 +00:00
idk
71ccd10ba6 Proxy Error Page CSS 2021-07-19 18:30:52 +00:00
zzz
426fbcbfa3 Prop 157 updates
- Fix registration of reply key/tag with SKM
- Allow OTBRM down client tunnel
- Disable tunnel hop throttles for allowLocal
- Various cleanups
2021-07-18 14:22:57 -04:00
zzz
a7d9ca920f Prop 157 updates
- Don't require AES keys for short records
- Derive keys from noise ck
- Use derived keys to garlic-encrypt reply at OBEP
- Register reply key with SKM
- Only use short message for client tunnels if client supports EC
- Set nonce for chacha/poly reply record
- Add tagsReceived() for single tag to MuxedSKM
- Add extended TunnelCreatorConfig.toStringFull()
- BRR toString() enhancements
- Test enhancements
2021-07-16 12:28:04 -04:00
idk
f40eff6b7e Merge branch 'master' of 127.0.0.1:i2p-hackers/i2p.i2p 2021-07-14 15:34:45 -04:00
idk
187ebf4c4a remove echelon.i2p from the English-language readme.html 2021-07-14 14:43:35 -04:00
zzz
1e7b13db66 HopConfig: Remove unused reply fields
previously moved to TunnelCreatorConfig
toString() enhancements
2021-07-14 10:51:57 -04:00
zzz
bc13f64403 Prop. 157 javadoc updates 2021-07-13 11:32:11 -04:00
zzz
617fff175e Tunnels: Prop. 157 updates
- remove ITBM
- remove plaintext slot from OTBRM
2021-07-13 09:47:30 -04:00
zzz
8710aa0065 Fix package for new "filter" 2021-07-13 08:23:32 -04:00
idk
558aa6e421 Merge branch 'x-i2p-location' into 'master'
Adds an X-I2P-Location header filter to the default I2P site

See merge request i2p-hackers/i2p.i2p!22
2021-07-12 14:21:23 +00:00
idk
1911132f11 Adds an X-I2P-Location header filter to the default I2P site 2021-07-12 14:21:23 +00:00
zzz
373924e650 Streaming: Reduce immediate ack delay 2021-07-07 08:31:17 -04:00
zzz
9c74cafd92 UPnP: IPv6 address validation fix 2021-07-02 07:51:01 -04:00
zzz
e88eed760d Streaming: Minor cleanups
- Remove unused stream.trend stat
- Optimization of getting first value from TreeMap
- Only notify reader of input stream when new data available
2021-06-27 11:50:20 -04:00
zzz
b7322e1647 Tests: Add resources to test jars
Fix duplicate classes in i2ptest.jar
Change classpath in routertest.jar to point to i2ptest.jar
2021-06-22 10:00:44 -04:00
zzz
bb19fcdac3 Tunnels: Changes for new build messages (Prop. 157)
- Remove ITBM, change record length from 236 to 218 bytes
- Fix check of blank record in BuildReplyHandler
- Fix offset constants for short record in BuildRequestRecord
- Fix BuildMessageTestStandalone test 6 (short inbound)
- ITBM class removal TODO
2021-06-22 09:06:40 -04:00
zzz
d71a472367 fix deprecation in test 2021-06-21 12:06:29 -04:00
zzz
e5186b0f7b Improve error handling on sort 2021-06-20 09:39:12 -04:00
zzz
fd6219356d Jetty: Case-insensitive sort on directory listing, put directories first 2021-06-20 09:28:10 -04:00
zzz
ea8597d1fb Console: Add preliminary Permissions-Policy header
other places TODO
2021-06-18 09:58:57 -04:00
zzz
970be35084 Transport: Remove 4/6 caps config
since 0.9.50 is out.
Log tweaks
2021-06-18 09:23:22 -04:00
zzz
c65b4689d0 SSU: Fix handling of bad peer test responses
Always abort test with an unknown result,
to prevent false firewalled indication.
Log tweaks
2021-06-18 09:11:42 -04:00
zzz
7628168c3d Tunnels: Consolidate tunnel key generation
in BuildRequestor.createTunnelBuildMessage()
to prep for derived keys in prop. 157
2021-06-17 12:58:46 -04:00
zzz
65b57fed9f minor css fix on /stats 2021-06-16 09:50:39 -04:00
zzz
67288f27b6 Crypto: Increase key pools for slow machines
Increase EDH key pool for all
Return unused EDH keys to XDH pool
ref: http://zzz.i2p/topics/3139
2021-06-16 09:50:04 -04:00
zzz
10cc00a9c8 Console: Format news dates using DataHelper 2021-06-16 09:08:44 -04:00
zzz
2cbb9b44ea Unused field 2021-06-16 09:00:53 -04:00
zzz
f9e8fa8150 Tunnels: Continue work on prop. 157
- Add new internal-only ShortTunnelBuildReplyMessage,
  for processing of STBM as a reply.
- Add support for inbound tunnel tests to TunnelBuildMessageStandalone.
  The ITBM test is WIP.
- Add checks for unset plaintext record in ITBM and OTBRM
2021-06-13 15:28:48 -04:00
zzz
aa0e0b3a62 Tunnels: Change class of TunnelPoolSettings random key
from Hash to SessionKey. It's not a Hash.
2021-06-13 11:34:17 -04:00
zzz
4c6aa8cfc1 Tests: Add serialize/deserialize test for STBM/OTBRM 2021-06-13 10:52:42 -04:00
zzz
010d1a9953 Tunnels: Continue work on new build messages (proposal #157)
WIP, still disabled, proposal not complete

- Use ChaCha20 to encrypt/decrypt records
- Add OTBRM methods for plaintext record
- Add OTBRM checks for correct plaintext slot number
- Add BRR checks to prevent use of nonexistent AES key/IV
- Set plaintext reply at OBEP in BuildHandler
- Allow OTBRM in InboundMessageDistributor
- Remove timing measurements in BuildMessageProcessor.decrypt()
- Add test to BuildMessageTestStandalone for outbound build
- Add check for all replies to BuildMessageTestStandalone
- Log tweaks
2021-06-13 10:31:02 -04:00
zzz
3fbfb689af Tests: Add ECIES test to BuildMessageTestStandalone 2021-06-12 16:20:07 -04:00
zzz
2bb3cf046d Tests: Fix BuildMessageTestStandalone 2021-06-12 15:42:47 -04:00
zzz
988e0e796f Tests: Fixup tunnel test after build classes move 2021-06-12 10:45:18 -04:00
zzz
d93e16e52e UPnP: Bind to IPv6 addresses for search responses
Older miniupnpd 2.0 will send a SSDP search response with an IPv6 location to a IPv4 address,
but newer ones 2.2 won't. So we need to also bind to an IPv6 address for the SSDP search
to receive the router's IPv6 location. Then we can bind to our public IPv6 address
for a port forward and it will work when miniupnpd is configured for "secure".

Also, don't bind a POST request to a mismatched v4/v6 address.
2021-06-11 09:29:16 -04:00
zzz
d5a499591d Update: Make backup news URL configurable (see gitlab MR !33) 2021-06-10 12:36:52 -04:00
zzz
41c8f6d0d5 Merge branch 'dmg' into 'master'
Add support for dmg and exe updates

See merge request i2p-hackers/i2p.i2p!33
2021-06-10 16:18:31 +00:00
zzz
b73d5d6557 Add support for dmg and exe updates 2021-06-10 16:18:31 +00:00
zzz
4f12081b59 Tunnels: Move 3 build classes from tunnel to tunnel/pool
and make package private, so all the tunnel build classes are in one place.
2021-06-08 12:47:28 -04:00
zzz
ad48ff61f3 Console: Change all config page headers to "Configuration" 2021-06-08 10:25:00 -04:00
zzz
4aef8d66e3 Console: Remove "configure homepage" item from /home 2021-06-08 10:19:18 -04:00
zzz
2f371301ad NetDB: Prevent rare deadlock in rebuildRouterInfo()
by making it always nonblocking.
as reported by drzed
2021-06-08 10:06:41 -04:00
zzz
c2c922b665 Tunnels: Switch from SHA256 to SipHash for arbitrary deterministic sort
of peers. For efficiency.
ref: http://zzz.i2p/topics/3082
thx: jogger
2021-06-08 09:44:17 -04:00
zzz
aee9a3f639 Tunnels: Extend use of high cap peers in expl. tunnels at startup, after extended downtime 2021-06-08 09:28:15 -04:00
zzz
d9c98580d1 Continue implementation of short tunnel build messages (proposal 157)
- Generate and parse short record format
- Encrypt and decrypt short records
- Register handlers for 3 new messages ITBM/STBM/OTBRM
- Send ITBM/STBM if all hops support it (disabled)
- Reply with OTBRM at OBEP if STBM received (disabled)
- Send STBM at IBGW if ITBM received (disabled)
- Add logic for when to send new messages
- ChaCha encryption of other short records
- Fix compare logic in ITBM parser (ticket #2814)

All is still preliminary, disabled, untested; proposal is still incomplete

Still todo:
- Fill in plaintext record for ITBM/OTBRM
- OTBRM key/tag
2021-06-08 08:43:40 -04:00
zzz
8b4a93554f Router: Fix JobQueue getLastJobBegin() and getLastJobEnd() (ticket #2809) 2021-06-01 09:32:21 -04:00
zzz
f9b5ee697c Transport: Consolidate now() calls 2021-06-01 09:01:40 -04:00
zzz
6dab5b44ae unused import 2021-06-01 08:53:29 -04:00
zzz
e7bef3f4e8 Console: Fix deprecation in rrd4j 2021-06-01 08:51:16 -04:00
zzz
ff44ba4e07 i2psnark: Fix autostart for magnets 2021-06-01 08:50:18 -04:00
zzz
b88c8a4f6a UPnP: Fix IPv6 address check (ticket #2811) 2021-05-23 07:38:28 -04:00
zzz
58aa95df87 Router: Increase rekey probability 2021-05-21 09:52:26 -04:00
zzz
56a1184da7 Build: Update RRD4J version in manifest 2021-05-21 09:48:21 -04:00
zzz
ecc8b2a1c6 Console: Don't show default cost for NTCP2 either 2021-05-21 09:47:43 -04:00
zzz
288170a728 Console: Remove unused H cap from legend 2021-05-21 09:02:58 -04:00
zzz
b9efc002c0 RRD4J 3.8
Merged in our previous javadoc fixes
Their updated font-selector code remains commented
out in RrdGraphConstants.getFont()
Now requires Java 8
2021-05-21 07:36:57 -04:00
zzz
6926f5769e Systray: Drop unused BrowserChooser 2021-05-20 09:04:26 -04:00
zzz
9036aa84f6 Build: Remove broken list-changes targets 2021-05-20 08:56:21 -04:00
zzz
557c1d0f04 Console: Make the /confighome headers match the home page headers
Fix padding on file chooser buttons
2021-05-20 08:47:20 -04:00
zzz
2bb14c317f Debian files for 0.9.50
checklist updates
2021-05-19 09:50:47 -04:00
1030 changed files with 146753 additions and 107421 deletions

34
.github/workflows/ant.yml vendored Normal file
View File

@ -0,0 +1,34 @@
# Mostly copied from https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-ant
# zlatinb
name: Java CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'temurin'
- name : Generate override.properties
run: |
rm -f override.properties
echo "build.built-by=GitHub Actions" >> override.properties
echo "noExe=true" >> override.properties
- name: build with Ant
run: ant distclean pkg
- name: Upload installer.jar
uses: actions/upload-artifact@v2
with:
name: I2P-install.jar-${{ github.sha }}
path: install.jar

View File

@ -9,6 +9,7 @@ trans.cs = apps/i2ptunnel/locale/messages_cs.po
trans.da = apps/i2ptunnel/locale/messages_da.po
trans.de = apps/i2ptunnel/locale/messages_de.po
trans.es = apps/i2ptunnel/locale/messages_es.po
trans.es_AR = apps/i2ptunnel/locale/messages_es_AR.po
trans.fa = apps/i2ptunnel/locale/messages_fa.po
trans.fi = apps/i2ptunnel/locale/messages_fi.po
trans.fr = apps/i2ptunnel/locale/messages_fr.po
@ -43,6 +44,7 @@ trans.cs = apps/i2ptunnel/locale-proxy/messages_cs.po
trans.de = apps/i2ptunnel/locale-proxy/messages_de.po
trans.el = apps/i2ptunnel/locale-proxy/messages_el.po
trans.es = apps/i2ptunnel/locale-proxy/messages_es.po
trans.es_AR = apps/i2ptunnel/locale-proxy/messages_es_AR.po
trans.fa = apps/i2ptunnel/locale-proxy/messages_fa.po
trans.fi = apps/i2ptunnel/locale-proxy/messages_fi.po
trans.fr = apps/i2ptunnel/locale-proxy/messages_fr.po
@ -66,6 +68,7 @@ trans.tr_TR = apps/i2ptunnel/locale-proxy/messages_tr.po
trans.uk_UA = apps/i2ptunnel/locale-proxy/messages_uk.po
trans.vi = apps/i2ptunnel/locale-proxy/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale-proxy/messages_zh.po
trans.zh_TW = apps/i2ptunnel/locale-proxy/messages_zh_TW.po
[I2P.core]
type = PO
@ -96,6 +99,7 @@ trans.pt = core/locale/messages_pt.po
trans.pt_BR = core/locale/messages_pt_BR.po
trans.ro = core/locale/messages_ro.po
trans.ru_RU = core/locale/messages_ru.po
trans.sl = core/locale/messages_sl.po
trans.sv_SE = core/locale/messages_sv.po
trans.tk = core/locale/messages_tk.po
trans.tr_TR = core/locale/messages_tr.po
@ -115,6 +119,7 @@ trans.da = router/locale/messages_da.po
trans.de = router/locale/messages_de.po
trans.el = router/locale/messages_el.po
trans.es = router/locale/messages_es.po
trans.es_AR = router/locale/messages_es_AR.po
trans.et_EE = router/locale/messages_et.po
trans.fa = router/locale/messages_fa.po
trans.fi = router/locale/messages_fi.po
@ -133,6 +138,7 @@ trans.pt = router/locale/messages_pt.po
trans.pt_BR = router/locale/messages_pt_BR.po
trans.ro = router/locale/messages_ro.po
trans.ru_RU = router/locale/messages_ru.po
trans.sl = router/locale/messages_sl.po
trans.sv_SE = router/locale/messages_sv.po
trans.tk = router/locale/messages_tk.po
trans.tr_TR = router/locale/messages_tr.po
@ -151,6 +157,7 @@ trans.da = apps/routerconsole/locale/messages_da.po
trans.de = apps/routerconsole/locale/messages_de.po
trans.el = apps/routerconsole/locale/messages_el.po
trans.es = apps/routerconsole/locale/messages_es.po
trans.es_AR = apps/routerconsole/locale/messages_es_AR.po
trans.et_EE = apps/routerconsole/locale/messages_et.po
trans.fa = apps/routerconsole/locale/messages_fa.po
trans.fi = apps/routerconsole/locale/messages_fi.po
@ -184,6 +191,7 @@ trans.cs = apps/routerconsole/locale-news/messages_cs.po
trans.de = apps/routerconsole/locale-news/messages_de.po
trans.el = apps/routerconsole/locale-news/messages_el.po
trans.es = apps/routerconsole/locale-news/messages_es.po
trans.es_AR = apps/routerconsole/locale-news/messages_es_AR.po
trans.fa = apps/routerconsole/locale-news/messages_fa.po
trans.fi = apps/routerconsole/locale-news/messages_fi.po
trans.fr = apps/routerconsole/locale-news/messages_fr.po
@ -206,6 +214,7 @@ trans.pt_BR = apps/routerconsole/locale-news/messages_pt_BR.po
trans.ro = apps/routerconsole/locale-news/messages_ro.po
trans.ru_RU = apps/routerconsole/locale-news/messages_ru.po
trans.sk = apps/routerconsole/locale-news/messages_sk.po
trans.sl = apps/routerconsole/locale-news/messages_sl.po
trans.sq = apps/routerconsole/locale-news/messages_sq.po
trans.sr = apps/routerconsole/locale-news/messages_sr.po
trans.sv_SE = apps/routerconsole/locale-news/messages_sv.po
@ -228,6 +237,7 @@ trans.da = apps/routerconsole/locale-countries/messages_da.po
trans.de = apps/routerconsole/locale-countries/messages_de.po
trans.el = apps/routerconsole/locale-countries/messages_el.po
trans.es = apps/routerconsole/locale-countries/messages_es.po
trans.es_AR = apps/routerconsole/locale-countries/messages_es_AR.po
trans.et_EE = apps/routerconsole/locale-countries/messages_et.po
trans.fa = apps/routerconsole/locale-countries/messages_fa.po
trans.fi = apps/routerconsole/locale-countries/messages_fi.po
@ -253,6 +263,7 @@ trans.pt_BR = apps/routerconsole/locale-countries/messages_pt_BR.po
trans.ro = apps/routerconsole/locale-countries/messages_ro.po
trans.ru_RU = apps/routerconsole/locale-countries/messages_ru.po
trans.sk = apps/routerconsole/locale-countries/messages_sk.po
trans.sl = apps/routerconsole/locale-countries/messages_sl.po
trans.sq = apps/routerconsole/locale-countries/messages_sq.po
trans.sr = apps/routerconsole/locale-countries/messages_sr.po
trans.sv_SE = apps/routerconsole/locale-countries/messages_sv.po
@ -271,6 +282,7 @@ trans.cs = apps/i2psnark/locale/messages_cs.po
trans.de = apps/i2psnark/locale/messages_de.po
trans.el = apps/i2psnark/locale/messages_el.po
trans.es = apps/i2psnark/locale/messages_es.po
trans.es_AR = apps/i2psnark/locale/messages_es_AR.po
trans.fa = apps/i2psnark/locale/messages_fa.po
trans.fi = apps/i2psnark/locale/messages_fi.po
trans.fr = apps/i2psnark/locale/messages_fr.po
@ -305,6 +317,7 @@ trans.da = apps/susidns/locale/messages_da.po
trans.de = apps/susidns/locale/messages_de.po
trans.el = apps/susidns/locale/messages_el.po
trans.es = apps/susidns/locale/messages_es.po
trans.es_AR = apps/susidns/locale/messages_es_AR.po
trans.fa = apps/susidns/locale/messages_fa.po
trans.fi = apps/susidns/locale/messages_fi.po
trans.fr = apps/susidns/locale/messages_fr.po
@ -361,6 +374,7 @@ trans.pt_BR = apps/desktopgui/locale/messages_pt_BR.po
trans.ro = apps/desktopgui/locale/messages_ro.po
trans.ru_RU = apps/desktopgui/locale/messages_ru.po
trans.sk = apps/desktopgui/locale/messages_sk.po
trans.sl = apps/desktopgui/locale/messages_sl.po
trans.sr = apps/desktopgui/locale/messages_sr.po
trans.sv_SE = apps/desktopgui/locale/messages_sv.po
trans.sq = apps/desktopgui/locale/messages_sq.po
@ -383,6 +397,7 @@ trans.da = apps/susimail/locale/messages_da.po
trans.de = apps/susimail/locale/messages_de.po
trans.el = apps/susimail/locale/messages_el.po
trans.es = apps/susimail/locale/messages_es.po
trans.es_AR = apps/susimail/locale/messages_es_AR.po
trans.fa = apps/susimail/locale/messages_fa.po
trans.fi = apps/susimail/locale/messages_fi.po
trans.fr = apps/susimail/locale/messages_fr.po
@ -423,6 +438,7 @@ trans.cs = debian/po/cs.po
trans.de = debian/po/de.po
trans.el = debian/po/el.po
trans.es = debian/po/es.po
trans.es_AR = debian/po/es_AR.po
trans.fi = debian/po/fi.po
trans.fr = debian/po/fr.po
trans.gl = debian/po/gl.po
@ -439,6 +455,7 @@ trans.pt_BR = debian/po/pt_BR.po
trans.ro = debian/po/ro.po
trans.ru_RU = debian/po/ru.po
trans.sk = debian/po/sk.po
trans.sl = debian/po/sl.po
trans.sq = debian/po/sq.po
trans.sv_SE = debian/po/sv.po
trans.tk = debian/po/tk.po
@ -455,6 +472,7 @@ trans.az = installer/resources/locale/po/messages_az.po
trans.ca = installer/resources/locale/po/messages_ca.po
trans.de = installer/resources/locale/po/messages_de.po
trans.es = installer/resources/locale/po/messages_es.po
trans.es_AR = installer/resources/locale/po/messages_es_AR.po
trans.fi = installer/resources/locale/po/messages_fi.po
trans.fr = installer/resources/locale/po/messages_fr.po
trans.id = installer/resources/locale/po/messages_id.po
@ -473,6 +491,7 @@ trans.sv_SE = installer/resources/locale/po/messages_sv.po
trans.tr_TR = installer/resources/locale/po/messages_tr.po
trans.uk_UA = installer/resources/locale/po/messages_uk.po
trans.zh_CN = installer/resources/locale/po/messages_zh.po
trans.zh_TW = installer/resources/locale/po/messages_zh_TW.po
[I2P.getopt]
;;
@ -499,6 +518,7 @@ trans.az = core/java/src/gnu/getopt/MessagesBundle_az.properties
trans.cs = core/java/src/gnu/getopt/MessagesBundle_cs.properties
trans.de = core/java/src/gnu/getopt/MessagesBundle_de.properties
trans.es = core/java/src/gnu/getopt/MessagesBundle_es.properties
trans.es_AR = core/java/src/gnu/getopt/MessagesBundle_es_AR.properties
trans.fi = core/java/src/gnu/getopt/MessagesBundle_fi.properties
trans.fr = core/java/src/gnu/getopt/MessagesBundle_fr.properties
trans.gl = core/java/src/gnu/getopt/MessagesBundle_gl.properties
@ -517,6 +537,7 @@ trans.pt_BR = core/java/src/gnu/getopt/MessagesBundle_pt_BR.properties
trans.ro = core/java/src/gnu/getopt/MessagesBundle_ro.properties
trans.ru_RU = core/java/src/gnu/getopt/MessagesBundle_ru.properties
trans.sk = core/java/src/gnu/getopt/MessagesBundle_sk.properties
trans.sl = core/java/src/gnu/getopt/MessagesBundle_sl.properties
trans.sq = core/java/src/gnu/getopt/MessagesBundle_sq.properties
trans.sr = core/java/src/gnu/getopt/MessagesBundle_sr.properties
trans.sv_SE = core/java/src/gnu/getopt/MessagesBundle_sv.properties
@ -534,6 +555,7 @@ trans.ca = apps/ministreaming/locale/messages_ca.po
trans.cs = apps/ministreaming/locale/messages_cs.po
trans.de = apps/ministreaming/locale/messages_de.po
trans.es = apps/ministreaming/locale/messages_es.po
trans.es_AR = apps/ministreaming/locale/messages_es_AR.po
trans.fa = apps/ministreaming/locale/messages_fa.po
trans.fi = apps/ministreaming/locale/messages_fi.po
trans.fr = apps/ministreaming/locale/messages_fr.po
@ -550,11 +572,13 @@ trans.pt = apps/ministreaming/locale/messages_pt.po
trans.pt_BR = apps/ministreaming/locale/messages_pt_BR.po
trans.ro = apps/ministreaming/locale/messages_ro.po
trans.ru_RU = apps/ministreaming/locale/messages_ru.po
trans.sl = apps/ministreaming/locale/messages_sl.po
trans.sv_SE = apps/ministreaming/locale/messages_sv.po
trans.tk = apps/ministreaming/locale/messages_tk.po
trans.tr_TR = apps/ministreaming/locale/messages_tr.po
trans.uk_UA = apps/ministreaming/locale/messages_uk.po
trans.zh_CN = apps/ministreaming/locale/messages_zh.po
trans.zh_TW = apps/ministreaming/locale/messages_zh_TW.po
[I2P.manpages]
;;
@ -568,10 +592,13 @@ trans.ar = installer/resources/locale-man/man_ar.po
trans.az = installer/resources/locale-man/man_az.po
trans.de = installer/resources/locale-man/man_de.po
trans.es = installer/resources/locale-man/man_es.po
trans.es_AR = installer/resources/locale-man/man_es_AR.po
trans.fi = installer/resources/locale-man/man_fi.po
trans.fr = installer/resources/locale-man/man_fr.po
trans.hu = installer/resources/locale-man/man_hu.po
trans.id = installer/resources/locale-man/man_id.po
trans.it = installer/resources/locale-man/man_it.po
trans.ja = installer/resources/locale-man/man_ja.po
trans.ko = installer/resources/locale-man/man_ko.po
trans.nl = installer/resources/locale-man/man_nl.po
trans.pl = installer/resources/locale-man/man_pl.po
@ -582,6 +609,7 @@ trans.ru_RU = installer/resources/locale-man/man_ru.po
trans.sv_SE = installer/resources/locale-man/man_sv.po
trans.tr_TR = installer/resources/locale-man/man_tr.po
trans.zh_CN = installer/resources/locale-man/man_zh.po
trans.zh_TW = installer/resources/locale-man/man_zh_TW.po
[I2P.eepsite]
;;
@ -621,12 +649,16 @@ trans.zh_CN = installer/resources/eepsite/docroot/help/index_zh.html
;;
;; Text on /console
;;
;; NOTE: No support for country suffixes right now.
;; See ResourceHelper.java
;;
type = HTML
source_file = apps/routerconsole/resources/docs/readme.html
source_lang = en
trans.ar = apps/routerconsole/resources/docs/readme_ar.html
trans.de = apps/routerconsole/resources/docs/readme_de.html
trans.fr = apps/routerconsole/resources/docs/readme_fr.html
trans.hu = apps/routerconsole/resources/docs/readme_hu.html
;; Java converts id to in
trans.id = apps/routerconsole/resources/docs/readme_in.html
trans.it = apps/routerconsole/resources/docs/readme_it.html
@ -635,9 +667,11 @@ trans.pl = apps/routerconsole/resources/docs/readme_pl.html
trans.pt = apps/routerconsole/resources/docs/readme_pt.html
trans.ro = apps/routerconsole/resources/docs/readme_ro.html
trans.ru_RU = apps/routerconsole/resources/docs/readme_ru.html
trans.sl = apps/routerconsole/resources/docs/readme_sl.html
trans.tr_TR = apps/routerconsole/resources/docs/readme_tr.html
trans.uk_UA = apps/routerconsole/resources/docs/readme_uk.html
trans.zh_CN = apps/routerconsole/resources/docs/readme_zh.html
trans.zh_TW = apps/routerconsole/resources/docs/readme_zh_TW.html
[main]
host = https://www.transifex.com

View File

@ -1,5 +1,25 @@
# I2P in Docker
### Very quick start
If you just want to give I2P a quick try or are using it on a home network, follow these steps:
1. Create two directories `i2pconfig` and `i2ptorrents`
2. Copy the following text and save it in a file `docker-compose.yml`
```
version: "3.5"
services:
i2p:
image: geti2p/i2p
network_mode: host
volumes:
- ./i2pconfig:/i2p/.i2p
- ./i2ptorrents:/i2psnark
```
3. Execute `docker-compose up`
4. Start a browser and go to `http://127.0.0.1:7657` to complete the setup wizard.
Note that this quick-start approach is not recommended for production deployments on remote servers. Please read the rest of this document for more information.
### Building an image
There is an i2P image available over at [DockerHub](https://hub.docker.com). If you do not want to use that one, you can build one yourself:
```
@ -17,21 +37,26 @@ By the default the image limits the memory available to the Java heap to 512MB.
#### Ports
There are several ports which are exposed by the image. You can choose which ones to publish depending on your specific needs.
|Port|Description|TCP/UDP|
|---|---|---|
|4444|HTTP Proxy|TCP|
|4445|HTTPS Proxy|TCP|
|6668|IRC Proxy|TCP|
|7654|I2CP Protocol|TCP|
|7656|SAM Bridge TCP|TCP|
|7657|Router console|TCP|
|7658|I2P Site|TCP|
|7659|SMTP Proxy|TCP|
|7660|POP Proxy|TCP|
|12345|I2NP Protocol|TCP and UDP|
|Port|Interface|Description|TCP/UDP|
|---|---|---|---|
|4444|127.0.0.1|HTTP Proxy|TCP|
|4445|127.0.0.1|HTTPS Proxy|TCP|
|6668|127.0.0.1|IRC Proxy|TCP|
|7654|127.0.0.1|I2CP Protocol|TCP|
|7656|127.0.0.1|SAM Bridge TCP|TCP|
|7657|127.0.0.1|Router console|TCP|
|7658|127.0.0.1|I2P Site|TCP|
|7659|127.0.0.1|SMTP Proxy|TCP|
|7660|127.0.0.1|POP Proxy|TCP|
|7652|LAN interface|UPnP|TCP|
|7653|LAN interface|UPnP|UDP|
|12345|0.0.0.0|I2NP Protocol|TCP and UDP|
You probably want at least the Router Console (7657) and the HTTP Proxy (4444). If you want I2P to be able to receive incoming connections from the internet, and hence not think it's firewalled, publish the I2NP Protocol port (12345) - but make sure you publish to a different random port, otherwise others may be able to guess you're running I2P in a Docker image.
#### Networking
A best-practices guide for cloud deployments is beyond the scope of this document, but in general you should try to minimize the number of published ports, while exposing only the `I2NP` ports to the internet. That means that the services in the list above which are bound to `127.0.0.1` (which include the router console) will need to be accessed via other methods like ssh tunneling or be manually configured to bind to a different interface.
#### Example
Here is an example container that mounts `i2phome` as home directory, `i2ptorrents` for torrents, and opens HTTP Proxy, IRC, Router Console and I2NP Protocols. It also limits the memory available to the JVM to 256MB.
```

View File

@ -1,19 +1,19 @@
FROM jlesage/baseimage:alpine-3.10-glibc as builder
FROM jlesage/baseimage:alpine-3.15-glibc as builder
ENV APP_HOME="/i2p"
WORKDIR /tmp/build
COPY . .
RUN add-pkg --virtual build-base gettext tar bzip2 apache-ant openjdk8 \
RUN add-pkg --virtual build-base gettext tar bzip2 apache-ant openjdk17 \
&& ant preppkg-linux-only \
&& rm -rf pkg-temp/osid pkg-temp/lib/wrapper pkg-temp/lib/wrapper.* \
&& del-pkg build-base gettext tar bzip2 apache-ant openjdk8
&& del-pkg build-base gettext tar bzip2 apache-ant openjdk17
FROM jlesage/baseimage:alpine-3.10-glibc
FROM jlesage/baseimage:alpine-3.15-glibc
ENV APP_HOME="/i2p"
RUN add-pkg openjdk8-jre
RUN add-pkg openjdk17-jre
WORKDIR ${APP_HOME}
COPY --from=builder /tmp/build/pkg-temp .

View File

@ -212,10 +212,6 @@ Applications:
Copyright (c) 2006, Matthew Estes
See licenses/LICENSE-BlockFile.txt
BOB (BOB.jar):
Copyright (C) sponge
See licenses/COPYING-BOB.txt
Desktopgui (desktopgui.jar):
Copyright (c) Mathias De Maré
See licenses/LICENSE-DesktopGUI.txt
@ -264,14 +260,14 @@ Applications:
Zxing 3.4.1:
See licenses/LICENSE-Apache2.0.txt
Jetty 9.3.29.v20201019 (jetty-*.jar, org.mortbay.*.jar):
Jetty 9.3.30.v20211001 (jetty-*.jar, org.mortbay.*.jar):
(not included in most distribution packages, except for jetty-i2p.jar)
See licenses/ABOUT-Jetty.html
See licenses/NOTICE-Jetty.html
See licenses/LICENSE-Apache2.0.txt
See licenses/LICENSE-ECLIPSE-1.0.html
RRD4J 3.6 (jrobin.jar):
RRD4J 3.8 (jrobin.jar):
Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
Copyright (c) 2011 The OpenNMS Group, Inc.
Copyright 2011 The RRD4J Authors.
@ -339,9 +335,9 @@ Applications:
Systray (systray.jar):
Public domain.
Tomcat 9.0.45 (jasper-runtime.jar):
Tomcat 9.0.62 (jasper-runtime.jar):
(not included in most distribution packages)
Copyright 1999-2020 The Apache Software Foundation
Copyright 1999-2022 The Apache Software Foundation
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Tomcat.txt

View File

@ -64,13 +64,16 @@ your `~/.gradle/gradle.properties`:
systemProp.socksProxyHost=localhost
systemProp.socksProxyPort=9150
### Development builds
Automatic CI builds are available at the [continuous integration](https://github.com/i2p/i2p.i2p/actions/workflows/ant.yml) page.
### Docker
For more information how to run I2P in Docker, see [Docker.md](Docker.md)
## Contact info
Need help? See the IRC channel #i2p on irc.freenode.net
Bug reports: [https://trac.i2p2.de/report/1](https://trac.i2p2.de/report/1)
Bug reports: [https://i2pgit.org/i2p-hackers/i2p.i2p/-/issues](https://i2pgit.org/i2p-hackers/i2p.i2p/-/issues) [http://git.idk.i2p/i2p-hackers/i2p.i2p/-/issues](http://git.idk.i2p/i2p-hackers/i2p.i2p/-/issues)
Contact information, security issues, press inquiries: [https://geti2p.net/en/contact](https://geti2p.net/en/contact)

View File

@ -47,7 +47,8 @@ Need help?
IRC irc.freenode.net #i2p
Bug reports:
https://trac.i2p2.de/report/1
https://i2pgit.org/i2p-hackers/i2p.i2p/-/issues
http://git.idk.i2p/i2p-hackers/i2p.i2p/-/issues
Contact information, security issues, press inquiries:
https://geti2p.net/en/contact

View File

@ -1,14 +0,0 @@
#bob.config
#Tue Dec 30 00:00:00 UTC 2008
# Please leave this file here for testing.
# Thank you,
# Sponge
i2cp.tcp.port=7654
BOB.host=localhost
inbound.lengthVariance=0
i2cp.messageReliability=BestEffort
BOB.port=45678
outbound.length=1
inbound.length=1
outbound.lengthVariance=0
i2cp.tcp.host=localhost

View File

@ -1,12 +0,0 @@
sourceSets {
main {
java {
srcDir 'src'
}
}
}
dependencies {
compile project(':core')
compile project(':apps:ministreaming')
}

View File

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="BOB" default="default" basedir=".">
<description>Builds, tests, and runs the project BOB.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="BOB-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
<target depends="jar" description="Build BOB into a SINGLE JAR." name="onejar">
<!-- Make needed working dirs -->
<mkdir dir="${dist.dir}/lib" />
<mkdir dir="${dist.dir}/classes" />
<!-- Copy jars -->
<copy todir="${dist.dir}/lib" flatten="true" >
<path>
<pathelement path="${javac.classpath}" />
</path>
</copy>
<copy todir="${dist.dir}/lib" file="../../build/jbigi.jar" />
<!-- Extract the classes inside the jar files -->
<unjar dest="${dist.dir}/classes" >
<fileset dir="${dist.dir}/lib" >
<include name="**/*.jar" />
</fileset>
</unjar>
<!-- Recombine the classes into a new jar file -->
<jar jarfile="${dist.dir}/lib/all-in-one.jar" >
<fileset dir="${dist.dir}/classes" />
</jar>
<!-- Clean up work area -->
<delete dir="${dist.dir}/classes" followsymlinks="false" includeemptydirs="true"/>
<!-- Make the single jar file -->
<jar jarfile="dist/BOB-one.jar" >
<zipfileset src="${dist.jar}" excludes="META-INF/*" />
<zipfileset src="${dist.dir}/lib/all-in-one.jar" excludes="**/META-INF/*" />
<manifest>
<attribute name="Main-Class" value="net.i2p.BOB.Main" />
</manifest>
</jar>
<!-- Clean up the fake jar file -->
<delete file="${dist.dir}/lib/all-in-one.jar" />
</target>
</project>

View File

@ -1,3 +0,0 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

View File

@ -1,643 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
For the purpose of easier reading the script
is divided into following sections:
- initialization
- compilation
- jar
- execution
- debugging
- javadoc
- junit compilation
- junit execution
- junit debugging
- applet
- cleanup
-->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="BOB-impl">
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
<!--
======================
INITIALIZATION SECTION
======================
-->
<target name="-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init" name="-init-private">
<property file="nbproject/private/config.properties"/>
<property file="nbproject/private/configs/${config}.properties"/>
<property file="nbproject/private/private.properties"/>
</target>
<target depends="-pre-init,-init-private" name="-init-user">
<property file="${user.properties.file}"/>
<!-- The two properties below are usually overridden -->
<!-- by the active platform. Just a fallback. -->
<property name="default.javac.source" value="1.8"/>
<property name="default.javac.target" value="1.8"/>
<property name="javac.release" value="8"/>
</target>
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
<property file="nbproject/configs/${config}.properties"/>
<property file="nbproject/project.properties"/>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
<available file="${manifest.file}" property="manifest.available"/>
<condition property="manifest.available+main.class">
<and>
<isset property="manifest.available"/>
<isset property="main.class"/>
<not>
<equals arg1="${main.class}" arg2="" trim="true"/>
</not>
</and>
</condition>
<condition property="manifest.available+main.class+mkdist.available">
<and>
<istrue value="${manifest.available+main.class}"/>
<isset property="libs.CopyLibs.classpath"/>
</and>
</condition>
<condition property="have.tests">
<or>
<available file="${test.src.dir}"/>
</or>
</condition>
<condition property="have.sources">
<or>
<available file="${src.dir}"/>
</or>
</condition>
<condition property="netbeans.home+have.tests">
<and>
<isset property="netbeans.home"/>
<isset property="have.tests"/>
</and>
</condition>
<condition property="no.javadoc.preview">
<and>
<isset property="javadoc.preview"/>
<isfalse value="${javadoc.preview}"/>
</and>
</condition>
<property name="run.jvmargs" value=""/>
<property name="javac.compilerargs" value=""/>
<property name="work.dir" value="${basedir}"/>
<condition property="no.deps">
<and>
<istrue value="${no.dependencies}"/>
</and>
</condition>
<property name="javac.debug" value="true"/>
<property name="javadoc.preview" value="true"/>
<property name="application.args" value=""/>
<property name="source.encoding" value="${file.encoding}"/>
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
<and>
<isset property="javadoc.encoding"/>
<not>
<equals arg1="${javadoc.encoding}" arg2=""/>
</not>
</and>
</condition>
<property name="javadoc.encoding.used" value="${source.encoding}"/>
<property name="includes" value="**"/>
<property name="excludes" value=""/>
<property name="do.depend" value="false"/>
<condition property="do.depend.true">
<istrue value="${do.depend}"/>
</condition>
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
<and>
<isset property="jaxws.endorsed.dir"/>
<available file="nbproject/jaxws-build.xml"/>
</and>
</condition>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
<fail unless="src.dir">Must set src.dir</fail>
<fail unless="test.src.dir">Must set test.src.dir</fail>
<fail unless="build.dir">Must set build.dir</fail>
<fail unless="dist.dir">Must set dist.dir</fail>
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
<fail unless="dist.jar">Must set dist.jar</fail>
</target>
<target name="-init-macrodef-property">
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-javac">
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="${javac.debug}" name="debug"/>
<attribute default="/does/not/exist" name="sourcepath"/>
<element name="customize" optional="true"/>
<sequential>
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" release="${javac.release}">
<classpath>
<path path="@{classpath}"/>
</classpath>
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
<customize/>
</javac>
</sequential>
</macrodef>
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<sequential>
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</depend>
</sequential>
</macrodef>
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${build.classes.dir}" name="destdir"/>
<sequential>
<fail unless="javac.includes">Must set javac.includes</fail>
<pathconvert pathsep="," property="javac.includes.binary">
<path>
<filelist dir="@{destdir}" files="${javac.includes}"/>
</path>
<globmapper from="*.java" to="*.class"/>
</pathconvert>
<delete>
<files includes="${javac.includes.binary}"/>
</delete>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-junit">
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="**" name="testincludes"/>
<sequential>
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
<batchtest todir="${build.test.results.dir}">
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
</batchtest>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
<jvmarg line="${run.jvmargs}"/>
</junit>
</sequential>
</macrodef>
</target>
<target depends="-init-debug-args" name="-init-macrodef-nbjpda">
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="name"/>
<attribute default="${debug.classpath}" name="classpath"/>
<attribute default="" name="stopclassname"/>
<sequential>
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</nbjpdastart>
</sequential>
</macrodef>
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${build.classes.dir}" name="dir"/>
<sequential>
<nbjpdareload>
<fileset dir="@{dir}" includes="${fix.classes}">
<include name="${fix.includes}*.class"/>
</fileset>
</nbjpdareload>
</sequential>
</macrodef>
</target>
<target name="-init-debug-args">
<property name="version-output" value="java version &quot;${ant.java.version}"/>
<condition property="have-jdk-older-than-1.4">
<or>
<contains string="${version-output}" substring="java version &quot;1.0"/>
<contains string="${version-output}" substring="java version &quot;1.1"/>
<contains string="${version-output}" substring="java version &quot;1.2"/>
<contains string="${version-output}" substring="java version &quot;1.3"/>
</or>
</condition>
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
<istrue value="${have-jdk-older-than-1.4}"/>
</condition>
<condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
<os family="windows"/>
</condition>
<condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
<isset property="debug.transport"/>
</condition>
</target>
<target depends="-init-debug-args" name="-init-macrodef-debug">
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${main.class}" name="classname"/>
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="@{classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-java">
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="classname"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="${run.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}"/>
</jar>
</presetdef>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
<!--
===================
COMPILATION SECTION
===================
-->
<target depends="init" name="deps-jar" unless="no.deps"/>
<target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
<target depends="init" name="-check-automatic-build">
<available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
</target>
<target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
<antcall target="clean"/>
</target>
<target depends="init,deps-jar" name="-pre-pre-compile">
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="-pre-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-depend">
<j2seproject3:depend/>
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
<j2seproject3:javac/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
<target name="-pre-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile/>
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
</target>
<target name="-post-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
<!--
====================
JAR BUILDING SECTION
====================
-->
<target depends="init" name="-pre-pre-jar">
<dirname file="${dist.jar}" property="dist.jar.dir"/>
<mkdir dir="${dist.jar.dir}"/>
</target>
<target name="-pre-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
<j2seproject1:jar/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
<j2seproject1:jar manifest="${manifest.file}"/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
<j2seproject1:jar manifest="${manifest.file}">
<j2seproject1:manifest>
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
</j2seproject1:manifest>
</j2seproject1:jar>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<pathconvert property="run.classpath.with.dist.jar">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
</pathconvert>
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target name="-post-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
<!--
=================
EXECUTION SECTION
=================
-->
<target depends="init,compile" description="Run a main class." name="run">
<j2seproject1:java>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject1:java>
</target>
<target name="-do-not-recompile">
<property name="javac.includes.binary" value=""/>
</target>
<target depends="init,-do-not-recompile,compile-single" name="run-single">
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
<j2seproject1:java classname="${run.class}"/>
</target>
<!--
=================
DEBUGGING SECTION
=================
-->
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
<j2seproject1:nbjpdastart name="${debug.class}"/>
</target>
<target depends="init,compile" name="-debug-start-debuggee">
<j2seproject3:debug>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
</target>
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
<j2seproject3:debug classname="${debug.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
<target depends="init" name="-pre-debug-fix">
<fail unless="fix.includes">Must set fix.includes</fail>
<property name="javac.includes" value="${fix.includes}.java"/>
</target>
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
<j2seproject1:nbjpdareload/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
<!--
===============
JAVADOC SECTION
===============
-->
<target depends="init" name="-javadoc-build">
<mkdir dir="${dist.javadoc.dir}"/>
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
<classpath>
<path path="${javac.classpath}"/>
</classpath>
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
<filename name="**/*.java"/>
</fileset>
</javadoc>
</target>
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
</target>
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
<!--
=========================
JUNIT COMPILATION SECTION
=========================
-->
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
<mkdir dir="${build.test.classes.dir}"/>
</target>
<target name="-pre-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-test-depend">
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
<target name="-pre-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
<!--
=======================
JUNIT EXECUTION SECTION
=======================
-->
<target depends="init" if="have.tests" name="-pre-test-run">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
<j2seproject3:junit testincludes="**/*Test.java"/>
</target>
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init" if="have.tests" name="test-report"/>
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
<target depends="init" if="have.tests" name="-pre-test-run-single">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
<j2seproject3:junit excludes="" includes="${test.includes}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
<!--
=======================
JUNIT DEBUGGING SECTION
=======================
-->
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
<delete file="${test.report.file}"/>
<mkdir dir="${build.test.results.dir}"/>
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
<customize>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<arg value="${test.class}"/>
<arg value="showoutput=true"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
<!--
=========================
APPLET EXECUTION SECTION
=========================
-->
<target depends="init,compile-single" name="run-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject1:java classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject1:java>
</target>
<!--
=========================
APPLET DEBUGGING SECTION
=========================
-->
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject3:debug classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
<!--
===============
CLEANUP SECTION
===============
-->
<target depends="init" name="deps-clean" unless="no.deps"/>
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
</target>
<target name="-post-clean">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
</project>

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=209349b6
build.xml.script.CRC32=403e69e6
build.xml.stylesheet.CRC32=958a1d3e
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=209349b6
nbproject/build-impl.xml.script.CRC32=c51e188e
nbproject/build-impl.xml.stylesheet.CRC32=65b8de21

View File

@ -1,84 +0,0 @@
application.homepage=http://bob.i2p/
application.title=BOB
application.vendor=Sponge
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/BOB.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=**/*.html,**/*.txt
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
file.reference.i2p.jar=../../core/java/build/i2p.jar
file.reference.mstreaming.jar=../ministreaming/java/build/mstreaming.jar
includes=**
jar.compress=true
javac.classpath=\
${file.reference.mstreaming.jar}:\
${file.reference.i2p.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.version=1.8
javac.source=${javac.version}
javac.target=${javac.version}
javac.release=8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
jnlp.codebase.type=local
jnlp.codebase.url=file:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/dist
jnlp.descriptor=application
jnlp.enabled=false
jnlp.offline-allowed=false
jnlp.signed=false
main.class=net.i2p.BOB.Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>BOB</name>
<minimum-ant-version>1.9.8</minimum-ant-version>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -1,542 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import static net.i2p.app.ClientAppState.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Arrays;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import net.i2p.I2PAppContext;
import net.i2p.app.*;
import net.i2p.client.I2PClient;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.PortMapper;
import net.i2p.util.SimpleTimer2;
/**
* <span style="font-size:8px;font-family:courier;color:#EEEEEE;background-color:#000000">
* ################################################################################<br>
* ############################.#..........#..#..........##########################<br>
* #######################......................................###################<br>
* ####################...........................#.......#........################<br>
* #################..................##...................#.........##############<br>
* ###############................###...####.....#..###.....#.........#############<br>
* #############...........###..#..###...#####...###.##........#.......############<br>
* ###########................#......##...#####...##..##.......#..#........########<br>
* ##########.........................#....##.##..#...##.....................######<br>
* #########...................................#....#.........................#####<br>
* ########.........................................#...............#..........####<br>
* ########.........................................#..........#######..........###<br>
* #######.................................................############..........##<br>
* #######..........................................####################.........##<br>
* #######............####################......########################.........##<br>
* ######.............###############################################.##.........##<br>
* ######............################################################..##........##<br>
* ######............################################################..##........##<br>
* ######.............##############################################..##.........##<br>
* ######............##############################################...##..........#<br>
* ######............#..###########################################...##..........#<br>
* ######.............#############################################....#..........#<br>
* #######...........###############################################..##.........##<br>
* #######...........#####.#.#.#.########################.....#.####...##........##<br>
* ######............#..............##################.................##.........#<br>
* ######................####.........###############........#####......##........#<br>
* ######..............####..#.........############.......##.#.######...##.......##<br>
* ######.................#.####.........########...........##....###...##.......##<br>
* #######....#....###...................#######...............#...###..##.......##<br>
* #######.........###..###.....###.......######.##.#####.........####..##.......##<br>
* #######.....#...##############.........############......###########.###......##<br>
* #######....##...##########.......##...##############......#.############.....###<br>
* ########....#..########......######...##################################....####<br>
* ########....##.####################...##################################....####<br>
* ########..#.##..###################..##################################..#..####<br>
* ##########..###..#################...##################################...#.####<br>
* #########....##...##############....########..#####.################.##..#.#####<br>
* ############.##....##########.......#########.###.......###########..#.#########<br>
* ###############.....#######...#.......########.....##.....######.....###########<br>
* ###############......###....##..........##.......######....#.........#.#########<br>
* ##############............##..................##########..............##########<br>
* ##############..............................##########..#.............##########<br>
* ###############.......##..................#####..............####....###########<br>
* ###############.......#####.......#.............####.....#######.....###########<br>
* ################...#...####......##################.....########....############<br>
* ################...##..#####.........####.##.....#....##########....############<br>
* ##################..##..####...........#####.#....############.....#############<br>
* ##################......#####.................################....##############<br>
* ###################.....####..........##########..###########....###############<br>
* ####################..#..#..........................########.....###############<br>
* #####################.##.......###.................########....#################<br>
* ######################.........#.......#.##.###############....#################<br>
* #############.#######...............#####################....###################<br>
* ###..#.....##...####..........#.....####################....####################<br>
* ####......##........................##################....######################<br>
* #.##...###..............###.........###############......#######################<br>
* #...###..##............######...........................########################<br>
* ##.......###..........##########....#...#...........############################<br>
* ##.........##.......############################################################<br>
* ###........##.....##############################################################<br>
* ####.............###############################################################<br>
* ######.........#################################################################<br>
* #########....###################################################################<br>
* ################################################################################<br>
* </span>
* BOB, main command socket listener, launches the command parser engine.
*
* @author sponge
* @deprecated Please port applications to SAMv3
*/
@Deprecated
public class BOB implements Runnable, ClientApp {
public final static String PROP_CONFIG_LOCATION = "BOB.config";
public final static String PROP_BOB_PORT = "BOB.port";
public final static String PROP_BOB_HOST = "BOB.host";
public final static String PROP_CFG_VER = "BOB.CFG.VER";
/** unused when started via the ClientApp interface */
private static BOB _bob;
private final NamedDB database;
private final Properties props = new Properties();
private final AtomicBoolean spin = new AtomicBoolean(true);
private static final String P_RUNNING = "RUNNING";
private static final String P_STARTING = "STARTING";
private static final String P_STOPPING = "STOPPING";
private final AtomicBoolean lock = new AtomicBoolean(false);
// no longer used.
// private static int maxConnections = 0;
private final I2PAppContext _context;
private final Logger _log;
private final ClientAppManager _mgr;
private final String[] _args;
private volatile ClientAppState _state = UNINITIALIZED;
private volatile ServerSocket listener;
private volatile Thread _runner;
private volatile boolean _warned;
/**
* Stop BOB gracefully
* @deprecated unused
*/
@Deprecated
public synchronized static void stop() {
if (_bob != null)
_bob.shutdown(null);
}
/**
* For ClientApp interface.
* Does NOT open the listener socket or start threads; caller must call startup()
*
* @param mgr may be null
* @param args non-null
* @since 0.9.10
*/
public BOB(I2PAppContext context, ClientAppManager mgr, String[] args) {
_context = context;
// If we were run from command line, log to stdout
boolean logToStdout = false;
URL classResource = BOB.class.getResource("BOB.class");
if (classResource != null) {
String classPath = classResource.toString();
if (classPath.startsWith("jar")) {
String manifestPath = classPath.substring(0, classPath.lastIndexOf('!') + 1) +
"/META-INF/MANIFEST.MF";
try {
Manifest manifest = new Manifest(new URL(manifestPath).openStream());
Attributes attrs = manifest.getMainAttributes();
String mainClass = attrs.getValue("Main-Class");
if ("net.i2p.BOB.Main".equals(mainClass))
logToStdout = true;
} catch (IOException ioe) {}
}
}
_log = new Logger(context.logManager().getLog(BOB.class), logToStdout);
_mgr = mgr;
_args = args;
_state = INITIALIZED;
database = new NamedDB();
loadConfig();
}
/**
* Listen for incoming connections and handle them
*
* @param args
*/
public synchronized static void main(String[] args) {
try {
_bob = new BOB(I2PAppContext.getGlobalContext(), null, args);
_bob.startup();
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @since 0.9.10
*/
private void loadConfig() {
int i = 0;
boolean save = false;
// Set up all defaults to be passed forward to other threads.
// Re-reading the config file in each thread is pretty damn stupid.
String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config");
// This is here just to ensure there is no interference with our threadgroups.
SimpleTimer2 Y2 = SimpleTimer2.getInstance();
i = Y2.hashCode();
{
File cfg = new File(configLocation);
if (!cfg.isAbsolute()) {
cfg = new File(_context.getConfigDir(), configLocation);
}
FileInputStream fi = null;
try {
fi = new FileInputStream(cfg);
props.load(fi);
} catch (FileNotFoundException fnfe) {
_log.warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.", fnfe);
save = true;
} catch (IOException ioe) {
_log.warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.", ioe);
} finally {
if (fi != null) try { fi.close(); } catch (IOException ioe) {}
}
}
// Global router and client API configurations that are missing are set to defaults here.
if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
save = true;
}
if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
props.setProperty(I2PClient.PROP_TCP_PORT, Integer.toString(I2PClient.DEFAULT_LISTEN_PORT));
save = true;
}
if (!props.containsKey(PROP_BOB_PORT)) {
props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
save = true;
}
if (!props.containsKey("inbound.length")) {
props.setProperty("inbound.length", "3");
save = true;
}
if (!props.containsKey("outbound.length")) {
props.setProperty("outbound.length", "3");
save = true;
}
if (!props.containsKey("inbound.lengthVariance")) {
props.setProperty("inbound.lengthVariance", "0");
save = true;
}
if (!props.containsKey("outbound.lengthVariance")) {
props.setProperty("outbound.lengthVariance", "0");
save = true;
}
if (!props.containsKey(PROP_BOB_HOST)) {
props.setProperty(PROP_BOB_HOST, "localhost");
save = true;
}
// PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
if (!props.containsKey(PROP_CFG_VER)) {
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
props.setProperty(PROP_CFG_VER,"1");
save = true;
}
if (save) {
File cfg = new File(configLocation);
if (!cfg.isAbsolute()) {
cfg = new File(_context.getConfigDir(), configLocation);
}
FileOutputStream fo = null;
try {
_log.warn("Writing new defaults file " + cfg.getAbsolutePath());
fo = new FileOutputStream(cfg);
props.store(fo, cfg.getAbsolutePath());
} catch (IOException ioe) {
_log.error("IOException on BOB config file " + cfg.getAbsolutePath(), ioe);
} finally {
if (fo != null) try { fo.close(); } catch (IOException ioe) {}
}
}
}
/**
* @since 0.9.10
*/
private void startListener() throws IOException {
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
listener.setSoTimeout(500); // .5 sec
}
/**
* @since 0.9.10
*/
private void startThread() {
I2PAppThread t = new I2PAppThread(this, "BOBListener");
t.start();
_runner = t;
}
/**
* @since 0.9.10
*/
public void run() {
if (listener == null) return;
changeState(RUNNING);
_log.info("BOB is now running.");
if (_mgr != null)
_mgr.register(this);
_context.portMapper().register(PortMapper.SVC_BOB, props.getProperty(PROP_BOB_HOST),
Integer.parseInt(props.getProperty(PROP_BOB_PORT)));
int i = 0;
boolean g = false;
spin.set(true);
try {
Socket server = null;
while (spin.get()) {
//DoCMDS connection;
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (ConnectException ce) {
g = false;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
if (!_warned) {
_warned = true;
String s = "BOB is deprecated. Please port applications to SAMv3.";
_context.logManager().getLog(BOB.class).logAlways(Log.WARN, s);
_log.warn(s);
}
DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
Thread t = new I2PAppThread(conn_c);
t.setName("BOB.DoCMDS " + i);
t.start();
i++;
}
}
changeState(STOPPING);
} catch (Exception e) {
if (spin.get())
_log.error("Unexpected error while listening for connections", e);
else
e = null;
changeState(STOPPING, e);
} finally {
_log.info("BOB is now shutting down...");
_context.portMapper().unregister(PortMapper.SVC_BOB);
// Clean up everything.
try {
listener.close();
} catch (Exception ex) {
// nop
}
// Find all our "BOB.DoCMDS" threads, wait for them to be finished.
// We could order them to stop, but that could cause nasty issues in the locks.
visitAllThreads();
database.getReadLock();
NamedDB nickinfo;
try {
for (Object ndb : database.values()) {
nickinfo = (NamedDB) ndb;
nickinfo.getReadLock();
boolean released = false;
try {
if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
nickinfo.releaseReadLock();
released = true;
nickinfo.getWriteLock();
try {
nickinfo.add(P_STOPPING, Boolean.TRUE);
} finally {
nickinfo.releaseWriteLock();
}
}
} finally {
if (!released)
nickinfo.releaseReadLock();
}
}
} finally {
database.releaseReadLock();
}
changeState(STOPPED);
_log.info("BOB is now stopped.");
}
}
/**
* Find the root thread group,
* then find all theads with certain names and wait for them all to be dead.
*
*/
private static void visitAllThreads() {
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null) {
root = root.getParent();
}
// Visit each thread group
waitjoin(root, 0, root.getName());
}
private static void waitjoin(ThreadGroup group, int level, String tn) {
// Get threads in `group'
int numThreads = group.activeCount();
Thread[] threads = new Thread[numThreads * 2];
numThreads = group.enumerate(threads, false);
// Enumerate each thread in `group' and wait for it to stop if it is one of ours.
for (int i = 0; i < numThreads; i++) {
// Get thread
Thread thread = threads[i];
if (thread.getName().startsWith("BOB.DoCMDS ")) {
try {
if (thread.isAlive()) {
try {
thread.join();
} catch (InterruptedException ex) {
}
}
} catch (SecurityException se) {
//nop
}
}
}
// Get thread subgroups of `group'
int numGroups = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
numGroups = group.enumerate(groups, false);
// Recursively visit each subgroup
for (int i = 0; i < numGroups; i++) {
waitjoin(groups[i], level + 1, groups[i].getName());
}
}
////// begin ClientApp interface
/**
* @since 0.9.10
*/
@Override
public void startup() throws IOException {
if (_state != INITIALIZED)
return;
changeState(STARTING);
try {
startListener();
} catch (IOException e) {
_log.error("Error starting BOB on"
+ props.getProperty(PROP_BOB_HOST)
+ ":" + props.getProperty(PROP_BOB_PORT), e);
changeState(START_FAILED, e);
throw e;
}
startThread();
}
/**
* @since 0.9.10
*/
@Override
public void shutdown(String[] args) {
if (_state != RUNNING)
return;
changeState(STOPPING);
spin.set(false);
if (_runner != null)
_runner.interrupt();
else
changeState(STOPPED);
}
/**
* @since 0.9.10
*/
@Override
public ClientAppState getState() {
return _state;
}
/**
* @since 0.9.10
*/
@Override
public String getName() {
return "BOB";
}
/**
* @since 0.9.10
*/
@Override
public String getDisplayName() {
return "BOB " + Arrays.toString(_args);
}
////// end ClientApp interface
////// begin ClientApp helpers
/**
* @since 0.9.10
*/
private void changeState(ClientAppState state) {
changeState(state, null);
}
/**
* @since 0.9.10
*/
private synchronized void changeState(ClientAppState state, Exception e) {
_state = state;
if (_mgr != null)
_mgr.notify(this, state, null, e);
}
////// end ClientApp helpers
}

View File

@ -1,996 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClientFactory;
import net.i2p.data.Destination;
import net.i2p.util.I2PAppThread;
// needed only for debugging.
// import java.util.logging.Level;
// import java.util.logging.Logger;
/**
* Simplistic command parser for BOB
*
* @author sponge
*
*/
public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
public static final String BMAJ = "00", BMIN = "00", BREV = "10", BEXT = "";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private final Socket server;
private final Properties props;
private final NamedDB database;
private String line;
private Destination d;
private ByteArrayOutputStream prikey;
private boolean dk, ns, ip, op;
private NamedDB nickinfo;
private final Logger _log;
private final AtomicBoolean LIVE;
private final AtomicBoolean lock;
/* database strings */
private static final String P_DEST = "DESTINATION";
private static final String P_INHOST = "INHOST";
private static final String P_INPORT = "INPORT";
private static final String P_KEYS = "KEYS";
private static final String P_NICKNAME = "NICKNAME";
private static final String P_OUTHOST = "OUTHOST";
private static final String P_OUTPORT = "OUTPORT";
private static final String P_PROPERTIES = "PROPERTIES";
private static final String P_QUIET = "QUIET";
private static final String P_RUNNING = "RUNNING";
private static final String P_STARTING = "STARTING";
private static final String P_STOPPING = "STOPPING";
/* command strings */
private static final String C_help = "help";
private static final String C_clear = "clear";
private static final String C_getdest = "getdest";
private static final String C_getkeys = "getkeys";
private static final String C_getnick = "getnick";
private static final String C_inhost = "inhost";
private static final String C_inport = "inport";
private static final String C_list = "list";
private static final String C_lookup = "lookup";
private static final String C_newkeys = "newkeys";
private static final String C_option = "option";
private static final String C_outhost = "outhost";
private static final String C_outport = "outport";
private static final String C_quiet = "quiet";
private static final String C_quit = "quit";
private static final String C_setkeys = "setkeys";
private static final String C_setnick = "setnick";
private static final String C_show = "show";
private static final String C_show_props = "showprops";
private static final String C_start = "start";
private static final String C_status = "status";
private static final String C_stop = "stop";
private static final String C_verify = "verify";
private static final String C_visit = "visit";
private static final String C_zap = "zap";
/* all the commands available, plus description */
private static final String C_ALL[][] = {
{C_help, C_help + " <command> * Get help on a command."},
{C_clear, C_clear + " * Clear the current nickname out of the list."},
{C_getdest, C_getdest + " * Return the destination for the current nickname."},
{C_getkeys, C_getkeys + " * Return the keypair for the current nickname."},
{C_getnick, C_getnick + " tunnelname * Set the nickname from the database."},
{C_inhost, C_inhost + " hostname | IP * Set the inbound hostname or IP."},
{C_inport, C_inport + " port_number * Set the inbound port number nickname listens on."},
{C_list, C_list + " * List all tunnels."},
{C_lookup, C_lookup + " * Lookup an i2p address."},
{C_newkeys, C_newkeys + " * Generate a new keypair for the current nickname."},
{C_option, C_option + " I2CPoption=something * Set an I2CP option. NOTE: Don't use any spaces."},
{C_outhost, C_outhost + " hostname | IP * Set the outbound hostname or IP."},
{C_outport, C_outport + " port_number * Set the outbound port that nickname contacts."},
{C_quiet, C_quiet + " True | False * Don't send to the application the incoming destination."},
{C_quit, C_quit + " * Quits this session with BOB."},
{C_setkeys, C_setkeys + " BASE64_keypair * Sets the keypair for the current nickname."},
{C_setnick, C_setnick + " nickname * Create a new nickname."},
{C_show, C_show + " * Display the status of the current nickname."},
{C_show_props, C_show_props + " * Display the properties of the current nickname."},
{C_start, C_start + " * Start the current nickname tunnel."},
{C_status, C_status + " nickname * Display status of a nicknamed tunnel."},
{C_stop, C_stop + " * Stops the current nicknamed tunnel."},
{C_verify, C_verify + " BASE64_key * Verifies BASE64 destination."},
{C_visit, C_visit + " * Thread dump to wrapper.log."},
{C_zap, C_zap + " * Shuts down BOB."},
{"", "COMMANDS: " + // this is ugly, but...
C_help + " " +
C_clear + " " +
C_getdest + " " +
C_getkeys + " " +
C_getnick + " " +
C_inhost + " " +
C_inport + " " +
C_list + " " +
C_lookup + " " +
C_newkeys + " " +
C_option + " " +
C_outhost + " " +
C_outport + " " +
C_quiet + " " +
C_quit + " " +
C_setkeys + " " +
C_setnick + " " +
C_show + " " +
C_show_props + " " +
C_start + " " +
C_status + " " +
C_stop + " " +
C_verify + " " +
C_visit + " " +
C_zap
},
{" ", " "} // end of list
};
/**
* @param LIVE
* @param server
* @param props
* @param database
* @param _log
*/
DoCMDS(AtomicBoolean LIVE, AtomicBoolean lock, Socket server, Properties props, NamedDB database, Logger _log) {
this.lock = lock;
this.LIVE = LIVE;
this.server = server;
this.props = new Properties();
this.database = database;
this._log = _log;
Lifted.copyProperties(props, this.props);
}
private void rlock() {
rlock(nickinfo);
}
private void rlock(NamedDB Arg) {
database.getReadLock();
Arg.getReadLock();
}
private void runlock() {
runlock(nickinfo);
}
private void runlock(NamedDB Arg) {
Arg.releaseReadLock();
database.releaseReadLock();
}
private void wlock() {
wlock(nickinfo);
}
private void wlock(NamedDB Arg) {
database.getWriteLock();
Arg.getWriteLock();
}
private void wunlock() {
wunlock(nickinfo);
}
private void wunlock(NamedDB Arg) {
Arg.releaseWriteLock();
database.releaseWriteLock();
}
/**
* Try to print info from the database
*
* @param out
* @param info
* @param key
*/
private void trypnt(PrintStream out, NamedDB info, String key) {
rlock(info);
try {
out.print(" " + key + ": ");
if (info.exists(key)) {
out.print(info.get(key));
} else {
out.print("not_set");
}
} finally {
runlock(info);
}
}
/**
* Print true or false if an object exists
*
* @param out
* @param info
* @param key
*/
private void tfpnt(PrintStream out, NamedDB info, String key) {
rlock(info);
try {
out.print(" " + key + ": ");
out.print(info.exists(key));
} finally {
runlock(info);
}
}
/**
* Print an error message
*
* @param out
*/
private static void nns(PrintStream out) {
out.println("ERROR no nickname has been set");
}
/**
* Dump various information from the database
*
* @param out
* @param info
*/
private void nickprint(PrintStream out, NamedDB info) {
trypnt(out, info, P_NICKNAME);
trypnt(out, info, P_STARTING);
trypnt(out, info, P_RUNNING);
trypnt(out, info, P_STOPPING);
tfpnt(out, info, P_KEYS);
trypnt(out, info, P_QUIET);
trypnt(out, info, P_INPORT);
trypnt(out, info, P_INHOST);
trypnt(out, info, P_OUTPORT);
trypnt(out, info, P_OUTHOST);
out.println();
}
/**
* Dump properties information from the database
*
* @param out
* @param info
*/
private void propprint(PrintStream out, NamedDB info) {
trypnt(out, info, P_PROPERTIES);
}
/**
* Print information on a specific record, indicated by NamedDB
* @param out
* @param Arg
*/
private void ttlpnt(PrintStream out, String Arg) {
database.getReadLock();
try {
if (database.exists(Arg)) {
out.print("DATA");
nickprint(out, (NamedDB) database.get(Arg));
}
} finally {
database.releaseReadLock();
}
}
/**
* Is this NamedDB's tunnel active?
*
* @param Arg
* @return true if the tunnel is active
*/
private boolean tunnelactive(NamedDB Arg) {
boolean retval;
rlock(Arg);
try {
retval = (Arg.get(P_STARTING).equals(Boolean.TRUE) ||
Arg.get(P_STOPPING).equals(Boolean.TRUE) ||
Arg.get(P_RUNNING).equals(Boolean.TRUE));
} finally {
runlock();
}
return retval;
}
/**
* Does the base64 information look OK
*
* @param data
* @return OK
*/
private static boolean is64ok(String data) {
try {
new Destination(data);
return true;
} catch (Exception e) {
return false;
}
}
/**
* The actual parser.
* It probabbly needs a rewrite into functions, but I kind-of like inline code.
*
*/
public void run() {
dk = ns = ip = op = false;
try {
try {
// Get input from the client
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintStream out = new PrintStream(server.getOutputStream());
quit:
{
die:
{
prikey = new ByteArrayOutputStream();
out.println("BOB " + BOBversion);
out.println("OK");
while ((line = in.readLine()) != null) {
StringTokenizer token = new StringTokenizer(line, " "); // use a space as a delimiter
String Command = "";
String Arg = "";
NamedDB info;
if (token.countTokens() != 0) {
Command = token.nextToken();
Command =
Command.toLowerCase(Locale.US);
if (token.countTokens() != 0) {
Arg = token.nextToken();
} else {
Arg = "";
}
// The rest of the tokens are considered junk,
// and discarded without any warnings.
if (Command.equals(C_help)) {
for (int i = 0; !C_ALL[i][0].equals(" "); i++) {
if (C_ALL[i][0].equalsIgnoreCase(Arg)) {
out.println("OK " + C_ALL[i][1]);
}
}
} else if (Command.equals(C_visit)) {
visitAllThreads();
out.println("OK ");
} else if (Command.equals(C_lookup)) {
Destination dest = null;
String reply = null;
if (Arg.endsWith(".i2p")) {
try {
//try {
//dest = I2PTunnel.destFromName(Arg);
//} catch (DataFormatException ex) {
//}
dest = I2PAppContext.getGlobalContext().namingService().lookup(Arg);
if(dest != null) {
reply = dest.toBase64();
}
} catch (NullPointerException npe) {
// Could not find the destination!?
}
}
if (reply == null) {
out.println("ERROR Address Not found.");
} else {
out.println("OK " + reply);
}
} else if (Command.equals(C_getdest)) {
if (ns) {
if (dk) {
rlock();
try {
out.println("OK " + nickinfo.get(P_DEST));
} catch (Exception e) {
break die;
} finally {
runlock();
}
} else {
out.println("ERROR keys not set.");
}
} else {
nns(out);
}
} else if (Command.equals(C_list)) {
// Produce a formatted list of all nicknames
database.getReadLock();
try {
for (Object ndb : database.values()) {
try {
info = (NamedDB) ndb;
out.print("DATA");
} catch (Exception e) {
break die;
}
nickprint(out, info);
}
} finally {
database.releaseReadLock();
}
out.println("OK Listing done");
} else if (Command.equals(C_quit)) {
// End the command session
break quit;
} else if (Command.equals(C_zap)) {
// Kill BOB!! (let's hope this works!)
LIVE.set(false);
// End the command session
break quit;
} else if (Command.equals(C_newkeys)) {
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
// Make a new PublicKey and PrivateKey
prikey = new ByteArrayOutputStream();
d = I2PClientFactory.createClient().createDestination(prikey);
wlock();
try {
nickinfo.add(P_KEYS, prikey.toByteArray());
nickinfo.add(P_DEST, d.toBase64());
out.println("OK " + nickinfo.get(P_DEST));
} catch (Exception e) {
break die;
} finally {
wunlock();
}
dk = true;
} catch (I2PException ipe) {
_log.error("Error generating keys", ipe);
out.println("ERROR generating keys");
}
}
} catch (Exception e) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_getkeys)) {
// Return public key
if (dk) {
prikey = new ByteArrayOutputStream();
rlock();
try {
prikey.write(((byte[]) nickinfo.get(P_KEYS)));
} catch (Exception ex) {
break die;
} finally {
runlock();
}
out.println("OK " + net.i2p.data.Base64.encode(prikey.toByteArray()));
} else {
out.println("ERROR no public key has been set");
}
} else if (Command.equals(C_quiet)) {
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
wlock();
try {
nickinfo.add(P_QUIET, Boolean.valueOf(Arg));
} catch (Exception ex) {
break die;
} finally {
wunlock();
}
out.println("OK Quiet set");
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_verify)) {
if (is64ok(Arg)) {
out.println("OK");
} else {
out.println("ERROR not in BASE64 format");
}
} else if (Command.equals(C_setkeys)) {
// Set the NamedDB to a privatekey in BASE64 format
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
prikey = new ByteArrayOutputStream();
prikey.write(net.i2p.data.Base64.decode(Arg));
d = new Destination();
d.fromBase64(Arg);
} catch (Exception ex) {
Arg = "";
}
if ((Arg.length() == 884) && is64ok(Arg)) {
wlock();
try {
nickinfo.add(P_KEYS, prikey.toByteArray());
nickinfo.add(P_DEST, d.toBase64());
out.println("OK " + nickinfo.get(P_DEST));
} catch (Exception ex) {
break die;
} finally {
wunlock();
}
dk = true;
} else {
out.println("ERROR not in BASE64 format");
}
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_setnick)) {
ns = dk = ip = op = false;
database.getReadLock();
try {
nickinfo = (NamedDB) database.get(Arg);
if (!tunnelactive(nickinfo)) {
nickinfo = null;
ns = true;
}
} catch (Exception b) {
nickinfo = null;
ns = true;
} finally {
database.releaseReadLock();
}
// Clears and Sets the initial NamedDB structure to work with
if (ns) {
nickinfo = new NamedDB();
wlock();
try {
database.add(Arg, nickinfo);
nickinfo.add(P_NICKNAME, Arg);
nickinfo.add(P_STARTING, Boolean.FALSE);
nickinfo.add(P_RUNNING, Boolean.FALSE);
nickinfo.add(P_STOPPING, Boolean.FALSE);
nickinfo.add(P_QUIET, Boolean.FALSE);
nickinfo.add(P_INHOST, "localhost");
nickinfo.add(P_OUTHOST, "localhost");
Properties Q = new Properties();
Lifted.copyProperties(this.props, Q);
Q.setProperty("inbound.nickname", Arg);
Q.setProperty("outbound.nickname", Arg);
nickinfo.add(P_PROPERTIES, Q);
} catch (Exception e) {
break die;
} finally {
wunlock();
}
out.println("OK Nickname set to " + Arg);
} else {
out.println("ERROR tunnel is active");
}
} else if (Command.equals(C_option)) {
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
StringTokenizer otoken = new StringTokenizer(Arg, "="); // use an equal sign as a delimiter
if (otoken.countTokens() != 2) {
out.println("ERROR too many or no options.");
} else {
String pname = otoken.nextToken();
String pval = otoken.nextToken();
wlock();
try {
Properties Q = (Properties) nickinfo.get(P_PROPERTIES);
Q.setProperty(pname, pval);
nickinfo.add(P_PROPERTIES, Q);
} catch (Exception ex) {
break die;
} finally {
wunlock();
}
out.println("OK " + pname + " set to " + pval);
}
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_getnick)) {
// Get the NamedDB to work with...
boolean nsfail = false;
database.getReadLock();
try {
nickinfo = (NamedDB) database.get(Arg);
ns = true;
} catch (RuntimeException b) {
nsfail = true;
nns(out);
} finally {
database.releaseReadLock();
}
if (ns && !nsfail) {
rlock();
try {
dk = nickinfo.exists(P_KEYS);
ip = nickinfo.exists(P_INPORT);
op = nickinfo.exists(P_OUTPORT);
} catch (Exception ex) {
break die;
} finally {
runlock();
}
// Finally say OK.
out.println("OK Nickname set to " + Arg);
}
} else if (Command.equals(C_inport)) {
// Set the NamedDB inbound TO the router port
// app --> BOB
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
int prt;
wlock();
try {
nickinfo.kill(P_INPORT);
prt = Integer.parseInt(Arg);
if (prt > 1 && prt < 65536) {
try {
nickinfo.add(P_INPORT, Integer.valueOf(prt));
} catch (Exception ex) {
break die;
}
}
ip = nickinfo.exists(P_INPORT);
} catch (NumberFormatException nfe) {
out.println("ERROR not a number");
} finally {
wunlock();
}
if (ip) {
out.println("OK inbound port set");
} else {
out.println("ERROR port out of range");
}
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_outport)) {
// Set the NamedDB outbound FROM the router port
// BOB --> app
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
int prt;
wlock();
try {
nickinfo.kill(P_OUTPORT);
prt = Integer.parseInt(Arg);
if (prt > 1 && prt < 65536) {
nickinfo.add(P_OUTPORT, Integer.valueOf(prt));
}
ip = nickinfo.exists(P_OUTPORT);
} catch (NumberFormatException nfe) {
out.println("ERROR not a number");
} catch (Exception ex) {
break die;
} finally {
wunlock();
}
if (ip) {
out.println("OK outbound port set");
} else {
out.println("ERROR port out of range");
}
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_inhost)) {
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
wlock();
try {
nickinfo.add(P_INHOST, Arg);
} catch (Exception ex) {
break die;
} finally {
wunlock();
}
out.println("OK inhost set");
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_outhost)) {
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
wlock();
try {
nickinfo.add(P_OUTHOST, Arg);
} catch (Exception ex) {
break die;
} finally {
wunlock();
}
out.println("OK outhost set");
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_show)) {
// Get the current NamedDB properties
if (ns) {
out.print("OK");
nickprint(out, nickinfo);
} else {
nns(out);
}
} else if (Command.equals(C_show_props)) {
// Get the current options properties
if (ns) {
out.print("OK");
propprint(out, nickinfo);
} else {
nns(out);
}
} else if (Command.equals(C_start)) {
// Start the tunnel, if we have all the information
if (ns && dk && (ip || op)) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
MUXlisten tunnel;
try {
while (!lock.compareAndSet(false, true)) {
// wait
}
tunnel = new MUXlisten(lock, database, nickinfo, _log);
Thread t = new I2PAppThread(tunnel);
t.start();
// try {
// Thread.sleep(1000 * 10); // Slow down the startup.
// } catch(InterruptedException ie) {
// // ignore it
// }
out.println("OK tunnel starting");
} catch (I2PException e) {
lock.set(false);
out.println("ERROR starting tunnel: " + e);
} catch (IOException e) {
lock.set(false);
out.println("ERROR starting tunnel: " + e);
}
}
} catch (Exception ex) {
break die;
}
} else {
out.println("ERROR tunnel settings incomplete");
}
} else if (Command.equals(C_stop)) {
// Stop the tunnel, if it is running
if (ns) {
rlock();
boolean released = false;
try {
if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
runlock();
released = true;
wlock();
try {
nickinfo.add(P_STOPPING, Boolean.TRUE);
} catch (Exception e) {
break die;
} finally {
wunlock();
}
out.println("OK tunnel stopping");
} else {
out.println("ERROR tunnel is inactive");
}
} catch (Exception e) {
break die;
} finally {
if (!released)
runlock();
}
} else {
nns(out);
}
} else if (Command.equals(C_clear)) {
// Clear use of the NamedDB if stopped
if (ns) {
try {
if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
database.getWriteLock();
try {
database.kill((String) nickinfo.get(P_NICKNAME));
} catch (Exception e) {
} finally {
database.releaseWriteLock();
}
dk = ns = ip = op = false;
out.println("OK cleared");
}
} catch (Exception ex) {
break die;
}
} else {
nns(out);
}
} else if (Command.equals(C_status)) {
database.getReadLock();
try {
if (database.exists(Arg)) {
// Show status of a NamedDB
out.print("OK ");
try {
ttlpnt(out, Arg);
} catch (Exception e) {
out.println(); // this will cause an IOE if IOE
break die;
}
} else {
nns(out);
}
} catch (Exception e) {
break die;
} finally {
database.releaseReadLock();
}
} else {
out.println("ERROR UNKNOWN COMMAND! Try help");
}
}
}
} // die
out.print("ERROR A really bad error just happened, ");
} // quit
// Say goodbye.
out.println("OK Bye!");
} catch (IOException ioe) {
// not really needed, except to debug.
// BOB.warn("IOException on socket listen: " + ioe);
// ioe.printStackTrace();
}
} finally {
try {
server.close();
} catch (IOException ex) {
// nop
}
}
}
// Debugging... None of this is normally used.
/**
* Find the root thread group and print them all.
*
*/
private void visitAllThreads() {
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null) {
root = root.getParent();
}
// Visit each thread group
visit(root, 0, root.getName());
}
/**
* Recursively visits all thread groups under `group' and dumps them.
* @param group ThreadGroup to visit
* @param level Current level
*/
private static void visit(ThreadGroup group, int level, String tn) {
// Get threads in `group'
int numThreads = group.activeCount();
Thread[] threads = new Thread[numThreads * 2];
numThreads = group.enumerate(threads, false);
String indent = "------------------------------------".substring(0, level) + "-> ";
// Enumerate each thread in `group' and print it.
for (int i = 0; i < numThreads; i++) {
// Get thread
Thread thread = threads[i];
System.out.println("BOB: " + indent + tn + ": " + thread.toString());
}
// Get thread subgroups of `group'
int numGroups = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
numGroups = group.enumerate(groups, false);
// Recursively visit each subgroup
for (int i = 0; i < numGroups; i++) {
visit(groups[i], level + 1, groups[i].getName());
}
}
}

View File

@ -1,99 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.I2PAppThread;
/**
* Listen on I2P and connect to TCP
*
* @author sponge
*/
public class I2Plistener implements Runnable {
private final NamedDB info, database;
private final Logger _log;
private final I2PServerSocket serverSocket;
private final AtomicBoolean lives;
/**
* Constructor
* @param SS
* @param S unused
* @param info
* @param database
* @param _log
*/
I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
this.database = database;
this.info = info;
this._log = _log;
this.serverSocket = SS;
this.lives = lives;
}
/**
* Simply listen on I2P port, and thread connections
*
*/
public void run() {
boolean g = false;
I2PSocket sessSocket = null;
int conn = 0;
try {
try {
serverSocket.setSoTimeout(50);
while (lives.get()) {
try {
sessSocket = serverSocket.accept();
g = true;
} catch (ConnectException ce) {
g = false;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
g = false;
conn++;
// toss the connection to a new thread.
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
t.start();
}
}
} catch (I2PException e) {
// bad stuff
System.out.println("Exception " + e);
}
} finally {
try {
serverSocket.close();
} catch (I2PException ex) {
}
// System.out.println("I2Plistener: Close");
}
}
}

View File

@ -1,169 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PAppThread;
/**
* Process I2P-&gt;TCP
*
* @author sponge
*/
public class I2PtoTCP implements Runnable {
private I2PSocket I2P;
private final NamedDB info, database;
private Socket sock;
private final AtomicBoolean lives;
/**
* Constructor
*
* @param I2Psock
* @param info
* @param database
*/
I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database, AtomicBoolean lives) {
this.I2P = I2Psock;
this.info = info;
this.database = database;
this.lives = lives;
}
private void rlock() {
database.getReadLock();
info.getReadLock();
}
private void runlock() {
info.releaseReadLock();
database.releaseReadLock();
}
/**
* I2P stream to TCP stream thread starter
*
*/
public void run() {
String host;
int port;
boolean tell;
InputStream in = null;
OutputStream out = null;
InputStream Iin = null;
OutputStream Iout = null;
Thread t = null;
Thread q = null;
try {
die:
{
try {
rlock();
try {
host = info.get("OUTHOST").toString();
port = Integer.parseInt(info.get("OUTPORT").toString());
tell = info.get("QUIET").equals(Boolean.FALSE);
} catch (Exception e) {
break die;
} finally {
runlock();
}
sock = new Socket(host, port);
sock.setKeepAlive(true);
// make readers/writers
in = sock.getInputStream();
out = sock.getOutputStream();
Iin = I2P.getInputStream();
Iout = I2P.getOutputStream();
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
if (tell) {
// tell who is connecting
out.write(DataHelper.getASCII(I2P.getPeerDestination().toBase64()));
out.write(10); // nl
out.flush(); // not really needed, but...
}
// setup to cross the streams
TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA");
q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire!
t.start();
q.start();
while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
try {
Thread.sleep(10); //sleep for 10 ms
} catch (InterruptedException e) {
break die;
}
}
// System.out.println("I2PtoTCP: Going away...");
} catch (Exception e) {
// System.out.println("I2PtoTCP: Owch! damn!");
break die;
}
} // die
} finally {
try {
in.close();
} catch (Exception ex) {
}
try {
out.close();
} catch (Exception ex) {
}
try {
Iin.close();
} catch (Exception ex) {
}
try {
Iout.close();
} catch (Exception ex) {
}
try {
t.interrupt();
} catch (Exception e) {
}
try {
q.interrupt();
} catch (Exception e) {
}
try {
// System.out.println("I2PtoTCP: Close I2P");
I2P.close();
} catch (Exception e) {
tell = false;
}
//System.out.println("I2PtoTCP: Closed I2P");
try {
// System.out.println("I2PtoTCP: Close sock");
sock.close();
} catch (Exception e) {
tell = false;
}
// System.out.println("I2PtoTCP: Done");
}
}
}

View File

@ -1,46 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.util.Map;
import java.util.Properties;
/**
* Sets of "friendly" utilities to make life easier.
* Any "Lifted" code will apear here, and credits given.
* It's better to "Lift" a small chunk of "free" code than add in piles of
* code we don't need, and don't want.
*
* @author sponge
*/
public class Lifted {
/**
* Copy a set of properties from one Property to another.
* Lifted from Apache Derby code svn repository.
* Liscenced as follows:
* http://svn.apache.org/repos/asf/db/derby/code/trunk/LICENSE
*
* @param src_prop Source set of properties to copy from.
* @param dest_prop Dest Properties to copy into.
*
**/
public static void copyProperties(Properties src_prop, Properties dest_prop) {
for (Map.Entry<Object, Object> e : src_prop.entrySet()) {
dest_prop.put((String)e.getKey(), (String)e.getValue());
}
}
}

View File

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

View File

@ -1,416 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
*
* Multiplex listeners for TCP and I2P
*
* @author sponge
*/
public class MUXlisten implements Runnable {
private final NamedDB database, info;
private final Logger _log;
private final I2PSocketManager socketManager;
private final ByteArrayInputStream prikey;
private ThreadGroup tg;
private final String N;
private ServerSocket listener;
private static final int backlog = 50; // should this be more? less?
private final boolean go_out;
private final boolean come_in;
private final AtomicBoolean lock;
private final AtomicBoolean lives;
/**
* Constructor Will fail if INPORT is occupied.
*
* @param info DB entry for this tunnel
* @param database master database of tunnels
* @param _log
* @throws net.i2p.I2PException
* @throws java.io.IOException
*/
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Logger _log) throws I2PException, IOException, RuntimeException {
int port = 0;
InetAddress host = null;
this.lock = lock;
this.tg = null;
this.database = database;
this.info = info;
this._log = _log;
lives = new AtomicBoolean(false);
try {
wlock();
try {
this.info.add("STARTING", Boolean.TRUE);
} finally {
wunlock();
}
Properties Q = new Properties();
rlock();
try {
N = this.info.get("NICKNAME").toString();
prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
// Make a new copy so that anything else won't muck with our database.
Properties R = (Properties) info.get("PROPERTIES");
Lifted.copyProperties(R, Q);
this.go_out = info.exists("OUTPORT");
this.come_in = info.exists("INPORT");
if (this.come_in) {
port = Integer.parseInt(info.get("INPORT").toString());
host = InetAddress.getByName(info.get("INHOST").toString());
}
} finally {
runlock();
}
String i2cpHost = Q.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
int i2cpPort = I2PClient.DEFAULT_LISTEN_PORT;
String i2cpPortStr = Q.getProperty(I2PClient.PROP_TCP_PORT);
if (i2cpPortStr != null) {
try {
i2cpPort = Integer.parseInt(i2cpPortStr);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Invalid I2CP port specified [" + i2cpPortStr + "]");
}
}
if (this.come_in) {
this.listener = new ServerSocket(port, backlog, host);
}
socketManager = I2PSocketManagerFactory.createManager(
prikey, i2cpHost, i2cpPort, Q);
} catch (IOException e) {
// Something went bad.
wlock();
try {
this.info.add("STARTING", Boolean.FALSE);
} finally {
wunlock();
}
throw e;
} catch (RuntimeException e) {
// Something went bad.
wlock();
try {
this.info.add("STARTING", Boolean.FALSE);
} finally {
wunlock();
}
throw e;
} catch (Exception e) {
// Something else went bad.
wlock();
try {
this.info.add("STARTING", Boolean.FALSE);
} finally {
wunlock();
}
e.printStackTrace();
throw new RuntimeException(e);
}
}
private void rlock() {
database.getReadLock();
info.getReadLock();
}
private void runlock() {
info.releaseReadLock();
database.releaseReadLock();
}
private void wlock() {
database.getWriteLock();
info.getWriteLock();
}
private void wunlock() {
info.releaseWriteLock();
database.releaseWriteLock();
}
/**
* MUX sockets, fire off a thread to connect, get destination info, and do I/O
*
*/
public void run() {
I2PServerSocket SS = null;
Thread t = null;
Thread q = null;
try {
wlock();
try {
try {
info.add("RUNNING", Boolean.TRUE);
} catch (Exception e) {
lock.set(false);
return;
}
} catch (Exception e) {
lock.set(false);
return;
} finally {
wunlock();
}
lives.set(true);
lock.set(false);
quit:
{
try {
tg = new ThreadGroup(N);
{
// toss the connections to a new threads.
// will wrap with TCP and UDP when UDP works
if (go_out) {
// I2P -> TCP
SS = socketManager.getServerSocket();
I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log, lives);
t = new I2PAppThread(tg, conn, "BOBI2Plistener " + N);
t.start();
}
if (come_in) {
// TCP -> I2P
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log, lives);
q = new I2PAppThread(tg, conn, "BOBTCPlistener " + N);
q.start();
}
wlock();
try {
try {
info.add("STARTING", Boolean.FALSE);
} catch (Exception e) {
break quit;
}
} catch (Exception e) {
break quit;
} finally {
wunlock();
}
boolean spin = true;
while (spin && lives.get()) {
try {
Thread.sleep(1000); //sleep for 1 second
} catch (InterruptedException e) {
break quit;
}
rlock();
try {
try {
spin = info.get("STOPPING").equals(Boolean.FALSE);
} catch (Exception e) {
break quit;
}
} catch (Exception e) {
break quit;
} finally {
runlock();
}
}
} // die
} catch (Exception e) {
// System.out.println("MUXlisten: Caught an exception" + e);
break quit;
}
} // quit
} finally {
lives.set(false);
// Some grace time.
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
try {
wlock();
try {
info.add("STARTING", Boolean.FALSE);
info.add("STOPPING", Boolean.TRUE);
info.add("RUNNING", Boolean.FALSE);
} catch (Exception e) {
lock.set(false);
return;
}
} catch (Exception e) {
} finally {
wunlock();
}
// Start cleanup.
while (!lock.compareAndSet(false, true)) {
// wait
}
if (SS != null) {
try {
SS.close();
} catch (I2PException ex) {
}
}
if (listener != null) {
try {
listener.close();
} catch (IOException e) {
}
}
// Some grace time.
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
// Hopefully nuke stuff here...
{
String groupName = tg.getName();
try {
_log.warn("destroySocketManager " + groupName);
socketManager.destroySocketManager();
_log.warn("destroySocketManager Successful" + groupName);
} catch (Exception e) {
// nop
_log.warn("destroySocketManager Failed" + groupName);
_log.warn(e.toString());
}
}
// zero out everything.
try {
wlock();
try {
info.add("STARTING", Boolean.FALSE);
info.add("STOPPING", Boolean.FALSE);
info.add("RUNNING", Boolean.FALSE);
} catch (Exception e) {
lock.set(false);
return;
} finally {
wunlock();
}
} catch (Exception e) {
}
lock.set(false); // Should we force waiting for all threads??
// Wait around till all threads are collected.
if (tg != null) {
String groupName = tg.getName();
// System.out.println("BOB: MUXlisten: Starting thread collection for: " + groupName);
_log.warn("BOB: MUXlisten: Starting thread collection for: " + groupName);
if (tg.activeCount() + tg.activeGroupCount() != 0) {
// visit(tg, 0, groupName);
int foo = tg.activeCount() + tg.activeGroupCount();
// hopefully no longer needed!
// int bar = lives;
// System.out.println("BOB: MUXlisten: Waiting on threads for " + groupName);
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + groupName);
// visit(tg, 0, groupName);
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + groupName + "\n");
// Happily spin forever :-(
while (foo != 0) {
foo = tg.activeCount() + tg.activeGroupCount();
// if (lives != bar && lives != 0) {
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + groupName);
// visit(tg, 0, groupName);
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + groupName + "\n");
// }
// bar = lives;
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch (InterruptedException ex) {
// nop
}
}
}
// System.out.println("BOB: MUXlisten: Threads went away. Success: " + groupName);
_log.warn("BOB: MUXlisten: Threads went away. Success: " + groupName);
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
}
try {
socketManager.destroySocketManager();
} catch (Exception e) {
// nop
}
}
}
// Debugging... None of this is normally used.
/**
* Find the root thread group and print them all.
*
*/
private void visitAllThreads() {
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null) {
root = root.getParent();
}
// Visit each thread group
visit(root, 0, root.getName());
}
/**
* Recursively visits all thread groups under `group' and dumps them.
* @param group ThreadGroup to visit
* @param level Current level
*/
private static void visit(ThreadGroup group, int level, String tn) {
// Get threads in `group'
int numThreads = group.activeCount();
Thread[] threads = new Thread[numThreads * 2];
numThreads = group.enumerate(threads, false);
String indent = "------------------------------------".substring(0, level) + "-> ";
// Enumerate each thread in `group' and print it.
for (int i = 0; i < numThreads; i++) {
// Get thread
Thread thread = threads[i];
System.out.println("BOB: MUXlisten: " + tn + ": " + indent + thread.toString());
}
// Get thread subgroups of `group'
int numGroups = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
numGroups = group.enumerate(groups, false);
// Recursively visit each subgroup
for (int i = 0; i < numGroups; i++) {
visit(groups[i], level + 1, groups[i].getName());
}
}
}

View File

@ -1,39 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import net.i2p.util.SimpleTimer2;
/**
* Start from command line
*
* @author sponge
*
*/
public class Main {
/**
* @param args the command line arguments, these are not used yet
*/
public static void main(String[] args) {
// THINK THINK THINK THINK THINK THINK
SimpleTimer2 Y2 = SimpleTimer2.getInstance();
BOB.main(args);
Y2.stop();
}
}

View File

@ -1,106 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Internal database to relate nicknames to options to values
*
* @author sponge
*/
public class NamedDB {
private final Map<String, Object> data;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
/**
*
*/
public NamedDB() {
this.data = new HashMap<String, Object>();
}
public void getReadLock() {
lock.readLock().lock();
}
public void releaseReadLock() {
lock.readLock().unlock();
}
public void getWriteLock() {
lock.writeLock().lock();
}
public void releaseWriteLock() {
lock.writeLock().unlock();
}
/**
* Delete an object if it exists
*
* @param key
*/
public void kill(String key) {
data.remove(key);
}
/**
* Add object, deletes the old one if it exists
*
* @param key
* @param val
*/
public void add(String key, Object val) {
data.put(key, val);
}
/**
* Get the object, and return it, throws RuntimeException if not found
*
* @param key non-null
* @return Object non-null
* @throws java.lang.RuntimeException if not found
*/
public Object get(String key) throws RuntimeException {
Object rv = data.get(key);
if (rv != null)
return rv;
throw new RuntimeException("Key not found");
}
/**
* returns true if an object exists, else returns false
*
* @param key
* @return true if an object exists, else returns false
*/
public boolean exists(String key) {
return data.containsKey(key);
}
/**
* @since 0.9.29 replaces getcount() and getnext(int)
*/
public Collection<Object> values() {
return data.values();
}
}

View File

@ -1,121 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Shove data from one stream to the other.
*
* @author sponge
*/
public class TCPio implements Runnable {
private final InputStream Ain;
private final OutputStream Aout;
private final AtomicBoolean lives;
/**
* Constructor
*
* @param Ain InputStream
* @param Aout OutputStream
*
* param database
*/
TCPio(InputStream Ain, OutputStream Aout, AtomicBoolean lives) {
this.Ain = Ain;
this.Aout = Aout;
this.lives = lives;
}
/**
* Copy from source to destination...
* and yes, we are totally OK to block here on writes,
* The OS has buffers, and I intend to use them.
* We send an interrupt signal to the threadgroup to
* unwedge any pending writes.
*
*/
public void run() {
/*
* NOTE:
* The write method of OutputStream calls the write method of
* one argument on each of the bytes to be written out.
* Subclasses are encouraged to override this method and provide
* a more efficient implementation.
*
* So, is this really a performance problem?
* Should we expand to several bytes?
* I don't believe there would be any gain, since read method
* has the same reccomendations. If anyone has a better way to
* do this, I'm interested in performance improvements.
*
* --Sponge
*
* Tested with 128 bytes, and there was no performance gain.
* 8192 bytes did lower load average across many connections.
* Should I raise it higer? The correct thing to do would be to
* override... perhaps use NTCP, but I2P's streaming lib lacks
* anything NTCP compatable.
*
* --Sponge
*/
int b;
byte a[] = new byte[8192];
try {
try {
while (lives.get()) {
b = Ain.read(a, 0, 8192);
if (b > 0) {
Aout.write(a, 0, b);
} else if (b == 0) {
while(Ain.available() == 0) {
Thread.sleep(20);
}
} else {
/* according to the specs:
*
* The total number of bytes read into the buffer,
* or -1 if there is no more data because the end of
* the stream has been reached.
*
*/
// System.out.println("TCPio: End Of Stream");
break;
}
}
} catch (Exception e) {
}
// System.out.println("TCPio: Leaving.");
} finally {
// Eject!!! Eject!!!
//System.out.println("TCPio: Caught an exception " + e);
try {
Ain.close();
} catch (IOException ex) {
}
try {
Aout.close();
} catch (IOException ex) {
}
}
}
}

View File

@ -1,95 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.I2PAppThread;
/**
* Listen on TCP port and connect to I2P
*
* @author sponge
*/
public class TCPlistener implements Runnable {
private final NamedDB info, database;
private final Logger _log;
private final I2PSocketManager socketManager;
private final ServerSocket listener;
private final AtomicBoolean lives;
/**
* Constructor
* @param S
* @param info
* @param database
* @param _log
*/
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
this.database = database;
this.info = info;
this._log = _log;
this.socketManager = S;
this.listener = listener;
this.lives = lives;
}
/**
* Simply listen on TCP port, and thread connections
*
*/
public void run() {
boolean g = false;
int conn = 0;
Socket server = null;
try {
try {
listener.setSoTimeout(50); // We don't block, we cycle and check.
while (lives.get()) {
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
conn++;
// toss the connection to a new thread.
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
t.start();
g = false;
}
}
} catch (IOException ioe) {
}
} finally {
try {
listener.close();
} catch (IOException ex) {
}
//System.out.println("TCPlistener: " + Thread.currentThread().getName() + "Done.");
}
}
}

View File

@ -1,222 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.I2PAppThread;
/**
*
* Process TCP-&gt;I2P
*
* @author sponge
*/
public class TCPtoI2P implements Runnable {
private I2PSocket I2P;
private final Socket sock;
private final I2PSocketManager socketManager;
private final AtomicBoolean lives;
/**
* Constructor
* @param i2p
* @param socket
* @param info unused
* @param database unused
*/
TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database, AtomicBoolean lives) {
this.sock = socket;
this.socketManager = i2p;
this.lives = lives;
}
/**
* This is a more forgiving readline,
* it works on unbuffered streams
*
* @param in
* @return line of text as a String
* @throws IOException
*/
private static String lnRead(InputStream in) throws IOException {
StringBuilder builder = new StringBuilder();
int b;
char c;
while (true) {
b = in.read();
if (b == 13) {
//skip CR
continue;
}
if (b < 20 || b > 126) {
// exit on anything not legal
break;
}
c = (char) (b & 0x7f); // We only care about ASCII
builder.append(c);
}
return builder.toString();
}
/**
* Print an error message to out
*
* @param e
* @param out
* @throws java.io.IOException
*/
private void Emsg(String e, OutputStream out) throws IOException {
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
out.write("ERROR ".concat(e).getBytes("UTF-8"));
out.write(13);
out.write(10);
out.flush();
}
/**
* TCP stream to I2P stream thread starter
*
*/
public void run() {
String line, input;
InputStream Iin = null;
OutputStream Iout = null;
InputStream in = null;
OutputStream out = null;
Thread t = null;
Thread q = null;
try {
try {
in = sock.getInputStream();
out = sock.getOutputStream();
line = lnRead(in);
input = line.toLowerCase(Locale.US);
Destination dest = null;
if (input.endsWith(".i2p")) {
//dest = I2PTunnel.destFromName(input);
dest = I2PAppContext.getGlobalContext().namingService().lookup(input);
if (dest != null) {
line = dest.toBase64();
} else {
Emsg("Can't find destination: " + input, out);
return;
}
}
dest = new Destination();
dest.fromBase64(line);
try {
// get a client socket
I2P = socketManager.connect(dest);
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
// make readers/writers
Iin = I2P.getInputStream();
Iout = I2P.getOutputStream();
// setup to cross the streams
TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA");
q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire!
t.start();
q.start();
while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
Thread.sleep(10); //sleep for 10 ms
}
} catch (I2PException e) {
Emsg(e.toString(), out);
} catch (ConnectException e) {
Emsg(e.toString(), out);
} catch (NoRouteToHostException e) {
Emsg(e.toString(), out);
}
} catch (InterruptedIOException e) {
// We're breaking away.
} catch (InterruptedException e) {
// ditto
} catch (IOException e) {
try {
Emsg(e.toString(), out);
} catch (IOException ex) {
// ditto
}
} catch (DataFormatException e) {
try {
Emsg(e.toString(), out);
} catch (IOException ex) {
// ditto
}
}
} finally {
try {
t.interrupt();
} catch (Exception e) {
}
try {
q.interrupt();
} catch (Exception e) {
}
try {
in.close();
} catch (Exception e) {
}
try {
out.close();
} catch (Exception e) {
}
try {
Iin.close();
} catch (Exception e) {
}
try {
Iout.close();
} catch (Exception e) {
}
try {
// System.out.println("TCPtoI2P: Close I2P");
I2P.close();
} catch (Exception e) {
}
try {
// System.out.println("TCPtoI2P: Close sock");
sock.close();
} catch (Exception e) {
}
}
// System.out.println("TCPtoI2P: Done.");
}
}

View File

@ -1,140 +0,0 @@
/**
* WTFPL
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and license questions.
*/
package net.i2p.BOB;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSessionListener;
import net.i2p.data.Destination;
import net.i2p.util.Log;
/**
* UDP IO on I2P
*
* FIX ME: Untested, and incomplete!
* I have no personal need to UDP yet,
* however alot of p2p apps pretty much demand it.
* The skeletal frame is here, just needs to be finished.
*
* @author sponge
* @deprecated incomplete, unused
*/
@Deprecated
public class UDPIOthread implements I2PSessionListener, Runnable {
private final NamedDB info;
private final Log _log;
private final Socket socket;
private DataInputStream in;
private DataOutputStream out;
private final I2PSession _session;
// FIXME never set
private Destination _peerDestination;
private boolean up;
/**
* Constructor
* @param info
* @param _log
* @param socket
* @param _session
*/
UDPIOthread(NamedDB info, Log _log, Socket socket, I2PSession _session) {
this.info = info;
this._log = _log;
this.socket = socket;
this._session = _session;
}
/**
*
*/
public void run() {
byte data[] = new byte[1024];
up = true;
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
while (up) {
int c = in.read(data);
// Note: could do a loopback test here with a wrapper.
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
if (!ok) {
up = false; // Is this the right thing to do??
}
}
} catch (IOException ioe) {
_log.error("Error running", ioe);
} catch (I2PSessionException ise) {
_log.error("Error communicating", ise);
// } catch(DataFormatException dfe) {
// _log.error("Peer destination file is not valid", dfe);
} finally {
if (_session != null) {
try {
_session.destroySession();
} catch (I2PSessionException ise) {
// ignored
}
}
}
}
/**
*
* @param session
* @param msgId
* @param size
*/
public void messageAvailable(I2PSession session, int msgId, long size) {
// _log.debug("Message available: id = " + msgId + " size = " + size);
try {
byte msg[] = session.receiveMessage(msgId);
if (msg != null) {
out.write(msg);
out.flush();
}
} catch (I2PSessionException ise) {
up = false;
} catch (IOException ioe) {
up = false;
}
}
// Great, can these be used to kill ourselves.
/** required by {@link I2PSessionListener I2PSessionListener} to notify of disconnect */
public void disconnected(I2PSession session) {
_log.debug("Disconnected");
// up = false;
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of error */
public void errorOccurred(I2PSession session, String message, Throwable error) {
_log.debug("Error occurred: " + message, error);
// up = false;
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of abuse */
public void reportAbuse(I2PSession session, int severity) {
_log.debug("Abuse reported of severity " + severity);
// up = false;
}
}

View File

@ -1,21 +0,0 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) sponge
Planet Earth
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
See...
http://sam.zoy.org/wtfpl/
and
http://en.wikipedia.org/wiki/WTFPL
...for any additional details and license questions.

View File

@ -1,5 +0,0 @@
<html>
<body>
<p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P - DEPRECATED - Please port applications to SAMv3.</p>
</body>
</html>

View File

@ -9,6 +9,7 @@
<property name="javac.compilerargs" value="" />
<property name="javac.version" value="1.8" />
<property name="javac.release" value="8" />
<property name="manifest.classpath.name" value="Class-Path" />
<target name="all" depends="jar, emptyWar"/>
@ -57,8 +58,14 @@
<property name="workspace.changes.tr" value="" />
<jar basedir="${build}" destfile="${dist}/${jar}">
<manifest>
<attribute name="Main-Class" value="net.i2p.addressbook.Daemon"/>
<attribute name="${manifest.classpath.name}" value="i2p.jar" />
<attribute name="Main-Class" value="net.i2p.addressbook.CommandLine"/>
<attribute name="Specification-Title" value="I2P Address Book" />
<attribute name="Specification-Version" value="${api.version}" />
<attribute name="Specification-Vendor" value="The I2P Project https://geti2p.net/" />
<attribute name="Implementation-Title" value="I2P Java Address Book" />
<attribute name="Implementation-Version" value="${full.version}" />
<attribute name="Implementation-Vendor" value="The I2P Project https://geti2p.net/" />
<attribute name="Built-By" value="${build.built-by}" />
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />

View File

@ -0,0 +1,42 @@
package net.i2p.addressbook;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.i2p.CoreVersion;
/**
* Simple command line access to various utilities.
* Not a public API. Subject to change.
* Apps and plugins should use specific classes.
*
* @since 0.9.55
*/
public class CommandLine extends net.i2p.util.CommandLine {
protected static final List<String> ACLASSES = Arrays.asList(new String[] {
"net.i2p.addressbook.HostTxtParser",
"net.i2p.router.naming.BlockfileNamingService",
"net.metanotion.io.block.BlockFile",
});
protected CommandLine() {}
public static void main(String args[]) {
List<String> classes = new ArrayList<String>(ACLASSES.size() + CLASSES.size());
classes.addAll(ACLASSES);
classes.addAll(CLASSES);
if (args.length > 0) {
exec(args, classes);
}
usage(classes);
System.exit(1);
}
private static void usage(List<String> classes) {
System.err.println("I2P Address book version " + CoreVersion.VERSION + '\n' +
"USAGE: java -jar /path/to/addressbook.jar command [args]");
printCommands(classes);
}
}

View File

@ -17,6 +17,7 @@ import java.util.Properties;
import net.i2p.client.naming.HostTxtEntry;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SystemVersion;
@ -25,9 +26,9 @@ import net.i2p.util.SystemVersion;
* Utility class providing methods to parse and write files in a hosts.txt file
* format, and subscription file format.
*
* @since 0.9.26 modified from ConfigParser
* @since 0.9.26 modified from ConfigParser, public since 0.9.55 for CLI
*/
class HostTxtParser {
public class HostTxtParser {
private static final boolean isWindows = SystemVersion.isWindows();
@ -255,8 +256,23 @@ class HostTxtParser {
System.exit(2);
}
if (!e.hasValidSig()) {
if (!quiet)
System.err.println("Bad signature");
if (!quiet) {
System.err.println("Bad signature for " + e.getName());
String dest = e.getDest();
try {
Destination d = new Destination(dest);
System.err.println(dest);
System.err.println(d.toString());
} catch (Exception ex) {
System.err.println("Invalid destination: " + dest);
}
Properties p = e.getProps();
if (p != null) {
for (Map.Entry<?,?> m : p.entrySet()) {
System.err.println(m.getKey() + "=" + m.getValue());
}
}
}
System.exit(3);
}
Properties p = e.getProps();
@ -266,14 +282,30 @@ class HostTxtParser {
p.containsKey(HostTxtEntry.PROP_OLDNAME) ||
p.containsKey(HostTxtEntry.PROP_OLDSIG)) {
if (!e.hasValidSig()) {
if (!quiet)
System.err.println("Bad inner signature");
if (!quiet) {
System.err.println("Bad inner signature for " + e.getName());
for (Map.Entry<?,?> m : p.entrySet()) {
System.err.println(m.getKey() + "=" + m.getValue());
}
}
System.exit(4);
}
}
}
if (!quiet)
if (!quiet) {
System.err.println("Good signature for " + e.getName());
try {
String dest = e.getDest();
Destination d = new Destination(dest);
System.err.println(dest);
System.err.println(d.toString());
} catch (Exception ex) {}
if (p != null) {
for (Map.Entry<?,?> m : p.entrySet()) {
System.err.println(m.getKey() + "=" + m.getValue());
}
}
}
System.exit(0);
}

View File

@ -10,6 +10,7 @@
<property name="javac.version" value="1.8" />
<property name="javac.release" value="8" />
<property name="require.gettext" value="true" />
<property name="manifest.classpath.name" value="Class-Path" />
<condition property="no.bundle">
<isfalse value="${require.gettext}" />
@ -86,6 +87,7 @@
<jar basedir="${build}" excludes="messages-src/**" destfile="${dist}/${jar}">
<manifest>
<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/>
<attribute name="${manifest.classpath.name}" value="i2p.jar router.jar" />
<attribute name="Implementation-Version" value="${full.version}" />
<attribute name="Built-By" value="${build.built-by}" />
<attribute name="Build-Date" value="${build.timestamp}" />

View File

@ -10,9 +10,9 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-09-20 20:31+0000\n"
"Last-Translator: Vitaly Zdorovenko <stenliterziev@gmail.com>\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2022-02-09 19:23+0000\n"
"Last-Translator: zzzi2p\n"
"Language-Team: Bulgarian (http://www.transifex.com/otf/I2P/language/bg/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -27,69 +27,81 @@ msgstr "Стартиране на I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P е стартиран!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Стартиране"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "Стартиране на I2P Браузер"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Деактивиране"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Рестартиране на I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "Спиране на I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "Рестартирайте Незабавно"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Изключване в {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr ""
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr ""
msgstr "Мрежа"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr ""

View File

@ -4,19 +4,21 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# slrslr, 2022
# slrslr, 2021
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: zzzi2p\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: slrslr, 2022\n"
"Language-Team: Czech (http://www.transifex.com/otf/I2P/language/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -25,69 +27,81 @@ msgstr "Spustit I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P startuje!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Startuji"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "Spouštím I2P Browser"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr ""
msgstr "Nastavit I2P Systémovou Lištu"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Zapnout upozornění"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Vypnout upozornění"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Vypnout ikonu systémové lišty"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Restart I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "Zastavit I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr ""
msgstr "Restartovat I2P Hned"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr ""
msgstr "Zastavit I2P Hned"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr ""
msgstr "Zrušit I2P Zastavení"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr ""
msgstr "Zastavení za {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr ""
msgstr "Vypínání"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Síť"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr ""
msgstr "I2P: Pravé-kliknutí pro menu"

View File

@ -7,14 +7,15 @@
# blabla <blabla@trash-mail.com>, 2011
# Ettore Atalan <atalanttore@googlemail.com>, 2016
# foo <foo@bar>, 2009
# Georg Stadler, 2022
# Lars Schimmer <echelon@i2pmail.org>, 2016
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: Lars Schimmer <echelon@i2pmail.org>\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Georg Stadler, 2022\n"
"Language-Team: German (http://www.transifex.com/otf/I2P/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -29,69 +30,81 @@ msgstr "I2P starten"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P startet gerade!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Startend"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "I2P-Browser öffnen"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "I2P System Tray konfigurieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Deaktivieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Benachrichtigungen aktivieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Benachrichtigungen deaktivieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "I2P neustarten"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "I2P beenden"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "I2P sofort neustarten"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "I2P sofort beenden"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "Herunterfahren von I2P abbrechen"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Herunterfahren in {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Herunterfahren bevorstehend"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Netzwerk"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P: Rechtsklick für Menü"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P desktopgui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"POT-Creation-Date: 2022-02-09 19:13+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"
@ -25,69 +25,81 @@ msgstr ""
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr ""
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr ""
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr ""
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr ""

View File

@ -4,13 +4,14 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Hunor Paksy <heds@cock.li>, 2018
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: zzzi2p\n"
"PO-Revision-Date: 2021-06-20 09:44+0000\n"
"Last-Translator: AdminLMH <lehetmashogy@i2pmail.org>\n"
"Language-Team: Hungarian (http://www.transifex.com/otf/I2P/language/hu/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -41,7 +42,7 @@ msgstr "I2P Böngésző Indítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr ""
msgstr "I2P rendszertálca beállítások"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
@ -61,17 +62,17 @@ msgstr "I2P Leállítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr ""
msgstr "I2P Azonnali újraindítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr ""
msgstr "I2P Azonnali megállítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr ""
msgstr "I2P leállításának visszavonása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
@ -90,4 +91,4 @@ msgstr "Hálózat"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr ""
msgstr "I2P: Jobb-klikk a menüért"

View File

@ -4,15 +4,16 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# タカハシ <indexial@outlook.jp>, 2013
# daingewuvzeevisiddfddd, 2022
# タカハシ, 2013
# Masayuki Hatta <mhatta@mhatta.org>, 2018
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2018-08-17 22:08+0000\n"
"Last-Translator: Masayuki Hatta <mhatta@mhatta.org>\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2022-02-13 03:11+0000\n"
"Last-Translator: daingewuvzeevisiddfddd\n"
"Language-Team: Japanese (http://www.transifex.com/otf/I2P/language/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -27,69 +28,81 @@ msgstr "I2P を開始"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P を起動中!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "起動中"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "I2P ブラウザを起動"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "I2P システムトレイを設定"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "無効"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "通知を有効化"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "通知を無効化"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "システムトレイを無効化"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "I2P を再起動"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "I2P を停止"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "すぐに I2P を再起動"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "すぐに I2P を停止"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "I2P のシャットダウンを中止"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "{0} でシャットダウン"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "即時シャットダウン"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "ネットワーク"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P: 右クリックでメニュー"

View File

@ -4,14 +4,15 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Zagros <zagros21@cmail.nu>, 2020
# Zagros, 2021
# Zagros, 2020
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2020-09-23 21:02+0000\n"
"Last-Translator: Zagros <zagros21@cmail.nu>\n"
"PO-Revision-Date: 2021-08-30 21:05+0000\n"
"Last-Translator: Zagros\n"
"Language-Team: Kurdish (http://www.transifex.com/otf/I2P/language/ku/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -42,7 +43,7 @@ msgstr "وێبگەڕی I2P بکەوە"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr ""
msgstr "دەستکاری سیستەمی ئاگەدارکردنەوەی I2P بکە"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
@ -72,7 +73,7 @@ msgstr "دەستبەجێ I2P بوەستێنە"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "کووژاندنەوە I2P هەڵبوەشێنەوە"
msgstr "دەستهەڵگرتن لە کووژاندنەوەی I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format

View File

@ -0,0 +1,106 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Žan Šadl-Ferš, 2021
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2022-02-09 19:23+0000\n"
"Last-Translator: zzzi2p\n"
"Language-Team: Slovenian (http://www.transifex.com/otf/I2P/language/sl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: sl\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Zaženi I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P se zaganja!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Zaganja"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "Zaženi I2P brskalnik"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "Konfiguriraj I2P opravilno vrstico"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Ponovno zaženi I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "Ustavi I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "Nemudoma ponovno zaženi I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "Nemudoma ustavi I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "Prekliči zaustavitev od I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Zaustavi v {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Zaustavitev je neizbežna"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Omrežje"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P: Pritisnite na desno tipko miške za meni"

View File

@ -4,15 +4,16 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Besnik <besnik@programeshqip.org>, 2016,2019
# Besnik Bleta <besnik@programeshqip.org>, 2022
# Besnik Bleta <besnik@programeshqip.org>, 2016,2019
# Shpetim <shpetim@privacysolutions.no>, 2014
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2019-01-10 14:28+0000\n"
"Last-Translator: Besnik <besnik@programeshqip.org>\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2022-02-10 10:34+0000\n"
"Last-Translator: Besnik Bleta <besnik@programeshqip.org>\n"
"Language-Team: Albanian (http://www.transifex.com/otf/I2P/language/sq/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -27,69 +28,81 @@ msgstr "Nise I2P-në"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P po niset!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Po niset"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "Nis Shfletuesin I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "Formësoni Panel Sistemi I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Çaktivizoje"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Aktivizoni njoftimet"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Çaktivizoni njoftimet"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Çaktivizo panel sistemi"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Rinise I2P-në"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "Ndale I2P-në"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "Rinise I2P-në Menjëherë"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "Ndale I2P-në Menjëherë"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "Anuloje Mbylljen e I2P-së"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Mbylle për {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Mbyllje shumë shpejt"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Rrjet"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P: Djathtasklikoni për menu"

View File

@ -6,16 +6,16 @@
# Translators:
# 123hund123 <M8R-ra4r1r@mailinator.com>, 2011
# Anders Nilsson <anders@devode.se>, 2016
# Jonatan Nyberg, 2016-2017
# Jonatan Nyberg, 2018
# Jonatan Nyberg, 2017
# Jonatan Nyberg <jonatan@autistici.org>, 2016-2017,2021
# efef6ec5b435a041fce803c7f8af77d2_2341d43, 2018
# efef6ec5b435a041fce803c7f8af77d2_2341d43, 2017
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2018-06-17 14:17+0000\n"
"Last-Translator: Jonatan Nyberg\n"
"PO-Revision-Date: 2021-10-02 16:29+0000\n"
"Last-Translator: Jonatan Nyberg <jonatan@autistici.org>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.com/otf/I2P/language/sv_SE/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -51,7 +51,7 @@ msgstr "Konfigurera I2P-meddelandefältet"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Avaktivera"
msgstr "Inaktivera"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
@ -61,7 +61,7 @@ msgstr "Starta om I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Stoppar I2P"
msgstr "Stoppa I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278

View File

@ -4,20 +4,20 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Kaya Zeren <kayazeren@gmail.com>, 2013,2016
# Kaya Zeren <kayazeren@gmail.com>, 2013,2016,2022
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2022-02-10 04:40+0000\n"
"Last-Translator: Kaya Zeren <kayazeren@gmail.com>\n"
"Language-Team: Turkish (Turkey) (http://www.transifex.com/otf/I2P/language/tr_TR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: tr_TR\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -26,69 +26,81 @@ msgstr "I2P başlasın"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P başlatılıyor!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Başlatılıyor"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "I2P Tarayıcısını ın"
msgstr "I2P tarayıcısını "
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "I2P Sistem Tepsisi Ayarları"
msgstr "I2P sistem tepsisi ayarları"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Devre Dışı"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Bildirimleri etkinleştir"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Bildirimleri devre dışı bırak"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Sistem tepsisini devre dışı bırak"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "I2P Yeniden Başlasın"
msgstr "I2P yeniden başlasın"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "I2P Durdurulsun"
msgstr "I2P durdurulsun"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "I2P Hemen Yeniden Başlatılsın"
msgstr "I2P hemen yeniden başlatılsın"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "I2P Hemen Durdurulsun"
msgstr "I2P hemen durdurulsun"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "I2P Kapatmayı İptal Et"
msgstr "I2P kapatmayı iptal et"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "{0} içinde kapat"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Kapatılmak üzere"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Ağ"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P: Menüde sağ tık"

View File

@ -5,15 +5,15 @@
#
# Translators:
# ducki2p <ducki2p@gmail.com>, 2011
# Scott Rhodes <starring169@gmail.com>, 2021
# Scott Rhodes <starring169@gmail.com>, 2021-2022
# walking <walking@i2pmail.org>, 2011
# YFdyh000 <yfdyh000@gmail.com>, 2016
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2021-03-07 07:58+0000\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2022-02-16 16:05+0000\n"
"Last-Translator: Scott Rhodes <starring169@gmail.com>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/otf/I2P/language/zh_CN/)\n"
"MIME-Version: 1.0\n"
@ -29,69 +29,81 @@ msgstr "启动 I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr " I2P 正在启动!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "正在启动"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "启动 I2P 浏览器"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "配置 I2P 系统托盘"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "禁用"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "启用通知"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "禁用通知"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "禁用系统托盘"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "重启 I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "停止 I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "立即重启 I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "立即停止 I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "取消 I2P 关闭"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "{0} 后关闭"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "立即关闭"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "网络"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P右击获得菜单"

View File

@ -9,9 +9,9 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2018-10-04 00:43+0000\n"
"Last-Translator: erinm\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: 黃彥儒 <r1235613@gmail.com>, 2017\n"
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/otf/I2P/language/zh_TW/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -26,69 +26,81 @@ msgstr "啟動I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P已啟動"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "啟動中"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "開啟I2P瀏覽器"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "設定I2P系統文件夾"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "停用"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "启用通知"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "禁用通知"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "禁用系统托盘"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "重啟I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "停止I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "強制重啟I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "強制終止I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "取消停止I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "關閉於 {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "強制關閉"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "網路"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P右鍵開啟選單"

View File

@ -0,0 +1,227 @@
package net.i2p.desktopgui;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import javax.swing.SwingUtilities;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppState;
import net.i2p.app.NotificationService;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
/**
* A simplified Main that does not require router.jar, for App Context only.
* Invokes ExternalTrayManager only.
* No state tracking, ClientAppManager doesn't care.
*
* @since 0.9.54
*/
public class ExternalMain implements ClientApp, NotificationService {
private final I2PAppContext _appContext;
private final ClientAppManager _mgr;
private final Log log;
private TrayManager _trayManager;
private static final String PROP_SWING = "desktopgui.swing";
public ExternalMain(I2PAppContext ctx, ClientAppManager mgr, String args[]) {
_appContext = ctx;
_mgr = mgr;
log = _appContext.logManager().getLog(ExternalMain.class);
}
public ExternalMain() {
_appContext = I2PAppContext.getGlobalContext();
_mgr = _appContext.clientAppManager();
log = _appContext.logManager().getLog(ExternalMain.class);
}
public static void main(String[] args) {
// early check so we can bail out when started via CLI
if (!SystemTray.isSupported()) {
System.err.println("SystemTray not supported");
return;
}
ExternalMain main = new ExternalMain();
main.beginStartup(args);
}
/**
* Start the tray icon code (loads tray icon in the tray area).
* @throws AWTException on startup error, including systray not supported
*/
private synchronized void startUp() throws Exception {
final TrayManager trayManager;
boolean useSwingDefault = !(SystemVersion.isWindows() || SystemVersion.isMac());
boolean useSwing = _appContext.getProperty(PROP_SWING, useSwingDefault);
_trayManager = new ExternalTrayManager(_appContext, useSwing);
_trayManager.startManager();
if (_mgr != null)
_mgr.register(this);
}
/**
* Main method launching the application.
*
* @param args unused
*/
private void beginStartup(String[] args) {
String headless = System.getProperty("java.awt.headless");
boolean isHeadless = Boolean.parseBoolean(headless);
if (isHeadless) {
log.warn("Headless environment: not starting desktopgui!");
return;
}
if (SystemVersion.isMac())
setMacTrayIcon();
launchForeverLoop();
// We'll be doing GUI work, so let's stay in the event dispatcher thread.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
startUp();
} catch(Exception e) {
log.error("Failed while running desktopgui!", e);
}
}
});
}
/**
* Unless we do this, when we start DesktopGUI we get a Java coffee cup
* in the tray.
*
* Based on code from https://gist.github.com/bchapuis/1562406 , no apparent license.
* See also https://stackoverflow.com/questions/6006173/how-do-you-change-the-dock-icon-of-a-java-program
*
* TODO, if we wanted to add our own menu, see
* https://stackoverflow.com/questions/1319805/java-os-x-dock-menu
*
* TODO, if we want to make it bounce, see
* https://stackoverflow.com/questions/15079783/how-to-make-my-app-icon-bounce-in-the-mac-dock
*
* TODO, if we want to handle Quit, see
* https://nakkaya.com/2009/04/19/java-osx-integration/
*
* @since 0.9.33
*/
@SuppressWarnings("unchecked")
private void setMacTrayIcon() {
File f = new File(_appContext.getBaseDir(), "docs/themes/console/images/itoopie_sm.png");
if (!f.exists())
return;
try {
Class util = Class.forName("com.apple.eawt.Application");
Method getApplication = util.getMethod("getApplication", new Class[0]);
Object application = getApplication.invoke(util);
Class params[] = new Class[1];
params[0] = Image.class;
Method setDockIconImage = util.getMethod("setDockIconImage", params);
URL url = f.toURI().toURL();
Image image = Toolkit.getDefaultToolkit().getImage(url);
setDockIconImage.invoke(application, image);
} catch (Exception e) {
if (log.shouldWarn())
log.warn("Can't set OSX Dock icon", e);
}
}
/**
* Avoids the app terminating because no Window is opened anymore.
* More info: http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
*/
private static void launchForeverLoop() {
Runnable r = new Runnable() {
public void run() {
try {
Object o = new Object();
synchronized (o) {
o.wait();
}
} catch (InterruptedException ie) {
}
}
};
Thread t = new Thread(r, "DesktopGUI spinner");
t.setDaemon(false);
t.start();
}
/////// NotificationService methods
/**
* Send a notification to the user.
*
* @param source unsupported
* @param category unsupported
* @param priority unsupported
* @param title for the popup, translated
* @param message translated
* @param path unsupported
* @return 0, or -1 on failure
*/
public int notify(String source, String category, int priority, String title, String message, String path) {
TrayManager tm = _trayManager;
if (tm == null)
return -1;
return tm.displayMessage(priority, title, message, path);
}
/**
* Cancel a notification if possible.
* Unsupported.
*
* @return false always
*/
public boolean cancel(int id) {
return false;
}
/**
* Update the text of a notification if possible.
* Unsupported.
*
* @return false always
*/
public boolean update(int id, String title, String message, String path) {
return false;
}
/////// ClientApp methods
public synchronized void startup() {
beginStartup(null);
}
public synchronized void shutdown(String[] args) {
if (_trayManager != null)
_trayManager.stopManager();
}
public ClientAppState getState() {
return ClientAppState.INITIALIZED;
}
public String getName() {
return "desktopgui";
}
public String getDisplayName() {
return "Desktop GUI";
}
/////// end ClientApp methods
}

View File

@ -22,8 +22,8 @@ import net.i2p.desktopgui.router.RouterManager;
*/
class ExternalTrayManager extends TrayManager {
public ExternalTrayManager(I2PAppContext ctx, Main main, boolean useSwing) {
super(ctx, main, useSwing);
public ExternalTrayManager(I2PAppContext ctx, boolean useSwing) {
super(ctx, useSwing);
}
public PopupMenu getMainMenu() {

View File

@ -1,5 +1,6 @@
package net.i2p.desktopgui;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Desktop.Action;
import java.awt.MenuItem;
@ -29,21 +30,33 @@ class InternalTrayManager extends TrayManager {
private final RouterContext _context;
private final Log log;
private final Main _main;
private MenuItem _statusItem, _browserItem, _configItem, _restartItem, _stopItem,
_restartHardItem, _stopHardItem, _cancelItem;
_restartHardItem, _stopHardItem, _cancelItem,
_notificationItem1, _notificationItem2;
private JMenuItem _jstatusItem, _jbrowserItem, _jconfigItem, _jrestartItem, _jstopItem,
_jrestartHardItem, _jstopHardItem, _jcancelItem;
_jrestartHardItem, _jstopHardItem, _jcancelItem,
_jnotificationItem1, _jnotificationItem2;
private static final boolean CONSOLE_ENABLED = Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Action.BROWSE);
private static final String CONSOLE_BUNDLE_NAME = "net.i2p.router.web.messages";
public InternalTrayManager(RouterContext ctx, Main main, boolean useSwing) {
super(ctx, main, useSwing);
super(ctx, useSwing);
_context = ctx;
_main = main;
log = ctx.logManager().getLog(InternalTrayManager.class);
}
/**
* @since 0.9.53
*/
public void startManager() throws AWTException {
super.startManager();
displayMessage(Log.INFO, _t("Starting"), _t("I2P is starting!"), null);
}
public synchronized PopupMenu getMainMenu() {
PopupMenu popup = new PopupMenu();
@ -73,7 +86,35 @@ class InternalTrayManager extends TrayManager {
}
PopupMenu desktopguiConfigurationLauncher = new PopupMenu(_t("Configure I2P System Tray"));
MenuItem configSubmenu = new MenuItem(_t("Disable"));
final MenuItem notificationItem2 = new MenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
final MenuItem notificationItem1 = new MenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
MenuItem configSubmenu = new MenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
@ -173,6 +214,8 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
desktopguiConfigurationLauncher.add(notificationItem2);
desktopguiConfigurationLauncher.add(notificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
@ -187,6 +230,8 @@ class InternalTrayManager extends TrayManager {
_statusItem = statusItem;
_browserItem = browserLauncher;
_configItem = desktopguiConfigurationLauncher;
_notificationItem1 = notificationItem1;
_notificationItem2 = notificationItem2;
_restartItem = restartItem;
_stopItem = stopItem;
_restartHardItem = restartItem2;
@ -225,7 +270,35 @@ class InternalTrayManager extends TrayManager {
}
JMenu desktopguiConfigurationLauncher = new JMenu(_t("Configure I2P System Tray"));
JMenuItem configSubmenu = new JMenuItem(_t("Disable"));
final JMenuItem notificationItem2 = new JMenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
final JMenuItem notificationItem1 = new JMenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
JMenuItem configSubmenu = new JMenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
@ -325,6 +398,8 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
desktopguiConfigurationLauncher.add(notificationItem2);
desktopguiConfigurationLauncher.add(notificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
@ -339,6 +414,8 @@ class InternalTrayManager extends TrayManager {
_jstatusItem = statusItem;
_jbrowserItem = browserLauncher;
_jconfigItem = desktopguiConfigurationLauncher;
_jnotificationItem1 = notificationItem1;
_jnotificationItem2 = notificationItem2;
_jrestartItem = restartItem;
_jstopItem = stopItem;
_jrestartHardItem = restartItem2;
@ -390,6 +467,10 @@ class InternalTrayManager extends TrayManager {
_stopHardItem.setEnabled(!imminent);
if (_cancelItem != null)
_cancelItem.setEnabled(x && !imminent);
if (_notificationItem1 != null)
_notificationItem1.setEnabled(_showNotifications);
if (_notificationItem2 != null)
_notificationItem2.setEnabled(!_showNotifications);
if (_jstatusItem != null)
_jstatusItem.setText(status);
@ -407,6 +488,10 @@ class InternalTrayManager extends TrayManager {
_jstopHardItem.setVisible(!imminent);
if (_jcancelItem != null)
_jcancelItem.setVisible(x && !imminent);
if (_jnotificationItem1 != null)
_jnotificationItem1.setVisible(_showNotifications);
if (_jnotificationItem2 != null)
_jnotificationItem2.setVisible(!_showNotifications);
}
/**
@ -415,18 +500,24 @@ class InternalTrayManager extends TrayManager {
private void configureDesktopgui(boolean enable) {
String property = Main.PROP_ENABLE;
String value = Boolean.toString(enable);
try {
_context.router().saveConfig(property, value);
if (!enable) {
// TODO popup that explains how to re-enable in console
_main.shutdown(null);
}
} catch (Exception ex) {
log.error("Error saving config", ex);
if (!_context.router().saveConfig(property, value))
log.error("Error saving config");
if (!enable) {
// TODO popup that explains how to re-enable in console
_main.shutdown(null);
}
}
/**
* @since 0.9.53
*/
private void configureNotifications(boolean enable) {
_showNotifications = enable;
String value = Boolean.toString(enable);
if (!_context.router().saveConfig(PROP_NOTIFICATIONS, value))
log.error("Error saving config");
}
/**
* Build the console URL with info from the port mapper,
* and launch the browser at it.

View File

@ -5,6 +5,7 @@ package net.i2p.desktopgui;
*/
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.io.File;
import java.lang.reflect.Method;
@ -16,6 +17,7 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*;
import net.i2p.app.NotificationService;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.router.RouterContext;
import net.i2p.router.app.RouterApp;
@ -27,7 +29,7 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
/**
* The main class of the application.
*/
public class Main implements RouterApp {
public class Main implements RouterApp, NotificationService {
// non-null
private final I2PAppContext _appContext;
@ -55,7 +57,7 @@ public class Main implements RouterApp {
*/
public Main() {
_appContext = I2PAppContext.getGlobalContext();
if (_appContext instanceof RouterContext)
if (_appContext.isRouterContext())
_context = (RouterContext) _appContext;
else
_context = null;
@ -75,7 +77,7 @@ public class Main implements RouterApp {
if (_context != null)
trayManager = new InternalTrayManager(_context, this, useSwing);
else
trayManager = new ExternalTrayManager(_appContext, this, useSwing);
trayManager = new ExternalTrayManager(_appContext, useSwing);
trayManager.startManager();
_trayManager = trayManager;
changeState(RUNNING);
@ -95,6 +97,11 @@ public class Main implements RouterApp {
}
public static void main(String[] args) {
// early check so we can bail out when started via CLI
if (!SystemTray.isSupported()) {
System.err.println("SystemTray not supported");
return;
}
Main main = new Main();
main.beginStartup(args);
}
@ -198,6 +205,46 @@ public class Main implements RouterApp {
t.start();
}
/////// NotificationService methods
/**
* Send a notification to the user.
*
* @param source unsupported
* @param category unsupported
* @param priority unsupported
* @param title for the popup, translated
* @param message translated
* @param path unsupported
* @return 0, or -1 on failure
*/
public int notify(String source, String category, int priority, String title, String message, String path) {
TrayManager tm = _trayManager;
if (tm == null)
return -1;
return tm.displayMessage(priority, title, message, path);
}
/**
* Cancel a notification if possible.
* Unsupported.
*
* @return false always
*/
public boolean cancel(int id) {
return false;
}
/**
* Update the text of a notification if possible.
* Unsupported.
*
* @return false always
*/
public boolean update(int id, String title, String message, String path) {
return false;
}
/////// ClientApp methods
/** @since 0.9.26 */

View File

@ -8,21 +8,27 @@ import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.SwingWorker;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import net.i2p.I2PAppContext;
import net.i2p.apps.systray.UrlLauncher;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
/**
@ -31,24 +37,25 @@ import net.i2p.util.SystemVersion;
abstract class TrayManager {
protected final I2PAppContext _appContext;
protected final Main _main;
protected final boolean _useSwing;
///The tray area, or null if unsupported
protected SystemTray tray;
///Our tray icon, or null if unsupported
protected TrayIcon trayIcon;
protected volatile boolean _showNotifications;
private static final String PNG_DIR = "/desktopgui/resources/images/";
private static final String MAC_ICON = "itoopie_black_24.png";
private static final String WIN_ICON = "itoopie_white_24.png";
private static final String WIN_ICON_LIGHT = "itoopie_white_24.png";
private static final String WIN_ICON_DARK = "itoopie_black_24.png";
private static final String LIN_ICON = "logo.png";
protected static final String PROP_NOTIFICATIONS = "desktopgui.showNotifications";
/**
* Instantiate tray manager.
*/
protected TrayManager(I2PAppContext ctx, Main main, boolean useSwing) {
protected TrayManager(I2PAppContext ctx, boolean useSwing) {
_appContext = ctx;
_main = main;
_useSwing = useSwing;
}
@ -58,6 +65,7 @@ abstract class TrayManager {
public synchronized void startManager() throws AWTException {
if (!SystemTray.isSupported())
throw new AWTException("SystemTray not supported");
_showNotifications = _appContext.getBooleanPropertyDefaultTrue(PROP_NOTIFICATIONS);
tray = SystemTray.getSystemTray();
// Windows typically has tooltips; Linux (at least Ubuntu) doesn't
String tooltip = SystemVersion.isWindows() ? _t("I2P: Right-click for menu") : null;
@ -191,12 +199,20 @@ abstract class TrayManager {
*/
private Image getTrayImage() throws AWTException {
String img;
if (SystemVersion.isWindows())
img = WIN_ICON;
else if (SystemVersion.isMac())
if (SystemVersion.isWindows()) {
// too hard to get the theme out of the registry,
// use our console theme as a best guess
// so we have a contrasting icon
String theme = _appContext.getProperty("routerconsole.theme", "light");
if (theme.equals("dark"))
img = WIN_ICON_LIGHT;
else
img = WIN_ICON_DARK;
} else if (SystemVersion.isMac()) {
img = MAC_ICON;
else
} else {
img = LIN_ICON;
}
URL url = getClass().getResource(PNG_DIR + img);
if (url == null)
throw new AWTException("cannot load tray image " + img);
@ -204,6 +220,74 @@ abstract class TrayManager {
return image;
}
/**
* Send a notification to the user.
*
* @param title for the popup, translated
* @param message translated
* @param path unsupported
* @return 0, or -1 on failure
*/
public int displayMessage(int priority, String title, String message, String path) {
if (!_showNotifications)
return -1;
final TrayIcon ti = trayIcon;
if (ti == null)
return -1;
TrayIcon.MessageType type;
if (priority <= Log.DEBUG)
type = TrayIcon.MessageType.NONE;
else if (priority <= Log.INFO)
type = TrayIcon.MessageType.INFO;
else if (priority <= Log.WARN)
type = TrayIcon.MessageType.WARNING;
else
type = TrayIcon.MessageType.ERROR;
ti.displayMessage(title, message, type);
/*
* There's apparently no way to bind a particular message to an action
that comes back. We can't keep a queue because we don't get
an action back when the message is removed via timeout or user x-out.
On OSX, new messages dismiss previous ones.
On LXDE (and Gnome?), new messages go under previous ones. Timeout is only 10 seconds.
Message timeout is platform-dependent.
So the order of events is unknowable.
This only works if there is only one message ever.
if (path != null && path.length() > 0) {
if (path.charAt(0) == '/');
path = path.substring(1);
final String url = _appContext.portMapper().getConsoleURL() + path;
ti.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
ti.removeActionListener(this);
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
System.out.println("DIB " + arg0);
UrlLauncher launcher = new UrlLauncher(_appContext, null, null);
try {
launcher.openUrl(url);
System.out.println("DIB success " + url);
} catch (IOException e1) {
System.out.println("DIB fail " + url);
}
return null;
}
@Override
protected void done() {
System.out.println("done " + arg0);
}
}.execute();
}
});
}
*/
return 0;
}
protected String _t(String s) {
return DesktopguiTranslator._t(_appContext, s);
}

View File

@ -12,7 +12,7 @@ import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import org.apache.http.conn.util.InetAddressUtils;
import net.i2p.apache.http.conn.util.InetAddressUtils;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;

View File

@ -156,11 +156,11 @@ public class JSONRPC2Servlet extends HttpServlet {
} else {
out.println("<p>Current API password:<input name=\"password\" type=\"password\">");
}
out.println("<p>New API password (twice):<input name=\"password2\" type=\"password\">" +
"<input name=\"password3\" type=\"password\">" +
out.println("<p>New API password (twice): <input name=\"password2\" type=\"password\"> " +
"<input name=\"password3\" type=\"password\"> " +
"<input name=\"save\" type=\"submit\" value=\"Change API Password\">" +
"<p>If you forget the API password, stop i2pcontrol, delete the file <tt>" + _conf.getConfFile() +
"</tt>, and restart i2pcontrol.");
"<p>If you forget the API password, <a href=\"/configwebapps\">stop jsonrpc</a>, delete the file <tt>" + _conf.getConfFile() +
"</tt>, and <a href=\"/configwebapps\">restart jsonrpc</a>.");
out.println("</form>");
} else {
out.println("<p><a href=\"password\">Change API Password</a>");

View File

@ -96,7 +96,7 @@ public class RouterInfoHandler implements RequestHandler {
}
if (inParams.containsKey("i2p.router.status")) {
outParams.put("i2p.router.status", _context.throttle().getTunnelStatus());
outParams.put("i2p.router.status", _context.throttle().getLocalizedTunnelStatus());
}
if (inParams.containsKey("i2p.router.net.status")) {
@ -179,25 +179,44 @@ public class RouterInfoHandler implements RequestHandler {
int status = _context.commSystem().getStatus().getCode();
switch (status) {
case CommSystemFacade.STATUS_OK:
RouterAddress ra = _context.router().getRouterInfo().getTargetAddress("NTCP");
case CommSystemFacade.STATUS_OK:
case CommSystemFacade.STATUS_IPV4_OK_IPV6_UNKNOWN:
case CommSystemFacade.STATUS_IPV4_OK_IPV6_FIREWALLED:
case CommSystemFacade.STATUS_IPV4_FIREWALLED_IPV6_OK:
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_OK:
RouterAddress ra = _context.router().getRouterInfo().getTargetAddress("NTCP2");
if (ra == null || TransportUtil.isPubliclyRoutable(ra.getIP(), true))
return NETWORK_STATUS.OK;
return NETWORK_STATUS.ERROR_PRIVATE_TCP_ADDRESS;
case CommSystemFacade.STATUS_DIFFERENT:
case CommSystemFacade.STATUS_DIFFERENT:
case CommSystemFacade.STATUS_IPV4_SNAT_IPV6_OK:
case CommSystemFacade.STATUS_IPV4_SNAT_IPV6_UNKNOWN:
return NETWORK_STATUS.ERROR_SYMMETRIC_NAT;
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
if (_context.router().getRouterInfo().getTargetAddress("NTCP") != null)
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
case CommSystemFacade.STATUS_IPV4_FIREWALLED_IPV6_UNKNOWN:
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_FIREWALLED:
if (_context.router().getRouterInfo().getTargetAddress("NTCP2") != null)
return NETWORK_STATUS.WARN_FIREWALLED_WITH_INBOUND_TCP;
if (((FloodfillNetworkDatabaseFacade) _context.netDb()).floodfillEnabled())
return NETWORK_STATUS.WARN_FIREWALLED_AND_FLOODFILL;
if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)
return NETWORK_STATUS.WARN_FIREWALLED_AND_FAST;
return NETWORK_STATUS.FIREWALLED;
case CommSystemFacade.STATUS_HOSED:
case CommSystemFacade.STATUS_HOSED:
return NETWORK_STATUS.ERROR_UDP_PORT_IN_USE;
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
default:
case CommSystemFacade.STATUS_DISCONNECTED:
return NETWORK_STATUS.ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL;
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
case CommSystemFacade.STATUS_IPV4_UNKNOWN_IPV6_OK:
case CommSystemFacade.STATUS_IPV4_UNKNOWN_IPV6_FIREWALLED:
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_UNKNOWN:
default:
ra = _context.router().getRouterInfo().getTargetAddress("SSU");
if (ra == null && _context.router().getUptime() > 5 * 60 * 1000) {
if (_context.commSystem().countActivePeers() <= 0)

View File

@ -2,3 +2,11 @@
# This is for app context configuration of standalone i2psnark.
# Almost all configuration settings are in i2psnark.config.d/i2psnark.config
#
# disable browser launch on startup
#routerconsole.browser=/bin/false
# disable browser launch on startup (Windows)
#routerconsole.browser=NUL
# change browser
#routerconsole.browser=firefox
# disable system tray
#desktopgui.enabled=false

View File

@ -21,6 +21,8 @@
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
<!-- jsp-api.jar only present for debian builds -->
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
<!-- following jars only for standalone builds -->
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
</classpath>
</depend>
</target>
@ -60,6 +62,7 @@
<pathelement location="../../systray/java/build/systray.jar" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
</classpath>
</javac>
</target>
@ -147,6 +150,7 @@
<target name="warUpToDate">
<uptodate property="war.uptodate" targetfile="../i2psnark.war" >
<srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../resources/**/* ../web.xml" />
<srcfiles dir= "../resources" />
</uptodate>
</target>
@ -196,9 +200,16 @@
</target>
<target name="standalone" depends="standalone_prep">
<!-- doesn't support file permissions
<zip destfile="i2psnark-standalone.zip">
<zipfileset dir="./dist/" prefix="i2psnark/" />
<zipfileset dir="./i2psnark/" />
</zip>
-->
<exec executable="zip" failifexecutionfails="true" failonerror="true" >
<arg value="-r" />
<arg value="i2psnark-standalone.zip" />
<arg value="i2psnark" />
</exec>
</target>
<!-- make a fat jar for standalone -->
@ -227,6 +238,8 @@
<zipfileset src="../../ministreaming/java/build/mstreaming.jar" />
<zipfileset src="../../streaming/java/build/streaming.jar" />
<zipfileset src="../../systray/java/build/systray.jar" />
<zipfileset src="../../../build/jbigi.jar" />
<zipfileset src="../../desktopgui/dist/desktopgui.jar" />
<!-- Countries translations. The i2psnark translations are in the war but it's easier to put these here -->
<!-- 300KB just to translate "Brazil", but why not... -->
<!--
@ -305,33 +318,34 @@
</target>
<target name="standalone_prep" depends="standalone_jar, standalone_war">
<delete dir="./dist" />
<mkdir dir="./dist" />
<copy file="../launch-i2psnark" todir="./dist/" />
<copy file="../launch-i2psnark.bat" todir="./dist/" />
<mkdir dir="./dist/contexts" />
<copy file="../standalone-context.xml" tofile="./dist/contexts/context.xml" />
<mkdir dir="./dist/docroot" />
<copy file="../standalone-index.html" tofile="./dist/docroot/index.html" />
<mkdir dir="./dist/webapps" />
<copy file="../i2psnark.war" tofile="./dist/webapps/i2psnark.war" />
<copy file="../jetty-i2psnark.xml" tofile="./dist/jetty-i2psnark.xml" />
<copy file="../i2psnark-appctx.config" tofile="./dist/i2psnark-appctx.config" />
<copy file="./build/i2psnark-standalone.jar" tofile="./dist/i2psnark.jar" />
<copy file="../readme-standalone.txt" tofile="./dist/readme.txt" />
<delete dir="./i2psnark" />
<mkdir dir="./i2psnark" />
<copy file="../launch-i2psnark" todir="./i2psnark/" />
<chmod type="file" file="./i2psnark/launch-i2psnark" perm="+x" />
<copy file="../launch-i2psnark.bat" todir="./i2psnark/" />
<mkdir dir="./i2psnark/contexts" />
<copy file="../standalone-context.xml" tofile="./i2psnark/contexts/context.xml" />
<mkdir dir="./i2psnark/docroot" />
<copy file="../standalone-index.html" tofile="./i2psnark/docroot/index.html" />
<mkdir dir="./i2psnark/webapps" />
<copy file="../i2psnark.war" tofile="./i2psnark/webapps/i2psnark.war" />
<copy file="../jetty-i2psnark.xml" tofile="./i2psnark/jetty-i2psnark.xml" />
<copy file="../i2psnark-appctx.config" tofile="./i2psnark/i2psnark-appctx.config" />
<copy file="./build/i2psnark-standalone.jar" tofile="./i2psnark/i2psnark.jar" />
<copy file="../readme-standalone.txt" tofile="./i2psnark/readme.txt" />
<!-- temp so announces work -->
<copy file="../../../installer/resources/hosts.txt" tofile="./dist/hosts.txt" />
<copy todir="./dist/licenses" >
<copy file="../../../installer/resources/hosts.txt" tofile="./i2psnark/hosts.txt" />
<copy todir="./i2psnark/licenses" >
<fileset dir="../../../licenses" includes="LICENSE-GPLv2.txt, ABOUT-Jetty.html" />
</copy>
<mkdir dir="./dist/logs" />
<mkdir dir="./i2psnark/logs" />
</target>
<target name="clean">
<delete dir="./build" />
<delete file="../i2psnark.war" />
<delete file="./i2psnark-standalone.zip" />
<delete dir="./dist" />
<delete dir="./i2psnark" />
</target>
<target name="cleandep" depends="clean">
</target>

View File

@ -30,6 +30,7 @@ import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.RouterRestartException;
import net.i2p.data.Hash;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
@ -131,12 +132,13 @@ class ConnectionAcceptor implements Runnable
/**
* Effectively unused, would only be called if we changed
* I2CP host/port, which is hidden in the gui if in router context
* FIXME this only works if already running
*/
public synchronized void restart() {
Thread t = thread;
if (t != null)
t.interrupt();
else
startAccepting();
}
public int getPort()
@ -201,6 +203,24 @@ class ConnectionAcceptor implements Runnable
t.start();
}
}
catch (RouterRestartException rre) {
if (_log.shouldWarn())
_log.warn("Waiting for router restart", rre);
try {
Thread.sleep(2*60*1000);
} catch (InterruptedException ie) {}
while (true) {
if (_util.connected())
break;
if (_util.connect())
break;
try {
Thread.sleep(60*1000);
} catch (InterruptedException ie) { break; }
}
if (_log.shouldWarn())
_log.warn("Router restarted");
}
catch (I2PException ioe)
{
int level = stop ? Log.WARN : Log.ERROR;

View File

@ -23,6 +23,7 @@ import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketEepGet;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManager.DisconnectListener;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Base32;
@ -47,7 +48,7 @@ import org.klomp.snark.dht.KRPC;
* so we can run multiple instances of single Snarks
* (but not multiple SnarkManagers, it is still static)
*/
public class I2PSnarkUtil {
public class I2PSnarkUtil implements DisconnectListener {
private final I2PAppContext _context;
private final Log _log;
private final String _baseName;
@ -75,6 +76,7 @@ public class I2PSnarkUtil {
private List<String> _openTrackers;
private DHT _dht;
private long _startedTime;
private final DisconnectListener _discon;
private static final int EEPGET_CONNECT_TIMEOUT = 45*1000;
private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000;
@ -91,17 +93,18 @@ public class I2PSnarkUtil {
public I2PSnarkUtil(I2PAppContext ctx) {
this(ctx, "i2psnark");
this(ctx, "i2psnark", null);
}
/**
* @param baseName generally "i2psnark"
* @since Jetty 7
*/
public I2PSnarkUtil(I2PAppContext ctx, String baseName) {
public I2PSnarkUtil(I2PAppContext ctx, String baseName, DisconnectListener discon) {
_context = ctx;
_log = _context.logManager().getLog(Snark.class);
_log = _context.logManager().getLog(I2PSnarkUtil.class);
_baseName = baseName;
_discon = discon;
_opts = new HashMap<String, String>();
//setProxy("127.0.0.1", 4444);
setI2CPConfig("127.0.0.1", I2PClient.DEFAULT_LISTEN_PORT, null);
@ -324,8 +327,11 @@ public class I2PSnarkUtil {
if (opts.getProperty(I2PClient.PROP_GZIP) == null)
opts.setProperty(I2PClient.PROP_GZIP, "false");
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
if (_manager != null)
if (_manager != null) {
_startedTime = _context.clock().now();
if (_discon != null)
_manager.addDisconnectListener(this);
}
_connecting = false;
}
if (_shouldUseDHT && _manager != null && _dht == null)
@ -333,6 +339,23 @@ public class I2PSnarkUtil {
return (_manager != null);
}
/**
* DisconnectListener interface
* @since 0.9.53
*/
public void sessionDisconnected() {
synchronized(this) {
_manager = null;
_connecting = false;
if (_dht != null) {
_dht.stop();
_dht = null;
}
}
if (_discon != null)
_discon.sessionDisconnected();
}
/**
* @return null if disabled or not started
* @since 0.8.4
@ -537,6 +560,9 @@ public class I2PSnarkUtil {
return null;
}
/**
* Full Base64 of Destination
*/
public String getOurIPString() {
Destination dest = getMyDestination();
if (dest != null)

View File

@ -82,8 +82,9 @@ public class MetaInfo
* @param created_by may be null
* @param url_list may be null
* @param comment may be null
* @since public since 0.9.53, was package private
*/
MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
public MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
List<List<String>> announce_list, String created_by, List<String> url_list, String comment)
{
@ -442,9 +443,12 @@ public class MetaInfo
}
/**
* Returns the piece hashes. Only used by storage so package local.
* Returns the piece hashes.
*
* @return not a copy, do not modify
* @since public since 0.9.53, was package private
*/
byte[] getPieceHashes()
public byte[] getPieceHashes()
{
return piece_hashes;
}
@ -716,8 +720,9 @@ public class MetaInfo
if (infoMap != null)
return Collections.unmodifiableMap(infoMap);
// we should only get here if serving a magnet on a torrent we created
if (_log.shouldLog(Log.WARN))
_log.warn("Creating new infomap", new Exception());
// or on edit torrent save
if (_log.shouldDebug())
_log.debug("Creating new infomap", new Exception());
// otherwise we must create it
Map<String, BEValue> info = new HashMap<String, BEValue>();
info.put("name", new BEValue(DataHelper.getUTF8(name)));

View File

@ -279,7 +279,6 @@ class PeerCoordinator implements PeerListener
/**
* Bytes not yet in storage. Does NOT account for skipped files.
* Not exact (does not adjust for last piece size).
* Returns how many bytes are still needed to get the complete torrent.
* @return -1 if in magnet mode
*/
@ -287,8 +286,13 @@ class PeerCoordinator implements PeerListener
{
if (metainfo == null | storage == null)
return -1;
// XXX - Only an approximation.
return ((long) storage.needed()) * metainfo.getPieceLength(0);
int psz = metainfo.getPieceLength(0);
long rv = ((long) storage.needed()) * psz;
int last = metainfo.getPieces() - 1;
BitField bf = storage.getBitField();
if (bf != null && !bf.get(last))
rv -= psz - metainfo.getPieceLength(last);
return rv;
}
/**

View File

@ -590,8 +590,12 @@ public class Snark
private void x_startTorrent() {
boolean ok = _util.connect();
if (!ok)
fatalRouter("Unable to connect to I2P", null);
if (!ok) {
if (_util.getContext().isRouterContext())
fatalRouter(_util.getString("Unable to connect to I2P"), null);
else
fatalRouter(_util.getString("Error connecting to I2P - check your I2CP settings!") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort(), null);
}
if (coordinator == null) {
I2PServerSocket serversocket = _util.getServerSocket();
if (serversocket == null)
@ -1255,7 +1259,9 @@ public class Snark
*/
private void fatalRouter(String s, Throwable t) throws RouterException {
_log.error(s, t);
stopTorrent();
if (!_util.getContext().isRouterContext())
System.out.println(s);
stopTorrent(true);
if (completeListener != null)
completeListener.fatal(this, s);
throw new RouterException(s, t);
@ -1321,6 +1327,15 @@ public class Snark
}
}
/**
* Call after editing torrent.
* Caller must ensure infohash, files, etc. did not change.
*
* @since 0.9.53
*/
public void replaceMetaInfo(MetaInfo metainfo) {
meta = metainfo;
}
///////////// Begin StorageListener methods

View File

@ -29,7 +29,9 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import net.i2p.app.NotificationService;
import net.i2p.client.I2PClient;
import net.i2p.client.streaming.I2PSocketManager.DisconnectListener;
import net.i2p.crypto.SHA1Hash;
import net.i2p.crypto.SigType;
import net.i2p.data.Base64;
@ -57,7 +59,7 @@ import org.klomp.snark.dht.KRPC;
/**
* Manage multiple snarks
*/
public class SnarkManager implements CompleteListener, ClientApp {
public class SnarkManager implements CompleteListener, ClientApp, DisconnectListener {
/**
* Map of (canonical) filename of the .torrent file to Snark instance.
@ -83,8 +85,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
private final Log _log;
private final UIMessages _messages;
private final I2PSnarkUtil _util;
private PeerCoordinatorSet _peerCoordinatorSet;
private ConnectionAcceptor _connectionAcceptor;
private final PeerCoordinatorSet _peerCoordinatorSet;
private final ConnectionAcceptor _connectionAcceptor;
private Thread _monitor;
private volatile boolean _running;
private volatile boolean _stopping;
@ -130,7 +132,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
public static final String PROP_FILES_PUBLIC = "i2psnark.filesPublic";
public static final String PROP_OLD_AUTO_START = "i2snark.autoStart"; // oops
public static final String PROP_AUTO_START = "i2psnark.autoStart"; // convert in migration to new config file
public static final String DEFAULT_AUTO_START = "false";
private final boolean DEFAULT_AUTO_START;
//public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
//public static final String DEFAULT_LINK_PREFIX = "file:///";
public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
@ -140,7 +142,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
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[] THEMES = new String[] { "dark", "light", "ubergine", "vanilla" };
// Translators: Translate "ubergine" as "aubergine" or "eggplant" or "purple"
private static final String[] THEMES = new String[] { _x("ubergine"), _x("dark"), _x("light"), _x("vanilla") };
/** From CSSHelper */
private static final String PROP_DISABLE_OLD = "routerconsole.disableOldThemes";
private static final boolean DEFAULT_DISABLE_OLD = true;
@ -267,7 +270,10 @@ public class SnarkManager implements CompleteListener, ClientApp {
_contextName = ctxName;
_log = _context.logManager().getLog(SnarkManager.class);
_messages = new UIMessages(MAX_MESSAGES);
_util = new I2PSnarkUtil(_context, ctxName);
_util = new I2PSnarkUtil(_context, ctxName, this);
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util, _peerCoordinatorSet);
DEFAULT_AUTO_START = !ctx.isRouterContext();
String cfile = ctxName + CONFIG_FILE_SUFFIX;
File configFile = new File(cfile);
if (!configFile.isAbsolute())
@ -292,8 +298,6 @@ public class SnarkManager implements CompleteListener, ClientApp {
if (cmgr != null)
cmgr.register(this);
}
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util, _peerCoordinatorSet);
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
_monitor.start();
// only if default instance
@ -342,6 +346,18 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
}
/**
* DisconnectListener interface
* @since 0.9.53
*/
public void sessionDisconnected() {
if (!_context.isRouterContext()) {
addMessage(_t("Unable to connect to I2P"));
stopAllTorrents(true);
_stopping = false;
}
}
/*
* Called by the webapp at Jetty shutdown.
* Stops all torrents. Does not close the tunnel, so the announces have a chance.
@ -463,7 +479,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
public boolean shouldAutoStart() {
return Boolean.parseBoolean(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START));
return Boolean.parseBoolean(_config.getProperty(PROP_AUTO_START, Boolean.toString(DEFAULT_AUTO_START)));
}
/**
@ -814,7 +830,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
if (!_config.containsKey(PROP_DIR))
_config.setProperty(PROP_DIR, _contextName);
if (!_config.containsKey(PROP_AUTO_START))
_config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
_config.setProperty(PROP_AUTO_START, Boolean.toString(DEFAULT_AUTO_START));
if (!_config.containsKey(PROP_REFRESH_DELAY))
_config.setProperty(PROP_REFRESH_DELAY, Integer.toString(DEFAULT_REFRESH_DELAY_SECS));
if (!_config.containsKey(PROP_STARTUP_DELAY))
@ -847,7 +863,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
/**
* Get current theme.
* @return String -- the current theme
* @return String -- the current theme, untranslated
*/
public String getTheme() {
String theme;
@ -912,20 +928,29 @@ public class SnarkManager implements CompleteListener, ClientApp {
/**
* Get all themes
* @return String[] -- Array of all the themes found, non-null, unsorted
* @return Array of all the themes found, non-null, unsorted, untranslated. Not a copy, do not modify.
*/
public static String[] getThemes() {
return THEMES;
}
/** call from DirMonitor since loadConfig() is called before router I2CP is up */
private void getBWLimit() {
if (!_config.containsKey(PROP_UPBW_MAX)) {
/**
* Call from DirMonitor since loadConfig() is called before router I2CP is up.
* We also use this as a test that the router is there for standalone.
*
* @return true if we got a response from the router
*/
private boolean getBWLimit() {
boolean shouldSet = !_config.containsKey(PROP_UPBW_MAX);
if (shouldSet || !_context.isRouterContext()) {
int[] limits = BWLimits.getBWLimits(_util.getI2CPHost(), _util.getI2CPPort());
if (limits != null && limits[1] > 0)
if (limits == null)
return false;
if (shouldSet && limits[1] > 0)
_util.setMaxUpBW(limits[1]);
}
return true;
}
private void updateConfig() {
@ -1576,7 +1601,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
if (dataDir == null)
dataDir = getDataDir();
Snark torrent = null;
Snark torrent;
synchronized (_snarks) {
torrent = _snarks.get(filename);
}
@ -1693,18 +1718,31 @@ public class SnarkManager implements CompleteListener, ClientApp {
String link = linkify(torrent);
if (!dontAutoStart && shouldAutoStart() && running) {
if (!_util.connected()) {
addMessage(_t("Connecting to I2P"));
String msg = _t("Connecting to I2P");
addMessage(msg);
if (!_context.isRouterContext())
System.out.println(msg);
boolean ok = _util.connect();
if (!ok) {
addMessage(_t("Error connecting to I2P - check your I2CP settings!"));
if (_context.isRouterContext()) {
addMessage(_t("Unable to connect to I2P"));
} else {
msg = _t("Error connecting to I2P - check your I2CP settings!") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort();
addMessage(msg);
System.out.println(msg);
}
// this would rename the torrent to .BAD
//return false;
}
}
torrent.startTorrent();
addMessageNoEscape(_t("Torrent added and started: {0}", link));
if (!_context.isRouterContext())
System.out.println(_t("Torrent added and started: {0}", torrent.getBaseName()));
} else {
addMessageNoEscape(_t("Torrent added: {0}", link));
if (!_context.isRouterContext())
System.out.println(_t("Torrent added: {0}", torrent.getBaseName()));
}
return true;
}
@ -2363,6 +2401,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
String now = Long.toString(System.currentTimeMillis());
config.setProperty(PROP_META_ADDED, now);
config.setProperty(PROP_META_STAMP, now);
config.setProperty(PROP_META_RUNNING, "true");
// save
synchronized (_configLock) {
saveConfig();
@ -2491,11 +2530,19 @@ public class SnarkManager implements CompleteListener, ClientApp {
addMessage(_t("Torrent removed: \"{0}\"", torrent.getBaseName()));
}
/**
* This calls monitorTorrents() once a minute.
* It also gets the bandwidth limits and loads magnets on first run.
* For standalone, it also handles checking that the external router is there,
* and restarting torrents once the router appears.
*
*/
private class DirMonitor implements Runnable {
public void run() {
// don't bother delaying if auto start is false
long delay = (60L * 1000) * getStartupDelayMinutes();
if (delay > 0 && shouldAutoStart()) {
boolean autostart = shouldAutoStart();
if (delay > 0 && autostart) {
int id = _messages.addMessageNoEscape(_t("Adding torrents in {0}", DataHelper.formatDuration2(delay)));
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
// Remove that first message
@ -2504,17 +2551,80 @@ public class SnarkManager implements CompleteListener, ClientApp {
// here because we need to delay until I2CP is up
// although the user will see the default until then
getBWLimit();
boolean routerOK = false;
boolean doMagnets = true;
while (_running) {
File dir = getDataDir();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Directory Monitor loop over " + dir.getAbsolutePath());
if (routerOK &&
(_context.isRouterContext() || _util.connected() || _util.isConnecting())) {
autostart = shouldAutoStart();
} else {
// Test if the router is there
// For standalone, this will probe the router every 60 seconds if not connected
boolean oldOK = routerOK;
// standalone, first time only
if (doMagnets && !_context.isRouterContext())
dtgNotify(Log.INFO, _t("Connecting to I2P") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort());
routerOK = getBWLimit();
if (routerOK) {
autostart = shouldAutoStart();
if (autostart && !oldOK && !doMagnets && !_snarks.isEmpty()) {
// Start previously added torrents
for (Snark snark : _snarks.values()) {
Properties config = getConfig(snark);
String prop = config.getProperty(PROP_META_RUNNING);
if (prop == null || Boolean.parseBoolean(prop)) {
if (!_util.connected()) {
String msg = _t("Connecting to I2P");
addMessage(msg);
if (!_context.isRouterContext())
dtgNotify(Log.INFO, msg + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort());
// getBWLimit() was successful so this should work
boolean ok = _util.connect();
if (!ok) {
if (_context.isRouterContext()) {
addMessage(_t("Unable to connect to I2P"));
} else {
msg = _t("Error connecting to I2P - check your I2CP settings!") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort();
addMessage(msg);
dtgNotify(Log.ERROR, msg);
}
routerOK = false;
autostart = false;
break;
} else {
if (!_context.isRouterContext()) {
msg = "Connected to I2P at " + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort();
addMessage(msg);
dtgNotify(Log.INFO, msg);
}
}
}
addMessageNoEscape(_t("Starting up torrent {0}", linkify(snark)));
try {
snark.startTorrent();
} catch (Snark.RouterException re) {
// Snark.fatal() will log and call fatal() here for user message before throwing
break;
} catch (RuntimeException re) {
// Snark.fatal() will log and call fatal() here for user message before throwing
}
}
}
if (routerOK)
addMessage(_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
}
} else {
autostart = false;
}
}
boolean ok;
try {
// Don't let this interfere with .torrent files being added or deleted
synchronized (_snarks) {
ok = monitorTorrents(dir);
ok = monitorTorrents(dir, autostart);
}
} catch (RuntimeException e) {
_log.error("Error in the DirectoryMonitor", e);
@ -2523,12 +2633,12 @@ public class SnarkManager implements CompleteListener, ClientApp {
if (doMagnets) {
// first run only
try {
addMagnets();
addMagnets(autostart);
doMagnets = false;
} catch (RuntimeException e) {
_log.error("Error in the DirectoryMonitor", e);
}
if (!_snarks.isEmpty())
if (routerOK && !_snarks.isEmpty())
addMessage(_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
// To fix bug where files were left behind,
// but also good for when user removes snarks when i2p is not running
@ -2537,6 +2647,15 @@ public class SnarkManager implements CompleteListener, ClientApp {
// time i2psnark starts. See ticket #1658.
if (ok)
cleanupTorrentStatus();
if (!routerOK) {
if (_context.isRouterContext()) {
addMessage(_t("Unable to connect to I2P"));
} else {
String msg = _t("Error connecting to I2P - check your I2CP settings!") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort();
addMessage(msg);
dtgNotify(Log.ERROR, msg);
}
}
}
try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
}
@ -2553,8 +2672,12 @@ public class SnarkManager implements CompleteListener, ClientApp {
Storage storage = snark.getStorage();
if (meta == null || storage == null)
return;
if (snark.getDownloaded() > 0)
if (snark.getDownloaded() > 0) {
addMessageNoEscape(_t("Download finished: {0}", linkify(snark)));
dtgNotify(Log.INFO,
_t("Download finished: {0}", snark.getName()),
"/i2psnark/" + linkify(snark));
}
updateStatus(snark);
}
@ -2644,6 +2767,38 @@ public class SnarkManager implements CompleteListener, ClientApp {
// End Snark.CompleteListeners
/**
* Send a notification to the user via desktopgui and,
* if standalone, on the console.
*
* @param priority log level
* @param message translated
* @since 0.9.54
*/
private void dtgNotify(int priority, String message) {
dtgNotify(priority, message, null);
}
/**
* Send a notification to the user via desktopgui and,
* if standalone, on the console.
*
* @param priority log level
* @param message translated
* @param path in console for more information, starting with /, must be URL-escaped, or null
* @since 0.9.54
*/
private void dtgNotify(int priority, String message, String path) {
ClientAppManager cmgr = _context.clientAppManager();
if (cmgr != null) {
NotificationService ns = (NotificationService) cmgr.getRegisteredApp("desktopgui");
if (ns != null)
ns.notify("I2PSnark", null, priority, _t("I2PSnark"), message, path);
}
if (!_context.isRouterContext())
System.out.println(message);
}
/**
* An HTML link to the file if complete and a single file,
* to the directory if not complete or not a single file,
@ -2671,7 +2826,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
*
* @since 0.8.4
*/
private void addMagnets() {
private void addMagnets(boolean autostart) {
boolean changed = false;
for (Iterator<?> iter = _config.keySet().iterator(); iter.hasNext(); ) {
String k = (String) iter.next();
@ -2688,7 +2843,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
String tracker = config.getProperty(PROP_META_MAGNET_TR);
String dir = config.getProperty(PROP_META_MAGNET_DIR);
File dirf = (dir != null) ? (new File(dir)) : null;
addMagnet(name, ih, tracker, false, dirf);
addMagnet(name, ih, tracker, false, autostart, dirf, this);
} else {
iter.remove();
changed = true;
@ -2702,9 +2857,10 @@ public class SnarkManager implements CompleteListener, ClientApp {
/**
* caller must synchronize on _snarks
*
* @param shouldStart should we autostart the torrents
* @return success, false if an error adding any torrent.
*/
private boolean monitorTorrents(File dir) {
private boolean monitorTorrents(File dir, boolean shouldStart) {
boolean rv = true;
File files[] = dir.listFiles(new FileSuffixFilter(".torrent"));
List<String> foundNames = new ArrayList<String>(0);
@ -2724,7 +2880,6 @@ public class SnarkManager implements CompleteListener, ClientApp {
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("DirMon found: " + DataHelper.toString(foundNames) + " existing: " + DataHelper.toString(existingNames));
// lets find new ones first...
boolean shouldStart = shouldAutoStart();
for (String name : foundNames) {
if (existingNames.contains(name)) {
// already known. noop
@ -2789,6 +2944,14 @@ public class SnarkManager implements CompleteListener, ClientApp {
return _util.getString(s, o, o2);
}
/**
* mark for translation, does not translate
* @since 0.9.53
*/
private static String _x(String s) {
return s;
}
/**
* Unsorted map of name to Tracker object
* Modifiable, not a copy

View File

@ -0,0 +1,753 @@
package org.klomp.snark;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSessionMuxedListener;
import net.i2p.client.SendMessageOptions;
import net.i2p.client.datagram.I2PDatagramDissector;
import net.i2p.client.datagram.I2PDatagramMaker;
import net.i2p.client.datagram.I2PInvalidDatagramException;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
/**
* One of these for all trackers and info hashes.
* Ref: BEP 15, proposal 160
*
* The main difference from BEP 15 is that the announce response
* contains a 32-byte hash instead of a 4-byte IP and a 2-byte port.
*
* This implements only "fast mode".
* We send only repliable datagrams, and
* receive only raw datagrams, as follows:
*
*<pre>
* client tracker type
* ------ ------- ----
* announce --&gt; repliable
* &lt;-- ann resp raw
*</pre>
*
* @since 0.9.53, enabled in 0.9.54
*/
class UDPTrackerClient implements I2PSessionMuxedListener {
private final I2PAppContext _context;
private final Log _log;
/** hook to inject and receive datagrams */
private final I2PSession _session;
private final I2PSnarkUtil _util;
private final Hash _myHash;
/** unsigned dgrams */
private final int _rPort;
/** dest and port to tracker data */
private final ConcurrentHashMap<HostPort, Tracker> _trackers;
/** our TID to tracker */
private final Map<Integer, ReplyWaiter> _sentQueries;
private boolean _isRunning;
public static final int EVENT_NONE = 0;
public static final int EVENT_COMPLETED = 1;
public static final int EVENT_STARTED = 2;
public static final int EVENT_STOPPED = 3;
private static final int ACTION_CONNECT = 0;
private static final int ACTION_ANNOUNCE = 1;
private static final int ACTION_SCRAPE = 2;
private static final int ACTION_ERROR = 3;
private static final int SEND_CRYPTO_TAGS = 8;
private static final int LOW_CRYPTO_TAGS = 4;
private static final long DEFAULT_TIMEOUT = 15*1000;
private static final long DEFAULT_QUERY_TIMEOUT = 60*1000;
private static final long CLEAN_TIME = 163*1000;
/** in seconds */
private static final int DEFAULT_INTERVAL = 60*60;
private static final int MIN_INTERVAL = 15*60;
private static final int MAX_INTERVAL = 8*60*60;
private enum WaitState { INIT, SUCCESS, TIMEOUT, FAIL }
/**
*
*/
public UDPTrackerClient(I2PAppContext ctx, I2PSession session, I2PSnarkUtil util) {
_context = ctx;
_session = session;
_util = util;
_log = ctx.logManager().getLog(UDPTrackerClient.class);
_rPort = TrackerClient.PORT - 1;
_myHash = session.getMyDestination().calculateHash();
_trackers = new ConcurrentHashMap<HostPort, Tracker>(8);
_sentQueries = new ConcurrentHashMap<Integer, ReplyWaiter>(32);
}
/**
* Can't be restarted after stopping?
*/
public synchronized void start() {
if (_isRunning)
return;
_session.addMuxedSessionListener(this, I2PSession.PROTO_DATAGRAM_RAW, _rPort);
_isRunning = true;
}
/**
* Stop everything.
*/
public synchronized void stop() {
if (!_isRunning)
return;
_isRunning = false;
_session.removeListener(I2PSession.PROTO_DATAGRAM_RAW, _rPort);
_trackers.clear();
for (ReplyWaiter w : _sentQueries.values()) {
w.cancel();
}
_sentQueries.clear();
}
/**
* Announce and get peers for a torrent.
* Blocking!
* Caller should run in a thread.
*
* @param ih the Info Hash (torrent)
* @param max maximum number of peers to return
* @param maxWait the maximum time to wait (ms) must be > 0
* @param fast if true, don't wait for dest, no retx, ...
* @return null on fail or if fast is true
*/
public TrackerResponse announce(byte[] ih, byte[] peerID, int max, long maxWait,
String toHost, int toPort,
long downloaded, long left, long uploaded,
int event, boolean fast) {
long now = _context.clock().now();
long end = now + maxWait;
if (toPort < 0)
throw new IllegalArgumentException();
Tracker tr = getTracker(toHost, toPort);
if (tr.getDest(fast) == null) {
if (_log.shouldInfo())
_log.info("cannot resolve " + tr);
return null;
}
long toWait = end - now;
if (!fast)
toWait = toWait * 3 / 4;
if (toWait < 1000) {
if (_log.shouldInfo())
_log.info("out of time after resolving: " + tr);
return null;
}
if (fast) {
toWait = 0;
} else {
toWait = end - now;
if (toWait < 1000) {
if (_log.shouldInfo())
_log.info("out of time after getting conn: " + tr);
return null;
}
}
ReplyWaiter w = sendAnnounce(tr, 0, ih, peerID,
downloaded, left, uploaded, event, max, toWait);
if (fast)
return null;
if (w == null) {
if (_log.shouldInfo())
_log.info("initial announce failed: " + tr);
return null;
}
boolean success = waitAndRetransmit(w, end);
_sentQueries.remove(w.getID());
if (success)
return w.getReplyObject();
if (_log.shouldInfo())
_log.info("announce failed after retx: " + tr);
return null;
}
//////// private below here
/**
* @return non-null
*/
private Tracker getTracker(String host, int port) {
Tracker ndp = new Tracker(host, port);
Tracker odp = _trackers.putIfAbsent(ndp, ndp);
if (odp != null)
ndp = odp;
return ndp;
}
///// Sending.....
/**
* Send one time with a new tid
* @param toWait if <= 0 does not register
* @return null on failure or if toWait <= 0
*/
private ReplyWaiter sendAnnounce(Tracker tr, long connID,
byte[] ih, byte[] id,
long downloaded, long left, long uploaded,
int event, int numWant, long toWait) {
int tid = _context.random().nextInt();
byte[] payload = sendAnnounce(tr, tid, connID, ih, id, downloaded, left, uploaded, event, numWant);
if (payload != null) {
if (toWait > 0) {
ReplyWaiter rv = new ReplyWaiter(tid, tr, payload, toWait);
_sentQueries.put(Integer.valueOf(tid), rv);
if (_log.shouldInfo())
_log.info("Sent: " + rv + " timeout: " + toWait);
return rv;
}
if (_log.shouldInfo())
_log.info("Sent annc " + event + " to " + tr + " no wait");
}
return null;
}
/**
* Send one time with given tid
* @return the payload or null on failure
*/
private byte[] sendAnnounce(Tracker tr, int tid, long connID,
byte[] ih, byte[] id,
long downloaded, long left, long uploaded,
int event, int numWant) {
byte[] payload = new byte[98];
DataHelper.toLong8(payload, 0, connID);
DataHelper.toLong(payload, 8, 4, ACTION_ANNOUNCE);
DataHelper.toLong(payload, 12, 4, tid);
System.arraycopy(ih, 0, payload, 16, 20);
System.arraycopy(id, 0, payload, 36, 20);
DataHelper.toLong(payload, 56, 8, downloaded);
DataHelper.toLong(payload, 64, 8, left);
DataHelper.toLong(payload, 72, 8, uploaded);
DataHelper.toLong(payload, 80, 4, event);
DataHelper.toLong(payload, 92, 4, numWant);
DataHelper.toLong(payload, 96, 2, TrackerClient.PORT);
boolean rv = sendMessage(tr.getDest(true), tr.getPort(), payload, true);
return rv ? payload : null;
}
/**
* wait after initial send, resend if necessary
*/
private boolean waitAndRetransmit(ReplyWaiter w, long untilTime) {
synchronized(w) {
while(true) {
try {
long toWait = untilTime - _context.clock().now();
if (toWait <= 0)
return false;
w.wait(toWait);
} catch (InterruptedException ie) {
return false;
}
switch (w.getState()) {
case INIT:
continue;
case SUCCESS:
return true;
case FAIL:
return false;
case TIMEOUT:
if (_log.shouldInfo())
_log.info("Timeout: " + w);
long toWait = untilTime - _context.clock().now();
if (toWait <= 1000)
return false;
boolean ok = resend(w, Math.min(toWait, w.getSentTo().getTimeout()));
if (!ok)
return false;
continue;
}
}
}
}
/**
* Resend the stored payload
* @return success
*/
private boolean resend(ReplyWaiter w, long toWait) {
Tracker tr = w.getSentTo();
int port = tr.getPort();
if (_log.shouldInfo())
_log.info("Resending: " + w + " timeout: " + toWait);
boolean rv = sendMessage(tr.getDest(true), port, w.getPayload(), true);
if (rv) {
_sentQueries.put(Integer.valueOf(w.getID()), w);
w.schedule(toWait);
}
return rv;
}
/**
* Lowest-level send message call.
* @param dest may be null, returns false
* @param repliable true for conn request, false for announce
* @return success
*/
private boolean sendMessage(Destination dest, int toPort, byte[] payload, boolean repliable) {
if (!_isRunning) {
if (_log.shouldInfo())
_log.info("send failed, not running");
return false;
}
if (dest == null) {
if (_log.shouldInfo())
_log.info("send failed, no dest");
return false;
}
if (dest.calculateHash().equals(_myHash))
throw new IllegalArgumentException("don't send to ourselves");
if (repliable) {
I2PDatagramMaker dgMaker = new I2PDatagramMaker(_session);
payload = dgMaker.makeI2PDatagram(payload);
if (payload == null) {
if (_log.shouldWarn())
_log.warn("DGM fail");
return false;
}
}
SendMessageOptions opts = new SendMessageOptions();
opts.setDate(_context.clock().now() + 60*1000);
opts.setTagsToSend(SEND_CRYPTO_TAGS);
opts.setTagThreshold(LOW_CRYPTO_TAGS);
if (!repliable)
opts.setSendLeaseSet(false);
try {
boolean success = _session.sendMessage(dest, payload, 0, payload.length,
repliable ? I2PSession.PROTO_DATAGRAM : I2PSession.PROTO_DATAGRAM_RAW,
_rPort, toPort, opts);
if (success) {
// ...
} else {
if (_log.shouldWarn())
_log.warn("sendMessage fail");
}
return success;
} catch (I2PSessionException ise) {
if (_log.shouldWarn())
_log.warn("sendMessage fail", ise);
return false;
}
}
///// Reception.....
/**
* @param from dest or null if it didn't come in on signed port
*/
private void receiveMessage(Destination from, int fromPort, byte[] payload) {
if (payload.length < 8) {
if (_log.shouldInfo())
_log.info("Got short message: " + payload.length + " bytes");
return;
}
int action = (int) DataHelper.fromLong(payload, 0, 4);
int tid = (int) DataHelper.fromLong(payload, 4, 4);
ReplyWaiter waiter = _sentQueries.remove(Integer.valueOf(tid));
if (waiter == null) {
if (_log.shouldInfo())
_log.info("Rcvd msg with no one waiting: " + tid);
return;
}
if (action == ACTION_ANNOUNCE) {
receiveAnnounce(waiter, payload);
} else if (action == ACTION_ERROR) {
receiveError(waiter, payload);
} else {
// includes ACTION_CONNECT
if (_log.shouldInfo())
_log.info("Rcvd msg with unknown action: " + action + " for: " + waiter);
waiter.gotReply(false);
Tracker tr = waiter.getSentTo();
tr.gotError();
}
}
private void receiveAnnounce(ReplyWaiter waiter, byte[] payload) {
Tracker tr = waiter.getSentTo();
if (payload.length >= 22) {
int interval = Math.min(MAX_INTERVAL, Math.max(MIN_INTERVAL,
(int) DataHelper.fromLong(payload, 8, 4)));
int leeches = (int) DataHelper.fromLong(payload, 12, 4);
int seeds = (int) DataHelper.fromLong(payload, 16, 4);
int peers = (int) DataHelper.fromLong(payload, 20, 2);
if (22 + (peers * Hash.HASH_LENGTH) > payload.length) {
if (_log.shouldWarn())
_log.warn("Short reply");
waiter.gotReply(false);
tr.gotError();
return;
}
if (_log.shouldInfo())
_log.info("Rcvd " + peers + " peers from " + tr);
Set<Hash> hashes;
if (peers > 0) {
hashes = new HashSet<Hash>(peers);
for (int off = 20; off < payload.length; off += Hash.HASH_LENGTH) {
hashes.add(Hash.create(payload, off));
}
} else {
hashes = Collections.emptySet();
}
TrackerResponse resp = new TrackerResponse(interval, seeds, leeches, hashes);
waiter.gotResponse(resp);
tr.setInterval(interval);
} else {
waiter.gotReply(false);
tr.gotError();
}
}
private void receiveError(ReplyWaiter waiter, byte[] payload) {
String msg;
if (payload.length > 8) {
msg = DataHelper.getUTF8(payload, 8, payload.length - 8);
} else {
msg = "";
}
TrackerResponse resp = new TrackerResponse(msg);
waiter.gotResponse(resp);
Tracker tr = waiter.getSentTo();
tr.gotError();
}
// I2PSessionMuxedListener interface ----------------
/**
* Instruct the client that the given session has received a message
*
* Will be called only if you register via addMuxedSessionListener().
* Will be called only for the proto(s) and toPort(s) you register for.
*
* @param session session to notify
* @param msgId message number available
* @param size size of the message - why it's a long and not an int is a mystery
* @param proto 1-254 or 0 for unspecified
* @param fromPort 1-65535 or 0 for unspecified
* @param toPort 1-65535 or 0 for unspecified
*/
public void messageAvailable(I2PSession session, int msgId, long size, int proto, int fromPort, int toPort) {
// TODO throttle
try {
byte[] payload = session.receiveMessage(msgId);
if (payload == null)
return;
if (toPort == _rPort) {
// raw
receiveMessage(null, fromPort, payload);
} else {
if (_log.shouldWarn())
_log.warn("msg on bad port");
}
} catch (I2PSessionException e) {
if (_log.shouldWarn())
_log.warn("bad msg");
}
}
/** for non-muxed */
public void messageAvailable(I2PSession session, int msgId, long size) {}
public void reportAbuse(I2PSession session, int severity) {}
public void disconnected(I2PSession session) {
if (_log.shouldWarn())
_log.warn("UDPTC disconnected");
}
public void errorOccurred(I2PSession session, String message, Throwable error) {
if (_log.shouldWarn())
_log.warn("UDPTC got error msg: ", error);
}
public static class TrackerResponse {
private final int interval, complete, incomplete;
private final String error;
private final Set<Hash> peers;
/** success */
public TrackerResponse(int interval, int seeds, int leeches, Set<Hash> peers) {
this.interval = interval;
complete = seeds;
incomplete = leeches;
this.peers = peers;
error = null;
}
/** failure */
public TrackerResponse(String errorMsg) {
interval = DEFAULT_INTERVAL;
complete = 0;
incomplete = 0;
peers = null;
error = errorMsg;
}
public Set<Hash> getPeers() {
return peers;
}
public int getPeerCount() {
int pc = peers == null ? 0 : peers.size();
return Math.max(pc, complete + incomplete - 1);
}
public int getSeedCount() {
return complete;
}
public int getLeechCount() {
return incomplete;
}
public String getFailureReason() {
return error;
}
/** in seconds */
public int getInterval() {
return interval;
}
}
private static class HostPort {
protected final String host;
protected final int port;
/**
* @param port the announce port
*/
public HostPort(String host, int port) {
this.host = host;
this.port = port;
}
/**
* @return the announce port
*/
public int getPort() {
return port;
}
@Override
public int hashCode() {
return host.hashCode() ^ port;
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof HostPort))
return false;
HostPort dp = (HostPort) o;
return port == dp.port && host.equals(dp.host);
}
@Override
public String toString() {
return "UDP Tracker " + host + ':' + port;
}
}
private class Tracker extends HostPort {
private final Object destLock = new Object();
private Destination dest;
private long expires;
private long lastHeardFrom;
private long lastFailed;
private int consecFails;
private int interval = DEFAULT_INTERVAL;
private static final long DELAY = 15*1000;
public Tracker(String host, int port) {
super(host, port);
}
/**
* @param fast if true, do not lookup
* @return dest or null
*/
public Destination getDest(boolean fast) {
synchronized(destLock) {
if (dest == null && !fast)
dest = _util.getDestination(host);
return dest;
}
}
/** does not change state */
public synchronized void replyTimeout() {
consecFails++;
lastFailed = _context.clock().now();
}
public synchronized int getInterval() {
return interval;
}
/** sets heardFrom; calls notify */
public synchronized void setInterval(int interval) {
long now = _context.clock().now();
lastHeardFrom = now;
consecFails = 0;
this.interval = interval;
this.notifyAll();
}
/** sets heardFrom; calls notify */
public synchronized void gotError() {
long now = _context.clock().now();
lastHeardFrom = now;
consecFails = 0;
this.notifyAll();
}
/** doubled for each consecutive failure */
public synchronized long getTimeout() {
return DEFAULT_TIMEOUT << Math.min(consecFails, 3);
}
@Override
public String toString() {
return "UDP Tracker " + host + ':' + port + " hasDest? " + (dest != null);
}
}
/**
* Callback for replies
*/
private class ReplyWaiter extends SimpleTimer2.TimedEvent {
private final int tid;
private final Tracker sentTo;
private final byte[] data;
private TrackerResponse replyObject;
private WaitState state = WaitState.INIT;
/**
* Either wait on this object with a timeout, or use non-null Runnables.
* Any sent data to be remembered may be stored by setSentObject().
* Reply object may be in getReplyObject().
*/
public ReplyWaiter(int tid, Tracker tracker, byte[] payload, long toWait) {
super(SimpleTimer2.getInstance(), toWait);
this.tid = tid;
sentTo = tracker;
data = payload;
}
public int getID() {
return tid;
}
public Tracker getSentTo() {
return sentTo;
}
public byte[] getPayload() {
return data;
}
/**
* @return may be null depending on what happened. Cast to expected type.
*/
public synchronized TrackerResponse getReplyObject() {
return replyObject;
}
/**
* If true, we got a reply, and getReplyObject() may contain something.
*/
public synchronized WaitState getState() {
return state;
}
/**
* Will notify this.
* Also removes from _sentQueries and calls heardFrom().
* Sets state to SUCCESS or FAIL.
*/
public synchronized void gotReply(boolean success) {
cancel();
_sentQueries.remove(Integer.valueOf(tid));
setState(success ? WaitState.SUCCESS : WaitState.FAIL);
}
/**
* Will notify this and run onReply.
* Also removes from _sentQueries and calls heardFrom().
*/
private synchronized void setState(WaitState state) {
this.state = state;
this.notifyAll();
}
/**
* Will notify this.
* Also removes from _sentQueries and calls heardFrom().
* Sets state to SUCCESS.
*/
public synchronized void gotResponse(TrackerResponse resp) {
replyObject = resp;
gotReply(true);
}
/**
* Sets state to INIT.
*/
@Override
public synchronized void schedule(long toWait) {
state = WaitState.INIT;
super.schedule(toWait);
}
/** timer callback on timeout */
public synchronized void timeReached() {
// don't trump success or failure
if (state != WaitState.INIT)
return;
//if (action == ACTION_CONNECT)
// sentTo.connFailed();
//else
sentTo.replyTimeout();
setState(WaitState.TIMEOUT);
if (_log.shouldWarn())
_log.warn("timeout waiting for reply from " + sentTo);
}
@Override
public String toString() {
return "Waiting for ID: " + tid + " to: " + sentTo + " state: " + state;
}
}
}

View File

@ -100,6 +100,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private final ConcurrentHashMap<NID, Token> _incomingTokens;
/** recently unreachable, with lastSeen() as the added-to-blacklist time */
private final Set<NID> _blacklist;
private SimpleTimer2.TimedEvent _cleaner, _explorer;
/** hook to inject and receive datagrams */
private final I2PSession _session;
@ -623,6 +624,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
public synchronized void start() {
if (_isRunning)
return;
if (_log.shouldInfo())
_log.info("KRPC start", new Exception());
_session.addMuxedSessionListener(this, I2PSession.PROTO_DATAGRAM_RAW, _rPort);
_session.addMuxedSessionListener(this, I2PSession.PROTO_DATAGRAM, _qPort);
_knownNodes.start();
@ -630,9 +633,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
PersistDHT.loadDHT(this, _dhtFile, _backupDhtFile);
// start the explore thread
_isRunning = true;
// no need to keep ref, it will eventually stop
new Cleaner();
new Explorer(5*1000);
_cleaner = new Cleaner();
_explorer = new Explorer(5*1000);
_txPkts.set(0);
_rxPkts.set(0);
_txBytes.set(0);
@ -648,7 +650,10 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
if (!_isRunning)
return;
_isRunning = false;
// FIXME stop the explore thread
if (_log.shouldInfo())
_log.info("KRPC stop", new Exception());
_cleaner.cancel();
_explorer.cancel();
// unregister port listeners
_session.removeListener(I2PSession.PROTO_DATAGRAM, _qPort);
_session.removeListener(I2PSession.PROTO_DATAGRAM_RAW, _rPort);
@ -1640,6 +1645,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
public void disconnected(I2PSession session) {
if (_log.shouldLog(Log.WARN))
_log.warn("KRPC disconnected");
stop();
}
public void errorOccurred(I2PSession session, String message, Throwable error) {
@ -1760,7 +1766,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
if (_log.shouldLog(Log.INFO))
_log.info("Explore of " + keys.size() + " buckets done, new size: " + _knownNodes.size());
new Explorer(EXPLORE_TIME);
_explorer = new Explorer(EXPLORE_TIME);
}
}
}

View File

@ -32,14 +32,16 @@ public class ConfigUIHelper {
{ "cs", "cz", "Čeština", null },
{ "zh", "cn", "Chinese 中文", null },
//{ "zh_TW", "tw", "Chinese 中文", "Taiwan" },
//{ "da", "dk", "Dansk", null },
{ "da", "dk", "Dansk", null },
{ "de", "de", "Deutsch", null },
//{ "et", "ee", "Eesti", null },
{ "en", "us", "English", null },
{ "es", "es", "Español", null },
{ "es", "ar", "Español" ,"Argentina" },
{ "fa", "ir", "Persian فارسی", null },
{ "fr", "fr", "Français", null },
//{ "gl", "lang_gl", "Galego", null },
//{ "el", "gr", "Greek Ελληνικά", null },
{ "el", "gr", "Greek Ελληνικά", null },
{ "in", "id", "bahasa Indonesia", null },
{ "it", "it", "Italiano", null },
{ "ja", "jp", "Japanese 日本語", null },

View File

@ -1,13 +1,19 @@
package org.klomp.snark.standalone;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import org.eclipse.jetty.util.log.Log;
import net.i2p.I2PAppContext;
import net.i2p.apps.systray.UrlLauncher;
import net.i2p.data.DataHelper;
import net.i2p.desktopgui.ExternalMain;
import net.i2p.jetty.I2PLogger;
import net.i2p.jetty.JettyStart;
import net.i2p.util.SystemVersion;
/**
* @since moved from ../web and fixed in 0.9.27
@ -20,6 +26,7 @@ public class RunStandalone {
private String _host = "127.0.0.1";
private static RunStandalone _instance;
static final File APP_CONFIG_FILE = new File("i2psnark-appctx.config");
private static final String PROP_DTG_ENABLED = "desktopgui.enabled";
private RunStandalone(String args[]) throws Exception {
Properties p = new Properties();
@ -29,6 +36,13 @@ public class RunStandalone {
} catch (IOException ioe) {}
}
_context = new I2PAppContext(p);
// Do this after we have a context
// To take effect, must be set before any Jetty classes are loaded
try {
Log.setLog(new I2PLogger(_context));
} catch (Throwable t) {
System.err.println("INFO: I2P Jetty logging class not found, logging to stdout");
}
File base = _context.getBaseDir();
File xml = new File(base, "jetty-i2psnark.xml");
_jettyStart = new JettyStart(_context, null, new String[] { xml.getAbsolutePath() } );
@ -56,13 +70,18 @@ public class RunStandalone {
public void start() {
try {
_jettyStart.startup();
String url = "http://" + _host + ':' + _port + "/i2psnark/";
System.out.println("Starting i2psnark at " + url);
startTrayApp();
_jettyStart.startup();
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {}
UrlLauncher launch = new UrlLauncher(_context, null, new String[] { url } );
launch.startup();
String p = _context.getProperty("routerconsole.browser");
if (!("/bin/false".equals(p) || "NUL".equals(p))) {
UrlLauncher launch = new UrlLauncher(_context, null, new String[] { url } );
launch.startup();
}
} catch (Exception e) {
e.printStackTrace();
}
@ -82,4 +101,39 @@ public class RunStandalone {
} catch (InterruptedException ie) {}
System.exit(1);
}
/**
* @since 0.9.54 adapted from RouterConsoleRunner
*/
private static boolean isSystrayEnabled(I2PAppContext context) {
if (GraphicsEnvironment.isHeadless())
return false;
// default false except on OSX and Windows,
// and on Linux KDE and LXDE.
// Xubuntu XFCE works but doesn't look very good
// Ubuntu Unity was far too buggy to enable
// Ubuntu GNOME does not work, SystemTray.isSupported() returns false
String xdg = System.getenv("XDG_CURRENT_DESKTOP");
boolean dflt = SystemVersion.isWindows() ||
SystemVersion.isMac() ||
//"XFCE".equals(xdg) ||
"KDE".equals(xdg) ||
"LXDE".equals(xdg);
return context.getProperty(PROP_DTG_ENABLED, dflt);
}
/**
* @since 0.9.54 adapted from RouterConsoleRunner
*/
private void startTrayApp() {
try {
if (isSystrayEnabled(_context)) {
System.setProperty("java.awt.headless", "false");
ExternalMain dtg = new ExternalMain(_context, _context.clientAppManager(), null);
dtg.startup();
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}

View File

@ -3,12 +3,14 @@ package org.klomp.snark.web;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.Collator;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
@ -22,6 +24,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
@ -35,8 +38,10 @@ import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.servlet.util.ServletUtil;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SystemVersion;
import net.i2p.util.Translate;
import net.i2p.util.UIMessages;
@ -251,11 +256,12 @@ public class I2PSnarkServlet extends BasicServlet {
}
} else {
String base = addPaths(req.getRequestURI(), "/");
boolean showEdit = req.getParameter("showEdit") != null;
String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null,
req.getParameter("sort"));
req.getParameter("sort"), showEdit);
if (method.equals("POST")) {
// P-R-G
sendRedirect(req, resp, "");
sendRedirect(req, resp, showEdit ? "?showEdit" : "");
} else if (listing != null) {
setHTMLHeaders(resp, cspNonce, true);
resp.getWriter().write(listing);
@ -314,7 +320,9 @@ public class I2PSnarkServlet extends BasicServlet {
// we want it to go to the base URI so we don't refresh with some funky action= value
int delay = 0;
if (!isConfigure) {
if (isConfigure) {
out.write("<script src=\".resources/js/configui.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
} else {
delay = _manager.getRefreshDelaySeconds();
if (delay > 0) {
String jsPfx = _context.isRouterContext() ? "" : ".resources";
@ -343,25 +351,24 @@ public class I2PSnarkServlet extends BasicServlet {
out.write("</head>\n" +
"<body>" +
"<center>");
List<Tracker> sortedTrackers = null;
if (isConfigure) {
out.write("<div class=\"snarknavbar\"><a href=\"" + _contextPath + "/\" title=\"");
out.write(_t("Torrents"));
out.write("\" class=\"snarkNav nav_main\">");
if (_contextName.equals(DEFAULT_NAME))
out.write(_t("I2PSnark"));
else
out.write(_contextName);
out.write("</a>");
} else {
out.write("<div class=\"snarknavbar\"><a href=\"" + _contextPath + '/' + peerString + "\" title=\"");
out.write(_t("Refresh page"));
out.write("\" class=\"snarkNav nav_main\">");
if (_contextName.equals(DEFAULT_NAME))
out.write(_t("I2PSnark"));
else
out.write(_contextName);
out.write("</a>\n");
}
out.write("\" class=\"snarkNav nav_main\">");
if (_contextName.equals(DEFAULT_NAME))
out.write(_t("I2PSnark"));
else
out.write(_contextName);
if (!_context.isRouterContext()) {
out.write(' ' + CoreVersion.VERSION);
}
out.write("</a>");
List<Tracker> sortedTrackers = null;
if (!isConfigure) {
sortedTrackers = _manager.getSortedTrackers();
if (_context.isRouterContext() && _manager.hasModifiedTrackers()) {
for (Tracker t : sortedTrackers) {
@ -2498,7 +2505,7 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(_t("Theme"));
out.write(":<td colspan=\"2\">");
if (_manager.getUniversalTheming()) {
out.write("<select name='theme' disabled=\"disabled\" title=\"");
out.write("<select id=\"theme\" name=\"theme\" disabled=\"disabled\" title=\"");
out.write(_t("To change themes manually, disable universal theming"));
out.write("\"><option>");
out.write(_manager.getTheme());
@ -2508,15 +2515,21 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(_t("Configure"));
out.write("]</a>");
} else {
out.write("<select name='theme'>");
out.write("<select id=\"theme\" name=\"theme\">");
String theme = _manager.getTheme();
String[] themes = _manager.getThemes();
Arrays.sort(themes);
// translated sort
Map<String, String> tmap = new TreeMap<String, String>(Collator.getInstance());
for (int i = 0; i < themes.length; i++) {
if(themes[i].equals(theme))
out.write("\n<OPTION value=\"" + themes[i] + "\" SELECTED>" + themes[i]);
tmap.put(_t(themes[i]), themes[i]);
}
for (Map.Entry<String, String> e : tmap.entrySet()) {
String tr = e.getKey();
String opt = e.getValue();
if(opt.equals(theme))
out.write("\n<option value=\"" + opt + "\" SELECTED>" + tr + "</option>");
else
out.write("\n<OPTION value=\"" + themes[i] + "\">" + themes[i]);
out.write("\n<option value=\"" + opt + "\">" + tr + "</option>");
}
out.write("</select>\n");
}
@ -2943,7 +2956,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
private static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
private static final String HEADER_A = "<link href=\"";
private static final String HEADER_A = "<link id=\"pagestyle\" href=\"";
private static final String HEADER_B = "snark.css?" + CoreVersion.VERSION + "\" rel=\"stylesheet\" type=\"text/css\" >";
private static final String HEADER_C = "nocollapse.css?" + CoreVersion.VERSION + "\" rel=\"stylesheet\" type=\"text/css\" >";
@ -2984,8 +2997,8 @@ public class I2PSnarkServlet extends BasicServlet {
* @return String of HTML or null if postParams != null
* @since 0.7.14
*/
private String getListHTML(File xxxr, String base, boolean parent, Map<String, String[]> postParams, String sortParam)
throws IOException
private String getListHTML(File xxxr, String base, boolean parent, Map<String, String[]> postParams,
String sortParam, boolean showEdit) throws IOException
{
String decodedBase = decodePath(base);
String title = decodedBase;
@ -3027,6 +3040,10 @@ public class I2PSnarkServlet extends BasicServlet {
_manager.startTorrent(snark);
} else if (postParams.get("recheck") != null) {
_manager.recheckTorrent(snark);
} else if (postParams.get("editTorrent") != null) {
saveTorrentEdit(snark, postParams);
} else if (postParams.get("showEdit") != null) {
// P-R-G only
} else {
_manager.addMessage("Unknown command");
}
@ -3055,7 +3072,7 @@ public class I2PSnarkServlet extends BasicServlet {
r = new File("");
}
boolean showStopStart = snark != null;
boolean showStopStart = snark != null && !showEdit;
Storage storage = snark != null ? snark.getStorage() : null;
boolean showPriority = storage != null && !storage.complete() &&
r.isDirectory();
@ -3093,7 +3110,7 @@ public class I2PSnarkServlet extends BasicServlet {
final boolean includeForm = showStopStart || showPriority || er || ec;
if (includeForm) {
buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"").append(_nonce).append("\" >\n");
"<input type=\"hidden\" name=\"nonce\" value=\"").append(_nonce).append("\">\n");
if (sortParam != null) {
buf.append("<input type=\"hidden\" name=\"sort\" value=\"")
.append(DataHelper.stripHTML(sortParam)).append("\" >\n");
@ -3103,7 +3120,7 @@ public class I2PSnarkServlet extends BasicServlet {
// first table - torrent info
buf.append("<table class=\"snarkTorrentInfo\">\n" +
"<tr><th></th><th><b>")
.append(_t("Torrent"))
.append(showEdit ? _t("Edit Torrent") : _t("Torrent"))
.append("</b></th><th>")
.append(DataHelper.escapeHTML(snark.getBaseName()))
.append("</th></tr>\n");
@ -3117,7 +3134,7 @@ public class I2PSnarkServlet extends BasicServlet {
.append("</b></td><td><a href=\"").append(_contextPath).append('/').append(baseName).append("\">")
.append(DataHelper.escapeHTML(fullPath))
.append("</a></td></tr>\n");
if (storage != null) {
if (storage != null && !showEdit) {
buf.append("<tr><td>");
toThemeImg(buf, "file");
buf.append("</td><td><b>")
@ -3127,17 +3144,19 @@ public class I2PSnarkServlet extends BasicServlet {
.append("</td></tr>\n");
}
String hex = I2PSnarkUtil.toHex(snark.getInfoHash());
buf.append("<tr><td>");
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Info hash"))
.append("</b></td><td><span id=\"infohash\">")
.append(hex.toUpperCase(Locale.US))
.append("</span></td></tr>\n");
if (!showEdit) {
buf.append("<tr><td>");
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Info hash"))
.append("</b></td><td><span id=\"infohash\">")
.append(hex.toUpperCase(Locale.US))
.append("</span></td></tr>\n");
}
String announce = null;
MetaInfo meta = snark.getMetaInfo();
if (meta != null) {
if (meta != null && !showEdit) {
announce = meta.getAnnounce();
if (announce == null)
announce = snark.getTrackerURL();
@ -3218,7 +3237,7 @@ public class I2PSnarkServlet extends BasicServlet {
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Comment")).append("</b></td><td>")
.append(DataHelper.stripHTML(com))
.append(DataHelper.escapeHTML(com).replace("\r\n", "<br>").replace("\n", "<br>"))
.append("</td></tr>\n");
}
long dat = meta.getCreationDate();
@ -3239,7 +3258,7 @@ public class I2PSnarkServlet extends BasicServlet {
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Created By")).append("</b></td><td>")
.append(DataHelper.stripHTML(cby))
.append(DataHelper.escapeHTML(cby))
.append("</td></tr>\n");
}
long[] dates = _manager.getSavedAddedAndCompleted(snark);
@ -3275,6 +3294,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
}
if (!showEdit) { // don't bother to reindent
if (meta == null || !meta.isPrivate()) {
buf.append("<tr><td><a href=\"")
.append(MagnetURI.MAGNET_FULL).append(hex);
@ -3377,6 +3397,7 @@ public class I2PSnarkServlet extends BasicServlet {
.append(":</b> ")
.append(formatSize(snark.getPieceLength(0)))
.append("</span></td></tr>\n");
} // !showEdit
// buttons
if (showStopStart) {
@ -3390,7 +3411,7 @@ public class I2PSnarkServlet extends BasicServlet {
buf.append("<b>").append(_t("Starting")).append("&hellip;</b>");
} else if (snark.isAllocating()) {
buf.append("<b>").append(_t("Allocating")).append("&hellip;</b>");
} else {
} else if (isTopLevel && !showEdit) {
boolean isRunning = !snark.isStopped();
buf.append("<input type=\"submit\" value=\"");
if (isRunning)
@ -3398,14 +3419,23 @@ public class I2PSnarkServlet extends BasicServlet {
else
buf.append(_t("Start")).append("\" name=\"start\" class=\"starttorrent\">\n");
buf.append("<input type=\"submit\" name=\"recheck\" value=\"").append(_t("Force Recheck"));
if (isRunning)
if (isRunning) {
buf.append("\" class=\"disabled\" disabled=\"disabled\" title=\"")
.append(_t("Stop the torrent in order to check file integrity"))
.append("\">\n");
else
.append(_t("Torrent must be stopped"));
} else {
buf.append("\" class=\"reload\" title=\"")
.append(_t("Check integrity of the downloaded files"))
.append("\">\n");
.append(_t("Check integrity of the downloaded files"));
}
buf.append("\">\n" +
"<input type=\"submit\" name=\"showEdit\" value=\"").append(_t("Edit Torrent"));
if (isRunning) {
buf.append("\" class=\"disabled\" disabled=\"disabled\" title=\"")
.append(_t("Torrent must be stopped"));
} else {
buf.append("\" class=\"reload\" title=\"")
.append(_t("Add or remove trackers"));
}
buf.append("\">\n");
}
boolean showInOrder = storage != null && !storage.complete() &&
meta != null;
@ -3439,6 +3469,13 @@ public class I2PSnarkServlet extends BasicServlet {
}
buf.append("</table>\n");
if (snark != null && isTopLevel && showEdit) {
// Edit torrent. Show edit section only.
displayTorrentEdit(snark, base, buf);
buf.append("</form></div></div></center></body></html>");
return buf.toString();
}
if (snark != null && !r.exists()) {
// fixup TODO
buf.append("<table class=\"resourceError\" id=\"DoesNotExist\"><tr><th colspan=\"2\">")
@ -3481,7 +3518,7 @@ public class I2PSnarkServlet extends BasicServlet {
displayComments(snark, er, ec, esc, buf);
if (includeForm)
buf.append("</form>");
buf.append("</div></div></body></html>");
buf.append("</div></div></center></body></html>");
return buf.toString();
}
@ -3778,7 +3815,7 @@ public class I2PSnarkServlet extends BasicServlet {
// for stop/start/check
if (includeForm)
buf.append("</form>");
buf.append("</div></div></body></html>");
buf.append("</div></div></center></body></html>");
return buf.toString();
}
@ -4150,6 +4187,136 @@ public class I2PSnarkServlet extends BasicServlet {
buf.append("</div>");
}
/**
* @param snark non-null
* @since 0.9.53
*/
private void displayTorrentEdit(Snark snark, String base, StringBuilder buf) {
MetaInfo meta = snark.getMetaInfo();
if (meta == null)
return;
buf.append("<div id=\"snarkCommentSection\"><table class=\"snarkTorrentInfo\">\n");
//.append("<tr><th colspan=\"5\">")
//.append(_t("Edit Torrent"))
//.append("</th>")
//.append("</tr>");
boolean isRunning = !snark.isStopped();
if (isRunning) {
// shouldn't happen
buf.append("<tr><td colspan=\"5\">")
.append(_t("Torrent must be stopped"))
.append("</td></tr></table></div></form>");
return;
}
String announce = meta.getAnnounce();
if (announce == null)
announce = snark.getTrackerURL();
if (announce != null) {
// strip non-i2p trackers
if (!isI2PTracker(announce))
announce = null;
}
List<List<String>> alist = meta.getAnnounceList();
Set<String> annlist = new TreeSet<String>();
if (alist != null && !alist.isEmpty()) {
// strip non-i2p trackers
for (List<String> alist2 : alist) {
for (String s : alist2) {
if (isI2PTracker(s))
annlist.add(s);
}
}
}
if (announce != null)
annlist.add(announce);
if (!annlist.isEmpty()) {
buf.append("<tr><td colspan=\"3\"></td><td>").append("Primary").append("</td><td>")
.append("Delete").append("</td></tr>");
for (String s : annlist) {
int hc = s.hashCode();
buf.append("<tr><td>");
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Tracker")).append("</b></td><td>");
s = DataHelper.stripHTML(s);
buf.append("<span class=\"info_tracker\">");
buf.append(getShortTrackerLink(s, snark.getInfoHash()));
buf.append("</span> ");
//buf.append(s);
buf.append("</td><td>");
buf.append("<input type=\"radio\" class=\"optbox\" name=\"primary\" ");
if (s.equals(announce))
buf.append("checked=\"checked\" ");
buf.append("value=\"").append(hc);
buf.append("\"></td><td>");
buf.append("<input type=\"checkbox\" class=\"optbox\" name=\"trdelete.")
.append(hc).append("\" title=\"").append(_t("Mark for deletion")).append("\">");
buf.append("</td></tr>\n");
}
}
List<Tracker> newTrackers = _manager.getSortedTrackers();
for (Iterator<Tracker> iter = newTrackers.iterator(); iter.hasNext(); ) {
Tracker t = iter.next();
String announceURL = t.announceURL.replace("&#61;", "=");
if (announceURL.equals(announce) || annlist.contains(announceURL))
iter.remove();
}
if (!newTrackers.isEmpty()) {
buf.append("<tr><td colspan=\"3\"></td><td>").append("Primary").append("</td><td>")
.append("Add").append("</td></tr>");
for (Tracker t : newTrackers) {
String name = t.name;
int hc = t.announceURL.hashCode();
String announceURL = t.announceURL.replace("&#61;", "=");
buf.append("<tr><td>");
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Add Tracker")).append("</b></td><td>");
buf.append(name);
buf.append("</td><td><input type=\"radio\" class=\"optbox\" name=\"primary\" value=\"");
buf.append(hc);
buf.append("\"></td><td>");
buf.append("<input type=\"checkbox\" class=\"optbox\" id=\"").append(name).append("\" name=\"tradd.")
.append(hc).append("\" title=\"").append(_t("Add tracker")).append("\"> ")
.append("</td><td></td></tr>\n");
}
}
String com = meta.getComment();
if (com == null) {
com = "";
} else if (com.length() > 0) {
com = DataHelper.escapeHTML(com);
}
buf.append("<tr><td>");
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Comment")).append("</b></td>");
buf.append("<td colspan=\"2\" id=\"addCommentText\"><textarea name=\"nofilter_newTorrentComment\" cols=\"88\" rows=\"4\">")
.append(com).append("</textarea></td><td></td>");
buf.append("</tr>\n");
String cb = meta.getCreatedBy();
if (cb == null) {
cb = "";
} else if (cb.length() > 0) {
cb = DataHelper.escapeHTML(cb);
}
buf.append("<tr><td>");
toThemeImg(buf, "details");
buf.append("</td><td><b>")
.append(_t("Created By")).append("</b></td>");
buf.append("<td id=\"editTorrentCreatedBy\"><input type=\"text\" name=\"nofilter_newTorrentCreatedBy\" cols=\"44\" rows=\"1\" value=\"")
.append(cb).append("\"></td></tr>");
buf.append("<tr id=\"torrentInfoControl\"><td colspan=\"5\">");
buf.append("<input type=\"submit\" name=\"editTorrent\" value=\"");
buf.append(_t("Save Changes"));
buf.append("\" class=\"accept\"></td></tr>\n");
buf.append("</table></div>");
}
/**
* @param so null ok
* @return query string or ""
@ -4370,6 +4537,147 @@ public class I2PSnarkServlet extends BasicServlet {
_manager.setSavedCommentsEnabled(snark, yes);
}
/**
* @since 0.9.53
*/
private void saveTorrentEdit(Snark snark, Map<String, String[]> postParams) {
if (!snark.isStopped()) {
// shouldn't happen
_manager.addMessage(_t("Torrent must be stopped"));
return;
}
List<Integer> toAdd = new ArrayList<Integer>();
List<Integer> toDel = new ArrayList<Integer>();
Integer primary = null;
String newComment = "";
String newCreatedBy = "";
for (Map.Entry<String, String[]> entry : postParams.entrySet()) {
String key = entry.getKey();
String val = entry.getValue()[0]; // jetty arrays
if (key.startsWith("tradd.")) {
try {
toAdd.add(Integer.parseInt(key.substring(6)));
} catch (NumberFormatException nfe) {}
} else if (key.startsWith("trdelete.")) {
try {
toDel.add(Integer.parseInt(key.substring(9)));
} catch (NumberFormatException nfe) {}
} else if (key.equals("primary")) {
try {
primary = Integer.parseInt(val);
} catch (NumberFormatException nfe) {}
} else if (key.equals("nofilter_newTorrentComment")) {
newComment = val.trim();
} else if (key.equals("nofilter_newTorrentCreatedBy")) {
newCreatedBy = val.trim();
}
}
MetaInfo meta = snark.getMetaInfo();
if (meta == null) {
// shouldn't happen
_manager.addMessage("Can't edit magnet");
return;
}
String oldPrimary = meta.getAnnounce();
String oldComment = meta.getComment();
if (oldComment == null)
oldComment = "";
String oldCreatedBy = meta.getCreatedBy();
if (oldCreatedBy == null)
oldCreatedBy = "";
if (toAdd.isEmpty() && toDel.isEmpty() &&
(primary == null || primary.equals(oldPrimary)) &&
oldComment.equals(newComment) &&
oldCreatedBy.equals(newCreatedBy)) {
_manager.addMessage("No changes to torrent, not saved");
return;
}
List<List<String>> alist = meta.getAnnounceList();
Set<String> annlist = new TreeSet<String>();
if (alist != null && !alist.isEmpty()) {
// strip non-i2p trackers
for (List<String> alist2 : alist) {
for (String s : alist2) {
if (isI2PTracker(s))
annlist.add(s);
}
}
}
if (oldPrimary != null)
annlist.add(oldPrimary);
List<Tracker> newTrackers = _manager.getSortedTrackers();
for (Integer i : toDel) {
int hc = i.intValue();
for (Iterator<String> iter = annlist.iterator(); iter.hasNext(); ) {
String s = iter.next();
if (s.hashCode() == hc)
iter.remove();
}
}
for (Integer i : toAdd) {
int hc = i.intValue();
for (Tracker t : newTrackers) {
if (t.announceURL.hashCode() == hc) {
annlist.add(t.announceURL);
break;
}
}
}
String thePrimary = oldPrimary;
if (primary != null) {
int hc = primary.intValue();
for (String s : annlist) {
if (s.hashCode() == hc) {
thePrimary = s;
break;
}
}
}
List<List<String>> newAnnList;
if (annlist.isEmpty()) {
newAnnList = null;
thePrimary = null;
} else {
List<String> aalist = new ArrayList<String>(annlist);
newAnnList = Collections.singletonList(aalist);
if (!aalist.contains(thePrimary))
thePrimary = aalist.get(0);
}
if (newComment.equals(""))
newComment = null;
if (newCreatedBy.equals(""))
newCreatedBy = null;
MetaInfo newMeta = new MetaInfo(thePrimary, meta.getName(), null, meta.getFiles(), meta.getLengths(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.isPrivate(),
newAnnList, newCreatedBy, meta.getWebSeedURLs(), newComment);
if (!DataHelper.eq(meta.getInfoHash(), newMeta.getInfoHash())) {
// shouldn't happen
_manager.addMessage("Torrent edit failed, infohash mismatch");
return;
}
File f = new File(_manager.util().getTempDir(), "edit-" + _manager.util().getContext().random().nextLong() + ".torrent");
OutputStream out = null;
try {
out = new SecureFileOutputStream(f);
out.write(newMeta.getTorrentData());
out.close();
boolean ok = FileUtil.rename(f, new File(snark.getName()));
if (!ok) {
_manager.addMessage("Save edit changes failed");
return;
}
} catch (IOException ioe) {
try { if (out != null) out.close(); } catch (IOException ioe2) {}
_manager.addMessage("Save edit changes failed: " + ioe);
return;
} finally {
f.delete();
}
snark.replaceMetaInfo(newMeta);
_manager.addMessage("Torrent changes saved");
}
/** @since 0.9.32 */
private static boolean noCollapsePanels(HttpServletRequest req) {
// check for user agents that can't toggle the collapsible panels...

View File

@ -14,6 +14,10 @@
package org.klomp.snark.web;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
@ -21,6 +25,9 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.data.DataHelper;
import net.i2p.util.SystemVersion;
/* ------------------------------------------------------------ */
/**
@ -47,6 +54,8 @@ class MimeTypes
public MimeTypes() {
_mimeMap = new ConcurrentHashMap<String, String>();
if (!(SystemVersion.isWindows() || SystemVersion.isMac() || SystemVersion.getMaxMemory() < 100*1024*1024L))
loadSystemMimeTypes();
}
/* ------------------------------------------------------------ */
@ -86,6 +95,37 @@ class MimeTypes
}
}
/**
* Load mime types from /etc/mime.types
* Format: mimetype suffix1 suffix2 ...
*
* @since 0.9.54
*/
private void loadSystemMimeTypes() {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream("/etc/mime.types"), "ISO-8859-1"));
while (true) {
String line = in.readLine();
if (line == null)
break;
if (line.startsWith("#"))
continue;
String[] s = DataHelper.split(line, "[ \t]+", 16);
if (s.length < 2)
continue;
for (int i = 1; i < s.length; i++) {
_mimeMap.put(s[i].toLowerCase(Locale.US), s[0]);
//System.out.println("Mapping: '" + s[i] + "' -> '" + s[0] + "'");
}
}
//System.out.println("Loaded " + _mimeMap.size() + " mime types from /etc/mime.types");
} catch (IOException ioe) {
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
}
}
/* ------------------------------------------------------------ */
/** Get the MIME type by filename extension.
*

View File

@ -4,5 +4,36 @@
# The file jetty-i2psnark.xml must be present in the current directory.
# i2psnark will be accessed at http://127.0.0.1:8002/
#
# Raise the soft open files soft ulimit to this value, if able
OPEN_FILES_ULIMIT=2048
# Increase memory to 512 MB
JAVA_OPTS='-Xmx512m'
raiseopenfilesulimit() {
OPEN_FILES_SOFT=`ulimit -S -n` 2> /dev/null || return
if [ "$OPEN_FILES_SOFT" != "unlimited" ]
then
if [ "$OPEN_FILES_ULIMIT" -gt "$OPEN_FILES_SOFT" ]
then
OPEN_FILES_HARD=`ulimit -H -n` 2> /dev/null || return
if [ "$OPEN_FILES_HARD" != "unlimited" ]
then
if [ "$OPEN_FILES_ULIMIT" -gt "$OPEN_FILES_HARD" ]
then
OPEN_FILES_ULIMIT="$OPEN_FILES_HARD"
fi
fi
if [ "$OPEN_FILES_ULIMIT" -gt "$OPEN_FILES_SOFT" ]
then
ulimit -S -n "$OPEN_FILES_ULIMIT" > /dev/null 2>&1
fi
fi
fi
}
raiseopenfilesulimit
I2P="."
java -jar "$I2P/i2psnark.jar"
java $JAVA_OPTS -jar "$I2P/i2psnark.jar"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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