Compare commits

...

1426 Commits

Author SHA1 Message Date
zzz
9ef268796b Merge branch 'sybil-ip' into 'master'
Sybil: Disable IP checks for now

See merge request i2p-hackers/i2p.i2p!191
2024-04-28 11:52:25 +00:00
zzz
32167c5f8f Sybil: Disable IP checks for now 2024-04-28 11:52:25 +00:00
zzz
d123aeab0c Susimail: Search fixes
- Fix sorting and pagination within search results
- Bypass XSS filter and escape as necessary
2024-04-26 08:35:57 -04:00
zzz
b6fc908190 bump -2 2024-04-25 08:46:27 -04:00
zzz
cc3f747076 Merge branch 'susimail-search-v2' into 'master'
Susimail: Add search

See merge request i2p-hackers/i2p.i2p!189
2024-04-25 10:55:06 +00:00
zzz
d70f254c9a Merge branch 'ssu1-5' into 'master'
Transport: SSU1 removal part 5/n

See merge request i2p-hackers/i2p.i2p!190
2024-04-25 10:54:19 +00:00
zzz
87086cf315 Transport: SSU1 removal part 5/n 2024-04-25 10:54:19 +00:00
6decc16c41 CI: Give access to GITHUB_TOKEN to git sync CI job 2024-04-23 16:23:13 -04:00
zzz
daee078dcf Susimail: Add search 2024-04-22 21:19:46 -04:00
zzz
78ee4ac3cd Addressbook: Use standard time formatting for log
and set file permissions
2024-04-22 20:45:49 -04:00
zzz
098931b484 Profiles: Don't update last heard time on tunnel failure
dates back 20 years
2024-04-22 20:44:53 -04:00
zzz
eed87b90e0 Merge branch 'ssu1-4' into 'master'
Transport: SSU1 removal part 4/n

See merge request i2p-hackers/i2p.i2p!186
2024-04-22 19:41:58 +00:00
zzz
7db6cac1f6 Transport: SSU1 removal part 4/n 2024-04-22 19:41:58 +00:00
zzz
3cb7e660bc Merge branch 'ssu1-3' into 'master'
Transport: SSU1 removal part 3/n

See merge request i2p-hackers/i2p.i2p!185
2024-04-22 19:40:50 +00:00
zzz
b2135214e4 Transport: SSU1 removal part 3/n 2024-04-22 19:40:50 +00:00
b29be88d08 CI: use github actions to sync FROM i2pgit.org TO github.com instead of running a script on my server. PAT is not generated yet due to the need to determine what permissions it needs. This job will fail on the github side until I add the PAT. 2024-04-22 14:42:15 -04:00
33b9317d37 CI: add update-zip in useful location to github pages 2024-04-22 14:35:43 -04:00
22998bc707 Check in bionic changelog 2024-04-20 08:13:29 -04:00
zzz
33d56f5f2e Build: Update to Tomcat 9.0.88 2024-04-17 07:45:40 -04:00
zzz
84139e40fc bump -1 2024-04-15 10:45:34 -04:00
zzz
d4a36675be Susimail: Don't show multipart/related CID images as attachments also 2024-04-15 10:25:33 -04:00
zzz
8cf1ebf05d Susimail: Improve validateAddress()
causing some addresses to not be displayed

- Better regex for domain
- Use compiled pattern for matching
- Allow multiple matches for e.g. "foo@example.com" <foo@example.com>
2024-04-13 13:25:24 -04:00
zzz
8919e38582 Susimail: Don't show attachment flag for multipart/related emails 2024-04-13 12:38:39 -04:00
zzz
c0d6c944c3 Susimail: Add missing div ids for DnD
Were inadvertently not included in MR 172
2024-04-13 12:20:57 -04:00
zzz
42e856d597 Susimail: Increase compose form width (dark theme) 2024-04-13 11:22:42 -04:00
zzz
f91e6829ad Susimail: Don't show attachment flag for HTML emails 2024-04-13 10:59:19 -04:00
zzz
d5b627adc1 Susimail: Include sender name when replying
Consolidate sender string generation code
Add sender name to default config
2024-04-13 10:40:31 -04:00
zzz
ddb7568ed6 Susimail: Reply-all improvements
- Only show reply-all button if more than one recipient
- Dedup recipients
- Don't put To: recipients in Cc: line
- Don't put ourselves in To: or Cc: lines
2024-04-13 09:54:25 -04:00
zzz
0b56bd9f41 Console: Hide update download button in test mode 2024-04-13 09:12:57 -04:00
zzz
7f70126c60 javadoc fix 2024-04-11 08:46:20 -04:00
zzz
59be0ecab7 Kbuckets: Debug output tweak 2024-04-11 08:45:10 -04:00
zzz
1a5a32dd49 Sybil: Set file date in reason for bans loaded at startup 2024-04-11 08:37:18 -04:00
zzz
732cdd4527 Build: Extend cert age check 2024-04-11 08:07:26 -04:00
zzz
2ab0e52829 Build: Update i2psnark-standalone manifest 2024-04-11 08:05:34 -04:00
b98a81a3e6 fix changelog 2024-04-09 22:29:28 -04:00
bc93e1fdf8 update debian changelog 2024-04-09 22:11:07 -04:00
57eaea8f1e Router: Update version numbers for 2.5.0 release 2024-04-08 10:12:32 -04:00
f47bfa23ca Release: Update echelon's news and router certs 2024-04-07 10:00:57 -04:00
f8cc1b9ce1 Plugins: update zzz's plugin certificate 2024-04-07 09:01:15 -04:00
zzz
06302c0f31 Susimail: Fix loading mail bodies in non-inbox/drafts folders 2024-04-05 16:37:00 -04:00
zzz
bbf1e41a7b bump for review 2024-04-05 12:47:51 -04:00
zzz
64aa641f9c Pull translations from Transifex 2024-04-05 12:46:11 -04:00
zzz
2775e2eabf Susimail: Fix truncation of quoted-printable attachments 2024-04-05 11:36:50 -04:00
zzz
385ad4cb54 Susimail: Fix forwarding html-only email 2024-04-04 15:27:01 -04:00
zzz
d9c67ecc2e Susimail: Fix forwarding email with attachments lacking specified encoding
MailPart.encoding is now always non-null.
2024-04-04 14:48:08 -04:00
zzz
3a18721c52 Susimail: Fix 413 error forwarding email with attachments
Was actually an ISE in FileBuffer via getOutputStream().flush(), but XSSFilter converted it to a 413
Add logging in XSSFilter to make it easier to find next time
Javadoc fix
2024-04-04 13:59:09 -04:00
zzz
1bc4464444 Susimail: Fix initialization of textarea height 2024-04-04 12:34:12 -04:00
zzz
50ec9d34a1 Susimail: Only parse mail headers once
Double-parsing caused to: line to be duped as cc:
2024-04-04 11:43:10 -04:00
bdcbc1e393 Router: add -rc qualifier 2024-04-04 11:24:01 -04:00
8b371006fc GeoIP: document where to run the shell script from 2024-04-04 11:16:47 -04:00
2f0be8b80d Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2024-04-04 11:14:54 -04:00
d693e3b792 update geoip DB 4/3/2024 2024-04-03 10:06:57 -04:00
zzz
e98d92b9db javadoc fixes 2024-04-03 07:20:51 -04:00
zzz
6e7eb3cb6a blocklist update 2024-04-01 07:13:41 -04:00
dcfefdc0e6 BuildTime: Bump build time 2024-03-29 22:44:37 -04:00
zzz
a7fc9c6b93 poupdate-source 2024-03-27 09:10:49 -04:00
zzz
641dd79bab history for -8 2024-03-26 14:34:47 -04:00
747f8c82b7 Router: build -8 2024-03-26 12:41:18 -04:00
9e20ba7090 NetDB: refactor determination of router connection establishment 2024-03-26 12:40:45 -04:00
cdddc62fdd Router: build -7 2024-03-26 09:51:30 -04:00
bee407c6a1 CI: Fix job names for maven build tests, Router: Refactor exploratory message filter, refactor tunnel tests 2024-03-26 09:48:25 -04:00
9bf538ed64 Change format of filename for install .jar artifact 2024-03-25 15:50:09 -04:00
1b58933777 CI: Do jdk7 maven builds on checkins 2024-03-25 15:46:58 -04:00
zzz
97fe2bbed9 i2psnark: Add more known opentrackers
as requested
2024-03-25 10:41:47 -04:00
zzz
5545e712ad Susimail: Add partial Kurdish translation 2024-03-24 10:12:52 -04:00
zzz
663ec385c7 Console readme, i2prouter: Add Czech translation 2024-03-24 09:48:48 -04:00
zzz
3fb70b7412 Debian: Refresh patches 2024-03-24 09:37:45 -04:00
zzz
d179194e16 Eepsite: Add Japanese link to top of English help page 2024-03-23 11:46:42 -04:00
zzz
c24684cec8 Merge branch 'snark-private' into 'master'
i2psnark: Preserve private=0 in torrent files

See merge request i2p-hackers/i2p.i2p!187
2024-03-23 11:53:47 +00:00
zzz
9c1b926a09 i2psnark: Preserve private=0 in torrent files 2024-03-23 11:53:47 +00:00
zzz
b6aab62e2a streaming: Add Japanese translation 2024-03-20 09:29:56 -04:00
zzz
27f602819b eepsite: Add Japanese, update Spanish traslation 2024-03-20 09:22:14 -04:00
zzz
eb10e9251a i2prouter: Add Hungarian translation 2024-03-20 09:07:29 -04:00
zzz
d908109be5 Susimail: Add partial Solvenian and Estonian translations 2024-03-20 08:55:31 -04:00
ba18e3945d CI: Put a dev build onto github site, it is unsigned and will require users to allow it manually 2024-03-18 11:37:31 -04:00
zzz
6bb6210f70 i2psnark: Fix buttons on torrent details page (JRE 21) 2024-03-09 13:24:51 -05:00
zzz
95abb93002 i2psnark: Add torrent section and config page CSS fixes (non-default themes) 2024-03-03 14:32:47 -05:00
zzz
139afb670d i2psnark: Fix DnD js syntax error 2024-03-03 12:55:44 -05:00
zzz
77289b72b7 Reseeder list update 2024-03-03 11:40:39 -05:00
zzz
ba939ac382 Peer test: Cancel test if Bob picked a Charlie without a B cap
i2pd Bobs will do this, and i2pd Charlies will agree; issue reported to that project.
This improves on the workaround in the previous commit,
as it fails faster, and applies to IPv4 as well.
2024-03-01 17:16:06 -05:00
idk
b1069cbb3a Merge branch 'i2p.i2p.2.5.0-revert-outbound-changes' into 'master'
Router: revert changes to OutboundTunnelEndpoint

See merge request i2p-hackers/i2p.i2p!184
2024-02-29 20:45:32 +00:00
zzz
9c1f58f54d Peer test: Treat IPv6 test result as unknown if Charlie is firewalled and we did not hear from him
to greatly reduce false firewalled results. Firewalled charlies are generating a lot of false positives.
This appears to be a bug with firewalled ipv6 i2pd charlies, through the current version.
2024-02-29 08:06:59 -05:00
2af30251a6 Router: revert changes to OutboundTunnelEndpoint 2024-02-27 11:07:52 -05:00
zzz
92e7ebdf41 i2psnark: Don't allow changing data dir when connected
Delete all torrents except magnets when changing data dir
2024-02-26 08:35:24 -05:00
zzz
74ae210663 Merge branch 'dark-visited' into 'master'
Console: Use same color for visted links (dark theme)

See merge request i2p-hackers/i2p.i2p!183
2024-02-26 12:04:06 +00:00
zzz
bf3d160c5e SSU2: Update last rcv time when receiving data, not acks 2024-02-25 07:57:44 -05:00
zzz
f489b03f97 SSU2: Increase min version for peer test 2024-02-25 07:56:20 -05:00
zzz
593688cb2a SSU2: Remove unused constant 2024-02-25 07:54:09 -05:00
d3cf3509ca CI: build javadoc in gitlab ci 2024-02-19 15:26:13 -05:00
b90d6fd34e add write permission for pages to CI id-token 2024-02-19 14:50:40 -05:00
2a4279f8fc use setup pages action 2024-02-19 14:44:48 -05:00
708bd1b9d5 deploy javadoc to github pages using github CI 2024-02-19 14:39:18 -05:00
zzz
7b97fbf68f Console: Use same color for visted links (dark theme) 2024-02-19 07:27:38 -05:00
748ebb5742 build javadoc in CI, create a zip of it, and upload the zip to github. 2024-02-17 19:01:26 -05:00
zzz
72e9bba84d javadoc typos 2024-02-15 05:58:55 -05:00
zzz
0af58d7723 javadoc fix 2024-02-14 10:50:43 -05:00
zzz
c01dfb780d bump -6 2024-02-14 06:01:25 -05:00
zzz
6575fbfe6a Tests: Fix lone i2ptunnel test classpath,
add to top-level ant test target (was only run on gradle side)
2024-02-14 06:00:29 -05:00
zzz
4e99c392f6 Merge branch 'i2ptunnel-keepalive-server' into 'master'
Implement server-side HTTP persistence (keepalive) for the i2p socket

See merge request i2p-hackers/i2p.i2p!181
2024-02-14 10:48:20 +00:00
zzz
83ee28fbdc Implement server-side HTTP persistence (keepalive) for the i2p socket 2024-02-14 10:48:20 +00:00
zzz
91f5bb3540 Crypto: Add X25519DH vectors
and add note about public key high bit
2024-02-06 08:18:02 -05:00
zzz
92a649d655 bump -5 2024-02-02 12:28:11 -05:00
zzz
f2dc8ec180 Merge branch 'susimail-html' into 'master'
Susimail: Add support for HTML email

See merge request i2p-hackers/i2p.i2p!177
2024-02-02 15:43:44 +00:00
zzz
8aca5d0fe2 Susimail: Add support for HTML email 2024-02-02 15:43:43 +00:00
zzz
7040d3202a Merge branch 'i2ptunnel-keepalive-client' into 'master'
Implement client-side HTTP persistence (keepalive) for the browser-to-client proxy socket

See merge request i2p-hackers/i2p.i2p!176
2024-02-02 15:42:58 +00:00
zzz
23937c11de Implement client-side HTTP persistence (keepalive) for the browser-to-client proxy socket 2024-02-02 15:42:58 +00:00
zzz
3922795f9c CLI: Add sdns stamp decoder
to assist in DoH server list maintenance
2024-01-31 08:29:20 -05:00
zzz
bdaa9b1be9 Util: DoH server list update 2024-01-30 12:20:47 -05:00
zzz
4b757105ec Naming: Add .i2p.alt support to naming services 2024-01-30 08:02:51 -05:00
zzz
c6e6e7968c Util: Add .i2p.alt support to ConvertToHash 2024-01-30 07:24:24 -05:00
zzz
081a024deb Util: Add .alt to selfsigned cert alt names 2024-01-29 08:46:54 -05:00
zzz
1126b0ae4e i2psnark: Sanitize unicode LTR/RTL control chars 2024-01-29 08:34:34 -05:00
zzz
777da8dfb1 Crypto: Verify RSA sigs after signing
to detect corrupted sigs and prevent RSA fault attack
ref: https://eprint.iacr.org/2023/1711.pdf
2024-01-29 08:09:57 -05:00
zzz
2482b1dc18 Crypto: More efficient enum lookup by code 2024-01-29 07:54:22 -05:00
zzz
8da5e018d1 Merge branch 'gradle-85' into 'master'
Build: Update gradle to 8.5

See merge request i2p-hackers/i2p.i2p!180
2024-01-28 12:09:10 +00:00
zzz
c54ec4d458 Build: Update gradle to 8.5 2024-01-28 12:09:10 +00:00
zzz
fdb75d67df Build: Remove gradle reproducible/build in ant distclean 2024-01-27 08:41:08 -05:00
zzz
883aab8d5a Merge branch 'ssu1-2' into 'master'
Transport: SSU1 removal part 2/n

See merge request i2p-hackers/i2p.i2p!179
2024-01-27 12:27:27 +00:00
zzz
98b12c904e Transport: SSU1 removal part 2/n 2024-01-27 12:27:27 +00:00
zzz
7ebb3e7784 Merge branch 'rrd4j-3.9' into 'master'
Console: Update rrd4j to version 3.9

See merge request i2p-hackers/i2p.i2p!178
2024-01-27 12:23:26 +00:00
zzz
b0db90da49 Console: Update rrd4j to version 3.9 2024-01-27 12:23:26 +00:00
zzz
3b28fc3a98 susidns, i2ptunnel: Fix IDN decoding for newer codepoints
Without the ALLOW_UNASSIGNED flag, it will not decode to codepoints
newer than Unicode 3.2 (2002)
2024-01-23 07:16:09 -05:00
zzz
05c9e63bae Merge branch 'snark-dnd' into 'master'
i2psnark: Add js drag-n-drop

See merge request i2p-hackers/i2p.i2p!165
2024-01-22 13:25:31 +00:00
zzz
bb48a3d84a i2psnark: Add js drag-n-drop 2024-01-22 13:25:31 +00:00
zzz
1e5d362412 Merge branch 'susimail-dnd' into 'master'
Susimail: DnD for attachments

See merge request i2p-hackers/i2p.i2p!172
2024-01-22 13:22:49 +00:00
zzz
ce5c75cb61 SSU2: Drop small packets in UDPReceiver
now that SSU1 is disabled.
SSU2 min packet size is 40 and does not support 0-byte hole punch
2024-01-17 08:03:16 -05:00
zzz
67f15934b5 bump -4 2024-01-15 05:50:54 -05:00
zzz
39f1f826bb Merge branch 'i2cp-loopback' into 'master'
I2CP: Prevent loopback messages to same session (i2pd Github #2005)

See merge request i2p-hackers/i2p.i2p!173
2024-01-15 10:35:29 +00:00
zzz
f337c1b3c9 I2CP: Prevent loopback messages to same session (i2pd Github #2005) 2024-01-15 10:35:29 +00:00
zzz
ba39f58800 Merge branch 'snark-bw' into 'master'
i2psnark: Bandwidth limiter improvements

See merge request i2p-hackers/i2p.i2p!164
2024-01-15 10:05:46 +00:00
zzz
db52cc7811 i2psnark: Bandwidth limiter improvements 2024-01-15 10:05:46 +00:00
zzz
45403d804a i2ptunnel: Fix customs options box size
Possibly was changed back and forth due to iframe size issues?

reverts ccb0c279f7
which reverted eb72e4c9f5
2024-01-14 08:45:13 -05:00
zzz
85c07c8eaa Merge branch 'ssl-errors' into 'master'
i2ptunnel: Don't send html error messages on CONNECT

See merge request i2p-hackers/i2p.i2p!175
2024-01-14 11:46:35 +00:00
zzz
d70e1fa150 i2ptunnel: Don't send html error messages on CONNECT 2024-01-14 11:46:35 +00:00
zzz
8e66563e1c Merge branch 'ssu1-1' into 'master'
Transport: SSU1 removal part 1/n

See merge request i2p-hackers/i2p.i2p!174
2024-01-14 11:45:55 +00:00
zzz
74f57b874e Transport: SSU1 removal part 1/n 2024-01-14 11:45:55 +00:00
zzz
6a9b9267a3 Merge branch 'kac-compression' into 'master'
Data: Store compressed KeysAndCert

See merge request i2p-hackers/i2p.i2p!171
2024-01-14 11:44:17 +00:00
zzz
e3b37a64d0 Data: Store compressed KeysAndCert 2024-01-14 11:44:17 +00:00
zzz
37791e832b Merge branch 'i2ptunnel-keepalive-util' into 'master'
i2ptunnel: Prep for keepalive

See merge request i2p-hackers/i2p.i2p!166
2024-01-14 11:42:14 +00:00
zzz
e5b9f9f134 i2ptunnel: Prep for keepalive 2024-01-14 11:42:13 +00:00
zzz
20cbd0ee78 bump -3 2024-01-11 10:47:06 -05:00
zzz
dece43d2cf Susimail: DnD for attachments 2024-01-10 14:44:03 -05:00
zzz
e1ae3bce5a Merge branch 'susimail-markdown' into 'master'
Susimail: Add markdown js for plain text content

See merge request i2p-hackers/i2p.i2p!161
2024-01-10 18:36:12 +00:00
zzz
e25ce7fe84 Susimail: Add markdown js for plain text content 2024-01-10 18:36:11 +00:00
zzz
fc8cdfc7a8 Merge branch 'iframe' into 'master'
Console: Fix iframe size issues

See merge request i2p-hackers/i2p.i2p!160
2024-01-10 18:35:39 +00:00
zzz
d6d7044832 Console: Fix iframe size issues 2024-01-10 18:35:39 +00:00
zzz
af24f9122f Merge branch 'ssu2-relay-tag' into 'master'
SSU2: Delay sending relay tag

See merge request i2p-hackers/i2p.i2p!169
2024-01-10 17:04:33 +00:00
zzz
014d39c097 SSU2: Delay sending relay tag 2024-01-10 17:04:32 +00:00
zzz
a0d8f5f063 Transport: Ignore SSU1 enable config
so we may begin to remove SSU1 code
2024-01-08 12:22:05 -05:00
zzz
23fa8b9295 add sample testnet config 2024-01-04 08:06:30 -05:00
zzz
a6231992f2 bump -2 2024-01-02 08:53:08 -05:00
zzz
2dfe24fbca Merge branch 'susimail-loading' into 'master'
Susimail: Speed up initial loading by 35x

See merge request i2p-hackers/i2p.i2p!162
2024-01-02 13:37:23 +00:00
zzz
e742c117b0 Susimail: Speed up initial loading by 35x 2024-01-02 13:37:23 +00:00
zzz
011df13b7f Merge branch 'news-fetch' into 'master'
Console: News fetch improvements

See merge request i2p-hackers/i2p.i2p!163
2024-01-02 13:36:49 +00:00
zzz
71ff5be656 Console: News fetch improvements 2024-01-02 13:36:49 +00:00
zzz
2efc759908 Merge branch 'peer-selection' into 'master'
Tunnels: Peer selection adjustments

See merge request i2p-hackers/i2p.i2p!167
2024-01-02 13:34:15 +00:00
zzz
69da9f4034 Tunnels: Peer selection adjustments 2024-01-02 13:34:15 +00:00
zzz
5a2eba7426 Merge branch 'ri-size' into 'master'
Router: Enforce consistent max RI size

See merge request i2p-hackers/i2p.i2p!168
2024-01-02 13:33:51 +00:00
zzz
efcaa3f1d4 NetDB: Log level tweak 2023-12-28 07:43:28 -05:00
zzz
9cf8c2acab Router: Enforce consistent max RI size 2023-12-28 07:17:11 -05:00
zzz
b86aefb169 Susimail: Fix draft attachment thumbnails
missed lines in previous checkin
2023-12-27 08:12:33 -05:00
zzz
57b8a44afc Router: Enable congestion caps permanently 2023-12-26 09:30:21 -05:00
zzz
399507805f Util: Move SyntheticREDQueue from router to core
in prep for use by i2psnark, to follow
log tweak
2023-12-23 08:14:24 -05:00
zzz
394a2b1635 Susimail: Put error messages at the top 2023-12-23 07:49:23 -05:00
zzz
0b88668b7a Susimail: Show user name on folder view 2023-12-23 07:38:56 -05:00
zzz
cb5cdbe00f Susimail: Show size and thumbnail of draft attachments 2023-12-23 07:19:15 -05:00
zzz
222037cc27 Susimail: js auto-resize compose box 2023-12-23 06:56:29 -05:00
zzz
de96821e3b Susimail: Show dropdown on login page for selection from multiple accounts 2023-12-23 06:50:35 -05:00
zzz
d2ea6955ff Susimail: Bring back the logo, put it in the footer
clean up old header CSS
2023-12-23 06:29:09 -05:00
zzz
6c18981b5b Susimail: Add RegexOutputStream util
WIP, prep for enhancements to follow
2023-12-23 06:14:38 -05:00
zzz
2c03586e2d Susimail: Logging enhancements on file read failures
and UIDL mismatches
2023-12-23 06:10:38 -05:00
zzz
44dd19fe82 Susimail: Extract multipart type and content id
WIP, prep for enhancements to follow
2023-12-23 05:52:23 -05:00
zzz
dffa2b7a0d bump -1 2023-12-22 12:03:41 -05:00
zzz
1c4aa12e35 Console: Fix encoding issues in persisted news 2023-12-22 12:01:48 -05:00
zzz
2a9eb85c2e Util: Add 2nd order comparison in ObjectCounterUnsafe sort
to alphabetize ties in console charts
2023-12-22 11:55:58 -05:00
zzz
f476b3ed82 Transports: Don't flood huge RIs 2023-12-22 11:47:48 -05:00
zzz
a4881baf47 Susimail: Include attachment sizes in displayed draft size 2023-12-22 11:28:56 -05:00
zzz
385f6de3cb I2CP: Add router rates to bandwidth limits message 2023-12-22 11:08:19 -05:00
zzz
6b01b22d00 i2ptunnel: Log correct server host/port on error when there are multiple targets configured 2023-12-22 11:00:39 -05:00
zzz
e249449817 i2psnark: Adjust max peers for small torrents 2023-12-22 10:48:31 -05:00
zzz
e5e481a21a Susimail: Login form trimming and validation 2023-12-22 08:51:21 -05:00
zzz
3d95e8608a i2ptunnel: Change return code for host-not-in-addressbook to 502
ref: i2pd github #1987
2023-12-22 08:21:28 -05:00
zzz
70eaa0974c Data: KeysAndCert toString() tweak 2023-12-22 08:18:54 -05:00
zzz
f925d9db0a Util: Catch OOM in timer 2023-12-22 08:16:46 -05:00
zzz
d156c090b5 log tweak 2023-12-22 08:14:21 -05:00
zzz
1678715163 Plugins: Don't auto-update in test mode 2023-12-22 08:11:22 -05:00
zzz
3736bf2432 NTCP2: Add key validity check 2023-12-22 07:59:05 -05:00
zzz
2dcb628fb7 CLI: Add check for slow reseeds to reseed test 2023-12-22 07:54:39 -05:00
zzz
0265987db4 Blockfile: Fix bug in unused getNames()
would return only one entry after a long delay
2023-12-22 07:46:14 -05:00
zzz
ce5cf45f6d Ratchet: Use correct method for Elg2 keygen 2023-12-22 07:40:55 -05:00
zzz
e5484216d6 Router: Minor cleanups from release review 2023-12-22 07:24:45 -05:00
zzz
bd59a00865 PPA/Deb build doc updates 2023-12-22 07:08:05 -05:00
c5350f17bf Debian: update changelogs again 2023-12-20 20:28:57 -05:00
3c43103b93 Debian: update changelogs again 2023-12-20 20:27:09 -05:00
d30ccce44a Update debian changelogs 2023-12-20 14:57:47 -05:00
e49c18a073 Checklist: remind to update topic on i2p-dev 2023-12-19 16:46:30 -05:00
8af6e8bf9e History: match release version to API version 2023-12-19 07:34:13 -05:00
a587e09e24 Router: update versions 2023-12-18 12:37:12 -05:00
03635ad5c7 2.4.0: Pull in new translations, ant testscripts and po4update-man.sh 2023-12-18 12:26:44 -05:00
820d59915d Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2023-12-18 12:18:13 -05:00
9fe78025cd Router: Restore removed line from SURFJ 2023-12-17 20:55:41 -05:00
zzz
90e4c9f33a bump -19 2023-12-15 13:38:08 -05:00
zzz
e5d2580010 pull translations from tx 2023-12-15 13:36:36 -05:00
zzz
c577b2a05e blocklist update 2023-12-15 13:03:10 -05:00
zzz
b98b86bb6a Javadoc: More 0.9.61 2023-12-14 12:03:07 -05:00
zzz
198a16c76f Console: Whitespace fixes on config pages 2023-12-14 11:59:31 -05:00
ae1c939403 SAM/I2Ptunnel/I2PSnark: update Javadocs to reflect @since 0.9.61 2023-12-12 18:11:44 -05:00
b1f11cc056 Router: update javadoc API version for segmented netDb implementaion 2023-12-10 18:11:00 -05:00
0c2517e050 Console: use stormycloud.png for stormycloud plugin 2023-12-10 15:49:26 -05:00
2203529215 Console: add stormycloud icon 2023-12-10 15:48:51 -05:00
c9b1fd1eae Console: remove metrics from homepage 2023-12-10 15:37:47 -05:00
zzz
dee330f1e5 Console: Add home page addition criteria and validation/checkin steps 2023-12-10 12:32:52 -05:00
78985cd2fd Router: Update GeoIP and Build Time 2023-12-10 08:45:09 -05:00
zzz
143980bc3a Installer: Fix rare misidentification of OS
caused by matching on hostname, e.g. Linux on a Mac
2023-12-08 06:11:12 -05:00
zzz
61fa0e5d8b Susimail: Dark theme fixes
and improvements, and a couple light theme fixes too
2023-12-07 20:05:17 -05:00
zzz
c305530c25 Susimail: Show spam flags for all in spam folder 2023-12-07 10:02:08 -05:00
zzz
5008843b83 Susimail: Fix placement of bottom page nav 2023-12-07 08:51:07 -05:00
zzz
603613c576 bump -18 2023-12-06 09:56:05 -05:00
zzz
f4d22b0c8e SusiMail fixes:
- Flush output to fix truncated mails
- Close output for attachments
- Fix setting encoding for attachments
- Set length for binary encoding
2023-12-06 09:27:43 -05:00
zzz
bdb89581c8 bump -17 2023-12-05 12:43:07 -05:00
zzz
fb59d76af8 poupdate-source 2023-12-05 12:41:09 -05:00
zzz
4a7a9aac95 i2ptunnel: Remove dup headers in error pages 2023-12-05 08:43:00 -05:00
zzz
206cca210e Console: Sidebar CSS tweaks 2023-12-05 08:36:33 -05:00
zzz
4bb5792104 Susimail: CSS tweak 2023-12-03 14:29:01 -05:00
zzz
ffe0360650 Susimail: Fix binary content-encoding
previously unsupported, same as 8bit, ref: RFC 2045
2023-12-02 10:04:29 -05:00
zzz
e3493cc717 Susimail: Fix incorrect "previous" icons
They were copies of "first", not reverses of "next"
2023-12-02 06:28:34 -05:00
zzz
97a8f5249f Console: Fix sidebar not immediately showing results of /configsidebar changes 2023-12-02 05:23:22 -05:00
zzz
1c4d425420 Console: Fix sidebar not showing results of manual update check 2023-12-01 12:01:05 -05:00
zzz
63d7079026 Console: Fix HTML errors on /configupdate 2023-12-01 10:01:12 -05:00
zzz
26524e3e4b Console: Don't lose tabs in log messages 2023-12-01 09:14:33 -05:00
zzz
7048ba6784 i2psnark: Change js mime type as per RFC 9239 2023-12-01 08:18:18 -05:00
zzz
894a2d64ba Console: Clear out "proxy must be running" status after success 2023-12-01 08:07:12 -05:00
zzz
f495b86116 Console: Prevent overflow of sidebar status 2023-12-01 07:53:54 -05:00
zzz
97cb90ef16 restore stats 2023-12-01 05:59:03 -05:00
zzz
d833f53de0 new reseeds 2023-11-30 14:10:35 -05:00
zzz
4f34308e0f bump -16 2023-11-30 11:34:09 -05:00
zzz
84a66eec30 UPnP: Fixes for multiple IGDs
Fix handing of multiple IGDs
Improve logging about multiple IGDs
Add info on UPnP tab on how to disable an IGD
Log tweaks
2023-11-29 16:03:02 -05:00
zzz
c7e46ca52c UPnP: Make case of HTTP headers more standard 2023-11-29 15:57:14 -05:00
zzz
5399aa459f UPnP: Fix missing port in Host header causing failures on libupnp-based devices 2023-11-29 15:55:58 -05:00
zzz
63ac981053 javadoc fixes for org.minidns and net.i2p.router.naming 2023-11-29 06:53:01 -05:00
zzz
4897b67197 javadoc fix 2023-11-29 06:21:34 -05:00
zzz
387e4b93a9 Build: Handle QUALIFIER 2023-11-29 05:42:57 -05:00
02aa509701 Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2023-11-28 19:56:24 -05:00
fb09344781 Router: Use UNKNOWN when IMD doesn't have access to the destination nickname 2023-11-28 19:54:58 -05:00
zzz
5287da1f0f checklist update 2023-11-28 11:37:07 -05:00
idk
3ca7c09914 Update RouterVersion.java bump build number to -15 2023-11-27 20:41:20 +00:00
idk
5b70e4cd2c Merge branch 'i2p.i2p.2.4.0-revert-imd' into 'master'
Router: revert changes to IMD garlic handling

See merge request i2p-hackers/i2p.i2p!158
2023-11-27 20:30:40 +00:00
zzz
d61b8af138 i2psnark: Delay bandwidth limits check briefly
to avoid intermittent "Unable to connect to I2P" message at startup.
2023-11-27 06:52:26 -05:00
42b4f212bd Router: revert changes to IMD garlic handling 2023-11-26 08:20:26 -05:00
zzz
9fc2426e83 i2psnark: Remove things in html, not by hiding them in CSS 2023-11-25 12:47:48 -05:00
88b3fa1eb3 Router: get rid of getClientFloodfillNetworkDatabaseFacades, closes #472 2023-11-24 21:30:57 -05:00
bc5a27f8ac CI: update dind container 2023-11-23 19:30:27 -05:00
zzz
02dfdd5eb7 Util: Update default user-agent
as recommended by drzed
2023-11-23 06:04:16 -05:00
zzz
9d4bb311af i2psnark: Revise tagged string 2023-11-23 06:00:52 -05:00
be594a50c5 Router: add -rc 2023-11-21 17:39:03 -05:00
zzz
70fa743ae0 bump -14 2023-11-21 16:27:32 -05:00
zzz
a80f01f7b3 Merge branch '412-caps' into 'master'
Profiles: Increase congestion cap penalties (Gitlab #412)

Closes #412

See merge request i2p-hackers/i2p.i2p!157
2023-11-21 21:25:18 +00:00
zzz
e9f3b58b7d Profiles: Increase congestion cap penalties (Gitlab #412) 2023-11-21 21:25:18 +00:00
zzz
18b8d05597 CLI: Add "permanent" flag for IPv6 addresses 2023-11-21 09:21:19 -05:00
zzz
9b70d4be73 Addressbook: Workaround for i2p-projekt.i2p etag bug (Gitlab #454)
Will revert if it gets fixed server-side
2023-11-21 09:16:08 -05:00
zzz
761967ed4b i2ptunnel: Add thread number to server thread names
like we already do for clients, to make debugging easier
2023-11-21 08:50:34 -05:00
zzz
a08f59d42f Console: Don't list inner classes on /configlogging
Because the $ won't get through the XSS filter
2023-11-21 07:45:57 -05:00
ecd9140f89 CSS: reduce negative margin on wizard page 2023-11-19 22:25:41 -05:00
zzz
bcdd01448f Router: Don't log updated/started/stopped/crashed events when in test mode 2023-11-19 09:31:10 -05:00
zzz
725181b0dc bump -13 2023-11-18 18:27:17 -05:00
zzz
62079f8dd5 Merge branch 'snark-picker' into 'master'
i2psnark: Uncomment and fix local torrent file picker

See merge request i2p-hackers/i2p.i2p!153
2023-11-18 19:12:51 +00:00
zzz
cfa99b40a1 i2psnark: Uncomment and fix local torrent file picker 2023-11-18 19:12:50 +00:00
zzz
69848474c9 Merge branch 'i2ptunnel-jsp' into 'master'
i2ptunnel: Edit and wizard form improvements

See merge request i2p-hackers/i2p.i2p!154
2023-11-17 18:17:52 +00:00
zzz
b13d9f9769 i2ptunnel: Edit and wizard form improvements 2023-11-17 18:17:52 +00:00
zzz
9667b6469f Merge branch 'console-required' into 'master'
Console: Add "required" to input fields where necessary

See merge request i2p-hackers/i2p.i2p!156
2023-11-17 18:16:42 +00:00
zzz
246d321506 Merge branch 'dbid-cleanup' into 'master'
netDb: Replace all logging access to KNDF._dbid with toString()

See merge request i2p-hackers/i2p.i2p!155
2023-11-17 18:14:29 +00:00
zzz
65b74da95d netDb: Replace all logging access to KNDF._dbid with toString() 2023-11-17 18:14:28 +00:00
zzz
e7536715d4 Console: Add "required" to input fields where necessary 2023-11-16 14:32:43 -05:00
zzz
3facdaabc7 Build: Force build to die on fatal JspC errors 2023-11-16 14:07:39 -05:00
zzz
7ab06396a8 history for -12 2023-11-16 14:00:46 -05:00
idk
f8658957b3 Update RouterVersion.java to build number 12 2023-11-16 15:16:33 +00:00
idk
ed14d07091 Merge branch 'i2p.i2p.2.4.0-simplify-low-level-netdb-handling' into 'master'
Simplify handling of local leaseSets when using subDbs

See merge request i2p-hackers/i2p.i2p!147
2023-11-16 12:45:54 +00:00
idk
a0e9b73bb1 Simplify handling of local leaseSets when using subDbs 2023-11-16 12:45:54 +00:00
zzz
acccd2edd0 i2psnark: Sort tracker list on details page 2023-11-15 18:00:27 -05:00
zzz
676f4ac4a2 i2psnark: Tag untagged strings on torrent edit page 2023-11-15 17:26:36 -05:00
zzz
6ffeb94b83 i2psnark: Increase comment bucket size to reduce duplicates 2023-11-15 16:55:38 -05:00
zzz
60f817be63 i2psnark: Handle metainfo url-list as single byte string 2023-11-15 13:40:30 -05:00
idk
b1a403cbed Merge branch 'i2p.i2p.2.4.0-simplify-imd' into 'master'
Router: use DSM.getRecievedBy in FDSMH to determine whether or not to store a...

See merge request i2p-hackers/i2p.i2p!152
2023-11-12 20:54:26 +00:00
idk
096fbc9ff6 Router: use DSM.getRecievedBy in FDSMH to determine whether or not to store a... 2023-11-12 20:54:26 +00:00
zzz
ec9cf6e0c1 Router: Temp. ban routers publishing in the future 2023-11-12 13:22:11 -05:00
zzz
12684bffa3 Banlist: Throw if banning far in the past, to catch bugs 2023-11-12 11:24:05 -05:00
zzz
a2c5edf6c8 Sybil: Don't ban NAT64 addresses
To workaround i2pd bug, they are publishing them
2023-11-12 10:38:00 -05:00
zzz
4dadfcaab9 Console: Sybil page CSS fixes 2023-11-11 08:31:08 -05:00
zzz
fa72a246a8 Router: Fix congestion cap publishing
Broken in 2.3.0; fix will take effect in 2.4.0
2023-11-11 08:26:16 -05:00
zzz
11feb84d4a i2ptunnel: Exempt tunnel name from XSS filter (Gitlab #467) 2023-11-10 13:06:28 -05:00
zzz
f0b1ae9459 bump -11 2023-11-10 11:50:49 -05:00
zzz
44916e8aa1 Merge branch '468-lookups' into 'master'
NetDB: Lookup handler/throttler fixes (Gitlab #468)

Closes #468

See merge request i2p-hackers/i2p.i2p!151
2023-11-10 16:35:00 +00:00
zzz
bae6844e5d NetDB: Lookup handler/throttler fixes (Gitlab #468) 2023-11-10 16:35:00 +00:00
zzz
c5650478aa Console: Revert change that broke the published LS count on the debug LS tab 2023-11-09 12:15:03 -05:00
idk
d8415f29ca Merge branch 'i2p.i2p.2.4.0-revert-blocklist-changes' into 'master'
Revert Blocklist/Banlist Changes

See merge request i2p-hackers/i2p.i2p!149
2023-11-08 20:59:14 +00:00
idk
878f7b0e46 Revert Blocklist/Banlist Changes 2023-11-08 20:59:14 +00:00
zzz
8ce79f32b1 NetDB: Fix and deprecate unused store() method
was broken for LS2, would have thrown cast exception
2023-11-08 08:14:45 -05:00
idk
ea8b3f00c0 Merge branch 'i2p.i2p.2.4.0-reverse-throttler' into 'master'
I2p.i2p.2.4.0 reverse throttler

Closes #453

See merge request i2p-hackers/i2p.i2p!145
2023-11-07 21:07:18 +00:00
idk
57eb706e95 I2p.i2p.2.4.0 reverse throttler 2023-11-07 21:07:18 +00:00
zzz
3db4f23514 Update checklist for tx v3 2023-11-07 13:31:46 -05:00
zzz
93ff5ffa10 Translations: Fix up config file (Gitlab #408)
to revert mess caused by tx migrate and add missing file_filter lines

- Add comments back
- Restore trans.xx sorting within sections
- Add file_filter line for each section
- Add lang_map
2023-11-07 12:31:26 -05:00
idk
2ab938629d Merge branch 'i2p.i2p.2.4.0-cleanup-todos' into 'master'
Cleans up some dead code, revise comments and TODO's

See merge request i2p-hackers/i2p.i2p!148
2023-11-07 14:43:58 +00:00
idk
f363f9318e Cleans up some dead code, revise comments and TODO's 2023-11-07 14:43:58 +00:00
idk
204567f16b Merge branch 'revert-2fb4dc41' into 'master'
Revert "Merge branch 'i2p.i2p.2.4.0-or-2.5.0-delete-hostnames-from-terminal' into 'master'"

See merge request i2p-hackers/i2p.i2p!146
2023-11-06 01:44:42 +00:00
idk
c57ccfa0df Revert "Merge branch 'i2p.i2p.2.4.0-or-2.5.0-delete-hostnames-from-terminal' into 'master'" 2023-11-06 01:44:42 +00:00
idk
91458ca9bc Merge branch 'i2p.i2p.2.4.0-revert-buildhandler-changes' into 'master'
Router: remove commented out ban strategy and ratestats for tunnels that disrespect congestion caps

Closes #413

See merge request i2p-hackers/i2p.i2p!142
2023-11-03 15:03:12 +00:00
idk
5e076dc13b Router: remove commented out ban strategy and ratestats for tunnels that disrespect congestion caps 2023-11-03 15:03:12 +00:00
zzz
1d37db7704 Merge branch '402-NDF' into 'master'
NetDB: Type changes (Gitlab #402)

Closes #402

See merge request i2p-hackers/i2p.i2p!144
2023-11-03 14:07:02 +00:00
zzz
7e8e0b60d0 NetDB: Type changes (Gitlab #402) 2023-11-03 14:07:02 +00:00
zzz
b20954551e CLI: Test for more Java versions 2023-11-03 10:02:25 -04:00
zzz
5f0ac20b64 Console: RTL CSS tweaks 2023-11-03 09:51:15 -04:00
zzz
db62206008 Console: Profiles definitions CSS fixes 2023-11-02 16:13:47 -04:00
zzz
3ce5f64d75 Console: Use RTL CSS for Persian
thx drzed
2023-11-02 15:24:08 -04:00
zzz
8622b2d42b bump -10 2023-11-02 10:08:59 -04:00
zzz
9d1036935c Merge branch '465-subdb-ri' into 'master'
NetDB: Enforce no RIs in subdbs (Gitlab #465)

Closes #465

See merge request i2p-hackers/i2p.i2p!143
2023-11-02 14:01:41 +00:00
zzz
4ed709aa31 NetDB: Enforce no RIs in subdbs (Gitlab #465) 2023-11-02 14:01:41 +00:00
idk
291e630482 Merge branch 'i2p.i2p.2.4.0-unused' into 'master'
Remove unused functions from FNDS, SNDF, KNDF

Closes #466, #440, #463, and #462

See merge request i2p-hackers/i2p.i2p!141
2023-11-01 20:32:58 +00:00
idk
a460ae2ffc Remove unused functions from FNDS, SNDF, KNDF 2023-11-01 20:32:57 +00:00
idk
a320b254ef Merge branch 'i2p.i2p.2.4.0-move-receivedby-logic-to-dbe' into 'master'
Router: move getReceivedBy and getReceivedAsPublished into DatabaseEntry

Closes #430

See merge request i2p-hackers/i2p.i2p!132
2023-10-30 00:24:23 +00:00
idk
545057314f Merge branch '465-console' into 'master'
Console: Netdb tab fixes and cleanup (Gitlab #465)

See merge request i2p-hackers/i2p.i2p!140
2023-10-29 18:45:13 +00:00
zzz
a7a0956157 Console: Netdb tab fixes and cleanup (Gitlab #465) 2023-10-29 18:45:13 +00:00
zzz
5ea16d9554 bump -9 2023-10-28 11:47:37 -04:00
zzz
31bad7f8c3 Merge branch '460-subsessions-v2' into 'master'
NetDB: Fix lifecycle issues for subsessions (Gitlab #460, #406)

Closes #460

See merge request i2p-hackers/i2p.i2p!139
2023-10-28 15:42:05 +00:00
zzz
49128b5a2c NetDB: Fix lifecycle issues for subsessions (Gitlab #460, #406) 2023-10-28 15:42:05 +00:00
zzz
e7de354f47 Merge branch '458-gunzip' into 'master'
i2ptunnel: Fix gzip footer check in GunzipOutputStream (Gitlab #458)

Closes #458

See merge request i2p-hackers/i2p.i2p!134
2023-10-28 15:40:55 +00:00
zzz
052c9463e0 i2ptunnel: Fix gzip footer check in GunzipOutputStream (Gitlab #458) 2023-10-28 15:40:55 +00:00
zzz
34bff0806f Merge branch '452-proxy-conn' into 'master'
i2ptunnel: Remove nonstandard Proxy-Connection header (Gitlab #452)

Closes #452

See merge request i2p-hackers/i2p.i2p!130
2023-10-28 15:39:45 +00:00
zzz
7a317e5026 i2ptunnel: Remove nonstandard Proxy-Connection header (Gitlab #452) 2023-10-28 15:39:44 +00:00
idk
c74f160b8a Merge branch 'i2p.i2p-2.4.0-eliminate-useSubDbs' into 'master'
I2p.i2p 2.4.0 eliminate use sub dbs option -  Do not merge until after multihomeDb is merged

Closes #461

See merge request i2p-hackers/i2p.i2p!138
2023-10-27 16:06:24 +00:00
idk
7595b4259f I2p.i2p 2.4.0 eliminate use sub dbs option - Do not merge until after multihomeDb is merged 2023-10-27 16:06:24 +00:00
idk
37bb67bf18 Merge branch 'i2p.i2p-2.4.0-eliminate-multihomedb' into 'master'
I2p.i2p 2.4.0 eliminate multihomedb

Closes #409

See merge request i2p-hackers/i2p.i2p!137
2023-10-27 13:40:28 +00:00
idk
5ccdaf10d9 I2p.i2p 2.4.0 eliminate multihomedb 2023-10-27 13:40:28 +00:00
zzz
69e3d521f4 Console: Tweaks to advanced peers summary bar section 2023-10-25 07:28:00 -04:00
zzz
e204c50ba3 history for -8 2023-10-24 07:13:13 -04:00
idk
1334de31bb Router: build -8 2023-10-24 10:33:16 +00:00
idk
8fdd5fc22f Merge branch '406-lifecycle' into 'master'
NetDB: SubDB lifecycle fixes (Gitlab #406)

Closes #406

See merge request i2p-hackers/i2p.i2p!135
2023-10-24 02:35:52 +00:00
zzz
bf1b4cf502 NetDB: SubDB lifecycle fixes (Gitlab #406) 2023-10-24 02:35:52 +00:00
f5e3891abc CI: just echo last line for debugging purposes 2023-10-22 23:44:40 -04:00
d50e70bdfc CI: remove empty continuation line 2023-10-22 23:22:51 -04:00
40fb1cc4cf CI: add git to container 2023-10-22 23:03:42 -04:00
ed77522da6 CI: unset DOCKER_HOST in gitlab-ci.yml 2023-10-22 22:51:30 -04:00
2e32ad8bde CI: update dind image in .gitlab-ci.yml 2023-10-22 22:17:47 -04:00
zzz
83794107f3 SSU: Comment fix
re: LHMCache iteration order
2023-10-22 07:48:07 -04:00
zzz
d5462b31f3 Tests: Disable console scala tests in gradle tests
NPEs due to null log manager
2023-10-22 07:44:53 -04:00
zzz
ec68911568 Tests: Exclude BuildMessageTestStandalone from gradle tests
NPEs via junit; must be run via main()
Already disabled on ant side
2023-10-21 15:34:13 -04:00
zzz
6044d5425c SAM: Reset incoming socket if no subsession is matched (GItlab #456) 2023-10-21 08:42:50 -04:00
zzz
82c7e5a362 Build: Gradle build fixes 2023-10-20 11:33:55 -04:00
a23e09ca20 Router: fix failed ant builds in unit tests 2023-10-18 18:47:44 -04:00
00e3390437 Router: reverse changes to RepublishLeaseSetJob 2023-10-17 12:33:53 -04:00
c67ff1376a Router: fix broken null check in shouldThrottleBurstLookup 2023-10-17 12:30:40 -04:00
fb8bb645c2 Router: move getReceivedBy and getReceivedAsPublished into DatabaseEntry 2023-10-16 20:47:27 -04:00
2af65243a4 Router: remove 'Confirm Succeess' from ISJ, closes #455 2023-10-16 19:38:52 -04:00
idk
de2b122f7b Merge branch 'i2p.i2p.2.4.0-reverse-api-change' into 'master'
Router: Reverse API change from banlistRouterHard back to BanlistRouterForever

See merge request i2p-hackers/i2p.i2p!131
2023-10-16 23:31:07 +00:00
0acae98ccd Router: Reverse API change from banlistRouterHard back to BanlistRouterForever 2023-10-15 20:22:37 -04:00
a2446e1d0c Router: Remove all refs to ban-by-lookup-flood code. Don't create throttlers in the FNDF unles sit's the main db 2023-10-15 20:05:01 -04:00
195b4b9155 Router: bump build rev to -7 2023-10-12 20:19:31 -04:00
idk
5fe8a3bc82 Merge branch 'i2p.i2p.2.4.0-single-blind-cache' into 'master'
Switch back to a single blind cache

See merge request i2p-hackers/i2p.i2p!127
2023-10-13 00:02:28 +00:00
idk
35c4a4cca9 Switch back to a single blind cache 2023-10-13 00:02:28 +00:00
zzz
cef40151a9 Merge branch 'i2ptunnel-cleanup' into 'master'
i2ptunnel: HTTPResponseOutputStream cleanup

See merge request i2p-hackers/i2p.i2p!122
2023-10-12 18:58:59 +00:00
zzz
040bc58917 i2ptunnel: HTTPResponseOutputStream cleanup 2023-10-12 18:58:59 +00:00
zzz
8a840f97c7 bump -6 2023-10-12 11:05:04 -04:00
7d0c857eb5 Router: fix NPE in ClientManager, reduce log level of error in ClientConnectionRunner 2023-10-11 20:39:22 -04:00
79d456a8c3 Router: remove redundant cast in ConfigAdvancedHandler 2023-10-11 12:02:30 -04:00
zzz
3280dd1878 Add ramble.i2p to hosts.txt 2023-10-10 12:00:10 -04:00
zzz
dab30c8c76 Console: Sidebar download button CSS padding tweak (light theme) 2023-10-10 09:47:55 -04:00
zzz
f590128201 Merge branch 'unsigned-update' into 'master'
Updates: Unsigned update improvements

See merge request i2p-hackers/i2p.i2p!125
2023-10-10 12:17:21 +00:00
zzz
df4b3c0d13 Updates: Unsigned update improvements 2023-10-10 12:17:21 +00:00
zzz
0e525b109d Merge branch 'snark-shutdown' into 'master'
i2psnark: Shutdown incomplete torrents first

See merge request i2p-hackers/i2p.i2p!124
2023-10-10 11:56:18 +00:00
zzz
8fdad9c7dc i2psnark: Shutdown incomplete torrents first 2023-10-10 11:56:18 +00:00
zzz
93259d5bf9 Merge branch 'snark-menu' into 'master'
i2psnark-standalone: Add systray item for shutdown

See merge request i2p-hackers/i2p.i2p!123
2023-10-10 11:53:41 +00:00
zzz
dedfee4c82 i2psnark-standalone: Add systray item for shutdown 2023-10-10 11:53:41 +00:00
ccec1162b9 Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2023-10-09 14:54:11 -04:00
dec98e6b8d Router: remove the redundant casts, fixes #438 2023-10-09 14:53:52 -04:00
zzz
6305e85ce1 Console: Fix visibility of radio/checkboxes (light theme) 2023-10-09 10:29:57 -04:00
4c7846be2c Router: add protected isMainDb() function to KNDF and use it when we want to make sure we're the main db 2023-10-08 16:26:52 -04:00
6ada2f3b5e Router: Change name of STATUS to QUALIFIER, move it after BUILD 2023-10-07 16:06:52 -04:00
499106c9ae Router: javadoc add additional note to CM call 2023-10-07 15:54:46 -04:00
idk
6136890616 Merge branch 'i2p.i2p.2.4.0-client-netdbs-on-client-runner' into 'master'
Router: move segmented netDbs into CCRs.

Closes #404, #423, #420, and #439

See merge request i2p-hackers/i2p.i2p!120
2023-10-07 19:20:14 +00:00
idk
4872eedd83 Router: This moves all client sub-netDbs into the ClientConnectionRunners. This turns the FloodfillNetworkDatabaseSegmentor into a means of looking up netDb's and managing the main netDb and a special netDb for managing multihomes. It adds the ability to use sub-netDbs as a defense against netDb context confusion bugs, and also to switch to a single monolithic netDb if necessary. 2023-10-07 19:20:14 +00:00
zzz
1ae663c6a5 Merge branch '433-peertest-iae' into 'master'
SSU2: Prevent rare IAE in peer test timer (Gitlab #433)

Closes #433

See merge request i2p-hackers/i2p.i2p!121
2023-10-03 11:43:02 +00:00
f0b6638466 Router: check \!isClientDb() in KNDF before calling remove 2023-10-02 17:43:41 -04:00
zzz
cb4788019b SSU2: Prevent rare IAE in peer test timer (Gitlab #433) 2023-09-30 10:17:47 -04:00
zzz
d7d51f673f i2psnark: Search box CSS tweaks when iframed (Gitlab #448)
thx drzed for assistance
2023-09-29 17:30:40 -04:00
zzz
d2ab9a7ff4 bump -4 2023-09-29 06:16:14 -04:00
zzz
065ce2886c Merge branch '427-disable-ssu1' into 'master'
SSU1: Disable by default (Gitlab #427)

Closes #427

See merge request i2p-hackers/i2p.i2p!115
2023-09-29 09:58:51 +00:00
zzz
37eb6d383f SSU1: Disable by default (Gitlab #427) 2023-09-29 09:58:51 +00:00
zzz
1350c71c3d Merge branch '399-sam-accept' into 'master'
SAM: Accept fixes (Gitlab #399)

Closes #399

See merge request i2p-hackers/i2p.i2p!114
2023-09-29 09:57:12 +00:00
zzz
0ba97ed4cd SAM: Accept fixes (Gitlab #399) 2023-09-29 09:57:12 +00:00
zzz
60bf83a653 bump -3 2023-09-27 11:11:17 -04:00
zzz
8a1da2ce94 Merge branch '426-doctype' into 'master'
Console: Change all DOCTYPEs to standard html (Gitlab #426)

Closes #426

See merge request i2p-hackers/i2p.i2p!117
2023-09-27 14:17:22 +00:00
idk
d08e82e4f7 Merge branch '437-npe' into 'master'
Transport: Fix NPE during soft restart (Gitlab #437)

Closes #437

See merge request i2p-hackers/i2p.i2p!113
2023-09-26 02:18:12 +00:00
zzz
1dff57856a Transport: Fix NPE during soft restart (Gitlab #437) 2023-09-26 02:18:12 +00:00
idk
453f31099d Merge branch '445-snark-startall' into 'master'
i2psnark: Prevent start-all from within search results erroring on...

Closes #445

See merge request i2p-hackers/i2p.i2p!119
2023-09-26 02:16:51 +00:00
zzz
38f629b91c i2psnark: Prevent start-all from within search results erroring on... 2023-09-26 02:16:51 +00:00
idk
d7eb4db806 Merge branch '443-debian-jre' into 'master'
Debian: Change JRE dependency order (Gitlab #443, Debian #1024461)

Closes #443

See merge request i2p-hackers/i2p.i2p!118
2023-09-26 02:08:28 +00:00
idk
9f99ee66f7 Merge branch '415-itag-zeros' into 'master'
SSU2: Fix uncaught IAE caused by itags with zero values (Gitlab #415)

Closes #415

See merge request i2p-hackers/i2p.i2p!111
2023-09-26 02:07:45 +00:00
zzz
4cf919e3e6 SSU2: Fix uncaught IAE caused by itags with zero values (Gitlab #415) 2023-09-26 02:07:45 +00:00
idk
324c5be47d Merge branch '435-ntcp2-firewalled' into 'master'
NTCP2: Fix updating address on transition to firewalled (Gitlab #435)

Closes #435

See merge request i2p-hackers/i2p.i2p!116
2023-09-26 02:04:33 +00:00
zzz
ef1177689d NTCP2: Fix updating address on transition to firewalled (Gitlab #435) 2023-09-26 02:04:33 +00:00
zzz
69554e4687 Debian: Change JRE dependency order (Gitlab #443, Debian #1024461) 2023-09-23 16:40:31 -04:00
zzz
3d1cc888fa Console: Change all DOCTYPEs to standard html (Gitlab #426) 2023-09-23 16:11:37 -04:00
69d5dfc621 Router: bump build rev 2023-09-22 20:21:51 -04:00
ded7b6dda9 Router: eliminate mainNetDb() call from RouterContext, then replace all calls with calls to netDb() 2023-09-21 19:55:07 -04:00
a343f781d0 Router: don't call remove(dbe,persist) on a TDS 2023-09-21 15:00:04 -04:00
idk
16bfdb4943 Merge branch 'i2p.i2p.2.4.0-no-more-multihome-cache' into 'master'
I2p.i2p.2.4.0 no more multihome cache

See merge request i2p-hackers/i2p.i2p!110
2023-09-21 03:09:09 +00:00
idk
f9f21ba7f5 I2p.i2p.2.4.0 no more multihome cache 2023-09-21 03:09:09 +00:00
idk
790584b329 Merge branch 'i2p.i2p.2.4.0-segmented-netdb-safer-interfaces' into 'master'
Drastically reduces the interface of the FNDS/SNDF, force the use of explicit accessors, refactor FNDS/SNDF

See merge request i2p-hackers/i2p.i2p!107
2023-09-19 19:32:00 +00:00
idk
92a85b35fe Drastically reduces the interface of the FNDS/SNDF, force the use of explicit accessors, refactor FNDS/SNDF 2023-09-19 19:32:00 +00:00
idk
9cad050e6b Merge branch 'i2p.i2p.2.4.0-transient-client-subnetdbs' into 'master'
Router: if a KNDF isClientDb() then set up a TransientDataStore instead of a PersistentDataStore

See merge request i2p-hackers/i2p.i2p!108
2023-09-18 03:26:22 +00:00
d2b8d11645 Router: if a KNDF isClientDb() then set up a TransientDataStore instead of a PersistentDataStore 2023-09-15 12:14:38 -04:00
idk
b4c64e2808 Merge branch 'i2p.i2p.2.4.0-transifex' into 'master'
Project: regenerate updated transifex config files

Closes #408

See merge request i2p-hackers/i2p.i2p!103
2023-09-14 20:33:38 +00:00
idk
f184cc32df Merge branch 'i2p.i2p.2.4.0-undo-breaking-api-change' into 'master'
I2p.i2p.2.4.0 undo breaking api change

Closes #402

See merge request i2p-hackers/i2p.i2p!105
2023-09-14 20:33:28 +00:00
idk
40757b3028 I2p.i2p.2.4.0 undo breaking api change 2023-09-14 20:33:28 +00:00
aa1697e767 Project: regenerate updated transifex config files 2023-09-07 16:08:38 -04:00
idk
c1c8cfc29b Merge branch 'i2p.i2p.2.3.0-DLM-MR' into 'master'
NetDb: Disable Burst Banning on DLM.

See merge request i2p-hackers/i2p.i2p!102
2023-09-05 02:19:06 +00:00
dc68fdc0a0 NetDb: Disable Burst Banning on DLM.
Disable the banning of routers due to excessive Database Lookup
Messages (DLM) until a reliable method is identified for
discriminating between routers that are merely forwarding someone
else's DLM, and routers that are directly sending excessive
DLM.

Signed-off-by: obscuratus <obscuratus@mail.i2p>
2023-09-04 13:26:24 -05:00
4e6323453c Router: change logging of floodfill subdb to main subdb in FNDS. Add TODO comments to getLocalClientsBlindData and lookupClientsBySigningPublicKey. 2023-09-04 12:45:48 -04:00
76067312e1 Router: rename the floodfill netdb to the main netdb 2023-09-03 23:03:35 -04:00
7d9eecd05a Router: rename the floodfill netdb to the main netdb 2023-09-03 21:46:03 -04:00
d3ad082a82 Console: use clientOnly flag from caller when displaying client netDbs 2023-09-03 21:32:50 -04:00
idk
3d225b6f9f Merge branch 'i2p.i2p.2.4.0-test1' into 'master'
Nested NetDb Branch Redux

See merge request i2p-hackers/i2p.i2p!101
2023-08-31 02:53:07 +00:00
idk
88d9d0f9b7 Nested NetDb Branch Redux 2023-08-31 02:53:07 +00:00
idk
2fb4dc415c Merge branch 'i2p.i2p.2.4.0-or-2.5.0-delete-hostnames-from-terminal' into 'master'
AddressBook: add -d option to lookupdest command line which deletes a hostname...

See merge request i2p-hackers/i2p.i2p!99
2023-08-15 07:08:29 +00:00
idk
d2e899915b AddressBook: add -d option to lookupdest command line which deletes a hostname... 2023-08-15 07:08:28 +00:00
idk
79494c2396 Merge branch '2.3.0-lookup-tweaks' into 'master'
2.3.0 lookup tweaks

See merge request i2p-hackers/i2p.i2p!97
2023-08-15 07:07:19 +00:00
idk
d233209694 2.3.0 lookup tweaks 2023-08-15 07:07:18 +00:00
3fc704c445 Add Metrics and StormyCloud to homepage 2023-07-24 13:54:10 -04:00
d66a7424a7 Router: add option to include a release 'status' in the version number, i.e. beta1, rc1 2023-07-18 14:51:45 -04:00
idk
206cc00387 fix lunar changelog 2023-07-01 16:01:20 -04:00
idk
0d359bbc1b update debian changelogs 2023-07-01 11:10:55 -04:00
idk
2fcc947a12 revise icons again 2023-06-30 10:07:30 -04:00
idk
55b1da881b make blue version of notbob icon to match homepage color scheme 2023-06-30 01:01:31 -04:00
idk
ff94b2423e account for RAP vs RAR in multihomeCache 2023-06-29 23:40:56 -04:00
idk
2a3d4e9458 alter color scheme on new icons to match ours. We'll approach this later. 2023-06-29 18:20:01 -04:00
idk
cda6416bf9 fixup debian patch 2023-06-29 16:05:30 -04:00
idk
cd6a4ac758 update translations and manpages 2023-06-29 14:40:46 -04:00
idk
40a7149215 update versions and build numbers 2023-06-29 13:39:12 -04:00
idk
62c21a8de0 fix typo 2023-06-29 12:36:12 -04:00
idk
5c56856566 Merge branch 'i2p.i2p.2.2.1-always-copy-full-leaseSet-when-updating' into 'master'
screen leaseSets before storing them in KademliaNetworkDatabaseFacade.store,...

See merge request i2p-hackers/i2p.i2p!94
2023-06-29 16:23:08 +00:00
idk
8fd2235cde screen leaseSets before storing them in KademliaNetworkDatabaseFacade.store,... 2023-06-29 16:23:07 +00:00
idk
331b24237f Merge branch 'i2p.i2p.2.2.1-not-bob-icon' into 'master'
add notbob and ramble icons

See merge request i2p-hackers/i2p.i2p!96
2023-06-29 04:43:47 +00:00
idk
5edf9f715b add notbob and ramble icons 2023-06-29 04:43:47 +00:00
idk
eb0c8aaaa9 correct the error in the previous checkin 2023-06-26 16:44:37 -04:00
idk
e55e6bc7a2 move singleIPv6BlockList null check in clear outside of the synchronized block 2023-06-26 14:18:48 -04:00
idk
0ac7d69212 add null checks around _singleIPv6Blocklist 2023-06-26 14:12:39 -04:00
idk
ace62a1677 add notbob and ramble to the homepage, tooltips won't be translated for 2.3.0 but we'll live with that for now. 2023-06-23 17:51:21 -04:00
idk
95c29649bd Merge branch 'i2p.i2p.2.2.1-blocklist-expiration' into 'master'
add user-configurable expire-time to blocklists.

See merge request i2p-hackers/i2p.i2p!93
2023-06-19 00:05:03 +00:00
idk
912b534c31 add user-configurable expire-time to blocklists. 2023-06-19 00:05:02 +00:00
idk
b2fea266ee bump build time 2023-06-14 13:31:20 -04:00
idk
c30ad8d386 update geolite database 2023-06-14 12:45:36 -04:00
idk
3ce34ed338 Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2023-06-10 22:23:05 -04:00
idk
f3794ecd10 reverse the last change to i2psnark-standalone 2023-06-10 22:16:25 -04:00
idk
0bb220b85d Merge branch '2.2.1-xormsgmask-mr' into 'master'
Router/Tunnel: Constrain xor message ID mask to >= 0

See merge request i2p-hackers/i2p.i2p!92
2023-06-11 02:05:56 +00:00
badcf76e2f Router/Tunnel: Constrain xor message ID mask to >= 0 2023-06-11 02:05:55 +00:00
idk
90aacc6746 use RandomSource instead of Random 2023-06-04 18:23:17 +00:00
idk
f0df5d19ed add comment to the new getUniqueID code 2023-06-04 17:31:26 +00:00
idk
9c5118f763 re-add 3-arg add function and javadoc. 2023-06-04 17:27:24 +00:00
idk
722029d11e Merge branch 'i2p.i2p.2.2.1-xor-messageIDs-as-interface-change' into 'master'
Patches all INMP.add() calls to use replay "Contexts" specific to where they were called from.

See merge request i2p-hackers/i2p.i2p!91
2023-06-04 01:38:16 +00:00
idk
82aa4e19fb Patches all INMP.add() calls to use replay "Contexts" specific to where they were called from. 2023-06-04 01:38:15 +00:00
idk
63f2ae368c Merge branch 'i2p.i2p.dtg-menu-api' into 'master'
Adds a Menu API to the DTG

See merge request i2p-hackers/i2p.i2p!90
2023-05-31 14:39:53 +00:00
idk
785fc52a14 Adds a Menu API to the DTG 2023-05-31 14:39:53 +00:00
idk
997644a06d Merge branch 'i2p.i2p.congestion-caps' into 'master'
start implementing congestion caps handling by adding...

See merge request i2p-hackers/i2p.i2p!89
2023-05-31 14:34:19 +00:00
idk
43b4364918 start implementing congestion caps handling by adding... 2023-05-31 14:34:18 +00:00
idk
f308ebee74 bump rc 2023-05-25 03:39:18 +00:00
idk
687858e73d Router/Tunnel: xor message IDs in order to prevent cross-context leaks.
Adds unique message ID's per context to bloom filter for safer replay protection.

The transport and client tunnel managers use a message ID in order to prevent
messages from being replayed. Prior to this checkin, the message ID queue used
the same IDs in clients and transports. If a message was sent to a transport
and a client with the same message ID, the message ID in one would cause a replay
to be detected in the other.

The result would be that the message reply would come back empty, creating a
point of evidence that a client and a transport were hosted on the same router.

However, there is no way from the attackers POV to determine with certainty that
the message was dropped because the message was replayed, making it very easy to
demonstrate a potential information leak using a known router and a known client,
but more difficult, to use to deanonymize a known client on an unknown router
(i.e. by trying routers from the local NetDB).

So what we have here is a situation where an attacker observing router behavior
can say that a message was dropped, and that they have reason to believe it is
because it contained an ID which was replayed. This constitutes a potential
information leak and is resolved by this checkin.

patch created by @obscuratus, tested, reviewed and checked in by @obscuratus and @idk
2023-05-17 18:16:25 +00:00
idk
76197ce75d Merge branch '2.2.1-issue397-v2' into 'master'
Router/Tunnel: Handling Updates for Inbound Messages.

See merge request i2p-hackers/i2p.i2p!88
2023-05-08 17:44:58 +00:00
18d939bcd4 Router/Tunnel: Handling Updates for Inbound Messages. 2023-05-08 17:44:58 +00:00
idk
18a3893185 update po files with diff 2023-04-23 19:08:43 +00:00
idk
058f07c208 fix un-escaped character on configplugins.jsp 2023-04-22 15:11:10 +00:00
idk
a9d9c13869 Merge pull request #44 from Shoalsteed/master
Update configplugins.jsp
2023-04-22 11:01:10 -04:00
af3c32fc46 Merge branch 'i2p:master' into master 2023-04-20 13:24:45 -04:00
17b4409823 Update configplugins.jsp
Fixes Issue i2p.i2p/-#392
2023-04-18 12:54:34 -04:00
idk
85822c48da fix lunar changelog 2023-04-17 03:31:25 +00:00
idk
ecc87573e3 update debian changelogs 2023-04-17 03:04:04 +00:00
idk
f66f21434e 2.2.1 2023-04-12 21:23:18 +00:00
idk
c6d853575d fix makegeoip.sh script 2023-04-12 21:21:58 +00:00
idk
53bae90089 fix makegeoip script and update geoip data 2023-04-12 21:21:58 +00:00
idk
a50a65ac9f update version numbers in installer and resources 2023-04-12 21:21:32 +00:00
idk
ff4b8fc106 ignore shell scripts in root directory 2023-04-12 16:43:33 +00:00
idk
fe541df2c7 fix typo in checklist, add .tx to gitignore 2023-04-12 16:42:37 +00:00
idk
4585ec0b4c Merge branch 'lunar-bookworm-jakarta' into 'master'
WIP: Install and link jakara on Ubuntu>=Lunar, Debian>=Bookworm

Closes #374

See merge request i2p-hackers/i2p.i2p!87
2023-04-07 13:33:11 +00:00
idk
456ab3150a WIP: Install and link jakara on Ubuntu>=Lunar, Debian>=Bookworm 2023-04-07 13:33:10 +00:00
idk
b3748395ce Check in fixes for console 2023-04-06 18:54:03 +00:00
idk
b582695aa2 Merge pull request #43 from Shoalsteed/master
Updated Copy For /console, merging with changes requested, I'll be checking them in
2023-04-06 14:52:28 -04:00
06b7f75df3 Update readme.html 2023-04-05 14:55:08 -04:00
e2ca8d3268 Update readme.html 2023-04-05 14:41:50 -04:00
idk
0d4eec7f7f fix decimal/comma formatting issue on stats page 2023-03-31 23:08:45 +00:00
idk
837cb34353 Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2023-03-28 03:25:18 +00:00
idk
8b9cfc4e63 update outproxy user agent to latest TBB/Firefox ESR version, reported by dr|zed 2023-03-28 03:22:24 +00:00
idk
7d7768897d Merge branch 'add-tmp-to-install.jar' into 'master'
use tmp for install.jar to prevent confusion on build fails

See merge request i2p-hackers/i2p.i2p!85
2023-03-23 23:19:12 +00:00
c8b6e678f8 use tmp for install.jar to prevent confusion on build fails 2023-03-23 23:19:12 +00:00
idk
692c73994b fix some errors in startapp.sh shell script, including /JAVA_OPTS/JAVAOPTS/ thanks @bedaro, #41 2023-03-23 04:08:24 +00:00
idk
b5461f3b41 ignore override.properties when building docker 2023-03-19 15:00:48 +00:00
idk
37018f6eb0 Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2023-03-19 14:42:56 +00:00
daff55463b Router: Update and Clarify the Inline Documentation for VMCommSystem 2023-03-19 14:41:50 +00:00
ab676bf63c Detect When Running as a Podman Container 2023-03-19 14:41:50 +00:00
idk
8a0a533777 fix base directory path duplication in Dockerfile 2023-03-19 14:35:23 +00:00
idk
3c0eb9c52f Merge branch '2.1.0-9-mr-vmcommsystem-v2' into 'master'
Router: Update and Clarify the Inline Documentation for VMCommSystem

See merge request i2p-hackers/i2p.i2p!83
2023-03-18 17:33:32 +00:00
b3188a26a5 Router: Update and Clarify the Inline Documentation for VMCommSystem 2023-03-18 17:33:32 +00:00
idk
3ab904f164 Merge branch 'master' into 'master'
Detect When Running as a Podman Container

See merge request i2p-hackers/i2p.i2p!84
2023-03-18 17:32:38 +00:00
c71a42859d Detect When Running as a Podman Container 2023-03-18 17:32:38 +00:00
idk
cbe8d3f799 add blocklist 2023-03-14 22:42:24 +00:00
idk
ae4d3b5758 fix bionic changelog 2023-03-14 22:29:10 +00:00
idk
d12adcd933 update debian changelogs 2023-03-14 18:22:42 +00:00
idk
607613b7fd update debian changelog 2023-03-14 17:54:07 +00:00
idk
fdd0b6a280 remove hazardous plugin keys 2023-03-13 20:02:29 +00:00
idk
0401157703 fix non-zero build number change that was not checked in 2023-03-13 19:33:12 +00:00
idk
98931bb530 bump version and create tag for 2.2.0/0.9.58 2023-03-13 14:59:56 +00:00
idk
38666d2449 Send and check target destination in first streaming SYN packet 2023-03-13 01:30:17 +00:00
idk
ed513b6c15 remove stats.i2p from jump services 2023-03-13 00:02:08 +00:00
idk
11523c79f4 remove zzz.i2p and stats.i2p from console homepage 2023-03-12 00:57:14 +00:00
idk
4b87f4d2cc checkin reseed update 2023-03-07 19:50:58 +00:00
idk
bbd90a77bc check in changed translations 2023-03-07 17:30:15 +00:00
idk
0645359cb6 explicitly set i2p.dir.base and i2p.dir.config in router.config for Docker containers. fixes and closes #41. 2023-02-28 02:33:25 +00:00
idk
9369002418 Merge pull request #38 from jeanluc162/docker-multiarch
Changed baseimage to allow for multiarch build (specifically arm64)
2023-02-22 17:56:57 -05:00
zzz
37feda74f7 DTG: Remove "Start I2P" menu item in non-router context
Reported by R4SAS
2023-02-18 17:04:42 -05:00
zzz
e1da8d13d7 Sybil: Don't catch all the i2pds publishing ::1 2023-02-18 16:44:10 -05:00
zzz
a4f36c8e64 log message fix
reported by drzed
2023-02-17 18:48:42 -05:00
zzz
3636ec7cc6 javadoc fix 2023-02-17 13:36:45 -05:00
zzz
2acdcc5c93 Console: Add legend for congestion caps (proposal 162) 2023-02-17 11:26:49 -05:00
zzz
b44cb59a48 Transports: Add new inbound connection throttler
To limit rate increase of inbound conns
Add exemption system so inbound tunnel builds bypass the throttler
2023-02-16 10:26:14 -05:00
zzz
5918613ff4 Tunnels: Re-enable using U routers in some expl. tunnels
to give them cover
2023-02-15 12:24:50 -05:00
zzz
5499b23189 Blocklist: Increase size for slow routers
Store feed blocklist in main array for efficiency
2023-02-15 11:47:01 -05:00
zzz
601a1c917e Sybil: Disable analysis when in test mode 2023-02-15 11:28:20 -05:00
zzz
de978f3a10 SSU2: Remove dup stat update 2023-02-15 07:07:08 -05:00
zzz
48598d9c76 Console: More failing peers removal 2023-02-13 12:55:25 -05:00
zzz
46af72c529 Console, NetDB: Remove deprecated isFailing() calls 2023-02-13 10:28:51 -05:00
zzz
b82cefd904 Profiles: Remove the long-unused failing peers map, deprecate all related methods 2023-02-13 10:09:55 -05:00
zzz
8f0e3d0421 Profiles: Change the new-router bonus to a penalty
Don't penalize old routers after long downtime
2023-02-13 07:24:27 -05:00
zzz
6a04eedb9e Console: Set minimum displayed profile thresholds to 1 2023-02-13 07:19:31 -05:00
zzz
546e51e3d9 Router: Increase min version for tunnels and netdb to 0.9.51 2023-02-12 16:06:51 -05:00
zzz
86cbbd80cf Tunnels: Give up on building through U routers 2023-02-12 15:54:17 -05:00
zzz
18f598bc2c Console: Reduce max age of displayed profiles
to match age reductions in the organizer and limit output
2023-02-12 15:07:37 -05:00
zzz
69b73d4bc8 Profiles: Don't create new profile on message or lookup failures
Mark commErrorOccurred() unused
2023-02-12 15:06:33 -05:00
zzz
8ba5cb4d02 Profiles: Adjust capacity for send success/failure
Stub out adjustments for congestion caps
2023-02-12 14:23:10 -05:00
zzz
f9b9633ac0 Profiles: Downrate capacity of slow/unreachable peers
Use more efficient RI lookup
Comment out unused same-country code
2023-02-12 13:39:47 -05:00
zzz
6f80df48e0 bump -8 2023-02-12 10:17:57 -05:00
zzz
4a9ca43614 NetDB: Don't call heardAbout() unless peer is reachable
Consolidate hash() calls
2023-02-12 10:15:28 -05:00
zzz
afe236c62c Profiles: Limit storage and memory usage
Write profiles to disk more often
Delete old profiles on disk more often
Reduce max age of profiles
Limit age of profiles read in at startup based on downtime
Limit total profiles read in at startup
Change loaded profiles from a Set to a List for efficiency
Log tweaks
2023-02-12 10:11:46 -05:00
zzz
7a75ea4bef NetDB: Store handler updates
Drop some unsolicited RI stores when over thresholds
Don't update profile for banned/blocked RI
Don't flood RIs with blocked IP
Log tweaks
2023-02-12 07:58:24 -05:00
zzz
78ee005870 Data: Move LS RAP/RAR booleans up to superclass
Add RAR to I2NP DSM
WIP
2023-02-11 09:47:40 -05:00
zzz
dbe3445d7b Console: Fixup display of RI published in the future
String consolidation
2023-02-11 06:52:20 -05:00
zzz
cb90139342 NetDB: Increase flood thottle time 2023-02-11 06:34:04 -05:00
zzz
d6c6b5e092 NetDB: Expiration tweaks
Start expire job sooner if forced floodfill or downtime was short
Don't run refresh routers job if forced floodfill or downtime was short or vmcommsystem
Increase expire probability
Don't expire routers close to us just before midnight
Don't start expire leases job until 11 minutes after startup
Base probability out of 128 to reduce random usage
Consolidate now() calls
2023-02-11 06:02:57 -05:00
zzz
5d3dffbaa0 Util: Increase memory required to not be slow 2023-02-11 04:43:31 -05:00
zzz
21d39ebc36 i2psnark standalone: Add example config to disable notifications 2023-02-10 13:47:58 -05:00
zzz
1f81d35423 Router: Tighten skew calculation window 2023-02-10 12:42:36 -05:00
zzz
12239124d6 Profiles: Don't delete old profiles from disk until 90m uptime 2023-02-09 16:27:38 -05:00
zzz
71a1d6dd7b NetDB: Don't lookup before dropping after shutdown initiated 2023-02-09 14:38:21 -05:00
zzz
4881ac32b6 DTG: Support notification disable/enable in non-router context
by moving all the code from InternalTrayManager to TrayManager
and adding to the ExternalTrayManager menu
As requested by R4SAS
2023-02-09 14:09:10 -05:00
zzz
d3e5879068 NetDB: Improve efficiency of ExpireRoutersJob
by iterating through the map entries directly, as in ExpireLeasesJob
Expire RIs just before saving them at shutdown
2023-02-09 13:19:00 -05:00
zzz
e4e9fe2972 i2ptunnel: Tag untagged strings (Gitlab #387) 2023-02-09 11:42:48 -05:00
zzz
56ab3b59a2 bump -7 2023-02-08 09:46:38 -05:00
zzz
bc7355d61e Console: Debug page sockets table cleanup 2023-02-08 09:43:42 -05:00
zzz
7834f44973 NetDB: Minor cleanups and log tweaks 2023-02-08 09:36:32 -05:00
zzz
621862afa9 NetDB: Replace Set with List in ExpireLeasesJob for efficiency 2023-02-08 09:25:42 -05:00
zzz
af99250a69 NetDB: Further restrict what RIs we lookup before dropping
if floodfill, unreachable, or L class
Only kicks in if we don't have a lot of RIs to begin with
2023-02-08 09:20:10 -05:00
zzz
0bce9d1211 Profiles: Reduce initial/min/max expirations
Adjust expiration faster
Use more efficient RI lookup method
2023-02-08 09:10:27 -05:00
zzz
8b7f68e6f9 NTCP: Route RI block of another router to InNetMessagePool 2023-02-08 09:05:29 -05:00
zzz
6ac08e0929 Tunnels: Load RIs more efficiently in peer selector 2023-02-08 08:58:22 -05:00
zzz
b87fd621b1 NetDB: Implement faster RI expiration mode
exempt routers within our keyspace if we are floodfill
2023-02-08 08:52:12 -05:00
zzz
c94bfe6cd0 NTCP: Increase temp. inbound IP block time
Block IP on failed inbound
Ban peers that ban us
2023-02-08 08:32:06 -05:00
zzz
c08d6b3a18 log tweak 2023-02-08 08:27:20 -05:00
zzz
9e2bb1ad0a Transports: Check RI in handshake for matching IP 2023-02-08 08:25:09 -05:00
zzz
10e0596011 NetDB: Reduce min RI expiration 2023-02-08 08:19:34 -05:00
zzz
6216081259 NetDB: Increase closest-floodfill search size
Reduce max fail rate
Lookup RIs more efficiently
2023-02-08 08:10:46 -05:00
zzz
981946c950 NetDB: Don't explore if we have enough RIs 2023-02-08 08:05:30 -05:00
zzz
84e70ba013 Console: Load router infos more efficiently
Add routing key to router infos (advanced)
2023-02-08 07:52:22 -05:00
zzz
8ff421143f NetDB: Set max routers to load at startup 2023-02-08 07:40:18 -05:00
zzz
22b5cdf57a Console: Debug DHT tab dark theme fixup 2023-02-08 07:37:31 -05:00
zzz
cc58c96e98 Console: Fixup netdb search example 2023-02-08 07:36:30 -05:00
zzz
3816278a5e Router: Don't set congestion cap at startup because of high job lag 2023-02-08 07:32:56 -05:00
zzz
338985a4cc Sybil: Thread analyzer at reduced priority
Don't do pair distance check unless enough memory
2023-02-08 07:28:46 -05:00
zzz
c6fca9da6a bump -6 2023-02-04 09:26:32 -05:00
zzz
bdbbe148c3 Profiles: Make DBHistory rates final 2023-02-04 08:58:46 -05:00
zzz
f2b206b1e0 Router: Continue work on congestion caps (proposal 162)
Set caps based on job lag and share bandwidth
Add 20 minute rate to tunnel.participatingMessageCountAvgPerTunnel to
be used for congestion caps
Don't set congestion cap if hidden
2023-02-04 08:57:10 -05:00
zzz
c1f83d6ec9 Router: Stat cleanup
Remove old non-required client.timeoutCongestion* stats in OCMOSJ.
Remove RouterThrottle.getInboundRateDelta(), used only for those stats.
Remove transport.sendMessageSize rates longer than 60s, used only for getInboundRateDelta().
Remove transport.receiveMessageSize rates longer than 60s, unused anywhere.
Remove transport.sendProcessingTime rates longer than 60s, unused anywhere.
getInboundRateDelta() was broken anyway as it was looking at send, not receive size.
All of this was untouched since 2004.
9 total rates for required stats removed.
2023-02-04 08:49:40 -05:00
zzz
c53fe93839 i2psnark: Fix missing paren in tooltip
ref: http://zzz.i2p/topics/3577
2023-02-03 07:37:15 -05:00
zzz
190acf7ed2 i2psnark: Fix for torrents with # in the name
By using custom version of storeProps()/loadprops()
for torrent config files
ref: http://zzz.i2p/topics/3576
2023-02-03 07:32:52 -05:00
zzz
3d71a5404b Util: Fix check for illegal chars in storeProps()
ref: http://zzz.i2p/topics/3576
2023-02-03 07:28:42 -05:00
zzz
37beb53245 Profiles: Remove 30m tunnel history rates
to save a large amount of space.
30m rates were almost always within 10% of the 60m rates,
so we clearly don't need both.
Keep 60m because that's what we publish in the netdb.
Adjust rate weighting in CapacityCalculator accordingly.
2023-02-01 17:10:04 -05:00
zzz
019a8b6655 Profiles: Count all build rejections in tunnel history
Previously did not count probabalistic or transient codes
Reduce 10 minute acceptance rate for these codes
(previously adjusted the averaged rate)
Make rates final in TunnelHistory
Static rates array to reduce object churn
Prep for removing 30m rates
Reduce now() calls, pull out of loops
2023-02-01 16:23:45 -05:00
zzz
652da9ebd5 Console: Dark theme home page CSS tweaks 2023-02-01 16:01:25 -05:00
zzz
99703d53ba Ratchet: Don't bundle LS with ratchet ACK
Not necessary, and will be the wrong LS for EdDSA subsession
2023-02-01 08:47:58 -05:00
zzz
de7b8db504 Console: Don't list same client SKM twice on /debug for subsessions 2023-02-01 08:01:35 -05:00
zzz
1e28557ce2 cleanup buf.append(s.substring(a, b)) -> buf.append(s, a, b)
all over, for object churn
2023-01-31 07:31:02 -05:00
zzz
07a796bcf6 typo 2023-01-30 14:50:40 -05:00
zzz
665e63da5b Util: Add experimental config to bypass Fortuna and just use /dev/random
Refactor Fortuna so it may be extended
Reduce default buf size for Android
2023-01-30 14:04:50 -05:00
zzz
4ef4ae4df5 Streaming: Refactor sig checking
Save sig OK status in Packet
Fix spot where byte array cache was not used
Do not send NACK 0 for retransmitted SYNs
Remove 1-byte DataHelper.toLong() calls
2023-01-30 13:21:10 -05:00
zzz
ac50eefe07 Tunnels: Improve expl. build success in well-connected routers during congestion
by not using high cap tier. Congestion starts from the top.
Right now, the fastest routers have the worst expl. build success.
This will help correct that.
2023-01-30 12:40:39 -05:00
zzz
bd4415ad5c Blocklist: Don't maintain IPv6 blocklist unless we have an IPv6 address
Don't read in same-country blocklist unless configured or in strict country,
so we don't continue to block when no longer hidden
2023-01-30 11:51:44 -05:00
zzz
86c6800fbd NTCP2: Ensure we publish a "6" address on transition to firewalled
Do not call restartListening() on transition to firewalled
2023-01-30 11:11:48 -05:00
zzz
124ebe9fdf Tunnels: Refactor peer selection
by checking if a peer qualifies when adding, rather than
iterating through the whole netdb to generate an exclusion list at the start.
This was very inefficient and generated needless lookup storms via lookupBeforeDropping()
Same idea for getClosetHopExclude()
Goal is to never iterate through all the known routers, profiles, or connected peers
to select peers for a single tunnel.
Add ExcluderBase and 4 classes for various cases:
Excluder, ClosestHopExcluder, IBGWExcluder, and OBEPExcluder.

Change CSFI.getEstablished() from a Set to a List for efficiency
Improve efficiency of selectActivePeersNotFailingPeers()
by iterating through connected list rather than profiles.
Do not add not-connected peers to exclude set,
which would become huge for hidden routers.

Change getExclude() to shouldExclude()
The exclude set calls shouldExclude() in contains().
Pass the exclude set to ProfileOrganizer.

For client tunnels, do OBEP and IBGW checks at peer selection time,
not afterwards in ConnectChecker, so it doesn't fail at the end in checkTunnel().

Check closest hop when hidden.
Fail-fast for inbound when no connected peers and hidden, do not fall back to non-connected peers.
Should improve startup time for hidden routers.

Use ArraySet for matches to save space
Remove unused selectPeersLocallyUnreachable() and selectPeersRecentlyRejecting()

No peer selection policy changes here.
2023-01-30 08:05:39 -05:00
zzz
8b0cd9e36b Util: Add ArraySet.get() and new constructor 2023-01-29 13:27:51 -05:00
zzz
1e35f940da Util: Comment out main() test 2023-01-29 12:50:54 -05:00
cc00337ec1 pinned alpine base image version 2023-01-29 14:02:54 +01:00
zzz
5d4c173c31 Debug: Give dummy update a version 2023-01-29 07:35:10 -05:00
aac8f217e0 Merge branch 'master' into docker-multiarch 2023-01-28 15:51:22 +01:00
ac4daeb82c changed baseimage to allow for multiarch build (specifically arm64) 2023-01-28 15:47:09 +01:00
zzz
9fd31d014f Reseed test message fix 2023-01-28 07:52:52 -05:00
zzz
bfd7b1a5f5 Tools: Check RI dates and counts in reseed test 2023-01-28 07:43:53 -05:00
zzz
56e00fbe3a Tools: Delete reseed test files before retest 2023-01-28 06:26:08 -05:00
zzz
a27e1393f1 Router: Force the stragglers to rekey 2023-01-27 19:01:11 -05:00
idk
fd68634993 add build.built-by to gitlab override.properties and Dockerfile 2023-01-27 21:30:15 +00:00
zzz
3831348301 Tunnels: Reduce grace period from 120 to 90 sec. 2023-01-27 11:15:07 -05:00
zzz
9cbd7643db Tools: Add CLI reseed test 2023-01-27 10:51:17 -05:00
zzz
4d5a3fc73d Console: Debug page cleanups
Split sections into separate tabs
Clean up VersionAvailable.toString()
Don't limit height of DHT section
2023-01-27 08:01:43 -05:00
zzz
6117d8822e Router: One more conversion to ObjectCounterUnsafe 2023-01-27 07:10:01 -05:00
zzz
886adb12fc Tunnels: Pull now() calls out of loops 2023-01-26 17:04:55 -05:00
zzz
542a51658d i2psnark: Search fixes
Fix JS search when refresh disabled
Fix search cancel when JS disabled
2023-01-26 12:12:35 -05:00
zzz
ee055dbdc0 Console: Add git rev to version info 2023-01-26 10:03:14 -05:00
zzz
33a07f811e Console: Add build date to version info 2023-01-26 09:23:50 -05:00
zzz
2dfe05d682 Console: Comment out disabled non-js summary bar iframe refresh
to save space, included ~50x
Disabled in 2012 for "HTML compliance" reasons
2023-01-26 07:45:06 -05:00
zzz
ad64e9c21e SSU2: Zero out intermediate handshake KDF results in-memory when done
Minor cleanup in est. mgr
2023-01-26 07:13:54 -05:00
zzz
9275c79b39 Console: Add chart of peers in most part. tunnels (advanced) 2023-01-25 12:25:56 -05:00
zzz
8e4e0050c8 Console: Sort webapps.config on save 2023-01-25 11:33:28 -05:00
zzz
87618700b3 Util: New thread-unsafe version of ObjectCounter
for efficiency where thread safety not required
2023-01-25 09:09:02 -05:00
idk
3d88fab782 Merge branch 'docker_font_fix' into 'master'
Install fonts

See merge request i2p-hackers/i2p.i2p!78
2023-01-24 22:46:35 +00:00
zzz
bec1978861 Router: Preliminary support for congestion caps (proposal 162)
Publish based on max tunnels setting only, other limits todo.
Tested on a single router.
Publishing disabled until the next release.
No handling of the caps yet in peer selection or profiling, todo.
2023-01-24 10:47:56 -05:00
zzz
b5bd11ca5a i2psnark standalone: Fix running from outside the directory
Reported by Qubes
ref: http://zzz.i2p/topics/3555
2023-01-23 09:24:01 -05:00
zzz
ee167b6b74 Tunnels: Remove 0 event duration from addRateData() calls 2023-01-22 18:00:28 -05:00
zzz
0af5ea883a bump -4 2023-01-22 10:31:38 -05:00
zzz
9963503ebf i2psnark: Add max files per torrent config
No UI, must edit config file and restart.
ref: http://zzz.i2p/topics/3549

Contains code adapted from I2P+. License:
Permission is granted to upstream to incorporate I2P+ modifications under the license
of the applicable upstream subsystem as specified in LICENSE.txt.
2023-01-22 10:30:58 -05:00
zzz
be5a10194a Build: Fix list of changed files in manifests
Broken in move from mtn to git
Fix some places that were broken even with mtn
2023-01-22 10:08:53 -05:00
zzz
37104e30bf i2psnark: More search CSS and js 2023-01-21 16:38:10 -05:00
zzz
8d019a7275 i2psnark: Search box CSS 2023-01-21 16:00:27 -05:00
bc43249bba Install fonts 2023-01-21 19:57:08 +00:00
zzz
3da4369c96 bump -3 2023-01-21 12:47:05 -05:00
zzz
8bbddfc336 NTCP: NAT fixes part 4
Do not rebind internal port if only SSU external port changed
so "full cone" NAT will work
Log warning if NTCP configured with fixed port different from SSU
2023-01-21 11:51:25 -05:00
zzz
38c839c389 SSU: NAT fixes part 3
Eliminate Symmetric NAT errors for "full cone" NATs with different external port
Separate isPortFixed() states for IPv4 and IPv6
Allow port changes when state is unknown
Require two tests to transition from unknown IPv4 state
Save external port config on change
Don't reset external port config at startup
Add port change event to event log
2023-01-21 11:47:31 -05:00
zzz
b8815fc67b Console: Catch graph error in Docker (Gitlab #383) 2023-01-21 11:13:42 -05:00
zzz
537d6ef0d5 SSU2: Fix initial MTU when SSU1 disabled 2023-01-21 09:36:48 -05:00
zzz
a86ab694a5 SSU2: NAT fixes part 2
Fix rare peer test NPE if we did not set charlie's hash
2023-01-21 08:09:28 -05:00
zzz
9008893308 Console: NAT fixes part 1
Remove ERR- and WARN- prefixes from translated status strings
2023-01-21 07:53:38 -05:00
zzz
b10cf8f698 Build: Add i2psnark-release target 2023-01-19 09:06:58 -05:00
zzz
1b3aed6b6a i2psnark standalone: Add search icon, display full version 2023-01-19 08:51:04 -05:00
zzz
d39d21296f i2psnark: param rename fix, missed one 2023-01-18 12:25:41 -05:00
zzz
0cbbe6297e i2psnark: Rename search param to bypass the XSS filter
Fix encode/decode search param
Copy CSS to non-default themes, not tweaked yet
Add support for shorter nf_ prefix to XSS filter
Remove unneeded float_right, reported by drzed
2023-01-18 12:21:29 -05:00
zzz
1dbd94d52d i2psnark: Search CSS and JS
WIP, more polishing todo
default theme only, others to follow
2023-01-18 11:15:22 -05:00
zzz
d45df857d6 bump -2 2023-01-17 14:59:22 -05:00
zzz
83677f01fb i2psnark: Add basic search box
searches torrent names only
CSS fixups to follow
2023-01-17 14:57:47 -05:00
zzz
5fbf385805 i2psnark: Prep for libtorrent arrival
Use extension version if client not known
Consolidate getAzVersion() calls
Add notes about client identification
2023-01-17 14:50:35 -05:00
zzz
053f261e57 i2ptunnel: Fix typo for SSL outproxy host
for new and existing installs
Reported by Opicaak
2023-01-17 14:32:25 -05:00
zzz
eb03e19f03 Console: Don't say we updated all tunnel pool settings if there weren't any
minor cleanups
2023-01-15 14:08:40 -05:00
zzz
399575aba5 i2ptunnel: Return error message from IRC client on failure to build tunnels
previously just closed the socket
2023-01-15 12:38:00 -05:00
zzz
19e3122f48 i2ptunnel: Return error code from SOCKS client on failure to build tunnels
previously just closed the socket
2023-01-15 11:18:00 -05:00
zzz
acec9b5275 i2ptunnel: Return 503 from HTTP client on failure to build tunnels
previously just closed the socket
2023-01-15 10:37:55 -05:00
zzz
522cf05880 Console: Add netdb search by introducer count 2023-01-15 10:05:20 -05:00
zzz
a3fd28dcf4 i2ptunnel: Interrupt pending client tunnel build when stop button is clicked
Message/log cleanups
2023-01-15 10:02:17 -05:00
zzz
a4220f7bc6 Transport: Add 8080 to ports list
as suggested by drzed
2023-01-15 09:02:35 -05:00
zzz
d6891d4b7a Console: Show smoothed receive BPS for SSU peers
Don't show zero send/receive BPS after 15 sec idle; show smoothed value,
so display isn't mostly zeros.
BPS sorters will now work correctly and totals are more accurate.
Pass now to send/receive BPS methods and BW estimator
Comment out UDPTransport.noteSend()
Fix alignment issue in NTCP peers table
Show 0 instead of 0.00 for zero BPS
Change rounding mode of formatters
2023-01-15 08:17:09 -05:00
zzz
65d99d2082 Build: Provide hints on how to fix it when msgfmt fails 2023-01-15 07:05:55 -05:00
zzz
f3f4cd7a21 Console: Show if data structure is compressible (advanced)
Convert IPv6 addresses to canonical form
2023-01-14 08:08:25 -05:00
zzz
cf82d3a156 Transport: isValidPort() micro-optimization
add i2pd console to list
2023-01-14 07:03:16 -05:00
idk
2ba106e38e use buildI2PSnark rather than pkg as dependency of git-bundle 2023-01-13 20:31:03 +00:00
zzz
c4fd1b610b Router: Simplify published stats values
to be only what stats.i2p needs
Disabled until next release, to preserve dev build anonymity,
tested while enabled
Commented out unsed code
ref: http://zzz.i2p/topics/3515
2023-01-12 15:25:52 -05:00
zzz
841e277180 SAM: Abort tunnel build if control socket closes
Command error handling and message improvements
Implement simple HELP command
bump -1
2023-01-12 13:35:05 -05:00
zzz
0bb9984dfa Util: Add warning about copying router.config to another router 2023-01-12 06:58:51 -05:00
zzz
f814b85a86 Console: Add ability to search netdb for a range of ports
Minor cleanup of dup strings
2023-01-11 13:44:42 -05:00
zzz
904829c1d5 Console: Hide Hidden Services Manager link until TCG is running
Use PortMapper constants to check registration
Reported by lbt
2023-01-11 13:37:29 -05:00
zzz
b2d78e4724 Console: Add service true/false to version info
As proposed at http://zzz.i2p/topics/3520
2023-01-11 13:12:09 -05:00
zzz
34be58962a SSU2: Removed cached bitmasks
Waste of space and probably slower
2023-01-11 13:01:02 -05:00
zzz
fb7cd7e3ef Streaming: now() call consolidation 2023-01-11 12:57:43 -05:00
zzz
e1e65546b8 Build: Add bundle target alias, referenced in some docs
reported by lbt
2023-01-11 12:48:21 -05:00
zzz
a6e8d53b37 Console: Incorporate bionic build patch from previous checkin
Remove patch from debian files
2023-01-11 10:15:12 -05:00
zzz
87fbec3e39 Debian files for 2.1.0
Including bionic build fix
Don't know why focal worked without it
2023-01-11 09:53:37 -05:00
zzz
a5d649ba2d 2.1.0 2023-01-10 09:32:31 -05:00
zzz
1e34738fca SSU: Rewrite/fix previous Java 7 (Android) fix
Update checklist to specify bootclasspath, so these are caught in the future
bump -16-rc
2023-01-08 14:45:17 -05:00
zzz
433340c11b SSU: Fix NPE handling SSU1 peer test msg 7
Reported by drzed
2023-01-08 13:04:23 -05:00
zzz
d9a75a5afc AppArmor: Allow classes.jsa in other locations
Remove dup line
Reported/tested by lbt
2023-01-08 13:04:23 -05:00
idk
43090cbc32 put must be followed by get in order to contain the current key, UDPTransport 2023-01-08 00:42:32 +00:00
idk
e70229140b use a containsKey()+put instead of putIfAbsent because putIfAbsent is not present in Java 8, thereby breaking Maven builds 2023-01-08 00:28:26 +00:00
zzz
b4fb8ba2c9 bump for review -15-rc 2023-01-06 14:45:01 -05:00
zzz
5e23488a96 Blocklist update 2023-01-06 14:39:47 -05:00
zzz
9adbef3f27 Pull translations 2023-01-06 14:38:46 -05:00
zzz
09a97c31fc Reseed: Exclude SSU2 with introducers from local reseed file 2023-01-04 08:52:57 -05:00
zzz
76d8d9110a Console: Add link to sort netdb country chart by count 2023-01-03 10:10:35 -05:00
zzz
67c09c69f0 Console: Replace triangle icons with ** on the new peers tab
Can't get the icons to look nice
2023-01-03 09:29:32 -05:00
zzz
513a33abe6 Profiles: Capacity calculator minor cleanup 2023-01-02 16:44:31 -05:00
zzz
b313817399 Update annotation of tunnel reject codes 2023-01-02 16:21:47 -05:00
idk
0f7dca99d1 don't attempt to pass windows flags to cc when building jbigi, jcpuid on non-Windows platforms 2023-01-02 16:59:23 +00:00
zzz
c0891c4a4c Build: Add mockito to core javadocs path to prevent warnings in mavenCentral.deps task 2023-01-02 09:54:10 -05:00
idk
a94382458e set apart windows flags including JAVA_HOME in case the path contains a space 2023-01-02 02:28:44 +00:00
idk
6856969d01 add quotes around JAVA_HOME on windows so that it can use a JAVA_HOME that exists in %ProgramFiles% 2023-01-01 23:48:57 +00:00
idk
e4fba64fc1 Quote and shellcheck the jbigi.jar build scripts in order to fix errors when building jbigi jars on Windows 2023-01-01 23:09:10 +00:00
idk
0c4fd2dbb1 quote JAVA_HOME during jbigi build 2023-01-01 22:22:03 +00:00
idk
6ad90ca38a Change the gmp mirror so that when you try to build a jbigi.jar it does not fail. Can be changed back by editing core/c/jbigi/download_gmp.sh 2023-01-01 22:05:00 +00:00
zzz
edfc9b1454 I2CP: Reduce session limit to 50
Set limit to 0 if vmCommSystem
i2ptunnel: Do not retry if session limit exceeded
2023-01-01 13:08:25 -05:00
zzz
6bcc866f38 GeoIP 2023-01
bump BuildTime
2023-01-01 11:21:31 -05:00
zzz
04d0ecc1a7 i2psnark: Prep for JS DnD (Gitlab MR !73)
Strip file:// in create form for non-JS DnD
Add IDs to relevant elements for access by JS
JS to follow after further testing
2023-01-01 10:46:07 -05:00
zzz
2ad33706e3 i2psnark: Add missing button icons (dark/light themes) 2023-01-01 10:41:59 -05:00
zzz
952d9fd471 Build: Add jsdoc target
Doesn't really do much yet because none of our js has jsdocs
2023-01-01 10:40:33 -05:00
zzz
be7e213736 Pull translations from tx
preliminary in case TX API v2 stops working
2022-12-31 15:08:09 -05:00
zzz
5818f8e26d bump -14-rc 2022-12-31 14:10:58 -05:00
zzz
6b1859421f i2psnark: Throttle torrent startup to prevent OOMs
for a large number torrents
ref: http://zzz.i2p/topics/3475
2022-12-31 14:10:06 -05:00
zzz
4af2122176 Console: Change color palette for graph rendering on dark theme
to improve text readability.
Remove post-render CSS modification of graph images

Contains code adapted from I2P+. License:
Permission is granted to upstream to incorporate I2P+ modifications under the license
of the applicable upstream subsystem as specified in LICENSE.txt.
2022-12-31 14:02:27 -05:00
zzz
ec8d0a2f61 Console: Fix dark theme CSS color tweak affecting more than the intended inbound.png and outbound.png images 2022-12-31 08:37:23 -05:00
zzz
0792526c16 Console: Move hide/show news buttons back to the right (light theme)
unintended side-effect of CSS tweak in last release
2022-12-31 08:07:03 -05:00
zzz
b607304f7b i2psnark: Update tracker list after editing torrent (Gitlab #380) 2022-12-31 07:35:25 -05:00
zzz
f2940146c4 Util: Add methods to convert IPv6 addresses to canonical RFC 5952 strings
Moved from NetDbRenderer
Use in CLI only for now
CLI and conversion micro-optimizations
2022-12-30 06:21:40 -05:00
zzz
0d97dbf534 Tunnels: Add another tier for client tunnel build limiter
only if configured for 6 or more tunnels
2022-12-30 05:50:09 -05:00
zzz
f7d134066d UPnP: Catch AssertionError when closing SSDP multicast socket
Reported on Windows 10
ref: http://zzz.i2p/topics/3500
2022-12-30 05:33:10 -05:00
zzz
dcb8009c63 Tunnels: Limit requested client tunnels during congestion
This will probably also reduce builds at startup.
Limits may require tweaks after further testing.
2022-12-29 12:07:48 -05:00
zzz
32ffd056a1 Throttle: Don't parse default values every time 2022-12-26 14:47:33 -05:00
zzz
b5ce70955b bump -12 2022-12-26 14:15:30 -05:00
zzz
2b8d3477ce SSU1: Symmetric NAT detection fixes
Never let SSU1 test result be symmetric NAT, it's probably charlie
Don't use SSU1 test if we think we are symmetric NAT
Cleanup two places to call new fail() method
2022-12-26 14:13:43 -05:00
zzz
d655ad206c SSU: Fix NPE when SSU2 disabled 2022-12-26 07:21:49 -05:00
zzz
d16aaab35f Router: Don't blocklist our own IP 2022-12-26 07:13:10 -05:00
zzz
ba0fee151b SSU2: Redesign peer test symmetric NAT detection
- Send msg 6 even if msg 5 is not received, after a short delay, to detect symmetric NAT
- Prevent test result of symmetric NAT if Charlie is the one that appears to be symmetric natted.
- Mark if Charlie unreachable if apparently symmetric natted.
- Do not treat a different IP but same port as symmetric NAT
- Increase msg 6 retransmission frequency
- Ignore msg 5 received after sending msg 6
- Call externalAddressReceived() on reception of msg 7
- Add javadoc for testComplete() state machine

Most changes only affect SSU2; some SSU1 changes to follow.

ref: http://zzz.i2p/topics/3489
2022-12-26 06:14:55 -05:00
zzz
2ce2b894b7 SSU2: Minor cleanups
Rename isSnatted() to isSymNatted()
Minor rewrite in PeerState2.gotTermination()
Remove dead peer when pinging fails in intro manager
Cleanup ip length check in externalAddressReceived()
Log tweaks
2022-12-26 05:55:47 -05:00
zzz
d9979b8f97 Console: Sort tunnels by name on /tunnels, /configtunnels, /i2ptunnel 2022-12-26 05:38:35 -05:00
zzz
2d633a0bfd SSU2: Don't replace previous destroyed peer in the cache
kill the new one instead
2022-12-23 16:39:30 -05:00
zzz
fdbdd10a89 SSU2: Refactor in-session PacketBuilder2 methods to throw IOE
Primarily for Peer Test and Relay, so the test or relay can be aborted.
Previously, sends on a dead PeerState2 were not detected or prevented.
Catch IOE throughout where necessary around all build() calls.
Add a fail() method in PeerTestManager
2022-12-23 15:47:09 -05:00
zzz
a6f7f9ec12 SSU1 peer test log level reduction
SSU2 peer test state add alice IP/port back to logging, needed for debugging
2022-12-23 14:29:19 -05:00
zzz
3dd242c1c7 SSU2: Peer test with our current address, not our address from the Bob session,
which could be different, esp. with temporary IPv6 addresses.
Could result in an erroneous SNAT result.
Add logging if different when starting test.
Check address block received in msg 6, use in logging only for now
Add logging of address block received in msg 7 if different than expected (possible SNAT)
Remove isValidPort() check in msg 5 recently added, already checked in code above
Add notes about possible externalAddressReceived() calls from peer test
Add notes about our address in PeerState2
2022-12-23 09:04:09 -05:00
zzz
defe514a31 SSU2: Enforce that address block is present in session created
Simplify check in EstablishmentManager.sendConfirmation(), we don't need to validate
RemoteHostId IP again, we did it before connecting.
Add check that received port is >= 1024.
2022-12-23 07:42:50 -05:00
zzz
31d0bc33d6 Blocklist: Don't add IPv4 addresses permanently banned to the transient list
Already hidden on /configpeers, so don't waste the space
2022-12-23 07:36:22 -05:00
zzz
3580430005 bump -11 2022-12-22 09:59:22 -05:00
zzz
ac799b7ffa SSU2: Further restrict states when we will be a peer test Charlie
and also use those states for when to publish B cap
2022-12-22 09:50:39 -05:00
zzz
4c8e0149f3 SSU2: Peer Test fixes
Check for dup msg 5
Store the time msg 6 sent
Ignore msg 5 after sending msg 6
Ignore msg 7 before receiving msg 4
Validate ip/port in msg 7
Update rcv times for dups
Log tweaks
2022-12-22 08:38:08 -05:00
zzz
150a68a3e0 SSU: Peer Test scheduling fixes
At startup, and for IPv6 so it doesn't lose out to IPv4
PeerTestEvent logging cleanup
2022-12-22 08:20:32 -05:00
zzz
321a21ae9b Util: Add SimpleTimer2.TimedEvent.toString()
to clean up timer crash messages
2022-12-22 07:27:04 -05:00
zzz
d73be206e5 SSU2: Remove ENABLE_xxx feature flags used in early development 2022-12-21 16:19:30 -05:00
zzz
c521d75ef7 CLI: List available commands more compactly 2022-12-21 09:42:57 -05:00
zzz
479ccd57df CLI: Add a "help" command 2022-12-21 07:36:03 -05:00
zzz
4e174df746 Router: Add IPv6 analysis to Sybil checker
Add to console sybil page
Fix links for IPs close to us
Header and reason tweaks
Increase verified family credit
2022-12-21 07:00:38 -05:00
zzz
a71f62c566 Router: Add IPv6 localhost and wildcard to blocklist 2022-12-20 15:12:12 -05:00
zzz
5ddb70eaea Util: Rewrite Addresses.getIPOnly() for 10x speedup 2022-12-20 15:09:10 -05:00
zzz
fd58472cc5 Sybil: Pass reason to the blocklist, for logging only 2022-12-20 14:54:35 -05:00
zzz
e9c74c7c45 bump -10 2022-12-20 08:54:55 -05:00
zzz
903477e905 Change calls from Addresses.getIP() to Addresses.getIPOnly() for peer IPs
getIPOnly() is more efficient for pure IP addresses (no hostnames)
2022-12-20 08:51:29 -05:00
zzz
fd2af4d89c log typo 2022-12-20 08:46:04 -05:00
zzz
ccb01ccf7f SSU2: Bundle RI with peer test messages 2 and 4 if possible
similar to previous checkin for relay intro
2022-12-20 08:44:55 -05:00
zzz
4d65024977 SSU2: Peer test improvements
- Return OK as Alice when only receiving msg 5, unless snatted (SSU 1 also)
- Allow and handle firewalled Charlie as Alice
- Only create peer test data once as Alice
- Store test status and send-to-Alice time in test state to support retransmission
- Don't delete state after sending msg 4 as Bob, for possible retransmission
- Check for IP mismatch from Charlie as Alice, abort test and assume good
- Check for port mismatch from Charlie as Alice and validate
- Skip unroutable addresses when searching through RI for the right one
- Respond to retransmitted msg 1 as Bob
- Respond to retransmitted msg 2 as Charlie
- Update Charlie timer to retransmit msg 5
- Only send Charlie RI to Alice (as Bob) if test was accepted
- Convert timers to SimpleTimer2 (SSU 1 also)
- Log tweaks
2022-12-20 06:12:38 -05:00
zzz
72e2161924 CLI: Add NewsHandler CLI to fetch news from servers 2022-12-19 10:09:58 -05:00
zzz
7bd220adfc Console: Fix IPv6 searches for compressed/expanded address format 2022-12-19 08:35:15 -05:00
zzz
6092e35b65 Router: Time initialization fixes and cleanups
Most changes are relevant only if NTP is disabled or failed at startup.

- Require two peers that agree for transports to initialize time
- Briefly ban skewed peer when not initialized, so another peer will be the second sample
- Allow SSU2 to initialize time even for large skews
- Do not allow NTCP2 inbound to initialize time for large skews
- Disable SSU1 time initialization when SSU2 is enabled
- When SSU2 is disabled, allow SSU1 time initialization even for large skews
- Don't adjust to large inbound NTCP2 skews when not initialized
- Round time sent in NTCP2 DateTime block
- Adjust SSU2 skew for RTT
- Don't sort by absolute skew on SSU /peers tab so we can find median
- Only call System.currentTimeMillis() once in RouterClock.setOffset()
- Log tweaks
2022-12-19 06:45:30 -05:00
zzz
51d567ecb4 SSU2: Compress and bundle Alice RI with relay intro
as Bob, to send to Charlie, if it fits.
Otherwise, delay sending relay intro, so the RI DSM gets there first.
This makes relay faster and more reliable.
Periodically clean _nonceToAlice
Log tweaks
2022-12-18 07:06:52 -05:00
zzz
33f9bd8156 Transport: Fix NPE at shutdown caused by _currentAddresses change 2022-12-17 13:54:37 -05:00
zzz
73d226e7d7 bump -9 2022-12-17 11:59:34 -05:00
zzz
f26c616fdc SSU: Rewrite isTooClose()
to use actual local IP rather than iterating through getCurrentAddresses(),
more efficient and works even when firewalled
2022-12-17 11:56:12 -05:00
zzz
db459de0c6 Console: Fix UDP disabled error when SSU 1 disabled 2022-12-17 10:10:06 -05:00
zzz
ef542d8898 SSU2: split() and send in-session termination after certain session confirmed errors
containing a specific termination reason,
and create a post-termination handler directly from IES2 for any additional packets.
Don't do this unless we get intro key and validate static key in RI.
Don't blocklist the IP for a banned router unless we have validated
the static key to prevent spoofing.
Don't queue data packet after failure
Don't send additional terminations after receiving termination ack
2022-12-17 10:04:18 -05:00
zzz
58e95dc353 SSU: Don't call test forceRunSoon() in addPeer() to prevent test thrashing.
Also removes the rebuildIfNecessary() call claimed to be removed in previous checkin.
Since we aren't thrashing any more, reschedule test after UNKNOWN results,
with the delay depending on current state.
log tweaks
2022-12-17 09:41:41 -05:00
zzz
cdc61ee6ea Add change required for previous commit 2022-12-17 09:36:32 -05:00
zzz
2d2c8fdc96 SSU: Don't call rebuildIfNecessary() from dropPeer() and addPeer() every time
to prevent thrashing.
Only rebuild in dropPeer() if the peer was a published introducer.
Only rebuild in addPeer() if the peer offered to relay and we need introducers.
2022-12-17 09:33:47 -05:00
zzz
d9bb3d0b96 SSU2: log tweaks 2022-12-17 09:29:09 -05:00
zzz
05d60d70e2 SSU2: Immediately remove establish state from EstablishmentManager on fatal error
to free up space and prevent problems handling additional packets
2022-12-17 09:17:55 -05:00
zzz
67d20d4af5 Transport: Change _currentAddresses from COWAL to standard ArrayList and lock
COWAL caused problems because replaceAddress() was removing the wrong address,
since RouterAddress.equals() does not compare caps, so empty '4' and '6' addresses would be equal.
So we could temporarily end up with multiple v4/v6 addresses.
COWAL wasn't really buying us anything anyway.

Fix removeAddress() that called the listener even if no change.
2022-12-17 08:43:25 -05:00
zzz
95bf6be670 SSU2: PacketHandler log tweaks 2022-12-16 08:40:36 -05:00
zzz
8d132a0ba7 Console: Make the /configlogging overrides box bigger if necessary (advanced only) 2022-12-16 06:59:25 -05:00
zzz
bbbc127193 bump -8 2022-12-15 15:08:58 -05:00
zzz
21c7ad4a89 SSU2: Enhance PeerTestState logging
avoid dup previous charlies on list
2022-12-15 15:05:10 -05:00
zzz
af5456b846 add javadocs for banlist return values 2022-12-15 15:03:06 -05:00
zzz
2c955e300f SSU: Check banlist after session confirmed
blocklist IP if banned
2022-12-15 15:01:52 -05:00
zzz
138d674662 SSU2: Reduce log level of 'new ack not found' 2022-12-15 14:59:46 -05:00
zzz
9b0ace19c1 Router: Change transient IPv4 blocklist to LHMCache
Reduce transient blocklist sizes if slow
Improve logging of block source
2022-12-15 14:57:20 -05:00
zzz
3eb4083cb3 SSU2: Fix retransmission of session confirmed
Was setting packet length to number of packets.
Add check and log in UDPSender
Add notes where length is checked
2022-12-15 14:50:38 -05:00
zzz
799944b23b SSU2: Don't attempt to connect to ourselves as an introducer
reported by drzed
2022-12-15 14:17:24 -05:00
zzz
8bda9bf804 SSU2: Update activity on path challenge/response 2022-12-14 17:23:31 -05:00
zzz
232586c709 bump -7 2022-12-14 16:11:16 -05:00
zzz
32a9f47375 Tunnels: Reduce log level of can't-decrypt build messages 2022-12-14 16:09:30 -05:00
zzz
9d50e4d5ed NTCP: Log source of clock adjustment at startup 2022-12-14 14:58:44 -05:00
zzz
f50f55bb54 Merge branch 'fix/chacha' into 'master'
Fix wrong arguments order in ChaCha20 encrypt

See merge request i2p-hackers/i2p.i2p!72

Broken in 1.8.0. Almost certainly broke LS2 encrypted leaseset, but not yet tested.
Did not break anything else. I tested that this fix didn't break anything.
2022-12-14 19:54:10 +00:00
zzz
e71ba76d98 SSU2: Catch "shift too big" IAE from acked bitfield while sending termination
Add preliminary code to terminate session before
there are too many unacked messages to cause the IAE
(untested)
log tweaks

reported by drzed
2022-12-14 14:42:12 -05:00
zzz
4aa6d15933 SSU2: Another consolidation of keys for building retry 2022-12-14 14:35:12 -05:00
zzz
980276b966 SSU2: Preliminary fixes for handling retransmitted retries
and storing session request packet for retransmission
Previously, we would regenerate handshake state on every retry,
and we would not re-save the new session request packet after a retry.
Check for wrong token received in additional retries.
2022-12-14 14:32:08 -05:00
zzz
cf32b7844b SSU2: Reject peer test or relay as Charlie if snatted
remove dup peer test 6 logging
2022-12-14 14:23:22 -05:00
zzz
a112c3a1ed SSU2: Consolidate dup encrypt header keys in IES2/OES2 2022-12-14 14:15:56 -05:00
zzz
9f9a88cf32 SSU2: Drop short session request messages in packet handler
both before and after retry, before passing to IES2
log tweaks
2022-12-14 14:06:18 -05:00
zzz
28a79def5a NTCP: Fix rare NPE sending termination
reported by drzed
2022-12-14 10:51:34 -05:00
zzz
4443fb464a Router: Add stack trace to log error
to catch the message-to-ourselves culprit
2022-12-13 16:27:48 -05:00
zzz
08c31aa6f6 Tunnels: Tighten the hop throttle more
after further testing, thx obscuratus + drzed
2022-12-13 12:39:02 -05:00
a393912213 Fix ChaCha20::encrypt 2022-12-14 00:53:52 +08:00
zzz
20f414c7fa SSU: Don't publish B cap when snatted
as suggested by orignal
2022-12-13 06:27:41 -05:00
zzz
580f954254 SSU2 Peer Test: Bob asks another Charlie on rejection 2022-12-12 12:22:22 -05:00
zzz
3472871e35 SSU: now() call reduction 2022-12-12 05:53:40 -05:00
zzz
803265660e SSU2: Destroy PS2 cipher states when done 2022-12-11 15:12:15 -05:00
zzz
4a4ca0cdf0 SSU2: Handle retransmitted token request
and resend retry.
Previously failed to decrypt it.
2022-12-11 15:11:12 -05:00
zzz
415e31e560 SSU2: Allow termination in retry
Handle skew reason in termination, possibly ban peer
Adjust clock at startup when terminated with skew reason
Don't send immediate termination to a too-close address
Javadoc fixes
Log tweaks
2022-12-11 11:35:31 -05:00
zzz
dc400c652a SSU2: Send termination on inbound session/token request
(rate limited) at conn limits or when alice is banned.
Process retry payload even if token is 0, to get termination reason
Wait longer for session request after retry, allowing for at least 2 retransmissions, to reduce IES2 failures
Ban peer if he bans us in retry
Remove unused writePayload()
Javadoc fixes
Log tweaks
2022-12-11 09:18:51 -05:00
zzz
897ea797cb Graphs: Fix RRD time skew handling
rrd4j throws different exception than jrobin did
2022-12-10 17:29:07 -05:00
zzz
01618c6202 SSU: Update activity timestamps for relay and peer test messages
Javadoc fixes
Log tweaks
2022-12-10 13:00:33 -05:00
zzz
337fd36633 SSU2: Peer Test fixes
Don't set AlicePortFromCharlie in msg 5, should be msg 7 only
Assume success if no address block in msg 7 (i2pd)
Require introducers for SNAT states
Don't log no charlie port if no IP
Add some TODO notes
Log tweaks
2022-12-10 12:11:59 -05:00
zzz
75e23fd1e3 Tunnels: Tighten the hop throttle
drop sooner when over limit to better protect the network
penalize throttled peers in profile to discourage use in our tunnels
2022-12-09 09:23:45 -05:00
zzz
944dff0aa7 Console: Add peer IP/port to transport tab tooltips (advanced only) 2022-12-09 07:14:38 -05:00
zzz
7425484b55 SSU: Disable SSU1 option, part 6 - don't bid on SSU1 addresses 2022-12-09 06:37:19 -05:00
zzz
19269dbaf3 SSU2: Fix IAE creating ACK block
by removing unneeded 255 max ranges check in constructor.
Higher limit of 512 is enforced in PacketBuilder2.
Reported by drzed
2022-12-08 08:01:08 -05:00
zzz
59afc44c8a Console: Show "--" for values < 1 on profiles tabs 2022-12-07 17:35:14 -05:00
zzz
8ada237bfa Console: Remove "Standard" for peers and "unknown" for caps on profiles tabs 2022-12-07 17:27:50 -05:00
zzz
a77f016288 Console: Show "--" for 0% fail rate on floodfill tab 2022-12-07 17:04:38 -05:00
zzz
5a6f92bbbf Console: Change "integrated" to "floodfill" in summary bar 2022-12-07 17:01:02 -05:00
zzz
2e6a4930a0 Console: Fallback to receive MTU on MTU sort in SSU tab 2022-12-07 16:57:56 -05:00
zzz
855bb2af33 SSU2: Post-termination handler part 9
Cancel timers on eviction from cache
2022-12-07 15:55:21 -05:00
zzz
55e2fae135 SSU2: Post-termination handler part 8
Implement termination retransmission
Scale size of handler cache based on max conns
Kill handler sooner once we get an ack
Javadoc fixes
2022-12-07 10:19:18 -05:00
zzz
55f2d782ce SSU2: Post-termination handler part 7
Kill handlers at shutdown
2022-12-06 13:06:37 -05:00
zzz
41e05c8135 SSU2: Token improvements part 2
Don't send tokens in the handshake, now that we have a handler
to process tokens received in the termination ack
2022-12-06 12:52:43 -05:00
zzz
7fdd3d1711 SSU2: Post-termination handler part 6 WIP
Add the handler
2022-12-06 12:45:09 -05:00
zzz
809f927219 SSU2: Post-termination handler part 5 WIP
Don't create a new inbound token if we have one that's still good,
for when the handler retransmits terminations
2022-12-06 12:30:46 -05:00
zzz
ad18c98330 SSU2: Post-termination handler part 4 WIP
Save destroy reason in PeerState2
Add PeerState2 methods to get data for new handler
Log when token received
2022-12-06 12:18:56 -05:00
zzz
2451ea31bb SSU2: Post-termination handler part 3 WIP
PacketBuilder2 takes SSU2Sender
Don't check session lifetime or router shutdown to send token with termination
2022-12-06 12:14:16 -05:00
zzz
2e817416d5 SSU2: Post-termination handler part 2 WIP
PeerState2 implements SSU2Sender
2022-12-06 12:09:00 -05:00
zzz
0fd6c672d3 SSU2: Post-termination handler part 1 WIP
Add interface to go over PeerState2 and the new handler
2022-12-06 11:45:33 -05:00
zzz
3e4014a6f6 Debian: Change i2p-doc priority from extra to optional
per Debian manual, extra is deprecated and means the same thing as optional
https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities
2022-12-05 09:12:47 -05:00
zzz
706cd5a129 SSU2: Token improvements and fixes part 1
- Set cache size based on connection limit
- Track average inbound cache eviction time
- Set inbound expiration based on cache time
- Reduce max inbound expiration
- Fix saving inbound token sent after relay response or hole punch
- Dont send or save tokens if we are symmetric natted
- Sort persisted tokens by expiration so they are expired in correct order on reload
- Periodically expire tokens from cache
- Add getters to Token class
- Add missing case IPV4_SNAT_IPV6_UNKNOWN to EnumSets
2022-12-04 10:04:18 -05:00
zzz
974ffabd18 Debian changelog for 2.0.0-2ubuntu1 fix (gitlab #376) 2022-12-02 15:50:24 -05:00
zzz
d632e08386 Debian: Fix stray char in links file causing symlinks in / (gitlab #376) 2022-12-02 13:20:23 -05:00
zzz
5e623a349c Console: Hide totals row on /peers status tab if only one transport 2022-12-02 10:01:48 -05:00
zzz
8e7c8cab48 SSU: Disable SSU1 option, part 5 WIP - more MTU fixes 2022-12-02 09:15:28 -05:00
zzz
1eee60c0ce SSU: Disable SSU1 option, part 4 WIP - MTU fixes 2022-12-02 08:13:26 -05:00
zzz
1650ce35d0 SSU: Disable SSU1 option, part 3 WIP - NPE fixes 2022-12-01 17:27:19 -05:00
zzz
bdad71bd08 SSU: Disable SSU1 option, part 2 WIP
- Null out SSU1 things
- Don't publish SSU1 intro key
- Use all introducer slots for SSU2
2022-12-01 16:20:33 -05:00
zzz
2c460e095d default true 2022-12-01 10:47:01 -05:00
zzz
1b6ece965c Console: Hide SSU1 row on /peers status tab if disabled 2022-12-01 08:25:37 -05:00
zzz
d0cd620364 UDP: Add option to disable SSU 1 - Part 1 - WIP
More todo, do not attempt until feature is completed
2022-11-30 16:05:38 -05:00
zzz
f8e0ee65f2 i2ptunnel: Change enc type defaults
ECIES (ratchet) introduced about 4 years ago, and we are still defaulting to both ECIES and ElG in most places.

There are four cases:

- New install: $I2P/i2ptunnel.config as shipped
- New tunnel: i2ptunnel code sets default
- Existing tunnel, no enc type config: i2ptunnel code sets default
- Existing tunnel, config changed and saved via UI in last 4 years: Setting as in config file

Changes:

- New install: Change eepsite and IRC client to ECIES-only; shared clients remains both
- New tunnel: Change from both to ECIES-only
- Existing tunnel, no enc type config: Change servers to ECIES-only; clients remain both
- Existing tunnel with enc type config: No defaults, no change
2022-11-28 09:38:34 -05:00
zzz
f67b62a3a1 javadoc typo 2022-11-28 07:34:24 -05:00
zzz
6096fc993c SSU: Reduce log level on SSU1 intro slot, normal if it's a SSU2 slot 2022-11-28 07:32:08 -05:00
zzz
6b44254c16 Console: ConfigTunnels backend minor cleanup 2022-11-28 07:29:58 -05:00
zzz
b60be22754 Util: Add path length constraint = 0 to selfsigned certs 2022-11-28 07:15:19 -05:00
zzz
10b23915f1 i2ptunnel: Change default POP tunnel name to match the hostname 2022-11-26 12:44:09 -05:00
zzz
cb5d7f1f8d i2ptunnel: Fix SOCKS outproxy port configuration after testing
log tweaks
2022-11-26 10:54:22 -05:00
zzz
dfe36b64a5 Util: Fast check for random nextInt(1) and nextLong(1)
Document differences from Java's random for n=0
Entropy harvester cleanups, we're not going to add a factory as jrandom implied.
2022-11-26 09:36:30 -05:00
zzz
cb5be9530a SSU2: Avoid rare NPE handling apparent session confirmed without inbound state
reported by drzed
2022-11-26 09:31:31 -05:00
zzz
3d54dea3dd SSU: Don't build a 4 cap address at startup if configured for IPv6-only 2022-11-26 09:27:44 -05:00
zzz
d726737b23 Console: Hide IPv4/v6 columns on /peers status tab
if disabled or no address
2022-11-26 09:13:09 -05:00
zzz
d9a9c17d02 i2ptunnel: Allow IRCv3 ACCOUNT and CHGHOST through the filter 2022-11-25 10:49:12 -05:00
zzz
84f8506912 Profiles: Don't let one corrupt file kill the loader thread
Name the loader thread
Reported by Qubes
ref: http://zzz.i2p/topics/3469
2022-11-25 08:30:41 -05:00
zzz
c2efb40b62 Console: Tag some /netdb strings that are already tagged elsewhere 2022-11-24 13:42:41 -05:00
zzz
cae522f90b Console, i2psnark standalone: Fix UI configuration of Argentinan Spanish
Add partial Danish translation for i2psnark
Enable zh_TW UI configuration for i2psnark standalone
2022-11-24 12:41:21 -05:00
zzz
d036993b23 i2ptunnel: Outproxy type config UI HTML fixup
reported by drzed
2022-11-24 07:39:08 -05:00
zzz
21a90fc2ec Tunnels: Adjust expiration job start if default reject time overridden by config
reported by drzed
2022-11-23 17:51:18 -05:00
zzz
17aa96ce09 Console: Add LS lookup to search form 2022-11-23 17:12:47 -05:00
zzz
d82e2fe5ac bump -1 2022-11-23 12:24:29 -05:00
zzz
965f84bbfa Console: Add status and banned tabs to /peers (WIP)
Status tab now the default
2022-11-23 12:23:17 -05:00
zzz
a825949a8a i2ptunnel: Fix log message on config migration 2022-11-23 12:10:21 -05:00
zzz
6b2bbda02a SAM: Make enough space for dests with certs without realloc 2022-11-23 12:08:11 -05:00
zzz
495d91193c i2ptunnel: SOCKS 5 tunnel improvements and torsocks support
- Add support for Tor RESOLVE extension by caching and returning fake IP
- Handle user/pw when not required to support Tor stream isolation
  (not really isolating, just handling the authentication)
- Fix user/pw authentication
- Handle outproxy config changes after start
- Support CONNECT outproxies
- Add config UI for outproxy type
- Enable IPv6 (untested)
- Support outproxy config with :port (untested)
- Various cleanups

Further testing required
2022-11-23 12:03:08 -05:00
zzz
50ee30b133 Router: KeysAndCert compressible padding (Proposal 161, Gitlab MR !66)
Update some KeysAndCert and PKF debug output

ref: http://zzz.i2p/topics/3279

Replaces the 256-byte ElG key in dests with padding.
Make all padding in dests and router identities a repeating random 32-byte pattern.

This will make gzipped dests and router identities be much smaller:
Dests: appx. 320 bytes smaller (82% reduction)
RIs: appx. 288 bytes smaller (74% reduction)

Expected to primarily benefit database store messages and streaming SYNs.
Does not rekey or affect existing destinations or router identities.
Testers running this patch may be identifiable via transient destinations.
New installs with this patch will be identifiable via router identities.

This also will significantly speed up Destination creation as
we will no longer generate an ElG keypair.

Tested for several months.
2022-11-23 11:49:00 -05:00
zzz
c9ea1e1a22 SSU2: Increase Session Created max padding
to possibly make protocol identification harder
Preliminary; final value TBD.
2022-11-23 09:58:04 -05:00
zzz
98477eef9f SSU: Remove unneeded old queue latency check in UDPSender
as the queue is CoDel already
reported by drzed
2022-11-23 09:53:09 -05:00
zzz
0d571a5565 Build: Add debcheckpatch to release targets 2022-11-23 09:46:43 -05:00
zzz
dae60e5387 CLI: Sort MTU output by address 2022-11-23 09:45:30 -05:00
zzz
66567bc618 Console: Change mtn tunnel in help FAQ to git 2022-11-23 09:41:14 -05:00
zzz
a40adc5465 Crypto: Don't use AccessController in I2PProvider, deprecated as of Java 17
ref:
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/security/AccessController.html
2022-11-23 09:36:39 -05:00
zzz
5d259efdd8 Console: /configlogging fixes
Add UI for enabling log compression (requires routerconsole.advanced)
Don't save and display override changed message unless overrides changed
Only call ctx.logManager() once in helper/handler
2022-11-23 09:32:08 -05:00
zzz
fb14907fa8 Console: Remove brackets on /debug update and app manager sections and other cleanups for readability 2022-11-23 09:06:01 -05:00
zzz
77bf7f1658 Console: Dark theme banlist margin fix 2022-11-23 08:45:09 -05:00
zzz
eb5b18ed23 SusiDNS: Fix off-by-one in next page last item number 2022-11-23 08:43:03 -05:00
zzz
8fe9c487d3 Build: Windows script updates for 2.x.x 2022-11-22 13:26:04 -05:00
zzz
9b097da22f Debian files and doc updates for 2.0.0 2022-11-22 13:24:54 -05:00
zzz
3d4909381c Build fix for 2.x.x versions 2022-11-21 13:03:54 -05:00
zzz
8d1d9a020f 2.0.0 2022-11-21 13:00:21 -05:00
zzz
52adc9dc16 Pull translations from transifex 2022-11-18 13:45:25 -05:00
idk
f02bf9b72b quote %JAVA% in eepget.bat script on Windows to prevent paths from splitting. Closes 31 on i2p.www, which was mis-filed 2022-11-17 22:07:55 -05:00
idk
907e649647 update Docker.md to reflect safe defaults, close #374 2022-11-14 23:51:12 -05:00
idk
da17c8df52 Merge branch 'i2p.i2p-31337-master-patch-36622' into 'master'
Allow passing the IP address where the router console is reachable when running a Docker container

See merge request i2p-hackers/i2p.i2p!68
2022-11-14 18:55:22 +00:00
idk
d4155625e4 Allow passing the IP address where the router console is reachable when running a Docker container 2022-11-14 18:55:21 +00:00
zzz
114694434c SAM: Change default nickname for primary sessions 2022-11-12 17:00:11 -05:00
zzz
e54f5ffadd i2ptunnel: Fix IRC USER filtering
Wasn't passing through user and realname fields
Pass through RFC 2812 mode field if present
reported by RN
2022-11-12 15:26:27 -05:00
zzz
7b75ee5a0a SAM: Add warning at startup if not bound to localhost 2022-11-09 10:45:53 -05:00
zzz
d435e44e5f Update Debian doc 2022-11-09 10:37:20 -05:00
zzz
109402cea5 Refresh Debian patches 2022-11-09 10:36:34 -05:00
zzz
73cde7abba Systray: Javadoc fix, make new method private 2022-11-09 10:30:49 -05:00
zzz
2f3615e001 poupdate-source 2022-11-09 08:30:59 -05:00
idk
524b2ab417 Merge branch 'edge-registry-query' into 'master'
change registry query from retrieiving iexplore.exe to edge.exe

See merge request i2p-hackers/i2p.i2p!70
2022-11-07 02:44:16 +00:00
idk
d43c9d047b change registry query from retrieiving iexplore.exe to edge.exe 2022-11-07 02:44:15 +00:00
zzz
d774b63d83 Drop muwire from console home page 2022-11-06 11:38:18 -05:00
zzz
b54eb9b4d5 SSU: Temporarily ban ip/port after inbound handshake failure 2022-11-01 11:55:20 -04:00
zzz
5947275aae SSU2: Prep for more padding in handshake 2022-11-01 09:25:44 -04:00
zzz
f3f669dc2e SSU2: Fail IES2 on all session request after retry errors
Don't hexdump for RI errors
Don't throw ISE when sending 2nd retry
2022-11-01 09:21:09 -04:00
zzz
ddd6a37507 SSU: Prefer UDP in China
Don't exceed conn limit even when preference is always
2022-11-01 09:06:50 -04:00
zzz
37e93f6097 GeoIP 2022-11-01 2022-11-01 08:42:21 -04:00
idk
1e5a69a80b Swap old trac wiki with new mediawiki wiki 2022-10-29 10:22:40 -04:00
zzz
e12b3c697d SusiDNS: Comment out debug logging 2022-10-22 13:53:46 -04:00
zzz
0224a0f03b Console: Make NavHelper non-static
add NavService interface
hang off ClientAppManager
i2psnark: register additional instances with NavService
2022-10-19 15:33:53 -04:00
zzz
f83f467b28 SusiMail: Add icons to the buttons that were missing them (dark theme)
Change mark-all icon (light theme)
2022-10-19 13:05:50 -04:00
zzz
bed4563257 Debian: Change dependency from transitional package libservlet3.1-java
to libjsp-api-java and libservlet-api-java
and update symbolic links to the jars in /usr/share/java
Note that the previous symlink to servlet-api-3.1.jar was
another symlink to servlet-api.jar which was actually API 4 anyway.
2022-10-19 12:33:06 -04:00
zzz
d2d9a067ce javadoc fix 2022-10-19 11:46:19 -04:00
zzz
8fee843315 Tunnels: ConnectChecker fixes
add support for 4 and 6 caps
add support for SSU2
remove support for NTCP 1
2022-10-17 14:18:50 -04:00
zzz
21d665b812 Console: CSS fixes for lists in news entries 2022-10-17 11:04:36 -04:00
idk
144271e4ca Merge branch 'programdata-path-fix' into 'master'
remove Application Data from path to I2P service config on Windows

See merge request i2p-hackers/i2p.i2p!65
2022-10-16 21:58:34 +00:00
idk
24fb6c9347 remove Application Data from path to I2P service config on Windows 2022-10-16 21:58:33 +00:00
zzz
1c29d752bd SSU2 Relay: Use from port in hole punch if different from relay response port
to support Charlies behind symmetric NAT
Check for IP mismatch in hole punch
Ban Charlies with bad IP/port
Ban Charlies who ban us
2022-10-16 12:13:26 -04:00
zzz
3f1d2f9808 i2psnark: Increase piece limit to 64K
as requested by RABADA ref: http://zzz.i2p/topics/3436
2022-10-15 08:19:30 -04:00
zzz
166d1ba86b SSU2: Track recently-closed sessions (gitlab #370)
and drop packets received on them, to prevent SSU1 fallback processing
2022-10-10 11:33:05 -04:00
zzz
64873218ba SSU2: Enable by default 2022-09-28 09:26:28 -04:00
zzz
0eb96d6ef0 Installer: Fix error on Windows when username contains a space (gitlab #367)
in fixperms.bat
2022-09-28 09:17:44 -04:00
zzz
beaeb9c835 SSU2: Ensure min packet size for pings 2022-09-23 11:20:17 -04:00
zzz
5b1a023be6 SSU2: Convert 1276 MTU to 1280 to workaround bug in 1.9.0 2022-09-23 11:18:36 -04:00
zzz
c082fc8fa6 SSU2: Fail handshakes while inside sync
to prevent races and fail-after-fail ISE
Override fail() to destroy handshake state
2022-09-23 09:14:03 -04:00
zzz
0e8b757249 SSU2 IES2 reduce log levels 2022-09-20 12:01:08 -04:00
zzz
c1b241ab8f i2ptunnel, eepget: Add support for SHA-256 digest proxy auth (RFC 7616)
Requires re-saving user/pw on proxy side
2022-09-20 08:26:05 -04:00
zzz
ab49a149ba Router debug: Don't show enc. type for local router in tunnel config
as it was always showing ElG which was incorrect
ref: http://zzz.i2p/topics/3403
2022-09-14 08:28:10 -04:00
zzz
f64894ea12 Router: ProfileOrganizer and TunnelPeerSelector cleanup
of unused code, in prep for some redesign
2022-09-10 14:11:00 -04:00
zzz
a34bf5d408 Console: Include SSU2 addresses in transports chart
Linkify router family name in RI
2022-09-10 12:50:29 -04:00
zzz
ca569f0739 Router: Remove some ancient HandlerJobBuilder registration code 2022-09-10 08:12:42 -04:00
zzz
88a66928c1 SSU2: Enable handling of ack-immediate flag by default
test code that was off by default was previously checked in
2022-09-09 12:33:53 -04:00
idk
2144486917 Specify type on emptyList so it compiles with Java 8 2022-09-08 21:57:01 -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
1307 changed files with 177362 additions and 117097 deletions

View File

@ -29,3 +29,4 @@ installer/build
router/java/build
router/build
override.properties

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

@ -0,0 +1,120 @@
# 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]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
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@v4
with:
name: I2P-install-${{ github.sha }}.jar
path: install.jar
javadoc-latest:
runs-on: ubuntu-latest
steps:
- name: Setup Pages
uses: actions/configure-pages@v4
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
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 javadoc updater
- name: zip javadoc
run: cp i2pupdate.zip build/javadoc/i2pupdate.zip && zip -r javadoc.zip build/javadoc
- name: Upload javadoc.zip
uses: actions/upload-artifact@v4
with:
name: I2P-javadoc-${{ github.sha }}.zip
path: javadoc.zip
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload javadocs to github page
path: 'build/javadoc'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
build-java7:
runs-on: ubuntu-latest
steps:
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'temurin'
- name : Generate override.properties
run: |
git clone https://github.com/eyedeekay/openjdk-7 "$HOME/openjdk-7"
rm -f override.properties
echo "build.built-by=GitHub Actions" >> override.properties
echo "noExe=true" >> override.properties
echo "javac.compilerargs=-bootclasspath $HOME/openjdk-7/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar:$HOME/openjdk-7/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/jce.jar -Xlint:all" >> override.properties
- name: build with Ant
run: ./installer/resources/maven-dev-release.sh 1
- name: Upload servlet-i2p.jar
uses: actions/upload-artifact@v4
with:
name: servlet-i2p-${{ github.sha }}.jar
path: pkg-mavencentral/servlet-i2p*.jar
- name: Upload streaming.jar
uses: actions/upload-artifact@v4
with:
name: streaming-${{ github.sha }}.jar
path: pkg-mavencentral/streaming*.jar
- name: Upload mstreaming.jar
uses: actions/upload-artifact@v4
with:
name: mstreaming-${{ github.sha }}.jar
path: pkg-mavencentral/mstreaming*.jar
- name: Upload router.jar
uses: actions/upload-artifact@v4
with:
name: router-${{ github.sha }}.jar
path: pkg-mavencentral/router*.jar
- name: Upload i2p.jar
uses: actions/upload-artifact@v4
with:
name: i2p-${{ github.sha }}.jar
path: pkg-mavencentral/i2p*.jar

23
.github/workflows/github-sync.yml vendored Normal file
View File

@ -0,0 +1,23 @@
# File: .github/workflows/repo-sync.yml
on:
schedule:
- cron: "*/5 * * * *"
workflow_dispatch:
jobs:
repo-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: repo-sync
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: repo-sync/github-sync@v2
with:
source_repo: "https://i2pgit.org/i2p-hackers/i2p.i2p"
source_branch: "master"
destination_branch: "master"
github_token: ${{ secrets.PAT }}

2
.gitignore vendored
View File

@ -61,3 +61,5 @@ sloccount.sc
# TODO: why does this file appear?
apps/routerconsole/jsp/favicon.ico
.tx
/*.sh

View File

@ -52,6 +52,7 @@ test:ant:
- echo junit.home=/usr/share/java >> override.properties
- echo hamcrest.home=/usr/share/java >> override.properties
- echo mockito.home=/usr/share/java >> override.properties
- echo build.built-by=GitHub Actions >> override.properties
script:
- ant test
only:
@ -59,19 +60,55 @@ test:ant:
- merge_requests
- tags
test:javadoc:
stage: test
image: debian:unstable-slim
variables:
SCALA: https://downloads.lightbend.com/scala/2.12.13/scala-2.12.13.deb
LIBPREFIX: /usr/share/scala/lib
LIB_SCALATEST: https://repo1.maven.org/maven2/org/scalatest/scalatest_2.12/3.0.4/scalatest_2.12-3.0.4.jar
LIB_SCALACTIC: https://repo1.maven.org/maven2/org/scalactic/scalactic_2.12/3.0.4/scalactic_2.12-3.0.4.jar
before_script:
# Fix bug installing openjdk-11-jdk-headless's manuals
- mkdir -p /usr/share/man/man1/
- apt-get update -q
- apt-get install -y wget gettext
ant openjdk-21-jdk-headless
libmockito-java libhamcrest-java junit4
# Install specific version of scala
- wget -qO scala.deb "${SCALA}"
- dpkg -i scala.deb
# link to the scala libs with the name `ant test` expects
- ln -s "${LIBPREFIX}/scala-xml_2.12-1.0.6.jar" "${LIBPREFIX}/scala-xml.jar"
# Download required scala libs
- wget -qO "${LIBPREFIX}/scalactic.jar" "${LIB_SCALACTIC}"
- wget -qO "${LIBPREFIX}/scalatest.jar" "${LIB_SCALATEST}"
# Point ant to the right directories
- echo scalatest.libs=/usr/share/scala/lib > override.properties
- echo junit.home=/usr/share/java >> override.properties
- echo hamcrest.home=/usr/share/java >> override.properties
- echo mockito.home=/usr/share/java >> override.properties
- echo build.built-by=GitHub Actions >> override.properties
script:
- ant javadoc
only:
- master
- merge_requests
- tags
# Make sure we can build a docker image
# It's cached for later jobs
build_docker:
stage: build
image: docker:19.03.12
image: docker:24.0.7
services:
- docker:19.03.12-dind
- docker:24.0.7-dind
script:
# Try to load latest branch image from local tar or from registry
- docker load -i ci-exports/$CI_COMMIT_REF_SLUG.tar || docker pull $CI_REGISTRY_IMAGE:latest || true
- docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
- mkdir -p ci-exports/
- docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
- echo docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
variables:
# When using dind service, we need to instruct docker to talk with
# the daemon started inside of the service. The daemon is available
@ -89,7 +126,7 @@ build_docker:
# container, thanks to volume mount from config.toml
DOCKER_TLS_CERTDIR: "/certs"
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
# DOCKER_HOST: tcp://docker:2376
cache:
# The same key should be used across branches
key: "$CI_COMMIT_REF_SLUG"

View File

@ -1,7 +1,12 @@
;; warning - conversions for all Java bundles:
;; id->in, he->iw, iy, yi->ji
[I2P.i2ptunnel]
[main]
host = https://www.transifex.com
lang_map = ru_RU: ru, sv_SE: sv, tr_TR: tr, uk_UA: uk, zh_CN: zh, et_EE: et, id: in, he: iw
[o:otf:p:I2P:r:i2ptunnel]
file_filter = apps/i2ptunnel/locale/messages_<lang>.po
source_file = apps/i2ptunnel/locale/messages_en.po
source_lang = en
trans.ar = apps/i2ptunnel/locale/messages_ar.po
@ -9,6 +14,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
@ -35,7 +41,8 @@ trans.vi = apps/i2ptunnel/locale/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale/messages_zh.po
trans.zh_TW = apps/i2ptunnel/locale/messages_zh_TW.po
[I2P.proxy]
[o:otf:p:I2P:r:proxy]
file_filter = apps/i2ptunnel/locale-proxy/messages_<lang>.po
source_file = apps/i2ptunnel/locale-proxy/messages_en.po
source_lang = en
trans.ar = apps/i2ptunnel/locale-proxy/messages_ar.po
@ -43,6 +50,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,8 +74,10 @@ 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]
[o:otf:p:I2P:r:core]
file_filter = core/locale/messages_<lang>.po
type = PO
source_file = core/locale/messages_en.po
source_lang = en
@ -105,7 +115,8 @@ trans.vi = core/locale/messages_vi.po
trans.zh_CN = core/locale/messages_zh.po
trans.zh_TW = core/locale/messages_zh_TW.po
[I2P.router]
[o:otf:p:I2P:r:router]
file_filter = router/locale/messages_<lang>.po
type = PO
source_file = router/locale/messages_en.po
source_lang = en
@ -116,6 +127,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
@ -143,7 +155,8 @@ trans.vi = router/locale/messages_vi.po
trans.zh_CN = router/locale/messages_zh.po
trans.zh_TW = router/locale/messages_zh_TW.po
[I2P.routerconsole]
[o:otf:p:I2P:r:routerconsole]
file_filter = apps/routerconsole/locale/messages_<lang>.po
source_file = apps/routerconsole/locale/messages_en.po
source_lang = en
trans.ar = apps/routerconsole/locale/messages_ar.po
@ -153,6 +166,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
@ -177,7 +191,8 @@ trans.vi = apps/routerconsole/locale/messages_vi.po
trans.zh_CN = apps/routerconsole/locale/messages_zh.po
trans.zh_TW = apps/routerconsole/locale/messages_zh_TW.po
[I2P.welcome]
[o:otf:p:I2P:r:welcome]
file_filter = apps/routerconsole/locale-news/messages_<lang>.po
source_file = apps/routerconsole/locale-news/messages_en.po
source_lang = en
trans.ar = apps/routerconsole/locale-news/messages_ar.po
@ -186,6 +201,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
@ -218,7 +234,8 @@ trans.uk_UA = apps/routerconsole/locale-news/messages_uk.po
trans.zh_CN = apps/routerconsole/locale-news/messages_zh.po
trans.zh_TW = apps/routerconsole/locale-news/messages_zh_TW.po
[I2P.countries]
[o:otf:p:I2P:r:countries]
file_filter = apps/routerconsole/locale-countries/messages_<lang>.po
type = PO
source_file = apps/routerconsole/locale-countries/messages_en.po
source_lang = en
@ -231,6 +248,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
@ -256,6 +274,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
@ -266,14 +285,17 @@ trans.vi = apps/routerconsole/locale-countries/messages_vi.po
trans.zh_CN = apps/routerconsole/locale-countries/messages_zh.po
trans.zh_TW = apps/routerconsole/locale-countries/messages_zh_TW.po
[I2P.i2psnark]
[o:otf:p:I2P:r:i2psnark]
file_filter = apps/i2psnark/locale/messages_<lang>.po
source_file = apps/i2psnark/locale/messages_en.po
source_lang = en
trans.ar = apps/i2psnark/locale/messages_ar.po
trans.cs = apps/i2psnark/locale/messages_cs.po
trans.da = apps/i2psnark/locale/messages_da.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
@ -299,7 +321,8 @@ trans.vi = apps/i2psnark/locale/messages_vi.po
trans.zh_CN = apps/i2psnark/locale/messages_zh.po
trans.zh_TW = apps/i2psnark/locale/messages_zh_TW.po
[I2P.susidns]
[o:otf:p:I2P:r:susidns]
file_filter = apps/susidns/locale/messages_<lang>.po
source_file = apps/susidns/locale/messages_en.po
source_lang = en
trans.ar = apps/susidns/locale/messages_ar.po
@ -308,6 +331,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
@ -331,7 +355,8 @@ trans.vi = apps/susidns/locale/messages_vi.po
trans.zh_CN = apps/susidns/locale/messages_zh.po
trans.zh_TW = apps/susidns/locale/messages_zh_TW.po
[I2P.desktopgui]
[o:otf:p:I2P:r:desktopgui]
file_filter = apps/desktopgui/locale/messages_<lang>.po
source_file = apps/desktopgui/locale/messages_en.po
source_lang = en
trans.ar = apps/desktopgui/locale/messages_ar.po
@ -364,6 +389,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
@ -374,7 +400,8 @@ trans.vi = apps/desktopgui/locale/messages_vi.po
trans.zh_CN = apps/desktopgui/locale/messages_zh.po
trans.zh_TW = apps/desktopgui/locale/messages_zh_TW.po
[I2P.susimail]
[o:otf:p:I2P:r:susimail]
file_filter = apps/susimail/locale/messages_<lang>.po
source_file = apps/susimail/locale/messages_en.po
source_lang = en
trans.ar = apps/susimail/locale/messages_ar.po
@ -386,6 +413,8 @@ 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.et_EE = apps/susimail/locale/messages_et.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
@ -399,6 +428,7 @@ trans.id = apps/susimail/locale/messages_in.po
trans.it = apps/susimail/locale/messages_it.po
trans.ja = apps/susimail/locale/messages_ja.po
trans.ko = apps/susimail/locale/messages_ko.po
trans.ku = apps/susimail/locale/messages_ku.po
trans.mg = apps/susimail/locale/messages_mg.po
trans.nb = apps/susimail/locale/messages_nb.po
trans.nl = apps/susimail/locale/messages_nl.po
@ -408,6 +438,7 @@ trans.pt_BR = apps/susimail/locale/messages_pt_BR.po
trans.ro = apps/susimail/locale/messages_ro.po
trans.ru_RU = apps/susimail/locale/messages_ru.po
trans.sk = apps/susimail/locale/messages_sk.po
trans.sl = apps/susimail/locale/messages_sl.po
trans.sq = apps/susimail/locale/messages_sq.po
trans.sr = apps/susimail/locale/messages_sr.po
trans.sv_SE = apps/susimail/locale/messages_sv.po
@ -417,7 +448,8 @@ trans.vi = apps/susimail/locale/messages_vi.po
trans.zh_CN = apps/susimail/locale/messages_zh.po
trans.zh_TW = apps/susimail/locale/messages_zh_TW.po
[I2P.debconf]
[o:otf:p:I2P:r:debconf]
file_filter = debian/po/<lang>.po
source_file = debian/po/templates.pot
source_lang = en
trans.ar = debian/po/ar.po
@ -426,6 +458,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
@ -442,6 +475,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
@ -450,16 +484,20 @@ trans.uk_UA = debian/po/uk.po
trans.zh_CN = debian/po/zh.po
trans.zh_TW = debian/po/zh_TW.po
[I2P.i2prouter-script]
[o:otf:p:I2P:r:i2prouter-script]
file_filter = installer/resources/locale/po/messages_<lang>.po
source_file = installer/resources/locale/po/messages_en.po
source_lang = en
trans.ar = installer/resources/locale/po/messages_ar.po
trans.az = installer/resources/locale/po/messages_az.po
trans.ca = installer/resources/locale/po/messages_ca.po
trans.cs = installer/resources/locale/po/messages_cs.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.hu = installer/resources/locale/po/messages_hu.po
trans.id = installer/resources/locale/po/messages_id.po
trans.it = installer/resources/locale/po/messages_it.po
trans.ja = installer/resources/locale/po/messages_ja.po
@ -476,8 +514,9 @@ 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]
[o:otf:p:I2P:r:getopt]
;;
;; Java properties files (when not read with our DataHelper methods) must be ISO-8859-1 encoded.
;; See https://docs.oracle.com/javase/6/docs/api/java/util/Properties.html
@ -494,6 +533,7 @@ trans.zh_CN = installer/resources/locale/po/messages_zh.po
;; and should be escaped using native2ascii after downloading:
;; gl, pt, pt_BR, sq, sv, tr
;;
file_filter = core/java/src/gnu/getopt/MessagesBundle_<lang>.properties
source_file = core/java/src/gnu/getopt/MessagesBundle.properties
source_lang = en
type = PROPERTIES
@ -502,6 +542,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
@ -529,7 +570,8 @@ trans.uk_UA = core/java/src/gnu/getopt/MessagesBundle_uk.properties
trans.zh_CN = core/java/src/gnu/getopt/MessagesBundle_zh.properties
trans.zh_TW = core/java/src/gnu/getopt/MessagesBundle_zh_TW.properties
[I2P.streaming]
[o:otf:p:I2P:r:streaming]
file_filter = apps/ministreaming/locale/messages_<lang>.po
source_file = apps/ministreaming/locale/messages_en.po
source_lang = en
trans.ar = apps/ministreaming/locale/messages_ar.po
@ -538,6 +580,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
@ -546,6 +589,7 @@ trans.hu = apps/ministreaming/locale/messages_hu.po
;; Java converts id to in
trans.id = apps/ministreaming/locale/messages_in.po
trans.it = apps/ministreaming/locale/messages_it.po
trans.ja = apps/ministreaming/locale/messages_ja.po
trans.ko = apps/ministreaming/locale/messages_ko.po
trans.nb = apps/ministreaming/locale/messages_nb.po
trans.nl = apps/ministreaming/locale/messages_nl.po
@ -560,12 +604,14 @@ 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]
[o:otf:p:I2P:r:manpages]
;;
;; after adding languages here, add to debian/*.manpages also
;; You must run installer/resources/poupdate-man.sh first.
;;
file_filter = installer/resources/locale-man/man_<lang>.po
type = PO
source_file = installer/resources/locale-man/man.pot
source_lang = en
@ -573,11 +619,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
@ -588,13 +636,15 @@ 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]
[o:otf:p:I2P:r:eepsite]
;;
;; For any new translations, add links in installer/resources/eepsite/docroot/help/index.html
;; and copy new flags in build.xml copyflags-unlesspkg target,
;; and add to debian/i2p-router.links and debian-alt/*/i2p-router.links
;;
file_filter = installer/resources/eepsite/docroot/help/index_<lang>.po
type = HTML
source_file = installer/resources/eepsite/docroot/help/index.html
source_lang = en
@ -604,14 +654,14 @@ source_lang = en
trans.az = installer/resources/eepsite/docroot/help/index_az.html
trans.de = installer/resources/eepsite/docroot/help/index_de.html
trans.el = installer/resources/eepsite/docroot/help/index_el.html
;; not yet translated on TX, use old page
;;trans.es = installer/resources/eepsite/docroot/help/index_es.html
trans.es = installer/resources/eepsite/docroot/help/index_es.html
trans.fa = installer/resources/eepsite/docroot/help/index_fa.html
trans.fr = installer/resources/eepsite/docroot/help/index_fr.html
trans.hu = installer/resources/eepsite/docroot/help/index_hu.html
;; Java converts id to in
trans.id = installer/resources/eepsite/docroot/help/index_in.html
trans.it = installer/resources/eepsite/docroot/help/index_it.html
trans.ja = installer/resources/eepsite/docroot/help/index_ja.html
;; not yet translated on TX, use old page
;;trans.nl = installer/resources/eepsite/docroot/help/index_nl.html
trans.pl = installer/resources/eepsite/docroot/help/index_pl.html
@ -623,14 +673,19 @@ trans.tr_TR = installer/resources/eepsite/docroot/help/index_tr.html
trans.uk_UA = installer/resources/eepsite/docroot/help/index_uk.html
trans.zh_CN = installer/resources/eepsite/docroot/help/index_zh.html
[I2P.readme]
[o:otf:p:I2P:r:readme]
;;
;; Text on /console
;;
;; NOTE: No support for country suffixes right now.
;; See ResourceHelper.java
;;
file_filter = apps/routerconsole/resources/docs/readme_<lang>.html
type = HTML
source_file = apps/routerconsole/resources/docs/readme.html
source_lang = en
trans.ar = apps/routerconsole/resources/docs/readme_ar.html
trans.cs = apps/routerconsole/resources/docs/readme_cs.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
@ -642,10 +697,9 @@ 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
[main]
host = https://www.transifex.com
trans.zh_TW = apps/routerconsole/resources/docs/readme_zh_TW.html

View File

@ -1,13 +1,49 @@
# 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
ports:
- 127.0.0.1:4444:4444
- 127.0.0.1:6668:6668
- 127.0.0.1:7657:7657
- 54321:12345
- 54321:12345/udp
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:
```
docker build -t i2p .
docker build -t geti2p/i2p .
```
### Running a container
#### Environment Variables
It is possible to set the IP address where the I2P router is accessible by setting
the `IP_ADDR` environment variable in your `docker run` command or your `docker-compose`
file. For example, if you want to make your I2P router listen on all addresses, then
you should pass `-e IP_ADDR=0.0.0.0` to your `docker run` command.
It is also possible to configure the memory available to the I2P router using
environment variables. To do this, use the: `JVM_XMX` environment variable by passing,
for example, `-e JVM_XMX=256m`.
#### Volumes
The container requires a volume for the configuration data to be mounted. Optionally, you can mount a separate volume for torrent ("i2psnark") downloads. See the example below.
@ -17,33 +53,41 @@ 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.
```
docker build -t geti2p/i2p .
# I2NP port needs TCP and UDP. Change the 54321 to something random, greater than 1024.
docker run \
-e JVM_XMX=256m \
-v i2phome:/i2p/.i2p \
-v i2ptorrents:/i2psnark \
-p 4444:4444 \
-p 6668:6668 \
-p 7657:7657 \
-p 127.0.0.1:4444:4444 \
-p 127.0.0.1:6668:6668 \
-p 127.0.0.1:7657:7657 \
-p 54321:12345 \
-p 54321:12345/udp \ # I2NP port needs TCP and UDP. Change the 54321 to something random, greater than 1024.
i2p:latest
-p 54321:12345/udp \
geti2p/i2p:latest
```

View File

@ -1,24 +1,27 @@
FROM jlesage/baseimage:alpine-3.10-glibc as builder
FROM alpine:3.17.1 as builder
ENV APP_HOME="/i2p"
WORKDIR /tmp/build
COPY . .
RUN add-pkg --virtual build-base gettext tar bzip2 apache-ant openjdk8 \
RUN apk add --virtual build-base gettext tar bzip2 apache-ant openjdk17 \
&& echo "build.built-by=Docker" >> override.properties \
&& 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
&& apk del build-base gettext tar bzip2 apache-ant openjdk17
FROM jlesage/baseimage:alpine-3.10-glibc
FROM alpine:3.17.1
ENV APP_HOME="/i2p"
RUN add-pkg openjdk8-jre
RUN apk add openjdk17-jre ttf-dejavu
WORKDIR ${APP_HOME}
COPY --from=builder /tmp/build/pkg-temp .
# "install" i2p by copying over installed files
COPY docker/rootfs/ /
COPY --chown=root:root docker/rootfs/ /
RUN chmod +x /startapp.sh
# Mount home and snark
VOLUME ["${APP_HOME}/.i2p"]
@ -34,3 +37,4 @@ LABEL \
org.label-schema.vcs-url="https://github.com/i2p/i2p.i2p" \
org.label-schema.schema-version="1.0"
ENTRYPOINT ["/startapp.sh"]

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
@ -271,7 +267,7 @@ Applications:
See licenses/LICENSE-Apache2.0.txt
See licenses/LICENSE-ECLIPSE-1.0.html
RRD4J 3.8 (jrobin.jar):
RRD4J 3.9 (jrobin.jar):
Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
Copyright (c) 2011 The OpenNMS Group, Inc.
Copyright 2011 The RRD4J Authors.
@ -320,6 +316,10 @@ Applications:
See licenses/LICENSE-NDT.txt
Notice: I2P has changed specified portions of the Software, including the package edu.internet2.ndt.
Router Console Iframe-resizer 4.3.9:
Copyright (c) 2013-2023 David J. Bradshaw
See licenses/LICENSE-Iframe-resizer.txt
SAM (sam.jar):
Public domain.
@ -336,12 +336,19 @@ Applications:
GPLv2 (or any later version)
See licenses/LICENSE-GPLv2.txt
SusiMail Pagedown:
Original Markdown Copyright (c) 2004-2005 John Gruber
Original Showdown code copyright (c) 2007 John Fraser
Modifications and bugfixes (c) 2009 Dana Robinson
Modifications and bugfixes (c) 2009-2014 Stack Exchange Inc.
See licenses/LICENSE-pagedown.txt
Systray (systray.jar):
Public domain.
Tomcat 9.0.54 (jasper-runtime.jar):
Tomcat 9.0.88 (jasper-runtime.jar):
(not included in most distribution packages)
Copyright 1999-2021 The Apache Software Foundation
Copyright 1999-2024 The Apache Software Foundation
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Tomcat.txt
@ -355,7 +362,7 @@ distributions. See the source package for the additional license information.
Admin Manager:
Public domain
Gradle wrapper 5.2.1:
Gradle wrapper 8.5:
(not included in most distribution packages)
Copyright (c) 2017 the original author or authors.
Copyright (c) 2023 the original author or authors.
See licenses/LICENSE-Apache2.0.txt

View File

@ -64,6 +64,9 @@ 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

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}" />
@ -77,28 +84,36 @@
</jar>
</target>
<!-- actually the jar -->
<target name="warUpToDate">
<uptodate property="war.uptodate" targetfile="${dist}/${war}">
<srcfiles dir= "." includes="${build}/**/*.class, web.xml"/>
<uptodate property="war.uptodate" targetfile="${dist}/${jar}">
<srcfiles dir= "." includes="${build}/**/*.class"/>
</uptodate>
<condition property="shouldListChanges" >
<and>
<not>
<isset property="war.uptodate" />
</not>
<isset property="mtn.available" />
<isset property="git.available" />
</and>
</condition>
</target>
<target name="changes" depends="warUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<arg value="." />
</exec>
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />

View File

@ -136,9 +136,17 @@ class AddressBook implements Iterable<Map.Entry<String, HostTxtEntry>> {
File tmp = null;
try {
tmp = SecureFile.createTempFile("addressbook", null, I2PAppContext.getGlobalContext().getTempDir());
// Apache 2.4 mod_deflate etag bug workaround
// strip -gzip from the etag
// Gitlab #454
String loc = subscription.getLocation();
String etag = subscription.getEtag();
if (loc.startsWith("http://i2p-projekt.i2p/") && etag != null && etag.endsWith("-gzip\""))
etag = etag.substring(0, etag.length() - 6) + '"';
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, tmp.getAbsolutePath(), null,
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
loc, true, etag, subscription.getLastModified(), null);
if (get.fetch()) {
subscription.setEtag(get.getETag());
subscription.setLastModified(get.getLastModified());

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

@ -697,7 +697,7 @@ class Daemon {
StringBuilder buf = new StringBuilder(16);
final int sz = dests.size();
for (int i = 0; i < sz; i++) {
buf.append(dests.get(i).toBase64().substring(0, 6));
buf.append(dests.get(i).toBase64(), 0, 6);
if (i != sz - 1)
buf.append(", ");
}

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

@ -23,11 +23,14 @@ package net.i2p.addressbook;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Date;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.SecureFileOutputStream;
/**
* A simple log with automatic time stamping.
*
@ -57,9 +60,9 @@ class Log {
public void append(String entry) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.file,
bw = new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(this.file,
true), "UTF-8"));
String timestamp = new Date().toString();
String timestamp = DataHelper.formatTime(I2PAppContext.getGlobalContext().clock().now());
bw.write(timestamp + " -- " + entry);
bw.newLine();
} catch (IOException exp) {

View File

@ -762,6 +762,10 @@ public class BlockfileNamingService extends DummyNamingService {
*/
@Override
public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
if (hostname.endsWith(".i2p.alt")) {
// RFC 9476
hostname = hostname.substring(0, hostname.length() - 4);
}
Destination rv = lookup2(hostname, lookupOptions, storedOptions);
if (rv == null) {
// if hostname starts with "www.", strip and try again
@ -1431,6 +1435,8 @@ public class BlockfileNamingService extends DummyNamingService {
}
/**
* Broken prior to 0.9.62, would only return one name.
*
* @param options If non-null and contains the key "list", get
* from that list (default "hosts.txt", NOT all lists)
* Key "skip": skip that many entries
@ -1502,6 +1508,7 @@ public class BlockfileNamingService extends DummyNamingService {
break;
}
}
iter.next();
if (search != null && key.indexOf(search) < 0)
continue;
rv.add(key);

View File

@ -0,0 +1,8 @@
<html>
<body>
<p>
The BlockfileNamingService based on the Metanotion BlockFile Database.
This is the default NamingService for the router.
</p>
</body>
</html>

View File

@ -1,3 +1,7 @@
plugins {
id 'java-library'
}
sourceSets {
main {
java {
@ -8,10 +12,10 @@ sourceSets {
}
dependencies {
compile project(':core')
compile project(':router')
compile project(':installer')
compile project(':apps:systray')
api project(':core')
api project(':router')
api project(':installer')
api project(':apps:systray')
}
// Create the java files from the po files. The jar task will compile them.

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}" />
@ -63,17 +64,24 @@
</target>
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<arg value="." />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="compile, bundle, listChangedFiles" unless="jar.uptodate" >
@ -86,6 +94,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}" />
@ -106,7 +115,7 @@
<not>
<isset property="jar.uptodate" />
</not>
<isset property="mtn.available" />
<isset property="git.available" />
</and>
</condition>
</target>

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,14 +4,15 @@
# 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: 2021-07-08 09:41+0000\n"
"Last-Translator: slrslr\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"
@ -26,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 "Nastavit I2P Systémovou Lištu"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Zakázat"
#: 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 "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 "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 "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 "Zastavení za {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
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 "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: 2021-08-11 15:33+0000\n"
"POT-Creation-Date: 2023-03-06 14:52+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"
@ -19,75 +19,84 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
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:54
#: src/net/i2p/desktopgui/InternalTrayManager.java:206
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
msgid "Launch I2P Browser"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:75
#: src/net/i2p/desktopgui/InternalTrayManager.java:227
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
msgid "Configure I2P System Tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Disable"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:92
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
msgid "Restart I2P"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:109
#: src/net/i2p/desktopgui/InternalTrayManager.java:261
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
msgid "Stop I2P"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:125
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
msgid "Restart I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:142
#: src/net/i2p/desktopgui/InternalTrayManager.java:294
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
msgid "Stop I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:156
#: src/net/i2p/desktopgui/InternalTrayManager.java:308
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:362
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:364
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr ""
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:369
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
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:75
msgid "I2P: Right-click for menu"
msgstr ""
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr ""
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr ""

View File

@ -6,21 +6,22 @@
# Translators:
# ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009
# punkibastardo <punkibastardo@gmail.com>, 2011
# Juan Jaramillo <juanda097@protonmail.ch>, 2022
# punkibastardo <transifex.symons@slmail.me>, 2011
# strel, 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: strel\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Juan Jaramillo <juanda097@protonmail.ch>, 2022\n"
"Language-Team: Spanish (http://www.transifex.com/otf/I2P/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -29,69 +30,81 @@ msgstr "Iniciar 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 está iniciando!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Iniciando"
#: 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 "Lanzar navegador 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 "Configurar la bandeja de sistema de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Deshabilitar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Activar las notificaciones"
#: 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 "Desactivar las notificaciones"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Desactivar la bandeja del sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Reiniciar 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 "Detener 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 "Reiniciar I2P inmediatamente"
#: 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 "Detener I2P inmediatamente"
#: 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 "Cancelar el cierre de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Cierre en {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Cierre inminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Red"
#. 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: Clic secundario para menú"

View File

@ -9,15 +9,15 @@ 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-11-16 15:29+0000\n"
"Last-Translator: kaze kaze <kaze@rlab.be>\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: kaze kaze <kaze@rlab.be>, 2017\n"
"Language-Team: Spanish (Argentina) (http://www.transifex.com/otf/I2P/language/es_AR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es_AR\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -26,69 +26,81 @@ msgstr "Iniciando 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 esta iniciando!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Iniciando"
#: 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 "Lanzar el Navegador 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 "Configurar la Bandeja de Sistema de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Deshabilitar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Activar las notificaciones"
#: 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 "Desactivar las notificaciones"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Desactivar la bandeja del sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Riniciar 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 "Detener 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 " Reiniciar I2P inmediatamente "
#: 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 " Detener I2P inmediatamente "
#: 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 "Cancelar el Apagado de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Apagar en {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Apagado inminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Red"
#. 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 Clic derecho para el menú"

View File

@ -13,19 +13,20 @@
# AO <ao@localizationlab.org>, 2017
# Boxoa590, 2013
# Towinet, 2016
# vex vex, 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: 2019-12-03 16:10+0000\n"
"Last-Translator: AO <ao@localizationlab.org>\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: vex vex, 2022\n"
"Language-Team: French (http://www.transifex.com/otf/I2P/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -34,69 +35,81 @@ msgstr "Démarrer 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 démarre!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Démarrage"
#: 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 "Lancer le navigateur dI2P"
#: 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 "Configurer la zone de notification dI2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Désactiver"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Activer les notifications"
#: 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 "Désactiver les notifications"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Désactiver la zone de notification"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Redémarrer 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 "Arrêter 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 "Redémarrer I2P immédiatement"
#: 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 "Arrêter I2P immédiatement"
#: 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 "Annuler la fermeture dI2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Fermeture dans {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "La fermeture est imminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Réseau"
#. 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 : clic droit pour obtenir le menu"

View File

@ -5,13 +5,14 @@
#
# Translators:
# Hunor Paksy <heds@cock.li>, 2018
# vargaviktor <viktor.varga@gmail.com>, 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: 2021-06-20 09:44+0000\n"
"Last-Translator: AdminLMH <lehetmashogy@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: vargaviktor <viktor.varga@gmail.com>, 2022\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"
@ -26,69 +27,81 @@ msgstr "I2P indítása"
#: 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 indul!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "indítás"
#: 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 Böngésző Indítása"
#: 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 rendszertálca beállítások"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Kikapcsol"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Értesítések engedélyezése"
#: 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 "Értesítések tiltása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Tálcaikon letiltása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "I2P Újraindítása"
#: 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 Leállítása"
#: 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 Azonnali újraindítása"
#: 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 Azonnali megállítása"
#: 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 leállításának visszavonása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Kikapcsolás: {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Kikapcsolás hamarosan"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Hálózat"
#. 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: Jobb-klikk a menüért"

View File

@ -8,91 +8,101 @@
# mkkid <jokjok@hotmail.it>, 2011
# Leelium <bovas85@gmail.com>, 2012
# mkkid <jokjok@hotmail.it>, 2011
# Sebastiano Pistore <SebastianoPistore.info@protonmail.ch>, 2016-2017
# SebastianoPistore <SebastianoPistore.info@protonmail.ch>, 2016-2017
# V 41bis, 2023
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-07-30 07:04+0000\n"
"Last-Translator: Sebastiano Pistore <SebastianoPistore.info@protonmail.ch>\n"
"Language-Team: Italian (http://www.transifex.com/otf/I2P/language/it/)\n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: V 41bis, 2023\n"
"Language-Team: Italian (http://app.transifex.com/otf/I2P/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Avvia 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 "Avvio di I2P in corso!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Avvio in corso"
#: 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:221
msgid "Launch I2P Browser"
msgstr "Lancia il browser 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:242
msgid "Configure I2P System Tray"
msgstr "Configura icona di I2P nella Barra di notifica"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Disabilita"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Disattiva l'icona nella barra di Notifica"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
msgid "Restart I2P"
msgstr "Riavvia I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
msgid "Stop I2P"
msgstr "Arresta I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
msgid "Restart I2P Immediately"
msgstr "Riavvia subito I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
msgid "Stop I2P Immediately"
msgstr "Arresta subito I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr "Annulla arresto di I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr "Arresto in {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr "Arresto imminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
msgid "Network"
msgstr "Rete"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:75
msgid "I2P: Right-click for menu"
msgstr "I2P: Fai click destro per aprire il menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Attiva le notifiche"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Disattiva le notifiche"

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

@ -6,14 +6,15 @@
# Translators:
# Allan Nordhøy <epost@anotheragency.no>, 2014
# Allan Nordhøy <epost@anotheragency.no>, 2017
# Imre Kristoffer Eilertsen <imreeil42@gmail.com>, 2022-2023
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-19 14:52+0000\n"
"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
"Language-Team: Norwegian Bokmål (http://www.transifex.com/otf/I2P/language/nb/)\n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Imre Kristoffer Eilertsen <imreeil42@gmail.com>, 2022-2023\n"
"Language-Team: Norwegian Bokmål (http://app.transifex.com/otf/I2P/language/nb/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -21,75 +22,84 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Start 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 starter opp!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Starter opp"
#: 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:221
msgid "Launch I2P Browser"
msgstr "Kjør I2P-nettleser"
#: 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:242
msgid "Configure I2P System Tray"
msgstr "Sett opp I2P-systemkruv"
msgstr "Sett opp I2P-systemkurv"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Skru av"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Skru av systemkurven"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
msgid "Restart I2P"
msgstr "Omstart av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
msgid "Stop I2P"
msgstr "Stopp I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
msgid "Restart I2P Immediately"
msgstr "Umiddelbar omstart av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
msgid "Stop I2P Immediately"
msgstr "Umiddelbar stopp av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr "Avbryt nedstenging av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr "Skrur av om {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr "Skru av med en gang"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
msgid "Network"
msgstr "Nettverk"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:75
msgid "I2P: Right-click for menu"
msgstr "Høyreklikk-meny i I2P"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Skru på varsler"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Skru av varsler"

View File

@ -6,14 +6,15 @@
# Translators:
# PolishAnon <b790979@klzlk.com>, 2011
# polacco <polacco@i2pmail.org>, 2015
# Verdulo :-), 2016
# Verdulo, 2016
# Waldemar Napora, 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"
"Last-Translator: Verdulo :-)\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Waldemar Napora, 2022\n"
"Language-Team: Polish (http://www.transifex.com/otf/I2P/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -28,69 +29,81 @@ msgstr "Uruchom 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 "Uruchamianie 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 "Uruchamianie"
#: 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 "Uruchom przeglądarkę 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 "Konfiguruj I2P w zasobniku systemowym"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Wyłącz"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Włącz powiadomenia"
#: 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 "Wyłącz powiadomienia"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Wyłącz zasobnik systemowy"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "Zrestartuj 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 "Zatrzymaj 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 "Zrestartuj I2P natychmiast"
#: 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 "Wyłącz I2P natychmiast"
#: 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 "Anuluj zamykanie I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "Wyłączenie za {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "Zaraz zamknę"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "Sieć"
#. 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: kliknij prawym aby otworzyć menu"

View File

@ -4,93 +4,102 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Manuela Silva <manuela.silva@sky.com>, 2016
# wicked, 2013
# wicked, 2012
# Manuela Silva <mmsrs@sky.com>, 2016
# 1c13465e24d91aca4d3ddaa1bc3e7027_ae6ba28, 2013
# 1c13465e24d91aca4d3ddaa1bc3e7027_ae6ba28, 2012
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: Manuela Silva <manuela.silva@sky.com>\n"
"Language-Team: Portuguese (http://www.transifex.com/otf/I2P/language/pt/)\n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Manuela Silva <mmsrs@sky.com>, 2016\n"
"Language-Team: Portuguese (http://app.transifex.com/otf/I2P/language/pt/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Iniciar 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 está a iniciar!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "A Iniciar"
#: 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:221
msgid "Launch I2P Browser"
msgstr "Iniciar o browser 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:242
msgid "Configure I2P System Tray"
msgstr "Configurar Bandeja do Sistema do I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Desativar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Desativar bandeja do sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
msgid "Restart I2P"
msgstr "Reiniciar o I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
msgid "Stop I2P"
msgstr "Parar o I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
msgid "Restart I2P Immediately"
msgstr "Reiniciar o I2P imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
msgid "Stop I2P Immediately"
msgstr "Parar o I2P de imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr "Cancelar Encerramento do I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr "Encerramento em {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr "Encerramento eminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
msgid "Network"
msgstr "Rede"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:75
msgid "I2P: Right-click for menu"
msgstr "I2P: Clique direito para menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Ativar notificações"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Desativar notificações"

View File

@ -4,94 +4,105 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Cauan Henrique Zorzenon <cauanzorzenon@gmail.com>, 2023
# testsubject67 <deborinha97@hotmail.com>, 2014
# blueboy, 2013
# blueboy, 2015
# ce4434973f224b33f2ea48f4556be467_f116f03, 2022
# L., 2013
# L., 2015
# Rafael Ferrari, 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: Rafael Ferrari\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/otf/I2P/language/pt_BR/)\n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Cauan Henrique Zorzenon <cauanzorzenon@gmail.com>, 2023\n"
"Language-Team: Portuguese (Brazil) (http://app.transifex.com/otf/I2P/language/pt_BR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Conectar-se à I2P"
msgstr "Iniciar 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 "Conectando-se a 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 "Conectando"
#: 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:221
msgid "Launch I2P Browser"
msgstr "Lançar o navegador 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:242
msgid "Configure I2P System Tray"
msgstr "Configurar o ícone de sistema I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Desabilitar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Desativar bandeja do sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
msgid "Restart I2P"
msgstr "Reinicializar o roteador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
msgid "Stop I2P"
msgstr "Interromper o roteador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
msgid "Restart I2P Immediately"
msgstr "Reinicializar o I2P Imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
msgid "Stop I2P Immediately"
msgstr "Parar o I2P Imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr "Cancelar o desligamento do I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr "Desligando em {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr "Desligando agora"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
msgid "Network"
msgstr "Rede"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:75
msgid "I2P: Right-click for menu"
msgstr "I2P: Clique com o botão direito para o menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Ativar notificações"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Desativar notificações"

View File

@ -9,14 +9,15 @@
# foo <foo@bar>, 2009
# Foster Snowhill, 2013
# brianhopes <voganc-12@live.ru>, 2015
# Артём Котлубай <artemkotlubai@yandex.ru>, 2023
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: c4sp3r\n"
"Language-Team: Russian (Russia) (http://www.transifex.com/otf/I2P/language/ru_RU/)\n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Артём Котлубай <artemkotlubai@yandex.ru>, 2023\n"
"Language-Team: Russian (Russia) (http://app.transifex.com/otf/I2P/language/ru_RU/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -24,75 +25,84 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
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:221
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:242
msgid "Configure I2P System Tray"
msgstr "Настроить системный трей I2P"
msgstr "Настроить область уведомлений"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Отключить"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Убрать значок из области уведомлений"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
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:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
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:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
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:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
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:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr "Отменить выключение I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr "Выключение через {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr "Неотменяемое выключение"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
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:75
msgid "I2P: Right-click for menu"
msgstr "I2P: Правый щелчок для вызова меню"
msgstr "I2P: ПКМ для вызова меню"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Включить уведомления"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Отключить уведомления"

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

@ -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,312 @@
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.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
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, MenuService {
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 {
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;
}
/////// MenuService methods
/**
* Menu will start out shown and enabled, in the root menu
*
* @param message for the menu, translated
* @param callback fired on click
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback) {
return addMenu(message, callback, null);
}
/**
* Menu will start out enabled, as a submenu
*
* @param message for the menu, translated
* @param callback fired on click
* @param parent the parent menu this will be a submenu of, or null for top level
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback, MenuHandle parent) {
if (_trayManager == null)
return null;
return _trayManager.addMenu(message, callback, parent);
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.removeMenu(item);
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.showMenu(item);
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.hideMenu(item);
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.enableMenu(item);
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.disableMenu(item);
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.updateMenu(message, item);
}
/////// 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() {
@ -51,11 +51,15 @@ class ExternalTrayManager extends TrayManager {
}
});
popup.add(startItem);
initializeNotificationItems();
popup.add(_notificationItem2);
popup.add(_notificationItem1);
return popup;
}
public JPopupMenu getSwingMainMenu() {
JPopupMenu popup = new JPopupMenu();
/*
JMenuItem startItem = new JMenuItem(_t("Start I2P"));
startItem.addActionListener(new ActionListener() {
@Override
@ -79,6 +83,10 @@ class ExternalTrayManager extends TrayManager {
}
});
popup.add(startItem);
*/
initializeJNotificationItems();
popup.add(_jnotificationItem2);
popup.add(_jnotificationItem1);
return popup;
}
@ -86,5 +94,14 @@ class ExternalTrayManager extends TrayManager {
* Update the menu
* @since 0.9.26
*/
protected void updateMenu() {}
protected void updateMenu() {
if (_notificationItem1 != null)
_notificationItem1.setEnabled(_showNotifications);
if (_notificationItem2 != null)
_notificationItem2.setEnabled(!_showNotifications);
if (_jnotificationItem1 != null)
_jnotificationItem1.setVisible(_showNotifications);
if (_jnotificationItem2 != null)
_jnotificationItem2.setVisible(!_showNotifications);
}
}

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,6 +30,7 @@ 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;
private JMenuItem _jstatusItem, _jbrowserItem, _jconfigItem, _jrestartItem, _jstopItem,
@ -39,11 +41,20 @@ class InternalTrayManager extends TrayManager {
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 +84,8 @@ class InternalTrayManager extends TrayManager {
}
PopupMenu desktopguiConfigurationLauncher = new PopupMenu(_t("Configure I2P System Tray"));
MenuItem configSubmenu = new MenuItem(_t("Disable"));
MenuItem configSubmenu = new MenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
@ -173,6 +185,9 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
initializeNotificationItems();
desktopguiConfigurationLauncher.add(_notificationItem2);
desktopguiConfigurationLauncher.add(_notificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
@ -225,7 +240,8 @@ class InternalTrayManager extends TrayManager {
}
JMenu desktopguiConfigurationLauncher = new JMenu(_t("Configure I2P System Tray"));
JMenuItem configSubmenu = new JMenuItem(_t("Disable"));
JMenuItem configSubmenu = new JMenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
@ -325,6 +341,9 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
initializeJNotificationItems();
desktopguiConfigurationLauncher.add(_jnotificationItem2);
desktopguiConfigurationLauncher.add(_jnotificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
@ -390,6 +409,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 +430,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 +442,25 @@ 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
*/
@Override
protected 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,10 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
import net.i2p.app.NotificationService;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.router.RouterContext;
import net.i2p.router.app.RouterApp;
@ -27,7 +32,7 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
/**
* The main class of the application.
*/
public class Main implements RouterApp {
public class Main implements RouterApp, NotificationService, MenuService {
// non-null
private final I2PAppContext _appContext;
@ -55,7 +60,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 +80,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 +100,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 +208,129 @@ 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;
}
/////// MenuService methods
/**
* Menu will start out shown and enabled, in the root menu
*
* @param message for the menu, translated
* @param callback fired on click
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback) {
return addMenu(message, callback, null);
}
/**
* Menu will start out enabled, as a submenu
*
* @param message for the menu, translated
* @param callback fired on click
* @param parent the parent menu this will be a submenu of, or null for top level
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback, MenuHandle parent) {
if (_trayManager == null)
return null;
return _trayManager.addMenu(message, callback, parent);
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.removeMenu(item);
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.showMenu(item);
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.hideMenu(item);
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.enableMenu(item);
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.disableMenu(item);
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.updateMenu(message, item);
}
/////// ClientApp methods
/** @since 0.9.26 */

View File

@ -4,25 +4,38 @@ import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.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 java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
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.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.apps.systray.UrlLauncher;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
/**
@ -31,25 +44,32 @@ 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;
protected MenuItem _notificationItem1, _notificationItem2;
protected JMenuItem _jnotificationItem1, _jnotificationItem2;
private final AtomicInteger _id = new AtomicInteger();
private final List<MenuInternal> _menus;
private JPopupMenu _jPopupMenu;
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;
_menus = new ArrayList<MenuInternal>();
}
/**
@ -58,6 +78,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;
@ -97,6 +118,7 @@ abstract class TrayManager {
frame.setMinimumSize(new Dimension(0, 0));
frame.setSize(0, 0);
final JPopupMenu menu = getSwingMainMenu();
_jPopupMenu = menu;
menu.setFocusable(true);
frame.add(menu);
TrayIcon ti = new TrayIcon(getTrayImage(), tooltip, null);
@ -191,12 +213,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 +234,316 @@ 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;
}
/**
* Does not save. See InternalTrayManager.
*
* @since 0.9.58 moved up from InternalTrayManager
*/
protected void configureNotifications(boolean enable) {
_showNotifications = enable;
}
/**
* Initializes _notificationItem 1 and 2
*
* @since 0.9.58 pulled out of InternalTrayManager
*/
protected void initializeNotificationItems() {
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();
}
});
_notificationItem2 = notificationItem2;
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();
}
});
_notificationItem1 = notificationItem1;
}
/**
* Initializes _jnotificationItem 1 and 2
*
* @since 0.9.58 pulled out of InternalTrayManager
*/
protected void initializeJNotificationItems() {
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();
}
});
_jnotificationItem2 = notificationItem2;
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();
}
});
_jnotificationItem1 = notificationItem1;
}
/////// MenuService delegation methods
/**
* @since 0.9.59
*/
public MenuHandle addMenu(String message, final MenuCallback callback, MenuHandle p) {
MenuInternal parent = p != null ? (MenuInternal) p : null;
final int id = _id.incrementAndGet();
final MenuInternal rv;
if (_useSwing) {
final JMenuItem m = new JMenuItem(message);
rv = new MenuInternal(null, m, callback, id);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
rv.cb.clicked(rv);
return null;
}
}.execute();
}
});
_jPopupMenu.add(m);
} else {
final MenuItem m = new MenuItem(message);
rv = new MenuInternal(m, null, callback, id);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
rv.cb.clicked(rv);
return null;
}
}.execute();
}
});
trayIcon.getPopupMenu().add(m);
}
synchronized(_menus) {
_menus.add(rv);
}
updateMenu();
return rv;
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
if (_useSwing) {
_jPopupMenu.remove(mi.jm);
} else {
trayIcon.getPopupMenu().remove(mi.m);
}
updateMenu();
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setVisible(true);
updateMenu();
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setVisible(false);
updateMenu();
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setEnabled(true);
updateMenu();
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setEnabled(false);
updateMenu();
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setText(message);
updateMenu();
}
/////// MenuService internals
/**
* @since 0.9.59
*/
private MenuInternal getMenu(int id) {
synchronized(_menus) {
for (MenuInternal mi : _menus) {
if (mi.getID() == id)
return mi;
}
}
return null;
}
/**
* @since 0.9.59
*/
private static class MenuInternal implements MenuHandle {
private final MenuItem m;
private final JMenuItem jm;
private final MenuCallback cb;
private final int id;
public MenuInternal(MenuItem mm, JMenuItem jmm, MenuCallback cbb, int idd) {
m = mm; jm = jmm; cb = cbb; id = idd;
}
public int getID() { return id; }
private void setEnabled(boolean yes) {
if (m != null)
m.setEnabled(yes);
else
jm.setEnabled(yes);
}
private void setVisible(boolean yes) {
if (m != null)
m.setEnabled(yes);
else
jm.setVisible(yes);
}
private void setText(String text) {
if (m != null)
m.setLabel(text);
else
jm.setText(text);
}
}
protected String _t(String s) {
return DesktopguiTranslator._t(_appContext, s);
}

View File

@ -1,4 +1,5 @@
plugins {
id 'java-library'
id 'war'
}
@ -11,13 +12,15 @@ sourceSets {
}
dependencies {
providedCompile project(':router')
providedCompile project(':apps:jetty')
providedCompile files('../../installer/lib/wrapper/all/wrapper.jar')
api project(':router')
api project(':apps:jetty')
api files('../../installer/lib/wrapper/all/wrapper.jar')
api fileTree("../jetty/apache-tomcat-${tomcatVersion}")
api fileTree("../jetty/jetty-distribution-${jettyVersion}")
}
war {
archiveName 'jsonrpc.war'
archiveBaseName.set('jsonrpc')
webXml = file('web.xml')
}

View File

@ -92,7 +92,29 @@
</javac>
</target>
<target name="jar" depends="compile">
<target name="listChangedFiles" if="git.available" >
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
<arg value="../resources" />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="compile, listChangedFiles">
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
@ -108,7 +130,7 @@
</jar>
</target>
<target name="socketJar" depends="compileSocketJar">
<target name="socketJar" depends="compileSocketJar, listChangedFiles">
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
@ -124,7 +146,7 @@
</jar>
</target>
<target name="war" depends="compile" >
<target name="war" depends="compile, listChangedFiles" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<war destfile="build/jsonrpc.war" webxml="web.xml" >

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")) {
@ -170,7 +170,7 @@ public class RouterInfoHandler implements RequestHandler {
&& (!_context.router().gracefulShutdownInProgress())
&& !_context.clientManager().isAlive())
return (NETWORK_STATUS.ERROR_I2CP);
long skew = _context.commSystem().getFramedAveragePeerClockSkew(33);
long skew = _context.commSystem().getFramedAveragePeerClockSkew(10);
// Display the actual skew, not the offset
if (Math.abs(skew) > 60 * 1000)
return NETWORK_STATUS.ERROR_CLOCK_SKEW;
@ -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())
if (_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

@ -1,4 +1,5 @@
plugins {
id 'java-library'
id 'war'
}
@ -12,11 +13,14 @@ sourceSets {
}
dependencies {
compile project(':core')
providedCompile project(':apps:systray')
compile 'gnu.getopt:java-getopt:1.0.13'
providedCompile project(':apps:ministreaming')
providedCompile project(':apps:jetty')
api project(':core')
api project(':apps:systray')
api 'gnu.getopt:java-getopt:1.0.13'
api project(':apps:ministreaming')
api project(':apps:jetty')
// this is not needed except for standalone,
// but we build the standalone classes even for non-standalone
api project(':apps:desktopgui')
}
task i2psnarkJar(type: Jar) {

View File

@ -2,3 +2,13 @@
# 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
# disable system tray notification popups
#desktopgui.showNotifications=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,18 +62,26 @@
<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>
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value=".." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
@ -108,7 +118,7 @@
<not>
<isset property="war.uptodate" />
</not>
<isset property="mtn.available" />
<isset property="git.available" />
</and>
</condition>
</target>
@ -197,9 +207,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 -->
@ -228,6 +245,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... -->
<!--
@ -240,10 +259,12 @@
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
<attribute name="X-Compile-Source-JDK" value="${javac.version}" />
<attribute name="X-Compile-Target-JDK" value="${javac.version}" />
<!-- this is so Jetty will report its version correctly -->
<section name="org/eclipse/jetty/server/" >
<attribute name="Implementation-Vendor" value="Eclipse.org - Jetty" />
<attribute name="Implementation-Version" value="8.1.17.v20150415" />
<attribute name="Implementation-Version" value="${jetty.ver}" />
</section>
</manifest>
</jar>
@ -286,6 +307,12 @@
value="url(/i2psnark/.resources/themes/ubergine/images/" >
<include name="**/*.css" />
</replace>
<replace dir="build/standalone-resources/.resources/themes"
summary="true"
token="url(/themes/console/images/buttons/"
value="url(/i2psnark/.resources/icons/" >
<include name="**/*.css" />
</replace>
<!-- Rather than pulling in all the console theme images, let's just specify the ones we need -->
<copy file="../../routerconsole/jsp/themes/console/images/transparent.gif"
@ -296,6 +323,8 @@
todir="build/standalone-resources/.resources/themes/light/images" />
<copy file="../../routerconsole/jsp/themes/console/images/info/errortriangle.png"
todir="build/standalone-resources/.resources/themes/ubergine/images" />
<copy file="../../routerconsole/jsp/themes/console/images/buttons/search.png"
todir="build/standalone-resources/.resources/icons" />
<mkdir dir="build/standalone-resources/.resources/js" />
<copy file="../../routerconsole/jsp/js/ajax.js" todir="build/standalone-resources/.resources/js" />
@ -306,33 +335,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

@ -6,6 +6,7 @@ package org.klomp.snark;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PSession;
@ -32,7 +33,9 @@ class BWLimits {
session.connect();
rv = session.bandwidthLimits();
session.destroySession();
} catch (I2PSessionException ise) {}
} catch (I2PSessionException ise) {
I2PAppContext.getGlobalContext().logManager().getLog(BWLimits.class).warn("BWL fail", ise);
}
return rv;
}

View File

@ -0,0 +1,63 @@
package org.klomp.snark;
/**
* Bandwidth and bandwidth limits
*
* Maintain three bandwidth estimators:
* Sent, received, and requested.
*
* @since 0.9.62
*/
public interface BandwidthListener {
/**
* The average rate in Bps
*/
public long getUploadRate();
/**
* The average rate in Bps
*/
public long getDownloadRate();
/**
* We unconditionally sent this many bytes
*/
public void uploaded(int size);
/**
* We unconditionally received this many bytes
*/
public void downloaded(int size);
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
*/
public boolean shouldSend(int size);
/**
* Should we request this many bytes?
*/
public boolean shouldRequest(Peer peer, int size);
/**
* Current limit in BPS
*/
public long getUpBWLimit();
/**
* Current limit in BPS
*/
public long getDownBWLimit();
/**
* Are we currently over the limit?
*/
public boolean overUpBWLimit();
/**
* Are we currently over the limit?
*/
public boolean overDownBWLimit();
}

View File

@ -0,0 +1,179 @@
package org.klomp.snark;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.SyntheticREDQueue;
/**
* Bandwidth and bandwidth limits
*
* Maintain three bandwidth estimators:
* Sent, received, and requested.
*
* There are three layers of BandwidthListeners:
*<pre>
* BandwidthManager (total)
* PeerCoordinator (per-torrent)
* Peer/WebPeer (per-connection)
*</pre>
*
* Here at the top, we use SyntheticRedQueues for accurate
* and current moving averages of up, down, and requested bandwidth.
*
* At the lower layers, simple weighted moving averages of
* three buckets of 40 seconds each (2 minutes total) are used
* for up and down, and requested is delegated here.
*
* The lower layers must report to the next-higher layer.
*
* At the Peer layer, we report inbound piece data per-read,
* not per-piece, to get a smoother inbound estimate.
*
* Only the following data are counted by the BandwidthListeners:
*<ul><li>Pieces (both Peer and WebPeer)
*<li>ut_metadata
*</ul>
*
* No overhead at any layer is accounted for.
*
* @since 0.9.62
*/
public class BandwidthManager implements BandwidthListener {
private final I2PAppContext _context;
private final Log _log;
private SyntheticREDQueue _up, _down, _req;
BandwidthManager(I2PAppContext ctx, int upLimit, int downLimit) {
_context = ctx;
_log = ctx.logManager().getLog(BandwidthManager.class);
_up = new SyntheticREDQueue(ctx, upLimit);
_down = new SyntheticREDQueue(ctx, downLimit);
// Allow down limit a little higher based on testing
// Allow req limit a little higher still because it uses RED
// so it actually kicks in sooner.
_req = new SyntheticREDQueue(ctx, downLimit * 110 / 100);
}
/**
* Current limit in Bps
*/
void setUpBWLimit(long upLimit) {
int limit = (int) Math.min(upLimit, Integer.MAX_VALUE);
if (limit != getUpBWLimit())
_up = new SyntheticREDQueue(_context, limit);
}
/**
* Current limit in Bps
*/
void setDownBWLimit(long downLimit) {
int limit = (int) Math.min(downLimit, Integer.MAX_VALUE);
if (limit != getDownBWLimit()) {
_down = new SyntheticREDQueue(_context, limit);
_req = new SyntheticREDQueue(_context, limit * 110 / 100);
}
}
/**
* The average rate in Bps
*/
long getRequestRate() {
return (long) (1000f * _req.getBandwidthEstimate());
}
// begin BandwidthListener interface
/**
* The average rate in Bps
*/
public long getUploadRate() {
return (long) (1000f * _up.getBandwidthEstimate());
}
/**
* The average rate in Bps
*/
public long getDownloadRate() {
return (long) (1000f * _down.getBandwidthEstimate());
}
/**
* We unconditionally sent this many bytes
*/
public void uploaded(int size) {
_up.addSample(size);
}
/**
* We received this many bytes
*/
public void downloaded(int size) {
_down.addSample(size);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
*/
public boolean shouldSend(int size) {
boolean rv = _up.offer(size, 1.0f);
if (!rv && _log.shouldWarn())
_log.warn("Deny sending " + size + " bytes, upload rate " + DataHelper.formatSize(getUploadRate()) + "Bps");
return rv;
}
/**
* Should we request this many bytes?
*
* @param peer ignored
*/
public boolean shouldRequest(Peer peer, int size) {
boolean rv = !overDownBWLimit() && _req.offer(size, 1.0f);
if (!rv && _log.shouldWarn())
_log.warn("Deny requesting " + size + " bytes, download rate " + DataHelper.formatSize(getDownloadRate()) + "Bps" +
", request rate " + DataHelper.formatSize(getRequestRate()) + "Bps");
return rv;
}
/**
* Current limit in BPS
*/
public long getUpBWLimit() {
return _up.getMaxBandwidth();
}
/**
* Current limit in BPS
*/
public long getDownBWLimit() {
return _down.getMaxBandwidth();
}
/**
* Are we currently over the limit?
*/
public boolean overUpBWLimit() {
return getUploadRate() > getUpBWLimit();
}
/**
* Are we currently over the limit?
*/
public boolean overDownBWLimit() {
return getDownloadRate() > getDownBWLimit();
}
/**
* In HTML for debug page
*/
@Override
public String toString() {
return "<br><b>Bandwidth Limiters</b><br><b>Up:</b> " + _up +
"<br><b>Down:</b> " + _down +
"<br><b>Req:</b> " + _req +
"<br>";
}
}

View File

@ -4,8 +4,6 @@ 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.
@ -38,7 +36,7 @@ public class CommandLine extends net.i2p.util.CommandLine {
}
private static void usage(List<String> classes) {
System.err.println("I2PSnark version " + CoreVersion.VERSION + '\n' +
System.err.println("I2PSnark version " + SnarkManager.FULL_VERSION + '\n' +
"USAGE: java -jar /path/to/i2psnark.jar command [args]");
printCommands(classes);
}

View File

@ -83,4 +83,9 @@ public interface CompleteListener {
* @since 0.9.42
*/
public boolean shouldAutoStart();
/**
* @since 0.9.62
*/
public BandwidthListener getBandwidthListener();
}

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

@ -42,15 +42,5 @@ interface CoordinatorListener
*/
public boolean overUploadLimit(int uploaders);
/**
* Is i2psnark as a whole over its limit?
*/
public boolean overUpBWLimit();
/**
* Is a particular peer who has this recent download rate (in Bps) over our upstream bandwidth limit?
*/
public boolean overUpBWLimit(long total);
public void addMessage(String message);
}

View File

@ -190,6 +190,8 @@ abstract class ExtensionHandler {
}
if (log.shouldLog(Log.INFO))
log.info("Request chunk " + chk + " from " + peer);
// ignore the rv, always request
peer.shouldRequest(state.chunkSize(chk));
sendRequest(peer, chk);
}
} catch (Exception e) {
@ -230,7 +232,6 @@ abstract class ExtensionHandler {
sendPiece(peer, piece, pc, totalSize);
// Do this here because PeerConnectionOut only reports for PIECE messages
peer.uploaded(pc.length);
listener.uploaded(peer, pc.length);
} else if (type == TYPE_DATA) {
// On close reading of BEP 9, this is the total metadata size.
// Prior to 0.9.21, we sent the piece size, so we can't count on it.
@ -245,7 +246,6 @@ abstract class ExtensionHandler {
return;
int len = is.available();
peer.downloaded(len);
listener.downloaded(peer, len);
// this checks the size
done = state.saveChunk(piece, bs, bs.length - len, len);
if (log.shouldLog(Log.INFO))
@ -264,6 +264,8 @@ abstract class ExtensionHandler {
// get the next chunk
if (log.shouldLog(Log.INFO))
log.info("Request chunk " + chk + " from " + peer);
// ignore the rv, always request
peer.shouldRequest(state.chunkSize(chk));
sendRequest(peer, chk);
}
} else if (type == TYPE_REJECT) {

View File

@ -1,8 +1,15 @@
package org.klomp.snark;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
@ -13,6 +20,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@ -23,10 +31,12 @@ 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;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.ConcurrentHashSet;
@ -35,7 +45,9 @@ import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SystemVersion;
import net.i2p.util.Translate;
import org.klomp.snark.dht.DHT;
@ -47,7 +59,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 +87,8 @@ public class I2PSnarkUtil {
private List<String> _openTrackers;
private DHT _dht;
private long _startedTime;
private final DisconnectListener _discon;
private int _maxFilesPerTorrent = SnarkManager.DEFAULT_MAX_FILES_PER_TORRENT;
private static final int EEPGET_CONNECT_TIMEOUT = 45*1000;
private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000;
@ -91,17 +105,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);
@ -239,6 +254,11 @@ public class I2PSnarkUtil {
/** @since 0.9.1 */
public File getTempDir() { return _tmpDir; }
/** @since 0.9.58 */
public int getMaxFilesPerTorrent() { return _maxFilesPerTorrent; }
/** @since 0.9.58 */
public void setMaxFilesPerTorrent(int max) { _maxFilesPerTorrent = Math.max(max, 1); }
/**
* Connect to the router, if we aren't already
*/
@ -324,8 +344,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 +356,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 +577,9 @@ public class I2PSnarkUtil {
return null;
}
/**
* Full Base64 of Destination
*/
public String getOurIPString() {
Destination dest = getMyDestination();
if (dest != null)
@ -803,4 +846,90 @@ public class I2PSnarkUtil {
public String getString(int n, String s, String p) {
return Translate.getString(n, s, p, _context, BUNDLE_NAME);
}
private static final boolean SHOULD_SYNC = !(SystemVersion.isAndroid() || SystemVersion.isARM());
private static final Pattern ILLEGAL_KEY = Pattern.compile("[#=\\r\\n;]");
private static final Pattern ILLEGAL_VALUE = Pattern.compile("[\\r\\n]");
/**
* Same as DataHelper.loadProps() but allows '#' in values,
* so we can have filenames with '#' in them in torrent config files.
* '#' must be in column 1 for a comment.
*
* @since 0.9.58
*/
static void loadProps(Properties props, File f) throws IOException {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"), 1024);
String line = null;
while ( (line = in.readLine()) != null) {
if (line.trim().length() <= 0) continue;
if (line.charAt(0) == '#') continue;
if (line.charAt(0) == ';') continue;
int split = line.indexOf('=');
if (split <= 0) continue;
String key = line.substring(0, split);
String val = line.substring(split+1).trim();
props.setProperty(key, val);
}
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
}
}
/**
* Same as DataHelper.loadProps() but allows '#' in values,
* so we can have filenames with '#' in them in torrent config files.
* '#' must be in column 1 for a comment.
*
* @since 0.9.58
*/
static void storeProps(Properties props, File file) throws IOException {
FileOutputStream fos = null;
PrintWriter out = null;
IOException ioe = null;
File tmpFile = new File(file.getPath() + ".tmp");
try {
fos = new SecureFileOutputStream(tmpFile);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(fos, "UTF-8")));
out.println("# NOTE: This I2P config file must use UTF-8 encoding");
out.println("# Last saved: " + DataHelper.formatTime(System.currentTimeMillis()));
for (Map.Entry<Object, Object> entry : props.entrySet()) {
String name = (String) entry.getKey();
String val = (String) entry.getValue();
if (ILLEGAL_KEY.matcher(name).find()) {
if (ioe == null)
ioe = new IOException("Invalid character (one of \"#;=\\r\\n\") in key: \"" +
name + "\" = \"" + val + '\"');
continue;
}
if (ILLEGAL_VALUE.matcher(val).find()) {
if (ioe == null)
ioe = new IOException("Invalid character (one of \"\\r\\n\") in value: \"" +
name + "\" = \"" + val + '\"');
continue;
}
out.println(name + "=" + val);
}
if (SHOULD_SYNC) {
out.flush();
fos.getFD().sync();
}
out.close();
if (out.checkError()) {
out = null;
tmpFile.delete();
throw new IOException("Failed to write properties to " + tmpFile);
}
out = null;
if (!FileUtil.rename(tmpFile, file))
throw new IOException("Failed rename from " + tmpFile + " to " + file);
} finally {
if (out != null) out.close();
if (fos != null) try { fos.close(); } catch (IOException e) {}
}
if (ioe != null)
throw ioe;
}
}

View File

@ -63,7 +63,7 @@ public class MetaInfo
private final int piece_length;
private final byte[] piece_hashes;
private final long length;
private final boolean privateTorrent;
private final int privateTorrent; // 0: not present; 1: = 1; -1: = 0
private final List<List<String>> announce_list;
private final String comment;
private final String created_by;
@ -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)
{
@ -96,7 +97,7 @@ public class MetaInfo
this.piece_length = piece_length;
this.piece_hashes = piece_hashes;
this.length = length;
this.privateTorrent = privateTorrent;
this.privateTorrent = privateTorrent ? 1 : 0;
this.announce_list = announce_list;
this.comment = comment;
this.created_by = created_by;
@ -116,9 +117,37 @@ public class MetaInfo
//infoMap = null;
}
/**
* Preserves privateTorrent int value, for main()
*
* @since 0.9.62
*/
public MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
int piece_length, byte[] piece_hashes, long length, int privateTorrent,
List<List<String>> announce_list, String created_by, List<String> url_list, String comment)
{
this.announce = announce;
this.name = name;
this.name_utf8 = name_utf8;
this.files = files == null ? null : Collections.unmodifiableList(files);
this.files_utf8 = null;
this.lengths = lengths == null ? null : Collections.unmodifiableList(lengths);
this.piece_length = piece_length;
this.piece_hashes = piece_hashes;
this.length = length;
this.privateTorrent = privateTorrent;
this.announce_list = announce_list;
this.comment = comment;
this.created_by = created_by;
this.creation_date = I2PAppContext.getGlobalContext().clock().now();
this.url_list = url_list;
this.attributes = null;
this.info_hash = calculateInfoHash();
}
/**
* Creates a new MetaInfo from the given InputStream. The
* InputStream must start with a correctly bencoded dictonary
* InputStream must start with a correctly bencoded dictionary
* describing the torrent.
* Caller must close the stream.
*/
@ -143,7 +172,7 @@ public class MetaInfo
/**
* Creates a new MetaInfo from a Map of BEValues and the SHA1 over
* the original bencoded info dictonary (this is a hack, we could
* the original bencoded info dictionary (this is a hack, we could
* reconstruct the bencoded stream and recalculate the hash). Will
* NOT throw a InvalidBEncodingException if the given map does not
* contain a valid announce string.
@ -185,11 +214,20 @@ public class MetaInfo
if (val == null) {
this.url_list = null;
} else {
List<BEValue> bl1 = val.getList();
this.url_list = new ArrayList<String>(bl1.size());
for (BEValue bev : bl1) {
this.url_list.add(bev.getString());
List<String> urllist;
try {
List<BEValue> bl1 = val.getList();
urllist = new ArrayList<String>(bl1.size());
for (BEValue bev : bl1) {
urllist.add(bev.getString());
}
} catch (InvalidBEncodingException ibee) {
// BEP 19 says it's a list but the example there
// is for a single byte string, and we've seen this
// in the wild.
urllist = Collections.singletonList(val.getString());
}
this.url_list = urllist;
}
// misc. optional top-level stuff
@ -247,10 +285,11 @@ public class MetaInfo
// Transmission does numbers. So does libtorrent.
// We handle both as of 0.9.9.
// We switch to storing as number as of 0.9.14.
privateTorrent = "1".equals(o) ||
boolean privat = "1".equals(o) ||
((o instanceof Number) && ((Number) o).intValue() == 1);
privateTorrent = privat ? 1 : -1;
} else {
privateTorrent = false;
privateTorrent = 0;
}
val = info.get("piece length");
@ -442,9 +481,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;
}
@ -464,6 +506,14 @@ public class MetaInfo
* @since 0.9
*/
public boolean isPrivate() {
return privateTorrent > 0;
}
/**
* @return 0 (default), 1 (set to 1), -1 (set to 0)
* @since 0.9.62
*/
public int getPrivateTrackerStatus() {
return privateTorrent;
}
@ -716,18 +766,19 @@ 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)));
if (name_utf8 != null)
info.put("name.utf-8", new BEValue(DataHelper.getUTF8(name_utf8)));
// BEP 27
if (privateTorrent)
if (privateTorrent != 0)
// switched to number in 0.9.14
//info.put("private", new BEValue(DataHelper.getUTF8("1")));
info.put("private", new BEValue(Integer.valueOf(1)));
info.put("private", new BEValue(Integer.valueOf(privateTorrent > 0 ? 1 : 0)));
info.put("piece length", new BEValue(Integer.valueOf(piece_length)));
info.put("pieces", new BEValue(piece_hashes));
@ -862,7 +913,7 @@ public class MetaInfo
List<String> urls = url_list != null ? url_list : meta.getWebSeedURLs();
// changes/adds creation date
MetaInfo meta2 = new MetaInfo(an, meta.getName(), null, meta.getFiles(), meta.getLengths(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.isPrivate(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.getPrivateTrackerStatus(),
meta.getAnnounceList(), cb, urls, cm);
java.io.File from = new java.io.File(args[i]);
java.io.File to = new java.io.File(args[i] + ".bak");

View File

@ -2,6 +2,7 @@ package org.klomp.snark;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
@ -43,6 +44,7 @@ class PartialPiece implements Comparable<PartialPiece> {
private RandomAccessFile raf;
private final int pclen;
private final File tempDir;
private final BitField bitfield;
private static final int BUFSIZE = PeerState.PARTSIZE;
private static final ByteCache _cache = ByteCache.getInstance(16, BUFSIZE);
@ -66,6 +68,7 @@ class PartialPiece implements Comparable<PartialPiece> {
this.pclen = len;
//this.createdTime = 0;
this.tempDir = tempDir;
bitfield = new BitField((len + PeerState.PARTSIZE - 1) / PeerState.PARTSIZE);
// temps for finals
byte[] tbs = null;
@ -98,22 +101,27 @@ class PartialPiece implements Comparable<PartialPiece> {
//tfile = SecureFile.createTempFile("piece", null, tempDir);
// debug
tempfile = SecureFile.createTempFile("piece_" + piece.getId() + '_', null, tempDir);
//I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn("Created " + tempfile);
// tfile.deleteOnExit() ???
raf = new RandomAccessFile(tempfile, "rw");
// Do not preallocate the file space.
// Not necessary to call setLength(), file is extended when written
//traf.setLength(len);
}
/**
* Convert this PartialPiece to a request for the next chunk.
* Used by PeerState only. This depends on the downloaded value
* as set by setDownloaded() or read().
* Used by PeerState only.
*
* @return null if complete
*/
public synchronized Request getRequest() {
return new Request(this, this.off, Math.min(this.pclen - this.off, PeerState.PARTSIZE));
int chunk = off / PeerState.PARTSIZE;
int sz = bitfield.size();
for (int i = chunk; i < sz; i++) {
if (!bitfield.get(i))
return new Request(this, off, Math.min(pclen - off, PeerState.PARTSIZE));
if (i == sz - 1)
off = pclen;
else
off += PeerState.PARTSIZE;
}
return null;
}
/** piece number */
@ -129,28 +137,20 @@ class PartialPiece implements Comparable<PartialPiece> {
}
/**
* How many bytes are good - as set by setDownloaded() or read()
* @since 0.9.62
*/
public synchronized boolean isComplete() {
return bitfield.complete();
}
/**
* How many consecutive bytes are good - as set by read().
* There may be more good bytes after "holes".
*/
public synchronized int getDownloaded() {
return this.off;
}
/**
* Call this if necessary before returning a PartialPiece to the PeerCoordinator.
* We do not use a bitmap to track individual chunks received.
* Any chunks after a 'hole' will be lost.
* @since 0.9.1
*/
public synchronized void setDownloaded(int offset) {
this.off = offset;
}
/****
public long getCreated() {
return this.createdTime;
}
****/
/**
* Piece must be complete.
* The SHA1 hash of the completely read data.
@ -200,13 +200,47 @@ class PartialPiece implements Comparable<PartialPiece> {
*
* @since 0.9.1
*/
public void read(DataInputStream din, int offset, int len) throws IOException {
public void read(DataInputStream din, int offset, int len, BandwidthListener bwl) throws IOException {
if (offset % PeerState.PARTSIZE != 0)
throw new IOException("Bad offset " + offset);
int chunk = offset / PeerState.PARTSIZE;
// We read the data before checking if we have the chunk,
// because otherwise we'd have to break the peer connection
if (bs != null) {
din.readFully(bs, offset, len);
// Don't use readFully() so we may update the BandwidthListener as we go
//in.readFully(bs, offset, len);
int offs = offset;
int toRead = len;
while (toRead > 0) {
int numRead = din.read(bs, offs, toRead);
if (numRead < 0)
throw new EOFException();
offs += numRead;
toRead -= numRead;
bwl.downloaded(numRead);
}
synchronized (this) {
// only works for in-order chunks
if (this.off == offset)
this.off += len;
if (bitfield.get(chunk)) {
warn("Already have chunk " + chunk + " on " + this);
} else {
bitfield.set(chunk);
if (this.off == offset) {
this.off += len;
// if this filled in a hole, advance off
int sz = bitfield.size();
for (int i = chunk + 1; i < sz; i++) {
if (!bitfield.get(i))
break;
warn("Hole filled in before chunk " + i + " on " + this + ' ' + bitfield);
if (i == sz - 1)
off = pclen;
else
off += PeerState.PARTSIZE;
}
} else {
warn("Out of order chunk " + chunk + " on " + this + ' ' + bitfield);
}
}
}
} else {
// read in fully before synching on raf
@ -219,15 +253,46 @@ class PartialPiece implements Comparable<PartialPiece> {
ba = null;
tmp = new byte[len];
}
din.readFully(tmp);
// Don't use readFully() so we may update the BandwidthListener as we go
//din.readFully(tmp);
int offs = 0;
int toRead = len;
while (toRead > 0) {
int numRead = din.read(tmp, offs, toRead);
if (numRead < 0)
throw new EOFException();
offs += numRead;
toRead -= numRead;
bwl.downloaded(numRead);
}
synchronized (this) {
if (raf == null)
createTemp();
raf.seek(offset);
raf.write(tmp);
// only works for in-order chunks
if (this.off == offset)
this.off += len;
if (bitfield.get(chunk)) {
warn("Already have chunk " + chunk + " on " + this);
} else {
if (raf == null)
createTemp();
raf.seek(offset);
raf.write(tmp);
bitfield.set(chunk);
if (this.off == offset) {
this.off += len;
// if this filled in a hole, advance off
int sz = bitfield.size();
for (int i = chunk + 1; i < sz; i++) {
if (!bitfield.get(i))
break;
warn("Hole filled in before chunk " + i + " on " + this + ' ' + bitfield);
if (i == sz - 1)
off = pclen;
else
off += PeerState.PARTSIZE;
}
} else {
warn("Out of order chunk " + chunk + " on " + this + ' ' + bitfield);
}
}
}
if (ba != null)
_cache.release(ba, false);
@ -300,7 +365,6 @@ class PartialPiece implements Comparable<PartialPiece> {
try {
raf.close();
} catch (IOException ioe) {
I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn("Error closing " + raf, ioe);
}
tempfile.delete();
}
@ -339,4 +403,11 @@ class PartialPiece implements Comparable<PartialPiece> {
public String toString() {
return "Partial(" + piece.getId() + ',' + off + ',' + pclen + ')';
}
/**
* @since 0.9.62
*/
public static void warn(String s) {
I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn(s);
}
}

View File

@ -40,7 +40,7 @@ import net.i2p.util.Log;
import org.klomp.snark.bencode.BEValue;
import org.klomp.snark.bencode.InvalidBEncodingException;
public class Peer implements Comparable<Peer>
public class Peer implements Comparable<Peer>, BandwidthListener
{
protected final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
// Identifying property, the peer id of the other side.
@ -239,7 +239,7 @@ public class Peer implements Comparable<Peer>
*
* @param uploadOnly if we are complete with skipped files, i.e. a partial seed
*/
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield,
public void runConnection(I2PSnarkUtil util, PeerListener listener, BandwidthListener bwl, BitField bitfield,
MagnetState mState, boolean uploadOnly) {
if (state != null)
throw new IllegalStateException("Peer already started");
@ -288,7 +288,7 @@ public class Peer implements Comparable<Peer>
PeerConnectionIn in = new PeerConnectionIn(this, din);
PeerConnectionOut out = new PeerConnectionOut(this, dout);
PeerState s = new PeerState(this, listener, metainfo, in, out);
PeerState s = new PeerState(this, listener, bwl, metainfo, in, out);
if ((options & OPTION_EXTENSION) != 0) {
if (_log.shouldLog(Log.DEBUG))
@ -651,12 +651,17 @@ public class Peer implements Comparable<Peer>
return (s == null) || s.choked;
}
/////// begin BandwidthListener interface ///////
/**
* Increment the counter.
* @since 0.8.4
*/
public void downloaded(int size) {
downloaded.addAndGet(size);
PeerState s = state;
if (s != null)
s.getBandwidthListener().downloaded(size);
}
/**
@ -665,6 +670,9 @@ public class Peer implements Comparable<Peer>
*/
public void uploaded(int size) {
uploaded.addAndGet(size);
PeerState s = state;
if (s != null)
s.getBandwidthListener().uploaded(size);
}
/**
@ -688,13 +696,115 @@ public class Peer implements Comparable<Peer>
}
/**
* Returns the average rate in Bps
*/
public long getUploadRate()
{
return PeerCoordinator.getRate(uploaded_old);
}
public long getDownloadRate()
{
return PeerCoordinator.getRate(downloaded_old);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() after this.
* @since 0.9.62
*/
public boolean shouldSend(int size) {
PeerState s = state;
if (s != null) {
boolean rv = s.getBandwidthListener().shouldSend(size);
if (rv)
uploaded.addAndGet(size);
return rv;
}
return false;
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
public boolean shouldRequest(int size) {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().shouldRequest(this, size);
return false;
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
public boolean shouldRequest(Peer peer, int size) {
if (peer != this)
return false;
PeerState s = state;
if (s != null)
return s.getBandwidthListener().shouldRequest(this, size);
return false;
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getUpBWLimit() {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().getUpBWLimit();
return Integer.MAX_VALUE;
}
/**
* Is snark as a whole over its limit?
* @since 0.9.62
*/
public boolean overUpBWLimit()
{
PeerState s = state;
if (s != null)
return s.getBandwidthListener().overUpBWLimit();
return false;
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getDownBWLimit() {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().getDownBWLimit();
return Integer.MAX_VALUE;
}
/**
* Are we currently over the limit?
* @since 0.9.62
*/
public boolean overDownBWLimit() {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().overDownBWLimit();
return false;
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
* Resets the downloaded and uploaded counters to zero.
*/
public void resetCounters()
{
downloaded.set(0);
uploaded.set(0);
void setRateHistory() {
long up = uploaded.getAndSet(0);
PeerCoordinator.setRate(up, uploaded_old);
long down = downloaded.getAndSet(0);
PeerCoordinator.setRate(down, downloaded_old);
}
/////// end BandwidthListener interface ///////
public long getInactiveTime() {
PeerState s = state;
@ -761,28 +871,6 @@ public class Peer implements Comparable<Peer>
return s.bitfield.complete();
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
*/
public void setRateHistory(long up, long down)
{
PeerCoordinator.setRate(up, uploaded_old);
PeerCoordinator.setRate(down, downloaded_old);
}
/**
* Returns the 4-minute-average rate in Bps
*/
public long getUploadRate()
{
return PeerCoordinator.getRate(uploaded_old);
}
public long getDownloadRate()
{
return PeerCoordinator.getRate(downloaded_old);
}
/** @since 0.9.31 */
int getTotalCommentsSent() {
return _totalCommentsSent;

View File

@ -113,8 +113,7 @@ class PeerCheckerTask implements Runnable
uploaded += upload;
long download = peer.getDownloaded();
downloaded += download;
peer.setRateHistory(upload, download);
peer.resetCounters();
peer.setRateHistory();
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(peer + ":"
@ -127,10 +126,9 @@ class PeerCheckerTask implements Runnable
}
// Choke a percentage of them rather than all so it isn't so drastic...
// unless this torrent is over the limit all by itself.
// choke 5/8 of the time when seeding and 3/8 when leeching
// choke 3/8 of the time when seeding and 1/4 when leeching
boolean overBWLimitChoke = upload > 0 &&
((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 2 : 4))) ||
((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 4 : 5))) ||
(coordinator.overUpBWLimit(uploaded)));
// If we are at our max uploaders and we have lots of other

View File

@ -157,7 +157,7 @@ class PeerConnectionIn implements Runnable
Request req = ps.getOutstandingRequest(piece, begin, len);
if (req != null)
{
req.read(din);
req.read(din, peer);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Received data(" + piece + "," + begin + ") from " + peer);
ps.pieceMessage(req);

View File

@ -73,6 +73,7 @@ class PeerConnectionOut implements Runnable
{
try
{
boolean shouldThrottleRequests = false;
while (!quit && peer.isConnected())
{
Message m = null;
@ -89,7 +90,7 @@ class PeerConnectionOut implements Runnable
synchronized(sendQueue)
{
while (!quit && peer.isConnected() && sendQueue.isEmpty())
while (!quit && peer.isConnected() && (shouldThrottleRequests || sendQueue.isEmpty()))
{
try
{
@ -98,12 +99,13 @@ class PeerConnectionOut implements Runnable
// dout.flush();
// Wait till more data arrives.
sendQueue.wait(60*1000);
sendQueue.wait(shouldThrottleRequests ? 5000 : 60*1000);
}
catch (InterruptedException ie)
{
/* ignored */
}
shouldThrottleRequests = false;
}
state = peer.state;
if (!quit && state != null && peer.isConnected())
@ -125,7 +127,6 @@ class PeerConnectionOut implements Runnable
{
if (state.choking) {
it.remove();
//SimpleTimer.getInstance().removeEvent(nm.expireEvent);
if (peer.supportsFast()) {
Message r = new Message(Message.REJECT, nm.piece, nm.begin, nm.length);
if (_log.shouldLog(Log.DEBUG))
@ -135,23 +136,50 @@ class PeerConnectionOut implements Runnable
}
nm = null;
}
else if (nm.type == Message.REQUEST && state.choked)
else if (nm.type == Message.REQUEST)
{
it.remove();
//SimpleTimer.getInstance().removeEvent(nm.expireEvent);
nm = null;
if (state.choked) {
it.remove();
nm = null;
} else if (shouldThrottleRequests) {
// previous request in queue throttled, skip this one too
if (_log.shouldWarn())
_log.warn("Additional throttle: " + nm + " to " + peer);
nm = null;
} else if (!peer.shouldRequest(nm.length)) {
// request throttle, skip this and all others in this loop
if (_log.shouldWarn())
_log.warn("Throttle: " + nm + " to " + peer);
shouldThrottleRequests = true;
nm = null;
}
}
if (nm != null)
{
m = nm;
//SimpleTimer.getInstance().removeEvent(nm.expireEvent);
it.remove();
}
}
if (m == null) {
m = sendQueue.poll();
//SimpleTimer.getInstance().removeEvent(m.expireEvent);
m = sendQueue.peek();
if (m != null && m.type == Message.PIECE) {
// bandwidth limiting
// Pieces are the last thing in the queue to be sent so we can
// simply wait right here and then loop
if (!peer.shouldSend(Math.min(m.length, PeerState.PARTSIZE))) {
if (_log.shouldWarn())
_log.warn("Throttle: " + m + " to " + peer);
try {
sendQueue.wait(5000);
} catch (InterruptedException ie) {}
continue;
}
} else if (m != null && m.type == Message.REQUEST) {
if (shouldThrottleRequests)
continue;
}
m = sendQueue.poll();
}
}
}
@ -178,17 +206,14 @@ class PeerConnectionOut implements Runnable
// only count the rest of the upload after sendMessage().
int remainder = 0;
if (m.type == Message.PIECE) {
if (m.len <= PeerState.PARTSIZE) {
state.uploaded(m.len);
} else {
state.uploaded(PeerState.PARTSIZE);
// first PARTSIZE was signalled in shouldSend() above
if (m.len > PeerState.PARTSIZE)
remainder = m.len - PeerState.PARTSIZE;
}
}
m.sendMessage(dout);
if (remainder > 0)
state.uploaded(remainder);
peer.uploaded(remainder);
m = null;
}
}

View File

@ -55,7 +55,7 @@ import org.klomp.snark.dht.DHT;
/**
* Coordinates what peer does what.
*/
class PeerCoordinator implements PeerListener
class PeerCoordinator implements PeerListener, BandwidthListener
{
private final Log _log;
@ -124,6 +124,12 @@ class PeerCoordinator implements PeerListener
/** Timer to handle all periodical tasks. */
private final CheckEvent timer;
// RerequestEvent and related values
private final SimpleTimer2.TimedEvent rerequestTimer;
private final Object rerequestLock = new Object();
private boolean wasRequestAllowed;
private boolean isRerequestScheduled;
private final byte[] id;
private final byte[] infohash;
@ -145,6 +151,7 @@ class PeerCoordinator implements PeerListener
private final MagnetState magnetState;
private final CoordinatorListener listener;
private final BandwidthListener bwListener;
private final I2PSnarkUtil _util;
private final RandomSource _random;
@ -163,7 +170,7 @@ class PeerCoordinator implements PeerListener
* @param storage null if in magnet mode
*/
public PeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage,
CoordinatorListener listener, Snark torrent)
CoordinatorListener listener, Snark torrent, BandwidthListener bwl)
{
_util = util;
_random = util.getContext().random();
@ -174,6 +181,7 @@ class PeerCoordinator implements PeerListener
this.storage = storage;
this.listener = listener;
this.snark = torrent;
bwListener = bwl;
wantedPieces = new ArrayList<Piece>();
setWantedPieces();
@ -188,6 +196,9 @@ class PeerCoordinator implements PeerListener
timer = new CheckEvent(_util.getContext(), new PeerCheckerTask(_util, this));
timer.schedule((CHECK_PERIOD / 2) + _random.nextInt((int) CHECK_PERIOD));
// NOT scheduled until needed
rerequestTimer = new RerequestEvent();
// we don't store the last-requested time, so just delay a random amount
_commentsLastRequested.set(util.getContext().clock().now() - (COMMENT_REQ_INTERVAL - _random.nextLong(COMMENT_REQ_DELAY)));
}
@ -208,6 +219,42 @@ class PeerCoordinator implements PeerListener
}
}
/**
* Rerequest after unthrottled
* @since 0.9.62
*/
private class RerequestEvent extends SimpleTimer2.TimedEvent {
/** caller must schedule */
public RerequestEvent() {
super(_util.getContext().simpleTimer2());
}
public void timeReached() {
if (bwListener.shouldRequest(null, 0)) {
if (_log.shouldWarn())
_log.warn("Now unthrottled, rerequest timer poking all peers");
// so shouldRequest() won't fire us up again
synchronized(rerequestLock) {
wasRequestAllowed = true;
}
for (Peer p : peers) {
if (p.isInteresting() && !p.isChoked())
p.request();
}
synchronized(rerequestLock) {
isRerequestScheduled = false;
}
} else {
if (_log.shouldWarn())
_log.warn("Still throttled, rerequest timer reschedule");
synchronized(rerequestLock) {
wasRequestAllowed = false;
}
schedule(2*1000);
}
}
}
/**
* Only called externally from Storage after the double-check fails.
* Sets wantedBytes too.
@ -279,7 +326,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 +333,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;
}
/**
@ -324,6 +375,78 @@ class PeerCoordinator implements PeerListener
return downloaded.get();
}
/////// begin BandwidthListener interface ///////
/**
* Called when a peer has uploaded some bytes of a piece.
* @since 0.9.62 params changed
*/
public void uploaded(int size) {
uploaded.addAndGet(size);
bwListener.uploaded(size);
}
/**
* Called when a peer has downloaded some bytes of a piece.
* @since 0.9.62 params changed
*/
public void downloaded(int size) {
downloaded.addAndGet(size);
bwListener.downloaded(size);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
* @since 0.9.62
*/
public boolean shouldSend(int size) {
boolean rv = bwListener.shouldSend(size);
if (rv)
uploaded.addAndGet(size);
return rv;
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
public boolean shouldRequest(Peer peer, int size) {
boolean rv;
synchronized(rerequestLock) {
rv = bwListener.shouldRequest(peer, size);
if (!wasRequestAllowed && rv) {
// we weren't allowed and now we are
if (isRerequestScheduled) {
// just let the timer run when scheduled, do not pull it in
// to prevent thrashing
//if (_log.shouldWarn())
// _log.warn("Now unthrottled, BUT DON'T reschedule rerequest timer");
} else {
// schedule the timer
// we still have to throw it to the timer so we don't loop
if (_log.shouldWarn())
_log.warn("Now unthrottled, schedule rerequest timer");
isRerequestScheduled = true;
// no rush, wait at little while
rerequestTimer.reschedule(1000);
}
wasRequestAllowed = true;
} else if (wasRequestAllowed && !rv) {
// we were allowed and now we aren't
if (!isRerequestScheduled) {
// schedule the timer
if (_log.shouldWarn())
_log.warn("Now throttled, schedule rerequest timer");
isRerequestScheduled = true;
rerequestTimer.schedule(3*1000);
}
wasRequestAllowed = false;
}
}
return rv;
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
*/
@ -398,6 +521,49 @@ class PeerCoordinator implements PeerListener
return rate / (factor * CHECK_PERIOD / 1000);
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getUpBWLimit() {
return bwListener.getUpBWLimit();
}
/**
* Is snark as a whole over its limit?
*/
public boolean overUpBWLimit()
{
return bwListener.overUpBWLimit();
}
/**
* Is a particular peer who has downloaded this many bytes from us
* in the last CHECK_PERIOD over its limit?
*/
public boolean overUpBWLimit(long total)
{
return total * 1000 / CHECK_PERIOD > getUpBWLimit();
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getDownBWLimit() {
return bwListener.getDownBWLimit();
}
/**
* Are we currently over the limit?
* @since 0.9.62
*/
public boolean overDownBWLimit() {
return bwListener.overDownBWLimit();
}
/////// end BandwidthListener interface ///////
public MetaInfo getMetaInfo()
{
return metainfo;
@ -448,10 +614,12 @@ class PeerCoordinator implements PeerListener
if (metainfo == null)
return 6;
int pieces = metainfo.getPieces();
if (pieces <= 2)
if (pieces <= 10)
return 4;
if (pieces <= 5)
return 6;
if (pieces <= 25)
return 10;
if (pieces <= 80)
return 16;
//int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
// Now that we use temp files, no memory concern
@ -653,7 +821,7 @@ class PeerCoordinator implements PeerListener
{
public void run()
{
peer.runConnection(_util, listener, bitfield, magnetState, partialComplete);
peer.runConnection(_util, listener, PeerCoordinator.this, bitfield, magnetState, partialComplete);
}
};
String threadName = "Snark peer " + peer.toString();
@ -677,6 +845,8 @@ class PeerCoordinator implements PeerListener
{
if (storage == null || storage.getBitField().size() == 0)
return;
if (overUpBWLimit())
return;
// linked list will contain all interested peers that we choke.
// At the start are the peers that have us unchoked at the end the
@ -774,15 +944,6 @@ class PeerCoordinator implements PeerListener
*/
private static final int MAX_PARALLEL_REQUESTS = 4;
/**
* Returns one of pieces in the given BitField that is still wanted or
* -1 if none of the given pieces are wanted.
*/
public int wantPiece(Peer peer, BitField havePieces) {
Piece pc = wantPiece(peer, havePieces, true);
return pc != null ? pc.getId() : -1;
}
/**
* Returns one of pieces in the given BitField that is still wanted or
* null if none of the given pieces are wanted.
@ -999,28 +1160,6 @@ class PeerCoordinator implements PeerListener
}
}
/**
* Called when a peer has uploaded some bytes of a piece.
*/
public void uploaded(Peer peer, int size)
{
uploaded.addAndGet(size);
//if (listener != null)
// listener.peerChange(this, peer);
}
/**
* Called when a peer has downloaded some bytes of a piece.
*/
public void downloaded(Peer peer, int size)
{
downloaded.addAndGet(size);
//if (listener != null)
// listener.peerChange(this, peer);
}
/**
* Returns false if the piece is no good (according to the hash).
* In that case the peer that supplied the piece should probably be
@ -1155,7 +1294,7 @@ class PeerCoordinator implements PeerListener
}
if (uploaders.get() < allowedUploaders())
{
if(peer.isChoking())
if(peer.isChoking() && !overUpBWLimit())
{
uploaders.incrementAndGet();
interestedUploaders.incrementAndGet();
@ -1213,7 +1352,7 @@ class PeerCoordinator implements PeerListener
* Also mark the piece unrequested if this peer was the only one.
*
* @param peer partials, must include the zero-offset (empty) ones too.
* No dup pieces, piece.setDownloaded() must be set.
* No dup pieces.
* len field in Requests is ignored.
* @since 0.8.2
*/
@ -1734,27 +1873,6 @@ class PeerCoordinator implements PeerListener
interestedAndChoking.addAndGet(toAdd);
}
/**
* Is snark as a whole over its limit?
*/
public boolean overUpBWLimit()
{
if (listener != null)
return listener.overUpBWLimit();
return false;
}
/**
* Is a particular peer who has downloaded this many bytes from us
* in the last CHECK_PERIOD over its limit?
*/
public boolean overUpBWLimit(long total)
{
if (listener != null)
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
return false;
}
/**
* Convenience
* @since 0.9.2

View File

@ -120,36 +120,6 @@ interface PeerListener
*/
ByteArray gotRequest(Peer peer, int piece, int off, int len);
/**
* Called when a (partial) piece has been downloaded from the peer.
*
* @param peer the Peer from which size bytes where downloaded.
* @param size the number of bytes that where downloaded.
*/
void downloaded(Peer peer, int size);
/**
* Called when a (partial) piece has been uploaded to the peer.
*
* @param peer the Peer to which size bytes where uploaded.
* @param size the number of bytes that where uploaded.
*/
void uploaded(Peer peer, int size);
/**
* Called when we are downloading from the peer and need to ask for
* a new piece. Might be called multiple times before
* <code>gotPiece()</code> is called.
*
* @param peer the Peer that will be asked to provide the piece.
* @param bitfield a BitField containing the pieces that the other
* side has.
*
* @return one of the pieces from the bitfield that we want or -1 if
* we are no longer interested in the peer.
*/
int wantPiece(Peer peer, BitField bitfield);
/**
* Called when we are downloading from the peer and may need to ask for
* a new piece. Returns true if wantPiece() or getPartialPiece() would return a piece.

View File

@ -41,6 +41,7 @@ class PeerState implements DataLoader
private final Peer peer;
/** Fixme, used by Peer.disconnect() to get to the coordinator */
final PeerListener listener;
private final BandwidthListener bwListener;
/** Null before we have it. locking: this */
private MetaInfo metainfo;
/** Null unless needed. Contains -1 for all. locking: this */
@ -67,6 +68,7 @@ class PeerState implements DataLoader
private final List<Request> outstandingRequests = new ArrayList<Request>();
/** the tail (NOT the head) of the request queue */
private Request lastRequest = null;
private int currentMaxPipeline;
// FIXME if piece size < PARTSIZE, pipeline could be bigger
/** @since 0.9.47 */
@ -81,17 +83,23 @@ class PeerState implements DataLoader
/**
* @param metainfo null if in magnet mode
*/
PeerState(Peer peer, PeerListener listener, MetaInfo metainfo,
PeerState(Peer peer, PeerListener listener, BandwidthListener bwl, MetaInfo metainfo,
PeerConnectionIn in, PeerConnectionOut out)
{
this.peer = peer;
this.listener = listener;
bwListener = bwl;
this.metainfo = metainfo;
this.in = in;
this.out = out;
}
/**
* @since 0.9.62
*/
BandwidthListener getBandwidthListener() { return bwListener; }
// NOTE Methods that inspect or change the state synchronize (on this).
void keepAliveMessage()
@ -389,7 +397,6 @@ class PeerState implements DataLoader
void uploaded(int size)
{
peer.uploaded(size);
listener.uploaded(peer, size);
}
// This is used to flag that we have to back up from the firstOutstandingRequest
@ -408,8 +415,8 @@ class PeerState implements DataLoader
void pieceMessage(Request req)
{
int size = req.len;
peer.downloaded(size);
listener.downloaded(peer, size);
// Now reported byte-by-byte in PartialPiece
//peer.downloaded(size);
if (_log.shouldLog(Log.DEBUG))
_log.debug("got end of Chunk("
@ -417,11 +424,11 @@ class PeerState implements DataLoader
+ peer);
// Last chunk needed for this piece?
// FIXME if priority changed to skip, we will think we're done when we aren't
if (getFirstOutstandingRequest(req.getPiece()) == -1)
PartialPiece pp = req.getPartialPiece();
if (pp.isComplete())
{
// warning - may block here for a while
if (listener.gotPiece(peer, req.getPartialPiece()))
if (listener.gotPiece(peer, pp))
{
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got " + req.getPiece() + ": " + peer);
@ -445,6 +452,9 @@ class PeerState implements DataLoader
}
/**
* TODO this is how we tell we got all the chunks in pieceMessage() above.
*
*
* @return index in outstandingRequests or -1
*/
synchronized private int getFirstOutstandingRequest(int piece)
@ -873,65 +883,91 @@ class PeerState implements DataLoader
* By PeerCoordinator.updatePiecePriorities()
*</pre>
*/
synchronized void addRequest()
void addRequest()
{
// no bitfield yet? nothing to request then.
if (bitfield == null)
return;
if (metainfo == null)
return;
boolean more_pieces = true;
while (more_pieces)
{
more_pieces = outstandingRequests.size() < peer.getMaxPipeline();
// We want something and we don't have outstanding requests?
if (more_pieces && lastRequest == null) {
// we have nothing in the queue right now
if (!interesting) {
// If we need something, set interesting but delay pulling
// a request from the PeerCoordinator until unchoked.
if (listener.needPiece(this.peer, bitfield)) {
setInteresting(true);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we need something, setting interesting, delaying requestNextPiece()");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() needs nothing");
}
return;
}
if (choked) {
// If choked, delay pulling
// a request from the PeerCoordinator until unchoked.
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()");
return;
}
// huh? rv unused
more_pieces = requestNextPiece();
} else if (more_pieces) // We want something
// Initial bw check. We do the actual accounting in PeerConnectionOut.
// Implement a simple AIMD slow-start on the request queue size with
// currentMaxPipeline counter.
// Avoid cross-peer deadlocks from PeerCoordinator, call this outside the lock
if (!bwListener.shouldRequest(peer, 0)) {
synchronized(this) {
// Due to changes elsewhere we can let this go down to zero now
currentMaxPipeline /= 2;
}
if (_log.shouldWarn())
_log.warn(peer + " throttle request, interesting? " + interesting + " choked? " + choked +
" reqq: " + outstandingRequests.size() + " maxp: " + currentMaxPipeline);
return;
}
synchronized(this) {
// adjust currentMaxPipeline
long rate = bwListener.getDownloadRate();
long limit = bwListener.getDownBWLimit();
if (rate < limit * 7 / 10) {
if (currentMaxPipeline < peer.getMaxPipeline())
currentMaxPipeline++;
} else if (rate > limit * 9 / 10) {
currentMaxPipeline = 1;
} else if (currentMaxPipeline < 2) {
currentMaxPipeline++;
}
boolean more_pieces = true;
while (more_pieces)
{
int pieceLength;
boolean isLastChunk;
pieceLength = metainfo.getPieceLength(lastRequest.getPiece());
isLastChunk = lastRequest.off + lastRequest.len == pieceLength;
// Last part of a piece?
if (isLastChunk)
more_pieces = outstandingRequests.size() < currentMaxPipeline;
// We want something and we don't have outstanding requests?
if (more_pieces && lastRequest == null) {
// we have nothing in the queue right now
if (!interesting) {
// If we need something, set interesting but delay pulling
// a request from the PeerCoordinator until unchoked.
if (listener.needPiece(this.peer, bitfield)) {
setInteresting(true);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we need something, setting interesting, delaying requestNextPiece()");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() needs nothing");
}
return;
}
if (choked) {
// If choked, delay pulling
// a request from the PeerCoordinator until unchoked.
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()");
return;
}
more_pieces = requestNextPiece();
else
} else if (more_pieces) // We want something
{
PartialPiece nextPiece = lastRequest.getPartialPiece();
int nextBegin = lastRequest.off + PARTSIZE;
int maxLength = pieceLength - nextBegin;
int nextLength = maxLength > PARTSIZE ? PARTSIZE
: maxLength;
Request req
= new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
int pieceLength;
boolean isLastChunk;
pieceLength = metainfo.getPieceLength(lastRequest.getPiece());
isLastChunk = lastRequest.off + lastRequest.len == pieceLength;
// Last part of a piece?
if (isLastChunk)
more_pieces = requestNextPiece();
else
{
PartialPiece nextPiece = lastRequest.getPartialPiece();
int nextBegin = lastRequest.off + PARTSIZE;
int maxLength = pieceLength - nextBegin;
int nextLength = maxLength > PARTSIZE ? PARTSIZE
: maxLength;
Request req
= new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
}
}
}
}
@ -972,47 +1008,6 @@ class PeerState implements DataLoader
pp.release();
}
}
/******* getPartialPiece() does it all now
// Note that in addition to the bitfield, PeerCoordinator uses
// its request tracking and isRequesting() to determine
// what piece to give us next.
int nextPiece = listener.wantPiece(peer, bitfield);
if (nextPiece != -1
&& (lastRequest == null || lastRequest.getPiece() != nextPiece)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " want piece " + nextPiece);
// Fail safe to make sure we are interested
// When we transition into the end game we may not be interested...
if (!interesting) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " transition to end game, setting interesting");
interesting = true;
out.sendInterest(true);
}
int piece_length = metainfo.getPieceLength(nextPiece);
//Catch a common place for OOMs esp. on 1MB pieces
byte[] bs;
try {
bs = new byte[piece_length];
} catch (OutOfMemoryError oom) {
_log.warn("Out of memory, can't request piece " + nextPiece, oom);
return false;
}
int length = Math.min(piece_length, PARTSIZE);
Request req = new Request(nextPiece, bs, 0, length);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
return true;
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " no more pieces to request");
}
*******/
}
// failsafe

View File

@ -74,8 +74,8 @@ class Request
/**
* @since 0.9.1
*/
public void read(DataInputStream din) throws IOException {
piece.read(din, off, len);
public void read(DataInputStream din, BandwidthListener bwl) throws IOException {
piece.read(din, off, len, bwl);
}
/**

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)
@ -604,7 +608,7 @@ public class Snark
if (_log.shouldLog(Log.INFO))
_log.info("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient");
activity = "Collecting pieces";
coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this);
coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this, completeListener.getBandwidthListener());
coordinator.setUploaded(savedUploaded);
if (_peerCoordinatorSet != null) {
// multitorrent
@ -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,18 @@ 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;
TrackerClient tc = trackerclient;
if (tc != null)
tc.reinitialize();
}
///////////// Begin StorageListener methods
@ -1452,31 +1470,6 @@ public class Snark
return totalUploaders > limit;
}
/**
* Is i2psnark as a whole over its limit?
*/
public boolean overUpBWLimit() {
if (_peerCoordinatorSet == null)
return false;
long total = 0;
for (PeerCoordinator c : _peerCoordinatorSet) {
if (!c.halted())
total += c.getCurrentUploadRate();
}
long limit = 1024l * _util.getMaxUpBW();
if (_log.shouldLog(Log.INFO))
_log.info("Total up bw: " + total + " Limit: " + limit);
return total > limit;
}
/**
* Is a particular peer who has this recent download rate (in Bps) over our upstream bandwidth limit?
*/
public boolean overUpBWLimit(long total) {
long limit = 1024l * _util.getMaxUpBW();
return total > limit;
}
/**
* A unique ID for this torrent, useful for RPC
* @return positive value unless you wrap around

View File

@ -25,11 +25,15 @@ import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.CoreVersion;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import net.i2p.app.NavService;
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 +61,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 +87,9 @@ 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 final BandwidthManager _bwManager;
private Thread _monitor;
private volatile boolean _running;
private volatile boolean _stopping;
@ -100,6 +105,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
//public static final String PROP_EEP_PORT = "i2psnark.eepPort";
public static final String PROP_UPLOADERS_TOTAL = "i2psnark.uploaders.total";
public static final String PROP_UPBW_MAX = "i2psnark.upbw.max";
/** @since 0.9.62 */
public static final String PROP_DOWNBW_MAX = "i2psnark.downbw.max";
public static final String PROP_DIR = "i2psnark.dir";
private static final String PROP_META_PREFIX = "i2psnark.zmeta.";
private static final String PROP_META_RUNNING = "running";
@ -125,12 +132,12 @@ public class SnarkManager implements CompleteListener, ClientApp {
private static final String PROP_META_ACTIVITY = "activity";
private static final String CONFIG_FILE_SUFFIX = ".config";
private static final String CONFIG_FILE = "i2psnark" + CONFIG_FILE_SUFFIX;
public static final String CONFIG_FILE = "i2psnark" + CONFIG_FILE_SUFFIX;
private static final String COMMENT_FILE_SUFFIX = ".comments.txt.gz";
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 +147,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;
@ -159,17 +167,25 @@ public class SnarkManager implements CompleteListener, ClientApp {
private static final String PROP_COMMENTS = "i2psnark.comments";
/** @since 0.9.31 */
private static final String PROP_COMMENTS_NAME = "i2psnark.commentsName";
/** @since 0.9.58 */
public static final String PROP_MAX_FILES_PER_TORRENT = "i2psnark.maxFilesPerTorrent";
public static final int MIN_UP_BW = 10;
public static final int MIN_DOWN_BW = 2 * MIN_UP_BW;
public static final int DEFAULT_MAX_UP_BW = 25;
private static final int DEFAULT_MAX_DOWN_BW = 200;
public static final int DEFAULT_STARTUP_DELAY = 3;
public static final int DEFAULT_REFRESH_DELAY_SECS = 15;
private static final int DEFAULT_PAGE_SIZE = 50;
public static final int DEFAULT_TUNNEL_QUANTITY = 3;
public static final int DEFAULT_MAX_FILES_PER_TORRENT = 2000;
public static final String CONFIG_DIR_SUFFIX = ".d";
private static final String SUBDIR_PREFIX = "s";
private static final String B64 = Base64.ALPHABET_I2P;
private static final int MAX_MESSAGES = 100;
private static final String EXTRA = "";
/** @since 0.9.58 */
public static final String FULL_VERSION = CoreVersion.VERSION + EXTRA;
/**
* "name", "announceURL=websiteURL" pairs
@ -226,7 +242,9 @@ public class SnarkManager implements CompleteListener, ClientApp {
// psi go - unregistered
"uajd4nctepxpac4c4bdyrdw7qvja2a5u3x25otfhkptcjgd53ioq.b32.i2p",
// Vuze - unregistered
"crs2nugpvoqygnpabqbopwyjqettwszth6ubr2fh7whstlos3a6q.b32.i2p"
"crs2nugpvoqygnpabqbopwyjqettwszth6ubr2fh7whstlos3a6q.b32.i2p",
"opentracker.r4sas.i2p", "punzipidirfqspstvzpj6gb4tkuykqp6quurj6e23bgxcxhdoe7q.b32.i2p",
"opentracker.skank.i2p", "by7luzwhx733fhc5ug2o75dcaunblq2ztlshzd7qvptaoa73nqua.b32.i2p"
}));
static {
@ -267,7 +285,11 @@ 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);
_bwManager = new BandwidthManager(ctx, DEFAULT_MAX_UP_BW * 1024, DEFAULT_MAX_DOWN_BW * 1024);
DEFAULT_AUTO_START = !ctx.isRouterContext();
String cfile = ctxName + CONFIG_FILE_SUFFIX;
File configFile = new File(cfile);
if (!configFile.isAbsolute())
@ -285,15 +307,22 @@ public class SnarkManager implements CompleteListener, ClientApp {
*/
public void start() {
_running = true;
ClientAppManager cmgr = _context.clientAppManager();
if ("i2psnark".equals(_contextName)) {
// Register with the ClientAppManager so the rpc plugin can find us
// only if default instance
ClientAppManager cmgr = _context.clientAppManager();
if (cmgr != null)
cmgr.register(this);
} else {
// Register link with NavHelper
if (cmgr != null) {
NavService nav = (NavService) cmgr.getRegisteredApp("NavHelper");
if (nav != null) {
String name = DataHelper.stripHTML(_contextPath.substring(1));
nav.registerApp(name, name, _contextPath, null, "/themes/console/images/i2psnark.png");
}
}
}
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util, _peerCoordinatorSet);
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
_monitor.start();
// only if default instance
@ -342,6 +371,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.
@ -361,11 +402,20 @@ public class SnarkManager implements CompleteListener, ClientApp {
_connectionAcceptor.halt();
_idleChecker.cancel();
stopAllTorrents(true);
ClientAppManager cmgr = _context.clientAppManager();
if ("i2psnark".equals(_contextName)) {
// only if default instance
ClientAppManager cmgr = _context.clientAppManager();
if (cmgr != null)
cmgr.unregister(this);
} else {
// Unregister link with NavHelper
if (cmgr != null) {
NavService nav = (NavService) cmgr.getRegisteredApp("NavHelper");
if (nav != null) {
String name = DataHelper.stripHTML(_contextPath.substring(1));
nav.unregisterApp(name);
}
}
}
if (_log.shouldWarn())
_log.warn("Snark stop() end");
@ -417,6 +467,14 @@ public class SnarkManager implements CompleteListener, ClientApp {
/** hook to I2PSnarkUtil for the servlet */
public I2PSnarkUtil util() { return _util; }
/**
* The BandwidthManager.
* @since 0.9.62
*/
public BandwidthListener getBandwidthListener() {
return _bwManager;
}
/**
* Use if it does not include a link.
* Escapes '&lt;' and '&gt;' before queueing
@ -463,7 +521,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)));
}
/**
@ -685,7 +743,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
File conf = configFile(_configDir, ih);
synchronized(_configLock) { // one lock for all
try {
DataHelper.loadProps(rv, conf);
I2PSnarkUtil.loadProps(rv, conf);
} catch (IOException ioe) {}
}
return rv;
@ -814,7 +872,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 +905,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 +970,35 @@ 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)) {
int[] limits = BWLimits.getBWLimits(_util.getI2CPHost(), _util.getI2CPPort());
if (limits != null && limits[1] > 0)
_util.setMaxUpBW(limits[1]);
/**
* 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() {
int[] limits = BWLimits.getBWLimits(_util.getI2CPHost(), _util.getI2CPPort());
if (limits == null)
return false;
int up = limits[1];
if (up > 0) {
int maxup = getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW);
_util.setMaxUpBW(up);
_bwManager.setUpBWLimit(Math.min(up, maxup) * 1000L);
}
int down = limits[0];
if (down > 0) {
int maxdown = getInt(PROP_DOWNBW_MAX, DEFAULT_MAX_DOWN_BW);
_bwManager.setDownBWLimit(Math.min(down, maxdown) * 1000L);
}
return true;
}
private void updateConfig() {
@ -952,6 +1025,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
// _util.setProxy(eepHost, eepPort);
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
_util.setMaxFilesPerTorrent(getInt(PROP_MAX_FILES_PER_TORRENT, DEFAULT_MAX_FILES_PER_TORRENT));
_util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY));
_util.setFilesPublic(areFilesPublic());
_util.setOpenTrackers(getListConfig(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS));
@ -994,13 +1068,13 @@ public class SnarkManager implements CompleteListener, ClientApp {
public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay,
String startDelay, String pageSize, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme,
String upLimit, String upBW, String downBW, boolean useOpenTrackers, boolean useDHT, String theme,
String lang, boolean enableRatings, boolean enableComments, String commentName, boolean collapsePanels) {
synchronized(_configLock) {
locked_updateConfig(dataDir, filesPublic, autoStart, smartSort, refreshDelay,
startDelay, pageSize, seedPct, eepHost,
eepPort, i2cpHost, i2cpPort, i2cpOpts,
upLimit, upBW, useOpenTrackers, useDHT, theme,
upLimit, upBW, downBW, useOpenTrackers, useDHT, theme,
lang, enableRatings, enableComments, commentName, collapsePanels);
}
}
@ -1008,7 +1082,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
private void locked_updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay,
String startDelay, String pageSize, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme,
String upLimit, String upBW, String downBW, boolean useOpenTrackers, boolean useDHT, String theme,
String lang, boolean enableRatings, boolean enableComments, String commentName, boolean collapsePanels) {
boolean changed = false;
boolean interruptMonitor = false;
@ -1046,6 +1120,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
if ( limit != _util.getMaxUpBW()) {
if ( limit >= MIN_UP_BW ) {
_util.setMaxUpBW(limit);
_bwManager.setUpBWLimit(limit * 1000L);
changed = true;
_config.setProperty(PROP_UPBW_MAX, Integer.toString(limit));
addMessage(_t("Up BW limit changed to {0}KBps", limit));
@ -1054,6 +1129,20 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
}
}
if (downBW != null) {
int limit = (int) (_bwManager.getDownBWLimit() / 1024);
try { limit = Integer.parseInt(downBW.trim()); } catch (NumberFormatException nfe) {}
if ( limit != _bwManager.getDownBWLimit()) {
if ( limit >= MIN_DOWN_BW ) {
_bwManager.setDownBWLimit(limit * 1000L);
changed = true;
_config.setProperty(PROP_DOWNBW_MAX, Integer.toString(limit));
//addMessage(_t("Up BW limit changed to {0}KBps", limit));
} else {
//addMessage(_t("Minimum up bandwidth limit is {0}KBps", MIN_UP_BW));
}
}
}
if (startDelay != null && _context.isRouterContext()) {
int minutes = _util.getStartupDelay();
@ -1110,7 +1199,9 @@ public class SnarkManager implements CompleteListener, ClientApp {
if (dataDir != null && !dataDir.equals(getDataDir().getAbsolutePath())) {
dataDir = DataHelper.stripHTML(dataDir.trim());
File dd = areFilesPublic() ? new File(dataDir) : new SecureDirectory(dataDir);
if (!dd.isAbsolute()) {
if (_util.connected()) {
addMessage(_t("Stop all torrents before changing data directory"));
} else if (!dd.isAbsolute()) {
addMessage(_t("Data directory must be an absolute path") + ": " + dataDir);
} else if (!dd.exists() && !dd.mkdirs()) {
// save this tag for now, may need it again
@ -1126,10 +1217,16 @@ public class SnarkManager implements CompleteListener, ClientApp {
addMessage(_t("No write permissions for data directory") + ": " + dataDir);
changed = true;
interruptMonitor = true;
_config.setProperty(PROP_DIR, dataDir);
synchronized (_snarks) {
for (Snark snark : _snarks.values()) {
// leave magnets alone, remove everything else
if (snark.getMetaInfo() != null)
stopTorrent(snark, true);
}
_config.setProperty(PROP_DIR, dataDir);
}
addMessage(_t("Data directory changed to {0}", dataDir));
}
}
// Standalone (app context) language.
@ -1207,7 +1304,9 @@ public class SnarkManager implements CompleteListener, ClientApp {
Properties p = new Properties();
p.putAll(opts);
_util.setI2CPConfig(i2cpHost, port, p);
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
int max = getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW);
_util.setMaxUpBW(max);
_bwManager.setUpBWLimit(max * 1000);
addMessage(_t("I2CP and tunnel changes will take effect after stopping all torrents"));
} else if (!reconnect) {
// The usual case, the other two are if not in router context
@ -1222,7 +1321,9 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
addMessage(_t("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts));
_util.setI2CPConfig(i2cpHost, port, opts);
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
int max = getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW);
_util.setMaxUpBW(max);
_bwManager.setUpBWLimit(max * 1000);
boolean ok = _util.connect();
if (!ok) {
addMessage(_t("Unable to connect with the new settings, reverting to the old I2CP settings"));
@ -1431,9 +1532,6 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
}
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
public static final int MAX_FILES_PER_TORRENT = 2000;
/**
* Set of canonical .torrent filenames that we are dealing with.
* An unsynchronized copy.
@ -1576,7 +1674,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 +1791,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;
}
@ -2247,7 +2358,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
if (!subdir.exists())
subdir.mkdirs();
try {
DataHelper.storeProps(config, conf);
I2PSnarkUtil.storeProps(config, conf);
if (_log.shouldInfo())
_log.info("Saved config to " + conf /* , new Exception() */ );
} catch (IOException ioe) {
@ -2389,8 +2500,11 @@ public class SnarkManager implements CompleteListener, ClientApp {
*/
private String validateTorrent(MetaInfo info) {
List<List<String>> files = info.getFiles();
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
return _t("Too many files in \"{0}\" ({1})!", info.getName(), files.size());
if (files != null && files.size() > _util.getMaxFilesPerTorrent()) {
return _t("Too many files in \"{0}\" ({1})!", info.getName(), files.size()) +
" - limit is " + _util.getMaxFilesPerTorrent() + ", zip them or set " +
PROP_MAX_FILES_PER_TORRENT + '=' + files.size() + " in " +
_configFile.getAbsolutePath() + " and restart";
} else if ( (files == null) && (info.getName().endsWith(".torrent")) ) {
return _t("Torrent file \"{0}\" cannot end in \".torrent\"!", info.getName());
} else if (info.getPieces() <= 0) {
@ -2492,6 +2606,13 @@ 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
@ -2502,21 +2623,88 @@ public class SnarkManager implements CompleteListener, ClientApp {
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
// Remove that first message
_messages.clearThrough(id);
} else if (_context.isRouterContext()) {
// to wait for client manager to be up so we can get bandwidth limits
try { Thread.sleep(3000); } catch (InterruptedException ie) {}
}
// 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("Down bandwidth limit is {0} KBps", _bwManager.getUpBWLimit() / 1024) + "; " +
_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);
@ -2530,7 +2718,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
} 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
@ -2539,6 +2727,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) {}
}
@ -2555,8 +2752,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);
}
@ -2646,6 +2847,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,
@ -2704,9 +2937,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);
@ -2726,7 +2960,7 @@ 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();
int count = 0;
for (String name : foundNames) {
if (existingNames.contains(name)) {
// already known. noop
@ -2754,6 +2988,10 @@ public class SnarkManager implements CompleteListener, ClientApp {
disableTorrentFile(name);
rv = false;
}
if (shouldStart && (count++ & 0x0f) == 15) {
// try to prevent OOMs at startup
try { Thread.sleep(250); } catch (InterruptedException ie) {}
}
}
}
// Don't remove magnet torrents that don't have a torrent file yet
@ -2791,6 +3029,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
@ -2925,21 +3171,19 @@ public class SnarkManager implements CompleteListener, ClientApp {
}
/**
* If not connected, thread it, otherwise inline
* Always thread it
* @since 0.9.1
*/
public void startAllTorrents() {
if (_util.connected()) {
startAll();
} else {
if (!_util.connected()) {
addMessage(_t("Opening the I2P tunnel and starting all torrents."));
for (Snark snark : _snarks.values()) {
// mark it for the UI
snark.setStarting();
}
(new I2PAppThread(new ThreadedStarter(null), "TorrentStarterAll", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
(new I2PAppThread(new ThreadedStarter(null), "TorrentStarterAll", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
/**
@ -2969,6 +3213,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
* @since 0.9.1
*/
private void startAll() {
int count = 0;
for (Snark snark : _snarks.values()) {
if (snark.isStopped()) {
try {
@ -2976,6 +3221,10 @@ public class SnarkManager implements CompleteListener, ClientApp {
} catch (RuntimeException re) {
// Snark.fatal() will log and call fatal() here for user message before throwing
}
if ((count++ & 0x0f) == 15) {
// try to prevent OOMs
try { Thread.sleep(250); } catch (InterruptedException ie) {}
}
}
}
}
@ -2994,7 +3243,29 @@ public class SnarkManager implements CompleteListener, ClientApp {
if (finalShutdown && _log.shouldLog(Log.WARN))
_log.warn("SnarkManager final shutdown");
int count = 0;
for (Snark snark : _snarks.values()) {
Collection<Snark> snarks = _snarks.values();
// We do two passes so we shutdown the high-priority snarks first.
// Pass 1: All running, incomplete torrents,
// to make sure the status gets saved so there will be no recheck on restart.
for (Snark snark : snarks) {
if (!snark.isStopped()) {
Storage storage = snark.getStorage();
if (storage != null && !storage.complete()) {
if (count == 0)
addMessage(_t("Stopping all torrents and closing the I2P tunnel."));
count++;
if (finalShutdown)
snark.stopTorrent(true);
else
stopTorrent(snark, false);
if (count % 8 == 0) {
try { Thread.sleep(20); } catch (InterruptedException ie) {}
}
}
}
}
// Pass 2: All the rest of the torrents
for (Snark snark : snarks) {
if (!snark.isStopped()) {
if (count == 0)
addMessage(_t("Stopping all torrents and closing the I2P tunnel."));

View File

@ -87,7 +87,7 @@ public class Storage implements Closeable
/** bigger than this will be rejected */
public static final int MAX_PIECE_SIZE = 32*1024*1024;
/** The maximum number of pieces in a torrent. */
public static final int MAX_PIECES = 32*1024;
public static final int MAX_PIECES = 64*1024;
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
public static final int PRIORITY_SKIP = -9;
public static final int PRIORITY_NORMAL = 0;
@ -288,9 +288,13 @@ public class Storage implements Closeable
* @throws IOException if too many total files
*/
private void addFiles(List<File> l, File f) throws IOException {
int max = _util.getMaxFilesPerTorrent();
if (!f.isDirectory()) {
if (l.size() >= SnarkManager.MAX_FILES_PER_TORRENT)
throw new IOException("Too many files, limit is " + SnarkManager.MAX_FILES_PER_TORRENT + ", zip them?");
if (l.size() >= max)
throw new IOException(_util.getString("Too many files in \"{0}\" ({1})!", metainfo.getName(), l.size()) +
" - limit is " + max + ", zip them or set " +
SnarkManager.PROP_MAX_FILES_PER_TORRENT + '=' + l.size() + " in " +
SnarkManager.CONFIG_FILE + " and restart");
l.add(f);
} else {
File[] files = f.listFiles();
@ -900,7 +904,10 @@ public class Storage implements Closeable
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
// unicode newlines
0x2028, 0x2029
0x2028, 0x2029,
// LTR/RTL
// https://security.stackexchange.com/questions/158802/how-can-this-executable-have-an-avi-extension
0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x200e, 0x200f
};
// https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file

View File

@ -94,7 +94,8 @@ public class TrackerClient implements Runnable {
private static final Hash DSA_ONLY_TRACKER = ConvertToHash.getHash("cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa.b32.i2p");
private final I2PSnarkUtil _util;
private final MetaInfo meta;
// non-final for reinitialize()
private MetaInfo meta;
private final String infoHash;
private final String peerID;
private final String additionalTrackerURL;
@ -266,8 +267,22 @@ public class TrackerClient implements Runnable {
}
}
/**
* Call after editing torrent
* @since 0.9.57
*/
public synchronized void reinitialize() {
if (!_initialized || !stop)
return;
trackers.clear();
backupTrackers.clear();
meta = snark.getMetaInfo();
setup();
}
/**
* Do this one time only (not every time it is started).
* Unless torrent was edited.
* @since 0.9.1
*/
private void setup() {

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 greater than 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;
}
}
}

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