Compare commits
1384 Commits
Author | SHA1 | Date | |
---|---|---|---|
8cc561775b | |||
c08f79f71e | |||
7532276a00 | |||
ee29074a30 | |||
870ace55e2 | |||
ad7447f8ae | |||
4f827a5b1d | |||
be75455b84 | |||
96d3f67436 | |||
906bce637a | |||
3c0d0dfeee | |||
2ca5802e4d | |||
f4b06e586e | |||
525806d776 | |||
ed04747517 | |||
e13d336f2f | |||
5accdd24fc | |||
5c61c28772 | |||
3a767d84df | |||
d04ce7a2b7 | |||
b312fdeac1 | |||
30c8cf7b96 | |||
c43ca7de87 | |||
826951536b | |||
5f52edf831 | |||
29bc53d618 | |||
378c855902 | |||
546a588aa5 | |||
6e517c4a19 | |||
30d3f52f30 | |||
5dee6cb3d5 | |||
2a96c9a145 | |||
6435514e0d | |||
cd7a41924d | |||
b9452546c5 | |||
4fa89d5e86 | |||
63ece7e1aa | |||
4808055054 | |||
115016e75e | |||
ee09bfac66 | |||
530a3fcd10 | |||
0010229363 | |||
d241afcbd8 | |||
615257831c | |||
36a032d249 | |||
726079e0bb | |||
66421858e7 | |||
df7b3dd861 | |||
22ea79a4ff | |||
2025fe7c20 | |||
a11c529557 | |||
edaa2fba16 | |||
110f01a55b | |||
ada39a970e | |||
8c2641703c | |||
9fcb07250d | |||
47f39d0766 | |||
bcba5af8a9 | |||
aec1b3aeef | |||
a979ed770d | |||
5485568764 | |||
6f3597cc83 | |||
1202d09966 | |||
266eb8307c | |||
8843cc2948 | |||
2c4acce0f3 | |||
87beb2ea1a | |||
9c5b7760ba | |||
6964786552 | |||
d755756ee5 | |||
fbc970e4a7 | |||
364b905790 | |||
34a1085604 | |||
c460ac8ade | |||
49a09f61a2 | |||
08b4563f49 | |||
026f62f183 | |||
2307ac5a22 | |||
2b186421a7 | |||
1dc471e07e | |||
db1fb7ccf7 | |||
e5071a3b7c | |||
e6bfe0c10b | |||
919a97d4c8 | |||
61216b638d | |||
e065d2b01e | |||
746bad3c30 | |||
5bbd61b75c | |||
27eb7e46d0 | |||
c20bef3731 | |||
d5aaff7f06 | |||
fc60768a66 | |||
2024fb1b65 | |||
617ca79b8f | |||
5081755d0b | |||
7bfb5b1bf4 | |||
8d73529fa4 | |||
a19d04d3ba | |||
a9c7748a52 | |||
41e4e952b7 | |||
c0b0b5e4c5 | |||
e424479e7e | |||
a8804f3093 | |||
6479a24bb7 | |||
8b372ad306 | |||
86791a2f1b | |||
7cf0aad388 | |||
c5ea51beec | |||
7cc8e51d73 | |||
75ba58d68c | |||
cd35b219db | |||
4a863f8ce7 | |||
24264548a6 | |||
f9e4b1a56b | |||
13b54b864e | |||
05d45fe945 | |||
2781f6035a | |||
dc3378d084 | |||
9132e94143 | |||
b61e2aa73c | |||
7fdbae3b0f | |||
4dc6fc3b5d | |||
618275b1f9 | |||
7a1111d845 | |||
3af356840e | |||
911a278926 | |||
014063700f | |||
f7c0db0454 | |||
a534d25d82 | |||
bcf3e4a2d3 | |||
0cdfbd9803 | |||
a3e5654d86 | |||
2f9364db2b | |||
5d7c9ebf82 | |||
48da98d0e4 | |||
55e994ac3c | |||
6d46a21f9f | |||
fdc83484fd | |||
6786817fff | |||
b77cd0db15 | |||
20bef76878 | |||
7a30490482 | |||
3bc2e469cc | |||
d770d3c6da | |||
339a001592 | |||
ace57a96a9 | |||
2c26b8d422 | |||
e1eafa2394 | |||
39cb51c9eb | |||
fa5016ab04 | |||
b134ef1a74 | |||
234dff888d | |||
a08c15a3ee | |||
cfa894e7b6 | |||
d6c8e64575 | |||
dc91580e30 | |||
7ec1dd7a98 | |||
82f3f7506c | |||
e26df1c26b | |||
aea77cf225 | |||
a1e3ef9c5c | |||
7aece71342 | |||
bdbde54f04 | |||
157e035710 | |||
97d9a3a4e5 | |||
cb7f111ade | |||
35f670706a | |||
3fac888fe5 | |||
d843646b4f | |||
c2b73d9fb5 | |||
9da95b8165 | |||
5bcd8efe14 | |||
027a1d748d | |||
6d6e012c19 | |||
a8db6b007f | |||
f3576e54c6 | |||
0325f6c4d2 | |||
8225ce063a | |||
c2c379c994 | |||
7344c2af47 | |||
f484ea8c64 | |||
ac790492eb | |||
9ac5fb4890 | |||
2baee7413c | |||
16bec08f09 | |||
afb3c76922 | |||
2f526b35e8 | |||
2dc32aa310 | |||
10e669165a | |||
b6cb90d731 | |||
949a8901fb | |||
d608f450af | |||
e0a1341901 | |||
2cfb03f17d | |||
4dd0f51da4 | |||
d65a3e54a2 | |||
c212eacf19 | |||
46f341d782 | |||
ab4ff5548d | |||
d4713e1e6c | |||
8a3a1466c9 | |||
a5af9dc973 | |||
049a083e42 | |||
9683a110d6 | |||
c44698f61a | |||
106bccda0e | |||
b1aafa5aaf | |||
e2e43cd534 | |||
43b4fe8300 | |||
7c3e4fd947 | |||
9916ef4d3d | |||
ad4da54bc4 | |||
2415c5a38b | |||
ecbc0a2a2d | |||
10d37a9be5 | |||
590d2e4639 | |||
806a07acc5 | |||
8258cdd6cf | |||
2fcee6e87a | |||
27587e83c8 | |||
a0d6741ff5 | |||
63562ddd48 | |||
aac96b15b0 | |||
0f502b4229 | |||
a916f970b1 | |||
7f2d0acc3b | |||
8b6751f419 | |||
70e9cf5838 | |||
24020302fd | |||
d7e2f39d25 | |||
89d0d7b266 | |||
e3c222b5c1 | |||
a199015bc9 | |||
23617f7b30 | |||
f5f02236df | |||
ad76bc378c | |||
570d8d15af | |||
e254c5f31a | |||
2a92be5946 | |||
caab860351 | |||
32861b7ce9 | |||
a08802c4b6 | |||
6b51be6fae | |||
5b5c975884 | |||
605dfec5e7 | |||
71aa0cfba7 | |||
55e45c4274 | |||
8c880b2518 | |||
c43b16cfbb | |||
394903a8f0 | |||
e31c0636ab | |||
e9fe80f8e5 | |||
7671550a9f | |||
83d24fa90d | |||
3e2956da3f | |||
cf3fd01012 | |||
319071c73b | |||
ab8d9bb79b | |||
25eaf8cad7 | |||
c8f97d9c73 | |||
d3f1fe1c30 | |||
5fb01a01af | |||
617d1cd648 | |||
f672193fcf | |||
d3c490e9d7 | |||
2e8fd23f2b | |||
3eef403b04 | |||
f3b78fc82f | |||
80654b2732 | |||
05597ae914 | |||
0f1eb464e8 | |||
8745ffd42f | |||
db99e98658 | |||
9f1a663f63 | |||
db0b3da446 | |||
5d22d41201 | |||
b397de1d54 | |||
4bda79b263 | |||
697a9dbd06 | |||
accaabcfde | |||
5026cbdc8d | |||
16a14d4ebd | |||
c151352910 | |||
52e2aaa20d | |||
9df87ba167 | |||
b80f70fc54 | |||
939cdb019b | |||
fde36fe238 | |||
116be93160 | |||
40e820cabb | |||
d79387bd92 | |||
05f2a62cbb | |||
78a965dc90 | |||
5b603d6627 | |||
e93d2046d3 | |||
995871db8a | |||
501535f196 | |||
91e854e99c | |||
9b05d8e774 | |||
e70793c3bc | |||
abb2603bea | |||
c91218be27 | |||
9eab44128a | |||
f98101afa6 | |||
4fae7a8cb6 | |||
26cf1922db | |||
c087b0695f | |||
16930d2004 | |||
33939e7cfb | |||
e759ef5865 | |||
2be1b1ece4 | |||
1820a29aed | |||
ee9f85d53c | |||
afbb1dbe86 | |||
9244bd6b0f | |||
6bb4403207 | |||
24ebd503d4 | |||
285a5eed35 | |||
26aebe6a0f | |||
ca9f174171 | |||
ffbced22b3 | |||
45ca459ceb | |||
5a539f0619 | |||
c6cef72cb7 | |||
8081d053cc | |||
efdc8e5df0 | |||
b4911a2b2f | |||
7b70210c9a | |||
e3353df8bb | |||
25285fc059 | |||
7720f71e44 | |||
1657ac5357 | |||
299214aa1d | |||
5fd4488e08 | |||
87fcaf2651 | |||
f6b9cf6f21 | |||
eae18e61b7 | |||
96735f2543 | |||
54459d3b5c | |||
82444f9e7b | |||
3d8365a473 | |||
e2dc9715d2 | |||
d4f1230b37 | |||
7701693d37 | |||
b6704fce4e | |||
39a68d4a2b | |||
94633899d7 | |||
c45bc1554f | |||
789c8edc45 | |||
e0b44f43e3 | |||
b45069e377 | |||
c3a156ce4b | |||
ee5cc099ed | |||
f189587153 | |||
a1fb5ef6ed | |||
8c2550c39a | |||
abd96a920f | |||
1d3f0fe96c | |||
49a6cdbda6 | |||
2700028da7 | |||
51a1564566 | |||
bd068058c3 | |||
4591f77928 | |||
4f70a7d0fe | |||
6d67848096 | |||
c145ed103a | |||
f265db4037 | |||
62308f26bc | |||
2b4b47eff6 | |||
04ae0e2610 | |||
cada9fae44 | |||
949aea951e | |||
cfc49ab261 | |||
0e853a3119 | |||
a0cad7e8e9 | |||
880f1866dc | |||
05d22344b5 | |||
7212f855d8 | |||
54171e4be2 | |||
a820c01ba5 | |||
9d1ae891bb | |||
2df7247e83 | |||
a109ebef28 | |||
c0135b592d | |||
b7a0aeea34 | |||
66375e25c6 | |||
85482a67f5 | |||
d7e90969d0 | |||
9012baf51e | |||
3c8355790f | |||
e9f1da85e4 | |||
58adccfd4a | |||
040f3e016e | |||
505d5f5cae | |||
2a99e2a295 | |||
49fae646e2 | |||
f7780b6745 | |||
7a59d15e9c | |||
9b141bd9dd | |||
d0d062b6f4 | |||
375118fe02 | |||
7b59ceb4ae | |||
3aebe45a7d | |||
7c236c0fa0 | |||
7a7e650ca0 | |||
7a32f8efd6 | |||
2f8b55ceda | |||
b77be20cc1 | |||
101135a99a | |||
746c1bd628 | |||
b0502b1873 | |||
6801fc667a | |||
794db19b6d | |||
d4637818be | |||
33b7dca782 | |||
d7015cf2e6 | |||
5689fa8512 | |||
25e51a945c | |||
bfd1306a56 | |||
839986db22 | |||
ed443fe0d6 | |||
390981e10c | |||
56b3e6a993 | |||
f86f2701ff | |||
63d3685652 | |||
0a93466999 | |||
81664bc776 | |||
6d60a6f833 | |||
4186894a39 | |||
cfeafacd07 | |||
9c2edf5c6a | |||
72396f0f96 | |||
45388b0d48 | |||
a8ae36c403 | |||
164b39d8df | |||
ccc95087a1 | |||
b97f4f8bd7 | |||
76c1f47b20 | |||
ce74e49236 | |||
977d39aeb1 | |||
a821ea2752 | |||
b97197c0fa | |||
474691927a | |||
81dcbedd17 | |||
4f5cfdee57 | |||
2c7725a8e4 | |||
0ba6482da5 | |||
4c1fd67925 | |||
25683cc0de | |||
087fd5a909 | |||
fdfbab850a | |||
f1c50b7fc3 | |||
959bf4a7f4 | |||
5dda915467 | |||
66d8fd6c2a | |||
06efe306c3 | |||
15d1b005f5 | |||
7efab75c3c | |||
a9e4248c93 | |||
5338dc5540 | |||
09d3dc8e90 | |||
3bf95e566c | |||
958a5a3c4e | |||
7b48f6387f | |||
fcd2cdb136 | |||
6b59356bc5 | |||
1c7f098d9b | |||
103c15f000 | |||
0fd55f8b07 | |||
511c1e7b9d | |||
7df3bde2ce | |||
25e6b6e6c4 | |||
cb81f2c9ba | |||
6c25f0fd16 | |||
934f3d1814 | |||
e883fd6b1b | |||
e3b300e978 | |||
03a9f69739 | |||
be2dca8ee7 | |||
5c595ef289 | |||
d9534e5f23 | |||
00fa3806d8 | |||
6c5ef9acdc | |||
2db5914ba0 | |||
35a0dafb83 | |||
5f12688a90 | |||
f8d9af871a | |||
08a2b4bbf0 | |||
27a5793fd0 | |||
b1151f82b5 | |||
b6332f8313 | |||
e036cd4332 | |||
174fedc2e6 | |||
4803e60db4 | |||
abb62b93e3 | |||
95bb322cd7 | |||
670b4033cb | |||
715ae13997 | |||
77b88ab59d | |||
64235bd745 | |||
0a1960461a | |||
11249657ac | |||
188ac4f730 | |||
865116b3f4 | |||
9f28c06e9e | |||
3cd6520758 | |||
da1a50bfeb | |||
9ec79f50fa | |||
b15392ea85 | |||
b8339e72b0 | |||
6eaec7fd44 | |||
9e8f2ce771 | |||
e8e6f6f531 | |||
f16ba8ee06 | |||
76f11859b2 | |||
5be21a19db | |||
043359dd40 | |||
1b95b00b44 | |||
eaaf6af31d | |||
d8d50aaf41 | |||
5fcddd581e | |||
f1a9613a92 | |||
a2ce10759c | |||
5065aec773 | |||
25fc64933a | |||
bbdd54efc8 | |||
92597baab9 | |||
62786dcc09 | |||
c012e5bf17 | |||
5ed29b6c27 | |||
2d5decd943 | |||
9d167dc83a | |||
afe8394658 | |||
72db6d1a08 | |||
9d0e300924 | |||
4f548b7b27 | |||
cbd50372e4 | |||
3caee8bc71 | |||
6c64faf0ba | |||
65290f1ed7 | |||
498af5d203 | |||
883b53de0a | |||
cefc1f130d | |||
b2a137c5bc | |||
62f056f884 | |||
3944ea53d2 | |||
d372ea753f | |||
2528cd205d | |||
afd54fc212 | |||
8e7a9fc513 | |||
acb75f4212 | |||
c40b56c19d | |||
98027a06ec | |||
d92dfec1bf | |||
72a588bfbf | |||
213bc4bb71 | |||
1a01aa0ae4 | |||
0b0e3fffe4 | |||
1fc32c5e6f | |||
ba9f05ca06 | |||
629d12ade1 | |||
08929752a6 | |||
aaa5b4ca86 | |||
8d7e84494b | |||
99df95697a | |||
a877b21839 | |||
3f267693d2 | |||
30b7dbf1f7 | |||
f32d162b62 | |||
126fa320e5 | |||
ecae0b055d | |||
9bf22fb0d3 | |||
2a1d358141 | |||
579b450029 | |||
72eafe0920 | |||
f226392c9d | |||
2cd5c209f5 | |||
f0d444b32e | |||
4baff9fbab | |||
8e656427d8 | |||
aaa7302e80 | |||
33407fd5be | |||
513b93f789 | |||
08e54c515e | |||
55682810b1 | |||
ec893d09d0 | |||
f9b745a671 | |||
43b71a263c | |||
5c4672d1e3 | |||
7ca8e0c3a1 | |||
b530316850 | |||
fa92beae5a | |||
f58f703ecb | |||
6b83fc6b3b | |||
cdb390f7ce | |||
7b1caac9ac | |||
cec75fa60e | |||
eb23306b12 | |||
43f6813609 | |||
ea36b7b153 | |||
448ff4d398 | |||
e16227211f | |||
e07e329c26 | |||
a3d79aaa4e | |||
3fa9ae0b82 | |||
7feed50af4 | |||
0c0eb5765d | |||
e87ff25ef6 | |||
21e09cb0a5 | |||
04d54607ae | |||
ad8bfbdaab | |||
aca815c4aa | |||
24683c19a4 | |||
6b8dffc401 | |||
c4bb84058a | |||
c3dc76e35f | |||
993fa5c210 | |||
1cec793217 | |||
6029e1a291 | |||
7cc75c0cb9 | |||
e5248b09ab | |||
c39f047703 | |||
4562254862 | |||
8116d88aaf | |||
14362630d7 | |||
9af796a10a | |||
eeb884e8ce | |||
02baf905c6 | |||
df7029d2c2 | |||
c22b7568b1 | |||
73537d27d0 | |||
449d7ab589 | |||
0ddef91e16 | |||
b205af5a0d | |||
1e32170df2 | |||
f446a5f1fc | |||
fb21fb25ee | |||
deae0e8856 | |||
1cd54dc12e | |||
8ebc8bd209 | |||
9d11866f86 | |||
2c456c291a | |||
c5b3c2f430 | |||
e46e747ac0 | |||
e1a88c9426 | |||
23d3c33a12 | |||
ec8130f443 | |||
4b7aeb8418 | |||
18a0f01f8b | |||
df2e639692 | |||
708b3a662c | |||
4fee7844f8 | |||
891416e6b9 | |||
978cd2c484 | |||
c88c905926 | |||
bda4eb830e | |||
f5c1acc749 | |||
c4e6148b9f | |||
43029de2f3 | |||
7262c014c0 | |||
9f7bd99051 | |||
9e4f04cc18 | |||
454b2c8941 | |||
4c812c7bff | |||
f95b5324e0 | |||
64ee1b313b | |||
1ca651e803 | |||
f3a88398f2 | |||
412d641eb6 | |||
d7d058e772 | |||
278b917494 | |||
4b6989ef7b | |||
c10ea84ade | |||
0642fa8093 | |||
2db7c2bdd8 | |||
8682e7deb5 | |||
ea0747171f | |||
13349777ad | |||
ab0a5a06af | |||
6371f66677 | |||
105524d9c0 | |||
95e0492b32 | |||
234c084c2a | |||
94faf74aa4 | |||
e78dd1fdc3 | |||
38045d876d | |||
8433724452 | |||
e9f9e0dabb | |||
6bdf750c19 | |||
647a09b5b9 | |||
6144bfb437 | |||
88dbd7710a | |||
26a71232f0 | |||
f58a1768b9 | |||
125e6581e0 | |||
54105086ad | |||
3674ac2922 | |||
18c023e6f7 | |||
312ba2599f | |||
746dc6f884 | |||
edd4d4c114 | |||
56e0c3e047 | |||
1e83d1b304 | |||
74aa84b183 | |||
168c213288 | |||
d268a3852c | |||
01e87438c3 | |||
060f4e6632 | |||
3df5540a97 | |||
30dec5b9f5 | |||
43b437fc58 | |||
8e889cd292 | |||
eceac6def0 | |||
1e3d6776aa | |||
784ca67ddf | |||
0f6b49cc31 | |||
8cede2a2b2 | |||
38ed04bbd8 | |||
c393e70ca9 | |||
1c25c0f408 | |||
b7ebce48ee | |||
d6814a0489 | |||
6f24c74f8c | |||
d8389dcc46 | |||
9f939553ee | |||
529988f394 | |||
9f46aa1e18 | |||
418c1b6f96 | |||
8056fb9502 | |||
ab2e21147f | |||
6c00bb20b6 | |||
573ac357d8 | |||
5b139f9246 | |||
76d75b712e | |||
8bc2fd7e42 | |||
4533a86712 | |||
a6239e2ce3 | |||
1f8e61f480 | |||
c40f845279 | |||
aa74962263 | |||
42cbd6c12b | |||
ee51f69a5a | |||
0fb6e9cf6c | |||
e02845076d | |||
2dc3798116 | |||
fa252f5e8f | |||
580b9b450f | |||
f0730cd1c8 | |||
b045fb3a45 | |||
6c64111d7e | |||
37a2ccca95 | |||
b4615edfcc | |||
6019cf8148 | |||
e3d945201b | |||
05b17e5a00 | |||
13b3edfb07 | |||
f61372b2fd | |||
f85d8f7060 | |||
a0b4b7db86 | |||
827a92ef2f | |||
625d76b914 | |||
a1de894b64 | |||
413ab6d7e4 | |||
a3b1c79006 | |||
5a7d3ba4c8 | |||
8a1db31184 | |||
5190b2db1f | |||
820c573476 | |||
ab40454bce | |||
b65865b854 | |||
a5772e62c3 | |||
9976bea03f | |||
7997aeaca5 | |||
ba95084d27 | |||
e952e91b54 | |||
da21c0ddb7 | |||
0133711c3b | |||
6eae2cd460 | |||
9314eebc4f | |||
428cbdce2a | |||
7594c4383b | |||
e2f6911e9f | |||
9cdae03069 | |||
06946f026e | |||
d43dac5c04 | |||
b4d83b18fa | |||
f9424dbd6d | |||
e5212937af | |||
aeb6635e71 | |||
e94b478317 | |||
88216de42c | |||
1fcf707bb2 | |||
5101486fe7 | |||
7ae4d0e981 | |||
c644c128c0 | |||
2603f6fe45 | |||
957a296ca9 | |||
e4f44fa1e9 | |||
2b469567bb | |||
a2d90eebea | |||
850a8da0a9 | |||
ac6d711a99 | |||
5aa254a178 | |||
ad396adf39 | |||
05cce164f7 | |||
935b69bc71 | |||
61f800999a | |||
9833743eb9 | |||
ac65bc7302 | |||
b36f207bb2 | |||
e87a7c7bb4 | |||
7e5128bb85 | |||
0a178ec35e | |||
a5cd0bdd3f | |||
9cbf9d0422 | |||
097a05aab9 | |||
0e5b2598fb | |||
4f492e33e6 | |||
1828b2bd17 | |||
0c74e640df | |||
ffd2721627 | |||
f6ce4cb29f | |||
4863ef3360 | |||
9f7807ee10 | |||
b2285b0beb | |||
8e4f4f82a8 | |||
db2158d4c1 | |||
1c461bbeda | |||
0757f4f309 | |||
a2f287cdfe | |||
1ef448d518 | |||
f44b1a35bc | |||
26f02a4771 | |||
dc3c730937 | |||
77d45e7a3a | |||
45a59f009b | |||
dc6d6ead69 | |||
27693826a2 | |||
8a647b42d5 | |||
eba9f3c03b | |||
eacf46b367 | |||
83cacaad05 | |||
cf10451d14 | |||
44069645df | |||
4497463778 | |||
10b84418c3 | |||
fadda4ceec | |||
011a32f741 | |||
10bb3c100e | |||
2738d5851d | |||
219095404a | |||
001c361338 | |||
e21a172e95 | |||
4651b7007b | |||
5b4be5ba1b | |||
9c2c90c0b1 | |||
bdd0c3f961 | |||
b7013361c2 | |||
f73b3e522b | |||
fa6d17a1b8 | |||
c3e646ca22 | |||
fdc9e11fb4 | |||
a1ec838282 | |||
7da46517ae | |||
d8e2939307 | |||
8cad72c654 | |||
2cfc2bb60d | |||
1811e3b9cd | |||
960cd18d0a | |||
405b85c4b4 | |||
92e323df51 | |||
3f2c34903d | |||
3c260aa333 | |||
da41f3a93b | |||
aeb711acde | |||
a46ee9a5b2 | |||
088f9558ec | |||
376d61c155 | |||
285a2b92e5 | |||
8939c573ea | |||
3839d9873a | |||
116762ebce | |||
7dd8f00e95 | |||
29a3db4b5c | |||
5d95907996 | |||
2f940d01b6 | |||
517e170b88 | |||
b27fbb9b8e | |||
9b97d32ea8 | |||
d4f3952a90 | |||
f7840652ed | |||
08634c1ff6 | |||
dec4205890 | |||
b49ab59e3b | |||
7e1171ec9f | |||
3eae787957 | |||
9ecba4fc5e | |||
4fb9eef198 | |||
49ecfd8224 | |||
09a2854b8b | |||
82976e609f | |||
b2d6b60300 | |||
90737493e6 | |||
fe3abc79d6 | |||
9931112387 | |||
1cd646afe2 | |||
0d262d28b7 | |||
f33e950780 | |||
7094489536 | |||
2dd650df01 | |||
7e8037979f | |||
3a1c042cd2 | |||
ca81c35b3d | |||
6a2dfff34d | |||
5eccc01de6 | |||
1850e893e9 | |||
2341793546 | |||
1f1d089fda | |||
5372a50bcc | |||
83588d9b98 | |||
58e960ceb5 | |||
de07705671 | |||
49ff3cfbf3 | |||
e392469835 | |||
7745bd89a9 | |||
01bed932c7 | |||
157190757b | |||
e0f1047d72 | |||
15f0cda41f | |||
9a95122c7c | |||
d868f7c02a | |||
5ca2f306b8 | |||
c714c1a0c9 | |||
e6e6c00497 | |||
62a3da2fa6 | |||
f1f97e8ec5 | |||
6c361679c6 | |||
ae89d2f2ab | |||
8053fb5eae | |||
ebf5eb6e20 | |||
2e2bff3f0a | |||
a3f290e4d8 | |||
e0dd1f13e3 | |||
787def6a1c | |||
1f5d7d7b5b | |||
4bc5215833 | |||
7736545f5b | |||
1ecf4377c6 | |||
593d4dc508 | |||
93d366fea1 | |||
7973f2e8b9 | |||
bb14fa0b4e | |||
95aba0c537 | |||
df4143f036 | |||
ed0575e937 | |||
456ed0aab4 | |||
47c8389419 | |||
51fd4d70da | |||
79e32231fb | |||
80f9f857e5 | |||
5a4c2de425 | |||
7e547743c7 | |||
3f3d43df41 | |||
0cc72a49c8 | |||
35c9e99914 | |||
2e4bd1e440 | |||
22c0b8e524 | |||
faeb58f7e2 | |||
cdc184c5e5 | |||
2f9a4f0fa5 | |||
37437da34d | |||
6d3a5856b4 | |||
4d4538a346 | |||
327102a254 | |||
3602eb14f5 | |||
cf82b51a1f | |||
412d3bc2f8 | |||
4735508a0a | |||
9225d01b29 | |||
7782970d51 | |||
6f053287d5 | |||
7a88f59f08 | |||
d56aae8913 | |||
a309a14396 | |||
b80cbbdd4a | |||
5bc2dab1d2 | |||
8bbe7fabb3 | |||
c537d160a6 | |||
475187fcbc | |||
a379e36e24 | |||
a9054a3cab | |||
ea7a9c259f | |||
2cba48d4d7 | |||
42b79c5a20 | |||
be9523f1e4 | |||
6a8dd0f053 | |||
1b63aa411b | |||
33a7f3351b | |||
f7af5e1329 | |||
3a9a029d70 | |||
0aaacc86e2 | |||
1b8b7b741c | |||
66831c619b | |||
30628fb5f9 | |||
064ff8a7d2 | |||
9a18955de3 | |||
35da3f3334 | |||
335d45f03e | |||
c466cd77ad | |||
d998e2e9bb | |||
0a20315280 | |||
01753f5aea | |||
bcd22cfbf3 | |||
7e039d0339 | |||
ab08ac70aa | |||
5decf3cd7a | |||
5c6d757e35 | |||
4b75be804f | |||
6515e6ee17 | |||
55e8583663 | |||
3fbff71861 | |||
e5eea47b66 | |||
b10b0e8f57 | |||
631a367b1c | |||
8ea279fbe2 | |||
089572befd | |||
0f96b9569a | |||
d1114666de | |||
f676abc0d4 | |||
3492b7219b | |||
a12ae6e399 | |||
9b2e18a65b | |||
c52ccf7eef | |||
1282434684 | |||
4e844187f7 | |||
ccd67d658d | |||
62383819cb | |||
3febcf6043 | |||
a431137f45 | |||
5a6e14b9df | |||
536bc3112f | |||
81b2e6b789 | |||
4cf376ec1d | |||
d3a0c91398 | |||
43140d3efd | |||
3dd3bf829d | |||
bdcad06ece | |||
69fdfb0635 | |||
55a8002b9c | |||
e36f9b2273 | |||
70ae99f31a | |||
15565ca09c | |||
f188e02a5d | |||
4d005349a7 | |||
c65a97882e | |||
cf880548d9 | |||
b5876e7f04 | |||
2436ea1131 | |||
5395b6829a | |||
c3af134a5b | |||
cce72a5f1b | |||
32c143f8d7 | |||
895cb1f2e5 | |||
7986f5646e | |||
59a5776f9d | |||
fc8c0ccfe1 | |||
0930ead814 | |||
b5a17637cb | |||
460c8a319f | |||
7aa051ef4f | |||
c7c132c0ac | |||
d84b1125eb | |||
8d4a1899f2 | |||
3a0cdf1388 | |||
d8d76fd327 | |||
abf7296de1 | |||
316c20ee44 | |||
13e8c95667 | |||
a14ad423a6 | |||
e1a5d5e19a | |||
6e29eddaa7 | |||
65ae26a961 | |||
1afd946a94 | |||
d6820634ac | |||
95dd744633 | |||
219af36090 | |||
24e83398ba | |||
4172ed21a9 | |||
1cba7b8ec1 | |||
0bef85277e | |||
2f4c428316 | |||
4de0b73cd8 | |||
7ffb3f46b5 | |||
ad6cd05295 | |||
6e7ad3ecdb | |||
a6243d14c0 | |||
b0a477c5ca | |||
1d655c7abc | |||
abf2bead33 | |||
f1103bec7b | |||
fb1a6534dc | |||
22b1d5fe75 | |||
d2c939bc09 | |||
73f8cb4819 | |||
256bb771e1 | |||
cc533b0431 | |||
3c76fda8d9 | |||
c5555350ae | |||
22744084dc | |||
e4b212ec90 | |||
4be0af5de5 | |||
d771745981 | |||
7628842b0a | |||
6bcdb7fd92 | |||
27561fb632 | |||
f6ec3f66f8 | |||
2f0b9a8f94 | |||
3fb1a4ebc5 | |||
9abb0a1581 | |||
e60e29b70f | |||
d84352896f | |||
ee419454f4 | |||
68445fe195 | |||
12b2d4c00b | |||
fbb4d3a636 | |||
ca415376c7 | |||
718f73ebb1 | |||
fb47eef218 | |||
87dd473148 | |||
9bbbccee1a | |||
0088750b16 | |||
0aae2deb58 | |||
0d62b37c13 | |||
64ece1080c | |||
b4256e484a | |||
b0ea204be5 | |||
118d7fce09 | |||
5e498e0bd6 | |||
c312fa869b | |||
fe394b0b46 | |||
6039f3931d | |||
71d72b426f | |||
7d5042c507 | |||
e2b0e14771 | |||
0e9bfba84d | |||
99f53413a6 | |||
f46600d7fe | |||
0607a87514 | |||
1658690b97 | |||
eae0f3273b | |||
508beb2fc7 | |||
0de2f492d1 | |||
72a7393844 | |||
99f8468f63 | |||
a9e8fc2f1f | |||
e225244887 | |||
cbde15b00f | |||
8e38047d43 | |||
dc1d0195eb | |||
7d7f264bc0 | |||
b3c30b4fd2 | |||
6c87005eeb | |||
8d2a516044 | |||
dc0cc49dbf | |||
497bc5a414 | |||
2a71baef90 | |||
49a74e8610 | |||
6340fbb3d4 | |||
748203f4e7 | |||
a91cc94228 | |||
029ac71e58 | |||
e830b46173 | |||
a4d053f555 | |||
b298796060 | |||
895490df3d | |||
a09c06849b | |||
37c494bf0a | |||
d6fccc07be | |||
819efc132b | |||
8ffdae4182 | |||
efd6dcc8df | |||
70a17ecfaf | |||
15dbf67983 | |||
a43df30051 | |||
1bff5a7b9e | |||
ec49d9becf | |||
bc49f51dbb | |||
b869860a83 | |||
2772a0e5e4 | |||
46970f5a4a | |||
ccf9cd3f71 | |||
b9c464f8cb | |||
48510c1157 | |||
3035fcf080 | |||
930f402eb9 | |||
4e93191312 | |||
9bc4f6bacb | |||
9b42129fea | |||
0650137e32 | |||
a13e528972 | |||
82f8dd5635 | |||
7f93cb22ce | |||
e6738053b2 | |||
b74ab51438 | |||
d7a591ce3a | |||
cfe33a8bbd | |||
ca7593cdf2 | |||
b185d11daf | |||
5106c37ac4 | |||
5d40ad1749 | |||
24edce3daf | |||
cfd1ab7d78 | |||
bfaa648edd | |||
fd19210bce | |||
9a3b103324 | |||
0ee5c905e4 | |||
5f22a226cc | |||
56b3144c56 | |||
dad4bef70c | |||
13a04dba71 | |||
ab66dfcb65 | |||
ab349a5303 | |||
53a68ff5a3 | |||
29f13868b7 | |||
8ce71d724c | |||
e3de3dcc1d | |||
fa6a6fa4ef | |||
e78e4c93c0 | |||
0173f5877b | |||
32e829da74 | |||
68e81fa8c8 | |||
9f84d13542 | |||
48f591eea8 | |||
cb6dce4e03 | |||
e5e7f01e84 | |||
f90a320d95 | |||
96c94a294e | |||
ab81887138 | |||
d13e3d95d3 | |||
64f1fe0b51 | |||
0a77f88229 | |||
12d34a50ff | |||
92daa920d2 | |||
091d03b9d8 | |||
f7ee11cb44 | |||
6226b8ae6d | |||
a6a61421d9 | |||
5c20574044 | |||
aca006253a | |||
7a752cc7a2 | |||
de7dc2c1f7 | |||
35b5bf187e | |||
efbc4c5184 | |||
711c2b7dfd | |||
a4adb4709b | |||
7121b5fa31 | |||
c944648b99 | |||
45cdd556c7 | |||
429bd0a4e3 | |||
135f8c1be2 | |||
7b7a590e21 | |||
95728ef29f | |||
021b44724e | |||
ba0efe64c7 | |||
1a247d8d3a | |||
21b03e8e8a | |||
03790e3e4d | |||
9af239aa65 | |||
02fc700ac0 | |||
1fb5238642 | |||
461af7d0a2 | |||
cf3efc11ba | |||
b6e24b5094 | |||
0b590763f3 | |||
3cc4ee7199 | |||
4828cd2f16 | |||
45da7e8704 | |||
e00b88ca32 | |||
e497680ca8 | |||
dbb9eefe70 | |||
7388fdf820 | |||
0c46d561ec | |||
4248ab936c | |||
e5139113b1 | |||
0f1a4ad4cd | |||
00d99fb1a9 | |||
ee8dc4af2d | |||
d7b4be1e74 | |||
7ed509b76a | |||
c616f66e83 | |||
e8bfac27aa | |||
df3b3bfc8f | |||
ac358502ce | |||
2b905d2ed5 | |||
49c55ae12a | |||
d280d7a389 | |||
19ccdcd951 | |||
cac9b2e1f1 | |||
e0e42a0f87 | |||
1d845dab03 | |||
71b9bb67a6 | |||
06be251032 | |||
454a6ab177 | |||
1e1c3cdff0 | |||
52de5e569c | |||
2f97942286 | |||
4b1eabf1fc | |||
6c7f1cbf8a | |||
ffc582093b | |||
cc833f3ca4 | |||
00d0aa7830 | |||
54f649a4b4 | |||
1c2cd4dcb2 | |||
43d6851199 | |||
9527684cf7 | |||
1965815d7d | |||
cc2be105a6 | |||
e4c599b756 | |||
a8a21ddb73 | |||
942c31621b | |||
ca14002bd1 | |||
5eec098e2b | |||
37043195ba | |||
ab8e2cf34d | |||
882e08fc4f | |||
2e5caac8bf | |||
714fe82d2f | |||
1724e5b499 | |||
a5fa6acf5d | |||
59105a9ad6 | |||
abc23e9a49 | |||
72071566e7 | |||
055cd99dde | |||
d2c52e5c94 | |||
c7541f819a | |||
7972c0c862 | |||
3fee5a3781 | |||
db45e74fcc | |||
206e45b9e8 | |||
a9345953f3 | |||
eb324d7652 | |||
85adfc40fb | |||
f1bb8910cb | |||
8ca794dc57 | |||
fe3cd65c62 | |||
256c5356fb | |||
0bc6fd246f | |||
77ce768cb4 | |||
b23256dc4e | |||
5906fb7139 | |||
0606050231 | |||
47cd9beefa | |||
a87f8e8687 | |||
978de73351 | |||
a1ec01ec2d | |||
7aa9949332 | |||
71f3cd648f | |||
7f379027ca | |||
279f3e4934 | |||
bdd75793bc | |||
58660bed3c | |||
2ca0ae7529 | |||
3ee09df6ce | |||
9b866b8e06 | |||
4d4954c5b8 | |||
17751ffd57 | |||
e8773f6a98 | |||
112ddc7156 | |||
e5ec72b09b | |||
24daf00616 | |||
718375419e | |||
a16bcf8e51 | |||
5c28125350 | |||
937de87dbf | |||
cadbe2c2c0 | |||
290af4c187 | |||
fd4e57aafc | |||
524a25eb2c | |||
5022575429 | |||
b8f22bf3bf | |||
5a8b3eb8f3 | |||
d26ac84126 | |||
82045b3fde | |||
14ce5a2432 |
@ -3,9 +3,10 @@ Headless I2P installation instructions
|
|||||||
1) java -jar i2pinstall.exe -console (you've already done this)
|
1) java -jar i2pinstall.exe -console (you've already done this)
|
||||||
|
|
||||||
This will run the installer in text mode, including running the postinstall.sh
|
This will run the installer in text mode, including running the postinstall.sh
|
||||||
script, which will start the router and launch a browser.
|
script. After that, you may run 'sh i2prouter start'
|
||||||
|
which will start the router and attempt to launch a browser.
|
||||||
|
|
||||||
If you do not have an X server running, the browser launch will fail, and
|
If you do not have an X server running, the browser launch will probably fail, and
|
||||||
you may use:
|
you may use:
|
||||||
lynx http://localhost:7657/index.jsp
|
lynx http://localhost:7657/index.jsp
|
||||||
to configure the router.
|
to configure the router.
|
||||||
@ -13,9 +14,20 @@ to configure the router.
|
|||||||
If you're having trouble, swing by http://forum.i2p2.de/, check the
|
If you're having trouble, swing by http://forum.i2p2.de/, check the
|
||||||
website at http://www.i2p2.de/, or get on irc://irc.freenode.net/#i2p
|
website at http://www.i2p2.de/, or get on irc://irc.freenode.net/#i2p
|
||||||
|
|
||||||
|
I2P will create and store files and configuration data in the user directory
|
||||||
|
~/.i2p/ on Linux and %APPDATA%\I2P\ on Windows. This directory is created
|
||||||
|
when I2P is run for the first time. It also creates files in the system
|
||||||
|
temporary directory specified by the Java Virtual Machine.
|
||||||
|
To change the location of these directories, or to configure I2P to
|
||||||
|
put all files in this directory (the so-called "portable" configuration),
|
||||||
|
edit the files i2prouter (Linux) and wrapper.config (Linux and Windows)
|
||||||
|
where there are comments labeled "PORTABLE". Do this before you
|
||||||
|
run I2P for the first time.
|
||||||
|
|
||||||
To run I2P explicitly:
|
To run I2P explicitly:
|
||||||
(*nix): sh i2prouter start
|
(*nix): sh i2prouter start
|
||||||
(win*): I2P.exe
|
(win*): I2P.exe
|
||||||
|
(Platforms unsupported by the wrapper - PPC, ARM, etc): sh runplain.sh
|
||||||
|
|
||||||
To stop the router (gracefully):
|
To stop the router (gracefully):
|
||||||
lynx http://localhost:7657/configservice.jsp ("Shutdown gracefully")
|
lynx http://localhost:7657/configservice.jsp ("Shutdown gracefully")
|
||||||
|
11
INSTALL.txt
@ -1,10 +1,18 @@
|
|||||||
I2P source installation instructions
|
I2P source installation instructions
|
||||||
|
|
||||||
|
Prerequisites to build from source:
|
||||||
|
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
|
||||||
|
The SDK must have Pack200 support (java.util.jar.Pack200)
|
||||||
|
Apache Ant 1.7.0 or higher
|
||||||
|
Optional, For multilanguage support: The xgettext, msgfmt, and msgmerge tools installed
|
||||||
|
from the GNU gettext package http://www.gnu.org/software/gettext/
|
||||||
|
|
||||||
To build and install I2P from source, you must first build
|
To build and install I2P from source, you must first build
|
||||||
and package up the appropriate installer by running:
|
and package up the appropriate installer by running:
|
||||||
|
|
||||||
ant pkg
|
ant pkg
|
||||||
|
|
||||||
|
|
||||||
This will produce a few key files:
|
This will produce a few key files:
|
||||||
* install.jar: the GUI and console installer
|
* install.jar: the GUI and console installer
|
||||||
* i2pinstall.exe: the GUI and console installer wrapped for cross-platform execution
|
* i2pinstall.exe: the GUI and console installer wrapped for cross-platform execution
|
||||||
@ -18,9 +26,6 @@ Or run the GUI installer:
|
|||||||
|
|
||||||
Or move the update file into an existing installation directory and restart.
|
Or move the update file into an existing installation directory and restart.
|
||||||
|
|
||||||
You will need to have ant installed from http://ant.apache.org/
|
|
||||||
(1.7.0 or newer)
|
|
||||||
|
|
||||||
Supported JVMs:
|
Supported JVMs:
|
||||||
Windows: Latest available from http://java.sun.com/ (1.5+ supported)
|
Windows: Latest available from http://java.sun.com/ (1.5+ supported)
|
||||||
Linux: Latest available from http://java.sun.com/ (1.5+ supported)
|
Linux: Latest available from http://java.sun.com/ (1.5+ supported)
|
||||||
|
24
LICENSE.txt
@ -64,6 +64,9 @@ Public domain except as listed below:
|
|||||||
Copyright 2006 Gregory Rubin grrubin@gmail.com
|
Copyright 2006 Gregory Rubin grrubin@gmail.com
|
||||||
See licenses/LICENSE-HashCash.txt
|
See licenses/LICENSE-HashCash.txt
|
||||||
|
|
||||||
|
GettextResource from gettext v0.18:
|
||||||
|
Copyright (C) 2001, 2007 Free Software Foundation, Inc.
|
||||||
|
See licenses/LICENSE-LGPLv2.1.txt
|
||||||
|
|
||||||
|
|
||||||
Router:
|
Router:
|
||||||
@ -76,16 +79,14 @@ Public domain except as listed below:
|
|||||||
Copyright (C) 2003-2006 Satoshi Konno
|
Copyright (C) 2003-2006 Satoshi Konno
|
||||||
See licenses/LICENSE-UPnP.txt
|
See licenses/LICENSE-UPnP.txt
|
||||||
|
|
||||||
XMLPull library used by UPnP:
|
|
||||||
See licenses/LICENSE-Apache2.0.txt
|
|
||||||
|
|
||||||
GeoIP data free to use, courtesy http://ip-to-country.webhosting.info/
|
GeoIP data free to use, courtesy http://ip-to-country.webhosting.info/
|
||||||
|
|
||||||
|
|
||||||
Installer:
|
Installer:
|
||||||
Launch4j 2.0.RC3:
|
Launch4j 3.0.1:
|
||||||
Copyright (C) 2005 Grzegorz Kowal
|
Copyright (c) 2004, 2008 Grzegorz Kowal
|
||||||
See licenses/LICENSE-GPLv2.txt
|
See licenses/LICENSE-Launch4j.txt (in binary packages)
|
||||||
|
See installer/lib/launch4j/LICENSE.txt (in source packages)
|
||||||
The following projects are used by Launch4j...
|
The following projects are used by Launch4j...
|
||||||
MinGW binutils (http://www.mingw.org/)
|
MinGW binutils (http://www.mingw.org/)
|
||||||
|
|
||||||
@ -141,6 +142,7 @@ Applications:
|
|||||||
I2PSnark:
|
I2PSnark:
|
||||||
Copyright (C) 2003 Mark J. Wielaard
|
Copyright (C) 2003 Mark J. Wielaard
|
||||||
See licenses/LICENSE-GPLv2.txt
|
See licenses/LICENSE-GPLv2.txt
|
||||||
|
Silk icons: See licenses/LICENSE-SilkIcons.txt
|
||||||
|
|
||||||
I2PTunnel:
|
I2PTunnel:
|
||||||
(c) 2003 - 2004 mihi
|
(c) 2003 - 2004 mihi
|
||||||
@ -177,7 +179,12 @@ Applications:
|
|||||||
|
|
||||||
Router console:
|
Router console:
|
||||||
Public domain.
|
Public domain.
|
||||||
Flag icons public domain, courtesy mjames@gmail.com http://www.famfamfam.com/
|
Flag icons: public domain, courtesy mjames@gmail.com http://www.famfamfam.com/
|
||||||
|
Silk icons: See licenses/LICENSE-SilkIcons.txt
|
||||||
|
|
||||||
|
GeoIP Data:
|
||||||
|
Copyright (c) 2003 Direct Information Pvt. Ltd. All Rights Reserved.
|
||||||
|
See licenses/LICENSE-GeoIP.txt
|
||||||
|
|
||||||
SAM:
|
SAM:
|
||||||
Public domain.
|
Public domain.
|
||||||
@ -206,6 +213,9 @@ The following applications and libraries are not used or bundled in
|
|||||||
binary packages, therefore the licenses are not included in binary
|
binary packages, therefore the licenses are not included in binary
|
||||||
distributions. See the source package for the additional license information.
|
distributions. See the source package for the additional license information.
|
||||||
|
|
||||||
|
Admin Manager:
|
||||||
|
Public domain
|
||||||
|
|
||||||
Atalk:
|
Atalk:
|
||||||
Public domain
|
Public domain
|
||||||
|
|
||||||
|
51
Makefile.gcj
@ -5,7 +5,7 @@
|
|||||||
GCJ=gcj #/usr/local/gcc-4.0.2/bin/gcj
|
GCJ=gcj #/usr/local/gcc-4.0.2/bin/gcj
|
||||||
EXTRA_LD_PATH= #/usr/local/gcc-4.0.2/lib
|
EXTRA_LD_PATH= #/usr/local/gcc-4.0.2/lib
|
||||||
ANT=ant #/opt/apache-ant-1.6.5/bin/ant
|
ANT=ant #/opt/apache-ant-1.6.5/bin/ant
|
||||||
ANT_TARGET=buildclean
|
ANT_TARGET=build2
|
||||||
NATIVE_DIR=native
|
NATIVE_DIR=native
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -24,20 +24,22 @@ JAR_BASE=i2p.jar mstreaming.jar streaming.jar
|
|||||||
JAR_CLIENTS=i2ptunnel.jar sam.jar
|
JAR_CLIENTS=i2ptunnel.jar sam.jar
|
||||||
JAR_ROUTER=router.jar
|
JAR_ROUTER=router.jar
|
||||||
JAR_JBIGI=jbigi.jar
|
JAR_JBIGI=jbigi.jar
|
||||||
JAR_XML=xml-apis.jar resolver.jar xercesImpl.jar
|
|
||||||
JAR_CONSOLE=\
|
JAR_CONSOLE=\
|
||||||
i2psnark.jar \
|
|
||||||
javax.servlet.jar \
|
javax.servlet.jar \
|
||||||
commons-el.jar \
|
commons-el.jar \
|
||||||
commons-logging.jar \
|
commons-logging.jar \
|
||||||
jasper-runtime.jar \
|
jasper-runtime.jar \
|
||||||
ant-apache-bcel.jar \
|
|
||||||
ant.jar \
|
|
||||||
jasper-compiler.jar \
|
jasper-compiler.jar \
|
||||||
org.mortbay.jetty.jar \
|
org.mortbay.jetty.jar \
|
||||||
routerconsole.jar
|
routerconsole.jar
|
||||||
JAR_SUCKER=jdom.jar rome-0.7.jar sucker.jar
|
|
||||||
LIBI2P_JARS=${JAR_BASE} ${JAR_CLIENTS} ${JAR_ROUTER} ${JAR_JBIGI}
|
LIBI2P_JARS=${JAR_BASE} ${JAR_CLIENTS} ${JAR_ROUTER} ${JAR_JBIGI}
|
||||||
|
LIBSAM_JARS=${JAR_BASE} sam.jar
|
||||||
|
LIBROUTER_JARS=i2p.jar ${JAR_ROUTER} ${JAR_JBIGI}
|
||||||
|
LIBCONSOLE_JARS=${LIBROUTER_JARS} ${JAR_CONSOLE}
|
||||||
|
LIBSNARK_JARS=${LIBROUTER_JARS} i2psnark.jar
|
||||||
|
# update:
|
||||||
|
# similar error with gcj 4.3.3.
|
||||||
|
#
|
||||||
# unfortunately, its not quite ready for most end users, as the
|
# unfortunately, its not quite ready for most end users, as the
|
||||||
# ${JAR_CONSOLE} fails to compile with:
|
# ${JAR_CONSOLE} fails to compile with:
|
||||||
# org/apache/commons/logging/impl/LogKitLogger.java: In class 'org.apache.commons.logging.impl.LogKitLogger':
|
# org/apache/commons/logging/impl/LogKitLogger.java: In class 'org.apache.commons.logging.impl.LogKitLogger':
|
||||||
@ -95,7 +97,36 @@ native_shared: libi2p.so
|
|||||||
@echo " i2ptunnel will, so it will start all the proxies defined in i2ptunnel.config"
|
@echo " i2ptunnel will, so it will start all the proxies defined in i2ptunnel.config"
|
||||||
|
|
||||||
libi2p.so:
|
libi2p.so:
|
||||||
@echo "* Building libi2p.so"
|
@echo "* Building $@"
|
||||||
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/libi2p.so ${LIBI2P_JARS} ; cd .. )
|
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBI2P_JARS} ; cd .. )
|
||||||
@ls -l ${NATIVE_DIR}/libi2p.so
|
@ls -l ${NATIVE_DIR}/$@
|
||||||
@echo "* libi2p.so built"
|
@echo "* $@ built"
|
||||||
|
|
||||||
|
sam: jars libi2psam.so
|
||||||
|
|
||||||
|
libi2psam.so:
|
||||||
|
@echo "* Building $@"
|
||||||
|
@rm -f ${NATIVE_DIR}/$@
|
||||||
|
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBSAM_JARS} ; cd .. )
|
||||||
|
@ls -l ${NATIVE_DIR}/$@
|
||||||
|
@echo "* $@ built"
|
||||||
|
|
||||||
|
router: jars libi2prouter.so
|
||||||
|
|
||||||
|
libi2prouter.so:
|
||||||
|
@echo "* Building $@"
|
||||||
|
@rm -f ${NATIVE_DIR}/$@
|
||||||
|
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBROUTER_JARS} ; cd .. )
|
||||||
|
@ls -l ${NATIVE_DIR}/$@
|
||||||
|
@echo "* $@ built"
|
||||||
|
|
||||||
|
console: jars libi2pconsole.so
|
||||||
|
|
||||||
|
# doesn't work, see above
|
||||||
|
libi2pconsole.so:
|
||||||
|
@echo "* Building $@"
|
||||||
|
@rm -f ${NATIVE_DIR}/$@
|
||||||
|
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBCONSOLE_JARS} ; cd .. )
|
||||||
|
@ls -l ${NATIVE_DIR}/$@
|
||||||
|
@echo "* $@ built"
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
Prerequisites to build from source:
|
Prerequisites to build from source:
|
||||||
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
|
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
|
||||||
|
The SDK must have Pack200 support (java.util.jar.Pack200)
|
||||||
Apache Ant 1.7.0 or higher
|
Apache Ant 1.7.0 or higher
|
||||||
|
Optional, For multilanguage support: The xgettext, msgfmt, and msgmerge tools installed
|
||||||
|
from the GNU gettext package http://www.gnu.org/software/gettext/
|
||||||
|
|
||||||
To build:
|
To build:
|
||||||
ant pkg
|
ant pkg
|
||||||
Run 'ant' with no arguments to see other build options.
|
Run 'ant' with no arguments to see other build options.
|
||||||
See http://www.i2p2.de/download.html for installation instructions.
|
See INSTALL.txt or http://www.i2p2.de/download.html for installation instructions.
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
http://www.i2p2.de/
|
http://www.i2p2.de/
|
||||||
|
@ -1,43 +1,155 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Now in the future we only need to look for '#I2P' and '#/I2P'
|
||||||
|
# for modifications to rc.local and rc.local_shutdown.
|
||||||
|
# I was a moron for not doing it this way in the first place :-) -- Sponge
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
touch /etc/rc.d/rc.local
|
touch /etc/rc.d/rc.local
|
||||||
touch /etc/rc.d/rc.local_shutdown
|
touch /etc/rc.d/rc.local_shutdown
|
||||||
|
|
||||||
I2PRCA=`grep -c /etc/rc.d/rc.local -e i2p`
|
|
||||||
I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e i2p`
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
echo -n "Check 1: /etc/rc.d/rc.local "
|
||||||
|
I2PRCA=`grep -c /etc/rc.d/rc.local -e '/etc/rc.d/rc.i2p'`
|
||||||
|
|
||||||
if [ $I2PRCA -eq 0 ] ; then
|
if [ $I2PRCA -eq 0 ] ; then
|
||||||
|
echo '#I2P' >> /etc/rc.d/rc.local
|
||||||
|
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
|
||||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
||||||
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
||||||
echo "fi" >> /etc/rc.d/rc.local
|
echo "fi" >> /etc/rc.d/rc.local
|
||||||
echo "/etc/rc.d/rc.local modified."
|
echo '#/I2P' >> /etc/rc.d/rc.local
|
||||||
|
echo "modified."
|
||||||
else
|
else
|
||||||
echo "/etc/rc.d/rc.local looks OK"
|
echo -n "looks OK so far,"
|
||||||
|
# Fix old installs, or where people have modified.
|
||||||
|
|
||||||
|
echo -n " Check 1A: "
|
||||||
|
I2PRCC=`grep -c /etc/rc.d/rc.local -e 'i2p-\*\.tmp'`
|
||||||
|
|
||||||
|
if [ $I2PRCC -eq 0 ] ; then
|
||||||
|
DATA=$(cat /etc/rc.d/rc.local | sed -re 's/if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/#I2P\n\( cd \/tmp ; rm -Rf i2p-*.tmp \)\nif \[ -x \/etc\/rc.d\/rc.i2p \] ; then/')
|
||||||
|
echo "${DATA}" > /etc/rc.d/rc.local
|
||||||
|
echo -n "additional modifications applied,"
|
||||||
|
else
|
||||||
|
echo -n "looks OK so far,"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n " Check 1B: "
|
||||||
|
I2PRCE=`grep -c /etc/rc.d/rc.local -e 'i2p-\*\.tmp'`
|
||||||
|
if [ $I2PRCE -eq 0 ] ; then
|
||||||
|
DATATOP=$(cat /etc/rc.d/rc.local | sed -n '0,/i2p-\*\.tmp/p' | sed '$d' )
|
||||||
|
DATABOT=$(cat /etc/rc.d/rc.local | sed -n '/i2p-\*\.tmp/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||||
|
echo "${DATATOP}" > /etc/rc.d/rc.local
|
||||||
|
echo '#I2P' >> /etc/rc.d/rc.local
|
||||||
|
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
|
||||||
|
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
||||||
|
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
||||||
|
echo "fi" >> /etc/rc.d/rc.local
|
||||||
|
echo '#/I2P' >> /etc/rc.d/rc.local
|
||||||
|
echo "${DATABOT}" >> /etc/rc.d/rc.local
|
||||||
|
|
||||||
|
echo -n "additional modifications applied,"
|
||||||
|
else
|
||||||
|
echo -n "looks ok so far,"
|
||||||
|
fi
|
||||||
|
echo -n " Check 1C: "
|
||||||
|
I2PRCF=`grep -c /etc/rc.d/rc.local -e '#/I2P'`
|
||||||
|
if [ $I2PRCF -eq 0 ] ; then
|
||||||
|
DATATOP=$(cat /etc/rc.d/rc.local | sed -n '0,/^#I2P/p' | sed '$d' )
|
||||||
|
DATABOT=$(cat /etc/rc.d/rc.local | sed -n '/^#I2P/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||||
|
echo "${DATATOP}" > /etc/rc.d/rc.local
|
||||||
|
echo '#I2P' >> /etc/rc.d/rc.local
|
||||||
|
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
|
||||||
|
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
||||||
|
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
||||||
|
echo "fi" >> /etc/rc.d/rc.local
|
||||||
|
echo '#/I2P' >> /etc/rc.d/rc.local
|
||||||
|
echo "${DATABOT}" >> /etc/rc.d/rc.local
|
||||||
|
|
||||||
|
echo -n "additional modifications applied,"
|
||||||
|
else
|
||||||
|
echo -n "looks ok so far,"
|
||||||
|
fi
|
||||||
|
echo " Done."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo -n "Check 2: /etc/rc.d/rc.local_shutdown "
|
||||||
|
I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e '/etc/rc.d/rc.i2p'`
|
||||||
if [ $I2PRCB -eq 0 ] ; then
|
if [ $I2PRCB -eq 0 ] ; then
|
||||||
|
echo "#I2P" >> /etc/rc.d/rc.local_shutdown
|
||||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
||||||
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
||||||
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
||||||
echo "/etc/rc.d/rc.local_shutdown modified."
|
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "modified."
|
||||||
else
|
else
|
||||||
echo "/etc/rc.d/rc.local_shutdown looks OK"
|
echo -n "looks OK so far,"
|
||||||
|
# Fix old installs
|
||||||
|
|
||||||
|
echo -n " Check 1A: "
|
||||||
|
I2PRCG=`grep -c /etc/rc.d/rc.local_shutdown -e '#I2P'`
|
||||||
|
if [ $I2PRCG -eq 0 ] ; then
|
||||||
|
DATATOP=$(cat /etc/rc.d/rc.local_shutdown | sed -n '0,/^if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/p' | sed '$d' )
|
||||||
|
DATABOT=$(cat /etc/rc.d/rc.local_shutdown | sed -n '/^if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||||
|
echo "${DATATOP}" > /etc/rc.d/rc.local_shutdown
|
||||||
|
echo '#I2P' >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "${DATABOT}" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo -n "additional modifications applied,"
|
||||||
|
else
|
||||||
|
echo -n "looks OK so far,"
|
||||||
|
fi
|
||||||
|
echo -n " Check 1B: "
|
||||||
|
I2PRCH=`grep -c /etc/rc.d/rc.local_shutdown -e '#/I2P'`
|
||||||
|
if [ $I2PRCH -eq 0 ] ; then
|
||||||
|
DATATOP=$(cat /etc/rc.d/rc.local_shutdown | sed -n '0,/^#I2P/p' | sed '$d' )
|
||||||
|
DATABOT=$(cat /etc/rc.d/rc.local_shutdown | sed -n '/^#I2P/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||||
|
echo "${DATATOP}" > /etc/rc.d/rc.local_shutdown
|
||||||
|
echo '#I2P' >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo "${DATABOT}" >> /etc/rc.d/rc.local_shutdown
|
||||||
|
echo -n "additional modifications applied,"
|
||||||
|
else
|
||||||
|
echo -n "looks OK so far,"
|
||||||
|
fi
|
||||||
|
echo " Done."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /etc/rc.d/rc.i2p ] ; then
|
if [ -f /etc/rc.d/rc.i2p ] ; then
|
||||||
if [ -x /etc/rc.d/rc.i2p ] ; then
|
if [ -x /etc/rc.d/rc.i2p ] ; then
|
||||||
chmod +x /etc/rc.d/rc.i2p.new
|
chmod +x /etc/rc.d/rc.i2p.new
|
||||||
fi
|
fi
|
||||||
echo
|
# Hopefully get admin's attention.
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -e "\007" ; sleep 0.3
|
||||||
echo "It apears that you already have /etc/rc.d/rc.i2p"
|
echo "It apears that you already have /etc/rc.d/rc.i2p"
|
||||||
echo "You may wish to replace it with /etc/rc.d/rc.i2p.new"
|
echo "You should replace it with /etc/rc.d/rc.i2p.new as soon as possible"
|
||||||
echo
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -ne "\007" ; sleep 0.3
|
||||||
|
echo -e "\007" ; sleep 0.3
|
||||||
else
|
else
|
||||||
mv /etc/rc.d/rc.i2p.new /etc/rc.d/rc.i2p
|
mv /etc/rc.d/rc.i2p.new /etc/rc.d/rc.i2p
|
||||||
echo
|
echo
|
||||||
echo "Installation finished. The i2p start/stop script has been"
|
echo "Installation finished. The i2p start/stop script has been"
|
||||||
echo "installed on /etc/rc.d directory. You should chmod +x"
|
echo "installed in /etc/rc.d . You should chmod +x"
|
||||||
echo '/etc/rc.d/rc.i2p to start it on boot.'
|
echo '/etc/rc.d/rc.i2p to start it on boot.'
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
@ -1,42 +1,57 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Heavily based on the Slackware 12.1 SlackBuild
|
#
|
||||||
# Slackware build script for i2p
|
# Heavily based on the Slackware 12.2 SlackBuild
|
||||||
|
# Slackware build script for I2P
|
||||||
|
#
|
||||||
# PLEASE READ THIS:
|
# PLEASE READ THIS:
|
||||||
# Probably you will never have to update i2p packages with upgradepkg,
|
# How to start I2P:
|
||||||
# just because i2p have an auto-update function.
|
# After installpkg command, doinst.sh will execute a post-installation script
|
||||||
# How to start i2p:
|
# needed by I2P. After that you have to chmod +x /etc/rc.d/rc.i2p and start
|
||||||
# After installpkg command, doinst.sh will execute a postinstallation script
|
# I2P service with /etc/rc.d/rc.i2p start.
|
||||||
# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
|
#
|
||||||
# i2p service with /etc/rc.d/rc.i2p start.
|
|
||||||
# Now tell your browser to user this proxy: localhost on port 4444 and open
|
# Now tell your browser to user this proxy: localhost on port 4444 and open
|
||||||
# this page: http://localhost:7657/index.jsp
|
# this page: http://localhost:7657/index.jsp
|
||||||
# Here you can configure i2p, watch network status and navigate anonimously.
|
#
|
||||||
|
# Here you can configure I2P, watch network status and navigate anonimously.
|
||||||
# It's suggested to subscribe to various dns host, like i2host.i2p
|
# It's suggested to subscribe to various dns host, like i2host.i2p
|
||||||
# For any additional information, visit i2host.i2p and forum.i2p
|
# For any additional information, visit i2host.i2p and forum.i2p
|
||||||
|
#
|
||||||
|
|
||||||
CWD=$(pwd)
|
CWD=$(pwd)
|
||||||
TMP=/tmp
|
TMP=/tmp
|
||||||
PKG=/$TMP/package-base-i2p
|
PKG=/$TMP/package-base-i2p
|
||||||
rm -rf $PKG
|
|
||||||
mkdir -p $PKG
|
|
||||||
# put here installation dir, without first and last /
|
|
||||||
# es: usr/local
|
|
||||||
NAME=i2p-base
|
NAME=i2p-base
|
||||||
VERSION=0.0.1
|
VERSION=0.0.2
|
||||||
BUILD=1sim
|
BUILD=1sponge
|
||||||
ARCH=noarch
|
ARCH=noarch
|
||||||
INSTALL_DIR=opt
|
INSTALL_DIR=opt
|
||||||
|
|
||||||
|
# Less than slackware 13?
|
||||||
|
SLKPLT=$(cat /etc/slackware-version | sed -re "s/(Slackware )([0-9]*)(.*)/\2/")
|
||||||
|
if [ $SLKPLT -lt 13 ] ; then
|
||||||
|
EXT=tgz
|
||||||
|
else
|
||||||
|
EXT=txz
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf $PKG
|
||||||
|
mkdir -p $PKG
|
||||||
cd $PKG
|
cd $PKG
|
||||||
chown -R root:root .
|
chown -R root:root .
|
||||||
|
|
||||||
mkdir -p $PKG/etc/rc.d
|
mkdir -p $PKG/etc/rc.d
|
||||||
mkdir -p $PKG/install
|
mkdir -p $PKG/install
|
||||||
sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" $CWD/rc.i2p_def > $PKG/etc/rc.d/rc.i2p.new
|
sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" "$CWD/rc.i2p_def" > $PKG/etc/rc.d/rc.i2p.new
|
||||||
chmod 644 $PKG/etc/rc.d/rc.i2p.new
|
chmod 644 $PKG/etc/rc.d/rc.i2p.new
|
||||||
sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
|
cat "$CWD/doinst.sh" > $PKG/install/doinst.sh
|
||||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
cat "$CWD/slack-desc" > $PKG/install/slack-desc
|
||||||
|
|
||||||
cd $PKG
|
cd $PKG
|
||||||
requiredbuilder -v -y -s $CWD $PKG
|
#
|
||||||
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
|
# Not really that important to exec this
|
||||||
|
# as there aren't any deps we don't know.
|
||||||
|
#
|
||||||
|
# requiredbuilder -v -y -s $CWD $PKG
|
||||||
|
#
|
||||||
|
cat "$CWD/slack-required" > $PKG/install/slack-required
|
||||||
|
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.$EXT
|
||||||
|
@ -9,6 +9,22 @@ i2p_stop() {
|
|||||||
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory stop )"
|
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory stop )"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i2p_restart() {
|
||||||
|
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory restart)"
|
||||||
|
}
|
||||||
|
|
||||||
|
i2p_status() {
|
||||||
|
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory status )"
|
||||||
|
}
|
||||||
|
|
||||||
|
i2p_console() {
|
||||||
|
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory console )"
|
||||||
|
}
|
||||||
|
|
||||||
|
i2p_dump() {
|
||||||
|
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory dump )"
|
||||||
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
'start')
|
'start')
|
||||||
i2p_start
|
i2p_start
|
||||||
@ -17,11 +33,19 @@ case "$1" in
|
|||||||
i2p_stop
|
i2p_stop
|
||||||
;;
|
;;
|
||||||
'restart')
|
'restart')
|
||||||
i2p_stop
|
i2p_restart
|
||||||
i2p_start
|
;;
|
||||||
|
'status')
|
||||||
|
i2p_status
|
||||||
|
;;
|
||||||
|
'console')
|
||||||
|
i2p_console
|
||||||
|
;;
|
||||||
|
'dump')
|
||||||
|
i2p_dump
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "usage $0 start|stop|restart"
|
echo "usage $0 start|stop|restart|status|console|dump"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -49,16 +49,21 @@ echo
|
|||||||
echo "FINISHING I2P INSTALLATION. PLEASE WAIT."
|
echo "FINISHING I2P INSTALLATION. PLEASE WAIT."
|
||||||
|
|
||||||
cd $INST_DIR
|
cd $INST_DIR
|
||||||
sh postinstall.sh || (
|
|
||||||
echo "ERROR: failed execution of postinstall.sh. Please"
|
|
||||||
echo "cd into i2p installation directory and run "
|
|
||||||
echo "postinstall.sh manually with ./postinstall.sh"
|
|
||||||
exit 1
|
|
||||||
)
|
|
||||||
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
sh i2prouter stop || exit 1
|
|
||||||
|
OS_ARCH=`uname -m`
|
||||||
|
X86_64=`echo "$OS_ARCH" | grep x86_64`
|
||||||
|
if [ "X$X86_64" = "X" ]; then
|
||||||
|
wrapperpath="./lib/wrapper/linux"
|
||||||
|
else
|
||||||
|
wrapperpath="./lib/wrapper/linux64"
|
||||||
|
fi
|
||||||
|
cp $wrapperpath/libwrapper.so ./lib/
|
||||||
|
cp $wrapperpath/wrapper.jar ./lib/
|
||||||
|
cp $wrapperpath/i2psvc .
|
||||||
|
rm -rf ./lib/wrapper
|
||||||
|
chmod 744 ./i2psvc
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Installation finished."
|
echo "Installation finished."
|
||||||
|
@ -1,28 +1,35 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Heavily based on the Slackware 12.1 SlackBuild
|
#
|
||||||
# Slackware build script for i2p
|
# Heavily based on the Slackware 12.2 SlackBuild
|
||||||
|
# Slackware build script for I2P
|
||||||
|
#
|
||||||
# PLEASE READ THIS:
|
# PLEASE READ THIS:
|
||||||
# Probably you will never have to update i2p packages with upgradepkg,
|
# Probably you will never have to update I2P packages with upgradepkg,
|
||||||
# just because i2p have an auto-update function.
|
# just because I2P has an auto-update function.
|
||||||
# How to start i2p:
|
# Really you should not ever use any "upgrade" method.
|
||||||
# After installpkg command, doinst.sh will execute a postinstallation script
|
#
|
||||||
# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
|
# The correct way to upgrade is to:
|
||||||
# i2p service with /etc/rc.d/rc.i2p start.
|
# 1: install the upgrade
|
||||||
# Now tell your browser to user this proxy: localhost on port 4444 and open
|
# 2: remove the old package
|
||||||
# this page: http://localhost:7657/index.jsp
|
#
|
||||||
# Here you can configure i2p, watch network status and navigate anonimously.
|
# It is a terrible shame that upgradepkg doesn't do this, infact,
|
||||||
# It's suggested to subscribe to various dns host, like i2host.i2p
|
# it would actually be the correct way for *any* package!
|
||||||
# For any additional information, visit i2host.i2p and forum.i2p
|
#
|
||||||
|
#
|
||||||
|
|
||||||
BUILD=1sim
|
BUILD=1sponge
|
||||||
|
|
||||||
# put here installation dir, without first and last /
|
|
||||||
# es: usr/local
|
|
||||||
INSTALL_DIR=opt
|
INSTALL_DIR=opt
|
||||||
NAME=i2p
|
NAME=i2p
|
||||||
ARCH=noarch
|
ARCH=noarch
|
||||||
|
|
||||||
|
# Less than slackware 13?
|
||||||
|
SLKPLT=$(cat /etc/slackware-version | sed -re "s/(Slackware )([0-9]*)(.*)/\2/")
|
||||||
|
if [ $SLKPLT -lt 13 ] ; then
|
||||||
|
EXT=tgz
|
||||||
|
else
|
||||||
|
EXT=txz
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# This mess is here due to the totally moronic way i2p does versioning.
|
# This mess is here due to the totally moronic way i2p does versioning.
|
||||||
@ -64,8 +71,8 @@ mkdir -p $PKG
|
|||||||
cd $CWD/../../
|
cd $CWD/../../
|
||||||
|
|
||||||
ant distclean
|
ant distclean
|
||||||
ant dist
|
#ant dist
|
||||||
|
ant tarball
|
||||||
|
|
||||||
tar xjvf i2p.tar.bz2 -C $TMP
|
tar xjvf i2p.tar.bz2 -C $TMP
|
||||||
|
|
||||||
@ -76,6 +83,34 @@ mkdir -p $PKG/$INSTALL_DIR/
|
|||||||
cp -a ../i2p $PKG/$INSTALL_DIR/
|
cp -a ../i2p $PKG/$INSTALL_DIR/
|
||||||
|
|
||||||
mkdir -p $PKG/install
|
mkdir -p $PKG/install
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Preconfigureation to make package smaller
|
||||||
|
#############################################################################
|
||||||
|
cd $PKG/$INSTALL_DIR/i2p
|
||||||
|
|
||||||
|
# wrapper.config $INSTALL_PATH and $SYSTEM_java_io_tmpdir
|
||||||
|
sed "s|\$INSTALL_PATH|$INSTALL_DIR/i2p|g" wrapper.config > a
|
||||||
|
sed "s|\$SYSTEM_java_io_tmpdir|/var/tmp|g" a > wrapper.config
|
||||||
|
# eepget %INSTALL_PATH
|
||||||
|
sed "s|\$INSTALL_PATH|$INSTALL_DIR/i2p|g" eepget > a
|
||||||
|
rm eepget
|
||||||
|
mv a eepget
|
||||||
|
# runplain.sh %INSTALL_PATH and %SYSTEM_java_io_tmpdir
|
||||||
|
sed "s|%INSTALL_PATH|$INSTALL_DIR/i2p|g" runplain.sh > a
|
||||||
|
sed "s|%SYSTEM_java_io_tmpdir|/var/tmp|g" a > runplain.sh
|
||||||
|
# i2prouter %INSTALL_PATH and %SYSTEM_java_io_tmpdir
|
||||||
|
sed "s|%INSTALL_PATH|$INSTALL_DIR/i2p|g" i2prouter > a
|
||||||
|
sed "s|%SYSTEM_java_io_tmpdir|/var/tmp|g" a > i2prouter
|
||||||
|
|
||||||
|
chmod 744 ./i2prouter
|
||||||
|
chmod 744 ./osid
|
||||||
|
chmod 744 ./runplain.sh
|
||||||
|
chmod 744 ./eepget
|
||||||
|
chmod 744 ./scripts/i2pbench.sh
|
||||||
|
chmod 744 ./scripts/i2ptest.sh
|
||||||
|
rm -Rf ./lib/*.dll ./*.bat ./*.exe ./installer ./icons ./a postinstall.sh
|
||||||
|
|
||||||
mv $PKG/$INSTALL_DIR/i2p/*.config $PKG/install
|
mv $PKG/$INSTALL_DIR/i2p/*.config $PKG/install
|
||||||
mv $PKG/$INSTALL_DIR/i2p/blocklist.txt $PKG/$INSTALL_DIR/i2p/blocklist.txt.new
|
mv $PKG/$INSTALL_DIR/i2p/blocklist.txt $PKG/$INSTALL_DIR/i2p/blocklist.txt.new
|
||||||
mv $PKG/$INSTALL_DIR/i2p/eepsite/jetty.xml $PKG/$INSTALL_DIR/i2p/eepsite/jetty.xml.new
|
mv $PKG/$INSTALL_DIR/i2p/eepsite/jetty.xml $PKG/$INSTALL_DIR/i2p/eepsite/jetty.xml.new
|
||||||
@ -83,6 +118,13 @@ mv $PKG/$INSTALL_DIR/i2p/eepsite/docroot/index.html $PKG/$INSTALL_DIR/i2p/eepsit
|
|||||||
mv $PKG/$INSTALL_DIR/i2p/eepsite/docroot/favicon.ico $PKG/$INSTALL_DIR/i2p/eepsite/docroot/favicon.ico.new
|
mv $PKG/$INSTALL_DIR/i2p/eepsite/docroot/favicon.ico $PKG/$INSTALL_DIR/i2p/eepsite/docroot/favicon.ico.new
|
||||||
sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
|
sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||||
|
|
||||||
cd $PKG
|
cd $PKG
|
||||||
requiredbuilder -v -y -s $CWD $PKG
|
#
|
||||||
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
|
# requiredbuilder fucks up REALLY bad, and thinks java is perl?!
|
||||||
|
# It also did not catch the shell requirements! BOOOOOOOOOOO! HISSSSSSSS!
|
||||||
|
#
|
||||||
|
# requiredbuilder -v -y -s $CWD $PKG
|
||||||
|
#
|
||||||
|
cat $CWD/slack-required > $PKG/install/slack-required
|
||||||
|
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.$EXT
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
glibc >= 2.7-i486-17 | glibc-solibs >= 2.7-i486-17
|
jre >= 5
|
||||||
perl >= 5.10.0-i486-1
|
i2p-base >= 0.0.1
|
||||||
|
bash >= 3.1.017
|
||||||
|
|
||||||
|
19
android/AndroidManifest.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="net.i2p.router"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0.0">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<!-- 3 = 1.5, 2 = 1.1, 1 = 1.0; would probably work with 1 but don't have a 1.0 SDK to test against -->
|
||||||
|
<uses-sdk android:minSdkVersion="2" />
|
||||||
|
<application android:label="@string/app_name">
|
||||||
|
<activity android:name=".I2PAndroid"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:launchMode="singleTask" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
38
android/README.txt
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
These instructions are for a recent Android SDK (1.6 or later)..
|
||||||
|
Should also still work with a 1.5 SDK.
|
||||||
|
The build file is not compatible with the 1.1 SDK any more.
|
||||||
|
|
||||||
|
#Download the SDK from http://developer.android.com/sdk/index.html
|
||||||
|
#Unzip the android SDK in ../../
|
||||||
|
#So then the android tools will be in ../../android-sdk-linux_86/tools/
|
||||||
|
#
|
||||||
|
# now go to the available packages tab, check the box and click refresh,
|
||||||
|
# and download an SDK Platform
|
||||||
|
# Since I2P is configured to run on 1.1 or higher
|
||||||
|
# (API 2) download that one. Otherwise you must change the
|
||||||
|
# target in default.properties from android-2 to andriod-x
|
||||||
|
# where x is the API version.
|
||||||
|
|
||||||
|
# create a file local.properties with the following line:
|
||||||
|
# sdk-location=/path/to/your/android-sdk-linux_86
|
||||||
|
|
||||||
|
#then build the android apk file:
|
||||||
|
ant debug
|
||||||
|
|
||||||
|
# Create the android 1.1 (API 2) virtual device
|
||||||
|
# (don't make a custom hardware profile)
|
||||||
|
# A AVD created with the 1.5 SDK will not work with the newer tools
|
||||||
|
../../android-sdk-linux_86/tools/android create avd --name i2p --target 2
|
||||||
|
|
||||||
|
#then run the emulator:
|
||||||
|
../../android-sdk-linux_86/tools/emulator -avd i2p &
|
||||||
|
|
||||||
|
#then wait a couple minutes until the emulator is up
|
||||||
|
#then install the I2P app
|
||||||
|
ant install
|
||||||
|
|
||||||
|
#then run the debugger
|
||||||
|
../../android-sdk-linux_86/tools/ddms &
|
||||||
|
|
||||||
|
#to rebuild and reinstall to emulator:
|
||||||
|
ant reinstall
|
356
android/build.xml
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name=".I2PAndroid" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||||
|
It contain the path to the SDK. It should *NOT* be checked in in Version
|
||||||
|
Control Systems. -->
|
||||||
|
<property file="local.properties"/>
|
||||||
|
|
||||||
|
<!-- The build.properties file can be created by you and is never touched
|
||||||
|
by the 'android' tool. This is the place to change some of the default property values
|
||||||
|
used by the Ant rules.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
application-package
|
||||||
|
the name of your application package as defined in the manifest. Used by the
|
||||||
|
'uninstall' rule.
|
||||||
|
source-folder
|
||||||
|
the name of the source folder. Default is 'src'.
|
||||||
|
out-folder
|
||||||
|
the name of the output folder. Default is 'bin'.
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should be updated
|
||||||
|
using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your application and
|
||||||
|
should be checked in in Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="build.properties"/>
|
||||||
|
|
||||||
|
<!-- The default.properties file is created and updated by the 'android' tool, as well
|
||||||
|
as ADT.
|
||||||
|
This file is an integral part of the build system for your application and
|
||||||
|
should be checked in in Version Control Systems. -->
|
||||||
|
<property file="default.properties"/>
|
||||||
|
|
||||||
|
<!-- Custom Android task to deal with the project target, and import the proper rules.
|
||||||
|
This requires ant 1.6.0 or above. -->
|
||||||
|
<path id="android.antlibs">
|
||||||
|
<pathelement path="${sdk-location}/tools/lib/anttasks.jar" />
|
||||||
|
<pathelement path="${sdk-location}/tools/lib/sdklib.jar" />
|
||||||
|
<pathelement path="${sdk-location}/tools/lib/androidprefs.jar" />
|
||||||
|
<pathelement path="${sdk-location}/tools/lib/apkbuilder.jar" />
|
||||||
|
<pathelement path="${sdk-location}/tools/lib/jarutils.jar" />
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<taskdef name="setup"
|
||||||
|
classname="com.android.ant.SetupTask"
|
||||||
|
classpathref="android.antlibs"/>
|
||||||
|
|
||||||
|
<!-- Execute the Android Setup task that will setup some properties specific to the target,
|
||||||
|
and import the rules files.
|
||||||
|
To customize the rules, copy/paste them below the task, and disable import by setting
|
||||||
|
the import attribute to false:
|
||||||
|
<setup import="false" />
|
||||||
|
|
||||||
|
This will ensure that the properties are setup correctly but that your customized
|
||||||
|
targets are used.
|
||||||
|
-->
|
||||||
|
<setup import="false" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
================================================================================
|
||||||
|
New I2P rules
|
||||||
|
================================================================================
|
||||||
|
-->
|
||||||
|
|
||||||
|
<target name="buildrouter" depends="dirs" >
|
||||||
|
<!-- build router and core -->
|
||||||
|
<ant dir=".." target="buildrouter" />
|
||||||
|
|
||||||
|
<!-- router -->
|
||||||
|
<copy file="../build/router.jar" todir="${external-libs-folder}" />
|
||||||
|
|
||||||
|
<!-- core -->
|
||||||
|
<mkdir dir="tmp" />
|
||||||
|
<unjar src="../build/i2p.jar" dest="tmp/" />
|
||||||
|
<delete file="tmp/net/i2p/util/LogWriter.class" />
|
||||||
|
<!-- org.bouncycastle.crypto already in android
|
||||||
|
but we need a little trickery because our HMac is incompatible...
|
||||||
|
and the libs aren't in the SDK to compile against??? -->
|
||||||
|
<jar destfile="${external-libs-folder}/crypto.jar" >
|
||||||
|
<fileset dir="tmp/" >
|
||||||
|
<include name="org/bouncycastle/crypto/Digest.class" />
|
||||||
|
<include name="org/bouncycastle/crypto/Mac.class" />
|
||||||
|
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
|
||||||
|
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
|
||||||
|
</fileset>
|
||||||
|
</jar>
|
||||||
|
<delete>
|
||||||
|
<fileset dir="tmp/" >
|
||||||
|
<include name="org/bouncycastle/crypto/Digest.class" />
|
||||||
|
<include name="org/bouncycastle/crypto/Mac.class" />
|
||||||
|
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
|
||||||
|
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
|
||||||
|
</fileset>
|
||||||
|
</delete>
|
||||||
|
<!--
|
||||||
|
<delete dir="tmp/org/bouncycastle/" />
|
||||||
|
<delete file="tmp/net/i2p/crypto/HMACGenerator.class" />
|
||||||
|
-->
|
||||||
|
<delete file="tmp/org/bouncycastle/" />
|
||||||
|
<!-- lots of unneeded stuff could be deleted here -->
|
||||||
|
<jar destfile="${external-libs-folder}/i2p.jar" basedir="tmp/" />
|
||||||
|
|
||||||
|
<!-- some resources -->
|
||||||
|
<mkdir dir="res/drawable/" />
|
||||||
|
<copy file="../installer/resources/themes/console/images/i2plogo.png" todir="res/drawable/" />
|
||||||
|
<copy file="../installer/resources/blocklist.txt" tofile="res/raw/blocklist_txt" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="hackcleanup">
|
||||||
|
<delete file="${external-libs-folder}/crypto.jar" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- fix for property name change sometime after SDK 1.5 -->
|
||||||
|
<property name="android-jar" value="${android.jar}" />
|
||||||
|
<property name="android-aidl" value="${android.aidl}" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
================================================================================
|
||||||
|
From here down copied from SDK platforms/android-1.1/templates/android_rules.xml
|
||||||
|
and then modified
|
||||||
|
================================================================================
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This rules file is meant to be imported by the custom Ant task:
|
||||||
|
com.android.ant.AndroidInitTask
|
||||||
|
|
||||||
|
The following properties are put in place by the importing task:
|
||||||
|
android-jar, android-aidl, aapt, aidl, and dx
|
||||||
|
|
||||||
|
Additionnaly, the task sets up the following classpath reference:
|
||||||
|
android.target.classpath
|
||||||
|
This is used by the compiler task as the boot classpath.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Custom tasks -->
|
||||||
|
<taskdef name="aaptexec"
|
||||||
|
classname="com.android.ant.AaptExecLoopTask"
|
||||||
|
classpathref="android.antlibs"/>
|
||||||
|
|
||||||
|
<taskdef name="apkbuilder"
|
||||||
|
classname="com.android.ant.ApkBuilderTask"
|
||||||
|
classpathref="android.antlibs"/>
|
||||||
|
|
||||||
|
<!-- Properties -->
|
||||||
|
|
||||||
|
<property name="android-tools" value="${sdk-location}/tools" />
|
||||||
|
|
||||||
|
<!-- Input directories -->
|
||||||
|
<property name="source-folder" value="src" />
|
||||||
|
<property name="gen-folder" value="gen" />
|
||||||
|
<property name="resource-folder" value="res" />
|
||||||
|
<property name="asset-folder" value="assets" />
|
||||||
|
<property name="source-location" value="${basedir}/${source-folder}" />
|
||||||
|
|
||||||
|
<!-- folder for the 3rd party java libraries -->
|
||||||
|
<property name="external-libs-folder" value="libs" />
|
||||||
|
|
||||||
|
<!-- folder for the native libraries -->
|
||||||
|
<property name="native-libs-folder" value="libs" />
|
||||||
|
|
||||||
|
<!-- Output directories -->
|
||||||
|
<property name="gen-folder" value="gen" />
|
||||||
|
<property name="out-folder" value="bin" />
|
||||||
|
<property name="out-classes" value="${out-folder}/classes" />
|
||||||
|
<property name="out-classes-location" value="${basedir}/${out-classes}"/>
|
||||||
|
<!-- out folders for a parent project if this project is an instrumentation project -->
|
||||||
|
<property name="main-out-folder" value="../${out-folder}" />
|
||||||
|
<property name="main-out-classes" value="${main-out-folder}/classes"/>
|
||||||
|
|
||||||
|
<!-- Intermediate files -->
|
||||||
|
<property name="dex-file" value="classes.dex" />
|
||||||
|
<property name="intermediate-dex" value="${out-folder}/${dex-file}" />
|
||||||
|
<!-- dx does not properly support incorrect / or \ based on the platform
|
||||||
|
and Ant cannot convert them because the parameter is not a valid path.
|
||||||
|
Because of this we have to compute different paths depending on the platform. -->
|
||||||
|
<condition property="intermediate-dex-location"
|
||||||
|
value="${basedir}\${intermediate-dex}"
|
||||||
|
else="${basedir}/${intermediate-dex}" >
|
||||||
|
<os family="windows"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<!-- The final package file to generate -->
|
||||||
|
<property name="out-debug-package" value="${out-folder}/${ant.project.name}-debug.apk"/>
|
||||||
|
|
||||||
|
<!-- Tools -->
|
||||||
|
<condition property="exe" value=".exe" else=""><os family="windows"/></condition>
|
||||||
|
<property name="adb" value="${android-tools}/adb${exe}"/>
|
||||||
|
|
||||||
|
<!-- rules -->
|
||||||
|
|
||||||
|
<!-- Create the output directories if they don't exist yet. -->
|
||||||
|
<target name="dirs">
|
||||||
|
<echo>Creating output directories if needed...</echo>
|
||||||
|
<mkdir dir="${resource-folder}" />
|
||||||
|
<mkdir dir="${external-libs-folder}" />
|
||||||
|
<mkdir dir="${gen-folder}" />
|
||||||
|
<mkdir dir="${out-folder}" />
|
||||||
|
<mkdir dir="${out-classes}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Generate the R.java file for this project's resources. -->
|
||||||
|
<target name="resource-src" depends="dirs">
|
||||||
|
<echo>Generating R.java / Manifest.java from the resources...</echo>
|
||||||
|
<exec executable="${aapt}" failonerror="true">
|
||||||
|
<arg value="package" />
|
||||||
|
<arg value="-m" />
|
||||||
|
<arg value="-J" />
|
||||||
|
<arg path="${gen-folder}" />
|
||||||
|
<arg value="-M" />
|
||||||
|
<arg path="AndroidManifest.xml" />
|
||||||
|
<arg value="-S" />
|
||||||
|
<arg path="${resource-folder}" />
|
||||||
|
<arg value="-I" />
|
||||||
|
<arg path="${android-jar}" />
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Generate java classes from .aidl files. -->
|
||||||
|
<target name="aidl" depends="dirs">
|
||||||
|
<echo>Compiling aidl files into Java classes...</echo>
|
||||||
|
<apply executable="${aidl}" failonerror="true">
|
||||||
|
<arg value="-p${android-aidl}" />
|
||||||
|
<arg value="-I${source-folder}" />
|
||||||
|
<arg value="-o${gen-folder}" />
|
||||||
|
<fileset dir="${source-folder}">
|
||||||
|
<include name="**/*.aidl"/>
|
||||||
|
</fileset>
|
||||||
|
</apply>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Compile this project's .java files into .class files. -->
|
||||||
|
<!-- I2P add buildrouter -->
|
||||||
|
<target name="compile" depends="buildrouter, resource-src, aidl">
|
||||||
|
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
|
||||||
|
destdir="${out-classes}"
|
||||||
|
bootclasspathref="android.target.classpath">
|
||||||
|
<src path="${source-folder}" />
|
||||||
|
<src path="${gen-folder}" />
|
||||||
|
<classpath>
|
||||||
|
<fileset dir="${external-libs-folder}" includes="*.jar"/>
|
||||||
|
<pathelement path="${main-out-classes}"/>
|
||||||
|
</classpath>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Convert this project's .class files into .dex files. -->
|
||||||
|
<!-- I2P add hackcleanup -->
|
||||||
|
<target name="dex" depends="compile, hackcleanup">
|
||||||
|
<echo>Converting compiled files and external libraries into ${out-folder}/${dex-file}...</echo>
|
||||||
|
<apply executable="${dx}" failonerror="true" parallel="true">
|
||||||
|
<!-- I2P this is a bad sign that we need this -->
|
||||||
|
<arg value="-JXmx256m" />
|
||||||
|
<arg value="--dex" />
|
||||||
|
<arg value="--output=${intermediate-dex-location}" />
|
||||||
|
<arg path="${out-classes-location}" />
|
||||||
|
<fileset dir="${external-libs-folder}" includes="*.jar"/>
|
||||||
|
</apply>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Put the project's resources into the output package file
|
||||||
|
This actually can create multiple resource package in case
|
||||||
|
Some custom apk with specific configuration have been
|
||||||
|
declared in default.properties.
|
||||||
|
-->
|
||||||
|
<target name="package-resources">
|
||||||
|
<echo>Packaging resources</echo>
|
||||||
|
<aaptexec executable="${aapt}"
|
||||||
|
command="package"
|
||||||
|
manifest="AndroidManifest.xml"
|
||||||
|
resources="${resource-folder}"
|
||||||
|
assets="${asset-folder}"
|
||||||
|
androidjar="${android-jar}"
|
||||||
|
outfolder="${out-folder}"
|
||||||
|
basename="${ant.project.name}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Package the application and sign it with a debug key.
|
||||||
|
This is the default target when building. It is used for debug. -->
|
||||||
|
<target name="debug" depends="dex, package-resources">
|
||||||
|
<apkbuilder
|
||||||
|
outfolder="${out-folder}"
|
||||||
|
basename="${ant.project.name}"
|
||||||
|
signed="true"
|
||||||
|
verbose="false">
|
||||||
|
<file path="${intermediate-dex}" />
|
||||||
|
<sourcefolder path="${source-folder}" />
|
||||||
|
<jarfolder path="${external-libs-folder}" />
|
||||||
|
<nativefolder path="${native-libs-folder}" />
|
||||||
|
</apkbuilder>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Package the application without signing it.
|
||||||
|
This allows for the application to be signed later with an official publishing key. -->
|
||||||
|
<target name="release" depends="dex, package-resources">
|
||||||
|
<apkbuilder
|
||||||
|
outfolder="${out-folder}"
|
||||||
|
basename="${ant.project.name}"
|
||||||
|
signed="false"
|
||||||
|
verbose="false">
|
||||||
|
<file path="${intermediate-dex}" />
|
||||||
|
<sourcefolder path="${source-folder}" />
|
||||||
|
<jarfolder path="${external-libs-folder}" />
|
||||||
|
<nativefolder path="${native-libs-folder}" />
|
||||||
|
</apkbuilder>
|
||||||
|
<echo>All generated packages need to be signed with jarsigner before they are published.</echo>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Install the package on the default emulator -->
|
||||||
|
<target name="install" depends="debug">
|
||||||
|
<echo>Installing ${out-debug-package} onto default emulator...</echo>
|
||||||
|
<exec executable="${adb}" failonerror="true">
|
||||||
|
<arg value="install" />
|
||||||
|
<arg path="${out-debug-package}" />
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="reinstall" depends="debug">
|
||||||
|
<echo>Installing ${out-debug-package} onto default emulator...</echo>
|
||||||
|
<exec executable="${adb}" failonerror="true">
|
||||||
|
<arg value="install" />
|
||||||
|
<arg value="-r" />
|
||||||
|
<arg path="${out-debug-package}" />
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- Uinstall the package from the default emulator -->
|
||||||
|
<target name="uninstall">
|
||||||
|
<echo>Uninstalling ${application-package} from the default emulator...</echo>
|
||||||
|
<exec executable="${adb}" failonerror="true">
|
||||||
|
<arg value="uninstall" />
|
||||||
|
<arg path="${application-package}" />
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="help">
|
||||||
|
<!-- displays starts at col 13
|
||||||
|
|13 80| -->
|
||||||
|
<echo>Android Ant Build. Available targets:</echo>
|
||||||
|
<echo> help: Displays this help.</echo>
|
||||||
|
<echo> debug: Builds the application and sign it with a debug key.</echo>
|
||||||
|
<echo> release: Builds the application. The generated apk file must be</echo>
|
||||||
|
<echo> signed before it is published.</echo>
|
||||||
|
<echo> install: Installs the debug package onto a running emulator or</echo>
|
||||||
|
<echo> device. This can only be used if the application has </echo>
|
||||||
|
<echo> not yet been installed.</echo>
|
||||||
|
<echo> reinstall: Installs the debug package on a running emulator or</echo>
|
||||||
|
<echo> device that already has the application.</echo>
|
||||||
|
<echo> The signatures must match.</echo>
|
||||||
|
<echo> uninstall: uninstall the application from a running emulator or</echo>
|
||||||
|
<echo> device.</echo>
|
||||||
|
</target>
|
||||||
|
</project>
|
11
android/default.properties
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "build.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-2
|
18
android/res/layout/main.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Hello World, I2PAndroid"
|
||||||
|
/>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/i2plogo"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
3
android/res/raw/logger_config
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
logger.defaultLevel=INFO
|
||||||
|
logger.record.net.i2p.router.transport.FIFOBandwidthRefiller=ERROR
|
||||||
|
logger.record.net.i2p.stat.Rate=ERROR
|
22
android/res/raw/router_config
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# initial router.config
|
||||||
|
# temp directory
|
||||||
|
i2p.dir.temp=/data/data/net.i2p.router/files/tmp
|
||||||
|
i2p.dir.pid=/data/data/net.i2p.router/files/tmp
|
||||||
|
# save memory
|
||||||
|
prng.buffers=2
|
||||||
|
router.decayingBloomFilterM=20
|
||||||
|
stat.full=false
|
||||||
|
i2np.udp.maxConnections=30
|
||||||
|
# no I2CP
|
||||||
|
i2p.dummyClientFacade=true
|
||||||
|
# for now
|
||||||
|
#i2np.ntcp.enable=false
|
||||||
|
#
|
||||||
|
# UDP crashes the JVM, don't know why
|
||||||
|
#
|
||||||
|
i2np.udp.enable=false
|
||||||
|
# no COMM at all!!!
|
||||||
|
#i2p.vmCommSystem=true
|
||||||
|
# not on android
|
||||||
|
i2np.upnp.enable=false
|
||||||
|
routerconsole.geoip.enable=false
|
4
android/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">I2PAndroid</string>
|
||||||
|
</resources>
|
142
android/src/net/i2p/router/I2PAndroid.java
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package net.i2p.router;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.Resources.NotFoundException;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.i2p.router.Router;
|
||||||
|
import net.i2p.router.RouterLaunch;
|
||||||
|
// import net.i2p.util.NativeBigInteger;
|
||||||
|
|
||||||
|
public class I2PAndroid extends Activity
|
||||||
|
{
|
||||||
|
static Context _context;
|
||||||
|
private static final String DIR = "/data/data/net.i2p.router/files";
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
|
_context = this; // Activity extends Context
|
||||||
|
debugStuff();
|
||||||
|
initialize();
|
||||||
|
// 300ms per run
|
||||||
|
// 5x slower than java on my server and 50x slower than native on my server
|
||||||
|
// NativeBigInteger.main(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRestart()
|
||||||
|
{
|
||||||
|
System.err.println("onRestart called");
|
||||||
|
super.onRestart();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStart()
|
||||||
|
{
|
||||||
|
System.err.println("onStart called");
|
||||||
|
super.onStart();
|
||||||
|
RouterLaunch.main(null);
|
||||||
|
System.err.println("Router.main finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume()
|
||||||
|
{
|
||||||
|
System.err.println("onResume called");
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPause()
|
||||||
|
{
|
||||||
|
System.err.println("onPause called");
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStop()
|
||||||
|
{
|
||||||
|
System.err.println("onStop called");
|
||||||
|
super.onStop();
|
||||||
|
|
||||||
|
// from routerconsole ContextHelper
|
||||||
|
List contexts = RouterContext.listContexts();
|
||||||
|
if ( (contexts == null) || (contexts.isEmpty()) )
|
||||||
|
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
|
||||||
|
RouterContext ctx = (RouterContext)contexts.get(0);
|
||||||
|
|
||||||
|
// shutdown() doesn't return so use shutdownGracefully()
|
||||||
|
ctx.router().shutdownGracefully(Router.EXIT_HARD);
|
||||||
|
System.err.println("shutdown complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
System.err.println("onDestroy called");
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Context getContext() {
|
||||||
|
return _context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void debugStuff() {
|
||||||
|
System.err.println("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
|
||||||
|
System.err.println("java.vendor" + ": " + System.getProperty("java.vendor"));
|
||||||
|
System.err.println("java.version" + ": " + System.getProperty("java.version"));
|
||||||
|
System.err.println("os.arch" + ": " + System.getProperty("os.arch"));
|
||||||
|
System.err.println("os.name" + ": " + System.getProperty("os.name"));
|
||||||
|
System.err.println("os.version" + ": " + System.getProperty("os.version"));
|
||||||
|
System.err.println("user.dir" + ": " + System.getProperty("user.dir"));
|
||||||
|
System.err.println("user.home" + ": " + System.getProperty("user.home"));
|
||||||
|
System.err.println("user.name" + ": " + System.getProperty("user.name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() {
|
||||||
|
// Until we can edit the router.config on the device,
|
||||||
|
// copy it from the resource every time.
|
||||||
|
// File f = new I2PFile("router.config");
|
||||||
|
// if (!f.exists()) {
|
||||||
|
copyResourceToFile(R.raw.router_config, "router.config");
|
||||||
|
copyResourceToFile(R.raw.logger_config, "logger.config");
|
||||||
|
copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Set up the locations so Router and WorkingDir can find them
|
||||||
|
System.setProperty("i2p.dir.base", DIR);
|
||||||
|
System.setProperty("i2p.dir.config", DIR);
|
||||||
|
System.setProperty("wrapper.logfile", DIR + "/wrapper.log");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyResourceToFile(int resID, String f) {
|
||||||
|
InputStream in = null;
|
||||||
|
FileOutputStream out = null;
|
||||||
|
|
||||||
|
System.err.println("Creating file " + f + " from resource");
|
||||||
|
byte buf[] = new byte[4096];
|
||||||
|
try {
|
||||||
|
// Context methods
|
||||||
|
in = getResources().openRawResource(resID);
|
||||||
|
out = openFileOutput(f, 0);
|
||||||
|
|
||||||
|
int read = 0;
|
||||||
|
while ( (read = in.read(buf)) != -1)
|
||||||
|
out.write(buf, 0, read);
|
||||||
|
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
} catch (Resources.NotFoundException nfe) {
|
||||||
|
} finally {
|
||||||
|
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||||
|
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
163
android/src/net/i2p/util/LogWriter.java
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package net.i2p.util;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* public domain
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bridge to android logging
|
||||||
|
*
|
||||||
|
* @author zzz
|
||||||
|
*/
|
||||||
|
class LogWriter implements Runnable {
|
||||||
|
private final static long CONFIG_READ_ITERVAL = 10 * 1000;
|
||||||
|
private long _lastReadConfig = 0;
|
||||||
|
private long _numBytesInCurrentFile = 0;
|
||||||
|
private OutputStream _currentOut; // = System.out
|
||||||
|
private int _rotationNum = -1;
|
||||||
|
private String _logFilenamePattern;
|
||||||
|
private File _currentFile;
|
||||||
|
private LogManager _manager;
|
||||||
|
|
||||||
|
private boolean _write;
|
||||||
|
|
||||||
|
private LogWriter() { // nop
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogWriter(LogManager manager) {
|
||||||
|
_manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopWriting() {
|
||||||
|
_write = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
_write = true;
|
||||||
|
try {
|
||||||
|
while (_write) {
|
||||||
|
flushRecords();
|
||||||
|
rereadConfig();
|
||||||
|
}
|
||||||
|
System.err.println("Done writing");
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Error writing the logs: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flushRecords() { flushRecords(true); }
|
||||||
|
public void flushRecords(boolean shouldWait) {
|
||||||
|
try {
|
||||||
|
List records = _manager._removeAll();
|
||||||
|
if (records == null) return;
|
||||||
|
for (int i = 0; i < records.size(); i++) {
|
||||||
|
LogRecord rec = (LogRecord) records.get(i);
|
||||||
|
writeRecord(rec);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (shouldWait) {
|
||||||
|
try {
|
||||||
|
synchronized (this) {
|
||||||
|
this.wait(10*1000);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ie) { // nop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String currentFile() {
|
||||||
|
return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rereadConfig() {
|
||||||
|
long now = Clock.getInstance().now();
|
||||||
|
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
|
||||||
|
_manager.rereadConfig();
|
||||||
|
_lastReadConfig = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeRecord(LogRecord rec) {
|
||||||
|
if (rec.getThrowable() == null)
|
||||||
|
log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage());
|
||||||
|
else
|
||||||
|
log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage(), rec.getThrowable());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(int priority, Class src, String name, String threadName, String msg) {
|
||||||
|
if (src != null) {
|
||||||
|
String tag = src.getName();
|
||||||
|
int dot = tag.lastIndexOf(".");
|
||||||
|
if (dot >= 0)
|
||||||
|
tag = tag.substring(dot + 1);
|
||||||
|
android.util.Log.println(toAndroidLevel(priority),
|
||||||
|
tag,
|
||||||
|
'[' + threadName + "] " + msg);
|
||||||
|
} else if (name != null)
|
||||||
|
android.util.Log.println(toAndroidLevel(priority),
|
||||||
|
name,
|
||||||
|
'[' + threadName + "] " + msg);
|
||||||
|
else
|
||||||
|
android.util.Log.println(toAndroidLevel(priority),
|
||||||
|
threadName, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(int priority, Class src, String name, String threadName, String msg, Throwable t) {
|
||||||
|
if (src != null) {
|
||||||
|
String tag = src.getName();
|
||||||
|
int dot = tag.lastIndexOf(".");
|
||||||
|
if (dot >= 0)
|
||||||
|
tag = tag.substring(dot + 1);
|
||||||
|
android.util.Log.println(toAndroidLevel(priority),
|
||||||
|
tag,
|
||||||
|
'[' + threadName + "] " + msg +
|
||||||
|
' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
|
||||||
|
} else if (name != null)
|
||||||
|
android.util.Log.println(toAndroidLevel(priority),
|
||||||
|
name,
|
||||||
|
'[' + threadName + "] " + msg +
|
||||||
|
' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
|
||||||
|
else
|
||||||
|
android.util.Log.println(toAndroidLevel(priority),
|
||||||
|
threadName,
|
||||||
|
msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int toAndroidLevel(int level) {
|
||||||
|
switch (level) {
|
||||||
|
case Log.DEBUG:
|
||||||
|
return android.util.Log.DEBUG;
|
||||||
|
case Log.INFO:
|
||||||
|
return android.util.Log.INFO;
|
||||||
|
case Log.WARN:
|
||||||
|
return android.util.Log.WARN;
|
||||||
|
case Log.ERROR:
|
||||||
|
case Log.CRIT:
|
||||||
|
default:
|
||||||
|
return android.util.Log.ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String replace(String pattern, int num) {
|
||||||
|
char c[] = pattern.toCharArray();
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
for (int i = 0; i < c.length; i++) {
|
||||||
|
if ( (c[i] != '#') && (c[i] != '@') )
|
||||||
|
buf.append(c[i]);
|
||||||
|
else
|
||||||
|
buf.append(num);
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -71,4 +71,44 @@
|
|||||||
nbproject/build-impl.xml file.
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
<target depends="jar" description="Build BOB into a SINGLE JAR." name="onejar">
|
||||||
|
<!-- Make needed working dirs -->
|
||||||
|
<mkdir dir="${dist.dir}/lib" />
|
||||||
|
<mkdir dir="${dist.dir}/classes" />
|
||||||
|
|
||||||
|
<!-- Copy jars -->
|
||||||
|
<copy todir="${dist.dir}/lib" flatten="true" >
|
||||||
|
<path>
|
||||||
|
<pathelement path="${javac.classpath}" />
|
||||||
|
</path>
|
||||||
|
</copy>
|
||||||
|
<copy todir="${dist.dir}/lib" file="../../installer/lib/jbigi/jbigi.jar" />
|
||||||
|
|
||||||
|
<!-- Extract the classes inside the jar files -->
|
||||||
|
<unjar dest="${dist.dir}/classes" >
|
||||||
|
<fileset dir="${dist.dir}/lib" >
|
||||||
|
<include name="**/*.jar" />
|
||||||
|
</fileset>
|
||||||
|
</unjar>
|
||||||
|
|
||||||
|
<!-- Recombine the classes into a new jar file -->
|
||||||
|
<jar jarfile="${dist.dir}/lib/all-in-one.jar" >
|
||||||
|
<fileset dir="${dist.dir}/classes" />
|
||||||
|
</jar>
|
||||||
|
|
||||||
|
<!-- Clean up work area -->
|
||||||
|
<delete dir="${dist.dir}/classes" followsymlinks="false" includeemptydirs="true"/>
|
||||||
|
|
||||||
|
<!-- Make the single jar file -->
|
||||||
|
<jar jarfile="dist/BOB-one.jar" >
|
||||||
|
<zipfileset src="${dist.jar}" excludes="META-INF/*" />
|
||||||
|
<zipfileset src="${dist.dir}/lib/all-in-one.jar" excludes="**/META-INF/*" />
|
||||||
|
<manifest>
|
||||||
|
<attribute name="Main-Class" value="net.i2p.BOB.Main" />
|
||||||
|
</manifest>
|
||||||
|
</jar>
|
||||||
|
|
||||||
|
<!-- Clean up the fake jar file -->
|
||||||
|
<delete file="${dist.dir}/lib/all-in-one.jar" />
|
||||||
|
</target>
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
compile.on.save=false
|
|
||||||
do.depend=false
|
|
||||||
do.jar=true
|
|
||||||
javac.debug=true
|
|
||||||
javadoc.preview=true
|
|
||||||
jaxws.endorsed.dir=/usr/local/netbeans-6.5/java2/modules/ext/jaxws21/api:/usr/local/netbeans-6.5/ide10/modules/ext/jaxb/api
|
|
||||||
user.properties.file=/root/.netbeans/6.5/build.properties
|
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
|
||||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
|
|
||||||
</project-private>
|
|
@ -1,5 +1,6 @@
|
|||||||
|
application.homepage=http://bob.i2p/
|
||||||
application.title=BOB
|
application.title=BOB
|
||||||
application.vendor=root
|
application.vendor=Sponge
|
||||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
|
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
|
||||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
|
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.spaces-per-tab=8
|
||||||
@ -11,6 +12,7 @@ build.classes.excludes=**/*.java,**/*.form
|
|||||||
# This directory is removed when the project is cleaned:
|
# This directory is removed when the project is cleaned:
|
||||||
build.dir=build
|
build.dir=build
|
||||||
build.generated.dir=${build.dir}/generated
|
build.generated.dir=${build.dir}/generated
|
||||||
|
build.generated.sources.dir=${build.dir}/generated-sources
|
||||||
# Only compile against the classpath explicitly listed here:
|
# Only compile against the classpath explicitly listed here:
|
||||||
build.sysclasspath=ignore
|
build.sysclasspath=ignore
|
||||||
build.test.classes.dir=${build.dir}/test/classes
|
build.test.classes.dir=${build.dir}/test/classes
|
||||||
@ -23,6 +25,7 @@ debug.test.classpath=\
|
|||||||
dist.dir=dist
|
dist.dir=dist
|
||||||
dist.jar=${dist.dir}/BOB.jar
|
dist.jar=${dist.dir}/BOB.jar
|
||||||
dist.javadoc.dir=${dist.dir}/javadoc
|
dist.javadoc.dir=${dist.dir}/javadoc
|
||||||
|
endorsed.classpath=
|
||||||
excludes=
|
excludes=
|
||||||
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
|
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
|
||||||
file.reference.i2p.jar=../../core/java/build/i2p.jar
|
file.reference.i2p.jar=../../core/java/build/i2p.jar
|
||||||
@ -33,7 +36,7 @@ file.reference.router.jar=../../router/java/build/router.jar
|
|||||||
file.reference.streaming.jar=../streaming/java/build/streaming.jar
|
file.reference.streaming.jar=../streaming/java/build/streaming.jar
|
||||||
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
|
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
|
||||||
includes=**
|
includes=**
|
||||||
jar.compress=false
|
jar.compress=true
|
||||||
javac.classpath=\
|
javac.classpath=\
|
||||||
${file.reference.router.jar}:\
|
${file.reference.router.jar}:\
|
||||||
${file.reference.i2ptunnel.jar}:\
|
${file.reference.i2ptunnel.jar}:\
|
||||||
@ -63,8 +66,9 @@ javadoc.splitindex=true
|
|||||||
javadoc.use=true
|
javadoc.use=true
|
||||||
javadoc.version=false
|
javadoc.version=false
|
||||||
javadoc.windowtitle=
|
javadoc.windowtitle=
|
||||||
|
jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
|
||||||
jnlp.codebase.type=local
|
jnlp.codebase.type=local
|
||||||
jnlp.codebase.url=file:/root/NetBeansProjects/i2p.i2p/apps/BOB/dist/
|
jnlp.codebase.url=file:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/dist
|
||||||
jnlp.descriptor=application
|
jnlp.descriptor=application
|
||||||
jnlp.enabled=false
|
jnlp.enabled=false
|
||||||
jnlp.offline-allowed=false
|
jnlp.offline-allowed=false
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.i2p.BOB;
|
package net.i2p.BOB;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -34,6 +35,8 @@ import java.net.Socket;
|
|||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.client.I2PClient;
|
import net.i2p.client.I2PClient;
|
||||||
import net.i2p.client.streaming.RetransmissionTimer;
|
import net.i2p.client.streaming.RetransmissionTimer;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@ -163,6 +166,7 @@ public class BOB {
|
|||||||
public static void stop() {
|
public static void stop() {
|
||||||
spin.set(false);
|
spin.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for incoming connections and handle them
|
* Listen for incoming connections and handle them
|
||||||
*
|
*
|
||||||
@ -185,16 +189,20 @@ public class BOB {
|
|||||||
i = Y2.hashCode();
|
i = Y2.hashCode();
|
||||||
try {
|
try {
|
||||||
{
|
{
|
||||||
|
File cfg = new File(configLocation);
|
||||||
|
if (!cfg.isAbsolute()) {
|
||||||
|
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
FileInputStream fi = new FileInputStream(configLocation);
|
FileInputStream fi = new FileInputStream(cfg);
|
||||||
props.load(fi);
|
props.load(fi);
|
||||||
fi.close();
|
fi.close();
|
||||||
} catch (FileNotFoundException fnfe) {
|
} catch (FileNotFoundException fnfe) {
|
||||||
warn("Unable to load up the BOB config file " + configLocation + ", Using defaults.");
|
warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.");
|
||||||
warn(fnfe.toString());
|
warn(fnfe.toString());
|
||||||
save = true;
|
save = true;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
warn("IOException on BOB config file " + configLocation + ", using defaults.");
|
warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.");
|
||||||
warn(ioe.toString());
|
warn(ioe.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,13 +235,17 @@ public class BOB {
|
|||||||
props.setProperty(PROP_BOB_HOST, "localhost");
|
props.setProperty(PROP_BOB_HOST, "localhost");
|
||||||
}
|
}
|
||||||
if (save) {
|
if (save) {
|
||||||
|
File cfg = new File(configLocation);
|
||||||
|
if (!cfg.isAbsolute()) {
|
||||||
|
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
warn("Writing new defaults file " + configLocation);
|
warn("Writing new defaults file " + cfg.getAbsolutePath());
|
||||||
FileOutputStream fo = new FileOutputStream(configLocation);
|
FileOutputStream fo = new FileOutputStream(cfg);
|
||||||
props.store(fo, configLocation);
|
props.store(fo, cfg.getAbsolutePath());
|
||||||
fo.close();
|
fo.close();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
error("IOException on BOB config file " + configLocation + ", " + ioe);
|
error("IOException on BOB config file " + cfg.getAbsolutePath() + ", " + ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,11 +256,13 @@ public class BOB {
|
|||||||
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
|
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
|
||||||
Socket server = null;
|
Socket server = null;
|
||||||
listener.setSoTimeout(500); // .5 sec
|
listener.setSoTimeout(500); // .5 sec
|
||||||
|
|
||||||
while (spin.get()) {
|
while (spin.get()) {
|
||||||
//DoCMDS connection;
|
//DoCMDS connection;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
server = listener.accept();
|
server = listener.accept();
|
||||||
|
server.setKeepAlive(true);
|
||||||
g = true;
|
g = true;
|
||||||
} catch (ConnectException ce) {
|
} catch (ConnectException ce) {
|
||||||
g = false;
|
g = false;
|
||||||
|
@ -25,6 +25,7 @@ package net.i2p.BOB;
|
|||||||
|
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.client.streaming.I2PServerSocket;
|
import net.i2p.client.streaming.I2PServerSocket;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
@ -43,6 +44,7 @@ public class I2Plistener implements Runnable {
|
|||||||
// private int tgwatch;
|
// private int tgwatch;
|
||||||
public I2PSocketManager socketManager;
|
public I2PSocketManager socketManager;
|
||||||
public I2PServerSocket serverSocket;
|
public I2PServerSocket serverSocket;
|
||||||
|
private AtomicBoolean lives;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -52,23 +54,13 @@ public class I2Plistener implements Runnable {
|
|||||||
* @param database
|
* @param database
|
||||||
* @param _log
|
* @param _log
|
||||||
*/
|
*/
|
||||||
I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
|
I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Log _log, AtomicBoolean lives) {
|
||||||
this.database = database;
|
this.database = database;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this._log = _log;
|
this._log = _log;
|
||||||
this.socketManager = S;
|
this.socketManager = S;
|
||||||
serverSocket = SS;
|
this.serverSocket = SS;
|
||||||
// tgwatch = 1;
|
this.lives = lives;
|
||||||
}
|
|
||||||
|
|
||||||
private void rlock() throws Exception {
|
|
||||||
database.getReadLock();
|
|
||||||
info.getReadLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runlock() throws Exception {
|
|
||||||
database.releaseReadLock();
|
|
||||||
info.releaseReadLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,50 +72,31 @@ public class I2Plistener implements Runnable {
|
|||||||
I2PSocket sessSocket = null;
|
I2PSocket sessSocket = null;
|
||||||
int conn = 0;
|
int conn = 0;
|
||||||
try {
|
try {
|
||||||
die:
|
try {
|
||||||
{
|
|
||||||
|
|
||||||
serverSocket.setSoTimeout(50);
|
serverSocket.setSoTimeout(50);
|
||||||
boolean spin = true;
|
|
||||||
while (spin) {
|
|
||||||
|
|
||||||
|
while (lives.get()) {
|
||||||
try {
|
try {
|
||||||
rlock();
|
sessSocket = serverSocket.accept();
|
||||||
} catch (Exception e) {
|
g = true;
|
||||||
break die;
|
} catch (ConnectException ce) {
|
||||||
|
g = false;
|
||||||
|
} catch (SocketTimeoutException ste) {
|
||||||
|
g = false;
|
||||||
}
|
}
|
||||||
try {
|
if (g) {
|
||||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
g = false;
|
||||||
} catch (Exception e) {
|
conn++;
|
||||||
try {
|
// toss the connection to a new thread.
|
||||||
runlock();
|
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
|
||||||
} catch (Exception e2) {
|
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
|
||||||
break die;
|
t.start();
|
||||||
}
|
|
||||||
break die;
|
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
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);
|
|
||||||
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
// System.out.println("Exception " + e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (I2PException e) {
|
||||||
|
// bad shit
|
||||||
|
System.out.println("Exception " + e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
|
@ -26,6 +26,7 @@ package net.i2p.BOB;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,6 +39,7 @@ public class I2PtoTCP implements Runnable {
|
|||||||
private I2PSocket I2P;
|
private I2PSocket I2P;
|
||||||
private NamedDB info, database;
|
private NamedDB info, database;
|
||||||
private Socket sock;
|
private Socket sock;
|
||||||
|
private AtomicBoolean lives;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -46,10 +48,11 @@ public class I2PtoTCP implements Runnable {
|
|||||||
* @param info
|
* @param info
|
||||||
* @param database
|
* @param database
|
||||||
*/
|
*/
|
||||||
I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database) {
|
I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database, AtomicBoolean lives) {
|
||||||
this.I2P = I2Psock;
|
this.I2P = I2Psock;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.database = database;
|
this.database = database;
|
||||||
|
this.lives = lives;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rlock() {
|
private void rlock() {
|
||||||
@ -99,6 +102,7 @@ public class I2PtoTCP implements Runnable {
|
|||||||
break die;
|
break die;
|
||||||
}
|
}
|
||||||
sock = new Socket(host, port);
|
sock = new Socket(host, port);
|
||||||
|
sock.setKeepAlive(true);
|
||||||
// make readers/writers
|
// make readers/writers
|
||||||
in = sock.getInputStream();
|
in = sock.getInputStream();
|
||||||
out = sock.getOutputStream();
|
out = sock.getOutputStream();
|
||||||
@ -113,35 +117,19 @@ public class I2PtoTCP implements Runnable {
|
|||||||
out.flush(); // not really needed, but...
|
out.flush(); // not really needed, but...
|
||||||
}
|
}
|
||||||
// setup to cross the streams
|
// setup to cross the streams
|
||||||
TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P
|
TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
|
||||||
TCPio conn_a = new TCPio(Iin, out /* , info, database */); // I2P -> app
|
TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
|
||||||
t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
|
t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
|
||||||
q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
|
q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
|
||||||
// Fire!
|
// Fire!
|
||||||
t.start();
|
t.start();
|
||||||
q.start();
|
q.start();
|
||||||
boolean spin = true;
|
while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
|
||||||
while (t.isAlive() && q.isAlive() && spin) { // AND is used here to kill off the other thread
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(10); //sleep for 10 ms
|
Thread.sleep(10); //sleep for 10 ms
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
break die;
|
break die;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
rlock();
|
|
||||||
} catch (Exception e) {
|
|
||||||
break die;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
runlock();
|
|
||||||
} catch (Exception e2) {
|
|
||||||
break die;
|
|
||||||
}
|
|
||||||
break die;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// System.out.println("I2PtoTCP: Going away...");
|
// System.out.println("I2PtoTCP: Going away...");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -150,14 +138,6 @@ public class I2PtoTCP implements Runnable {
|
|||||||
}
|
}
|
||||||
} // die
|
} // die
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
|
||||||
t.interrupt();
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
q.interrupt();
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
in.close();
|
in.close();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -174,6 +154,14 @@ public class I2PtoTCP implements Runnable {
|
|||||||
Iout.close();
|
Iout.close();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
t.interrupt();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
q.interrupt();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// System.out.println("I2PtoTCP: Close I2P");
|
// System.out.println("I2PtoTCP: Close I2P");
|
||||||
I2P.close();
|
I2P.close();
|
||||||
|
@ -43,7 +43,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class MUXlisten implements Runnable {
|
public class MUXlisten implements Runnable {
|
||||||
|
|
||||||
private NamedDB database, info;
|
private NamedDB database, info;
|
||||||
private Log _log;
|
private Log _log;
|
||||||
private I2PSocketManager socketManager;
|
private I2PSocketManager socketManager;
|
||||||
private ByteArrayInputStream prikey;
|
private ByteArrayInputStream prikey;
|
||||||
@ -54,6 +54,7 @@ public class MUXlisten implements Runnable {
|
|||||||
boolean go_out;
|
boolean go_out;
|
||||||
boolean come_in;
|
boolean come_in;
|
||||||
private AtomicBoolean lock;
|
private AtomicBoolean lock;
|
||||||
|
private AtomicBoolean lives;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor Will fail if INPORT is occupied.
|
* Constructor Will fail if INPORT is occupied.
|
||||||
@ -65,47 +66,84 @@ public class MUXlisten implements Runnable {
|
|||||||
* @throws java.io.IOException
|
* @throws java.io.IOException
|
||||||
*/
|
*/
|
||||||
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
|
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
|
||||||
int port = 0;
|
try {
|
||||||
InetAddress host = null;
|
int port = 0;
|
||||||
this.lock = lock;
|
InetAddress host = null;
|
||||||
this.tg = null;
|
this.lock = lock;
|
||||||
this.database = database;
|
this.tg = null;
|
||||||
this.info = info;
|
this.database = database;
|
||||||
this._log = _log;
|
this.info = info;
|
||||||
|
this._log = _log;
|
||||||
|
lives = new AtomicBoolean(false);
|
||||||
|
|
||||||
this.database.getReadLock();
|
this.database.getWriteLock();
|
||||||
this.info.getReadLock();
|
this.info.getWriteLock();
|
||||||
N = this.info.get("NICKNAME").toString();
|
this.info.add("STARTING", new Boolean(true));
|
||||||
prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
|
this.info.releaseWriteLock();
|
||||||
// Make a new copy so that anything else won't muck with our database.
|
this.database.releaseWriteLock();
|
||||||
Properties R = (Properties) info.get("PROPERTIES");
|
this.database.getReadLock();
|
||||||
Properties Q = new Properties();
|
this.info.getReadLock();
|
||||||
Lifted.copyProperties(R, Q);
|
|
||||||
this.database.releaseReadLock();
|
|
||||||
this.info.releaseReadLock();
|
|
||||||
|
|
||||||
this.database.getReadLock();
|
N = this.info.get("NICKNAME").toString();
|
||||||
this.info.getReadLock();
|
prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
|
||||||
this.go_out = info.exists("OUTPORT");
|
// Make a new copy so that anything else won't muck with our database.
|
||||||
this.come_in = info.exists("INPORT");
|
Properties R = (Properties) info.get("PROPERTIES");
|
||||||
if (this.come_in) {
|
Properties Q = new Properties();
|
||||||
port = Integer.parseInt(info.get("INPORT").toString());
|
Lifted.copyProperties(R, Q);
|
||||||
host = InetAddress.getByName(info.get("INHOST").toString());
|
this.database.releaseReadLock();
|
||||||
|
this.info.releaseReadLock();
|
||||||
|
|
||||||
|
this.database.getReadLock();
|
||||||
|
this.info.getReadLock();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
this.database.releaseReadLock();
|
||||||
|
this.info.releaseReadLock();
|
||||||
|
|
||||||
|
if (this.come_in) {
|
||||||
|
this.listener = new ServerSocket(port, backlog, host);
|
||||||
|
}
|
||||||
|
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
|
||||||
|
// I2PException, IOException, RuntimeException
|
||||||
|
// To bad we can't just catch and enumerate....
|
||||||
|
// } catch (I2PException e) {
|
||||||
|
// Something went bad.
|
||||||
|
// this.database.getWriteLock();
|
||||||
|
// this.info.getWriteLock();
|
||||||
|
// this.info.add("STARTING", new Boolean(false));
|
||||||
|
// this.info.releaseWriteLock();
|
||||||
|
// this.database.releaseWriteLock();
|
||||||
|
// throw new I2PException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Something went bad.
|
||||||
|
this.database.getWriteLock();
|
||||||
|
this.info.getWriteLock();
|
||||||
|
this.info.add("STARTING", new Boolean(false));
|
||||||
|
this.info.releaseWriteLock();
|
||||||
|
this.database.releaseWriteLock();
|
||||||
|
throw new IOException(e.toString());
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Something went bad.
|
||||||
|
this.database.getWriteLock();
|
||||||
|
this.info.getWriteLock();
|
||||||
|
this.info.add("STARTING", new Boolean(false));
|
||||||
|
this.info.releaseWriteLock();
|
||||||
|
this.database.releaseWriteLock();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Something else went bad.
|
||||||
|
this.database.getWriteLock();
|
||||||
|
this.info.getWriteLock();
|
||||||
|
this.info.add("STARTING", new Boolean(false));
|
||||||
|
this.info.releaseWriteLock();
|
||||||
|
this.database.releaseWriteLock();
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
this.database.releaseReadLock();
|
|
||||||
this.info.releaseReadLock();
|
|
||||||
|
|
||||||
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
|
|
||||||
if (this.come_in) {
|
|
||||||
this.listener = new ServerSocket(port, backlog, host);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything is OK as far as we can tell.
|
|
||||||
this.database.getWriteLock();
|
|
||||||
this.info.getWriteLock();
|
|
||||||
this.info.add("STARTING", new Boolean(true));
|
|
||||||
this.info.releaseWriteLock();
|
|
||||||
this.database.releaseWriteLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rlock() throws Exception {
|
private void rlock() throws Exception {
|
||||||
@ -142,18 +180,22 @@ public class MUXlisten implements Runnable {
|
|||||||
try {
|
try {
|
||||||
info.add("RUNNING", new Boolean(true));
|
info.add("RUNNING", new Boolean(true));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
lock.set(false);
|
||||||
wunlock();
|
wunlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
lock.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
wunlock();
|
wunlock();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
lock.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// socketManager.addDisconnectListener(new DisconnectListener());
|
// socketManager.addDisconnectListener(new DisconnectListener());
|
||||||
|
lives.set(true);
|
||||||
lock.set(false);
|
lock.set(false);
|
||||||
quit:
|
quit:
|
||||||
{
|
{
|
||||||
@ -166,14 +208,14 @@ public class MUXlisten implements Runnable {
|
|||||||
if (go_out) {
|
if (go_out) {
|
||||||
// I2P -> TCP
|
// I2P -> TCP
|
||||||
SS = socketManager.getServerSocket();
|
SS = socketManager.getServerSocket();
|
||||||
I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log);
|
I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log, lives);
|
||||||
t = new Thread(tg, conn, "BOBI2Plistener " + N);
|
t = new Thread(tg, conn, "BOBI2Plistener " + N);
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (come_in) {
|
if (come_in) {
|
||||||
// TCP -> I2P
|
// TCP -> I2P
|
||||||
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log);
|
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log, lives);
|
||||||
q = new Thread(tg, conn, "BOBTCPlistener " + N);
|
q = new Thread(tg, conn, "BOBTCPlistener " + N);
|
||||||
q.start();
|
q.start();
|
||||||
}
|
}
|
||||||
@ -195,7 +237,7 @@ public class MUXlisten implements Runnable {
|
|||||||
break quit;
|
break quit;
|
||||||
}
|
}
|
||||||
boolean spin = true;
|
boolean spin = true;
|
||||||
while (spin) {
|
while (spin && lives.get()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000); //sleep for 1 second
|
Thread.sleep(1000); //sleep for 1 second
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -226,26 +268,30 @@ public class MUXlisten implements Runnable {
|
|||||||
}
|
}
|
||||||
} // quit
|
} // quit
|
||||||
} finally {
|
} finally {
|
||||||
// Start cleanup.
|
lives.set(false);
|
||||||
while (!lock.compareAndSet(false, true)) {
|
// Some grace time.
|
||||||
// wait
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero out everything.
|
|
||||||
try {
|
try {
|
||||||
wlock();
|
wlock();
|
||||||
try {
|
try {
|
||||||
info.add("STARTING", new Boolean(false));
|
info.add("STARTING", new Boolean(false));
|
||||||
info.add("STOPPING", new Boolean(false));
|
info.add("STOPPING", new Boolean(true));
|
||||||
info.add("RUNNING", new Boolean(false));
|
info.add("RUNNING", new Boolean(false));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
lock.set(false);
|
||||||
wunlock();
|
wunlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wunlock();
|
wunlock();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
// Start cleanup.
|
||||||
|
while (!lock.compareAndSet(false, true)) {
|
||||||
|
// wait
|
||||||
|
}
|
||||||
if (SS != null) {
|
if (SS != null) {
|
||||||
try {
|
try {
|
||||||
SS.close();
|
SS.close();
|
||||||
@ -261,11 +307,41 @@ public class MUXlisten implements Runnable {
|
|||||||
|
|
||||||
// Some grace time.
|
// Some grace time.
|
||||||
try {
|
try {
|
||||||
Thread.sleep(250);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hopefully nuke stuff here...
|
||||||
|
{
|
||||||
|
String boner = tg.getName();
|
||||||
|
try {
|
||||||
|
_log.warn("destroySocketManager " + boner);
|
||||||
|
socketManager.destroySocketManager();
|
||||||
|
_log.warn("destroySocketManager Successful" + boner);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// nop
|
||||||
|
_log.warn("destroySocketManager Failed" + boner);
|
||||||
|
_log.warn(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// zero out everything.
|
||||||
|
try {
|
||||||
|
wlock();
|
||||||
|
try {
|
||||||
|
info.add("STARTING", new Boolean(false));
|
||||||
|
info.add("STOPPING", new Boolean(false));
|
||||||
|
info.add("RUNNING", new Boolean(false));
|
||||||
|
} catch (Exception e) {
|
||||||
|
lock.set(false);
|
||||||
|
wunlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wunlock();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
lock.set(false); // Should we force waiting for all threads??
|
lock.set(false); // Should we force waiting for all threads??
|
||||||
|
|
||||||
// Wait around till all threads are collected.
|
// Wait around till all threads are collected.
|
||||||
if (tg != null) {
|
if (tg != null) {
|
||||||
String boner = tg.getName();
|
String boner = tg.getName();
|
||||||
@ -276,7 +352,7 @@ public class MUXlisten implements Runnable {
|
|||||||
// visit(tg, 0, boner);
|
// visit(tg, 0, boner);
|
||||||
int foo = tg.activeCount() + tg.activeGroupCount();
|
int foo = tg.activeCount() + tg.activeGroupCount();
|
||||||
// hopefully no longer needed!
|
// hopefully no longer needed!
|
||||||
// int bar = foo;
|
// int bar = lives;
|
||||||
// System.out.println("BOB: MUXlisten: Waiting on threads for " + boner);
|
// System.out.println("BOB: MUXlisten: Waiting on threads for " + boner);
|
||||||
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
|
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
|
||||||
// visit(tg, 0, boner);
|
// visit(tg, 0, boner);
|
||||||
@ -284,12 +360,12 @@ public class MUXlisten implements Runnable {
|
|||||||
// Happily spin forever :-(
|
// Happily spin forever :-(
|
||||||
while (foo != 0) {
|
while (foo != 0) {
|
||||||
foo = tg.activeCount() + tg.activeGroupCount();
|
foo = tg.activeCount() + tg.activeGroupCount();
|
||||||
// if (foo != bar && foo != 0) {
|
// if (lives != bar && lives != 0) {
|
||||||
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
|
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
|
||||||
// visit(tg, 0, boner);
|
// visit(tg, 0, boner);
|
||||||
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n");
|
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n");
|
||||||
// }
|
// }
|
||||||
// bar = foo;
|
// bar = lives;
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
@ -356,5 +432,4 @@ public class MUXlisten implements Runnable {
|
|||||||
visit(groups[i], level + 1, groups[i].getName());
|
visit(groups[i], level + 1, groups[i].getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ package net.i2p.BOB;
|
|||||||
import net.i2p.client.streaming.RetransmissionTimer;
|
import net.i2p.client.streaming.RetransmissionTimer;
|
||||||
import net.i2p.util.SimpleScheduler;
|
import net.i2p.util.SimpleScheduler;
|
||||||
import net.i2p.util.SimpleTimer2;
|
import net.i2p.util.SimpleTimer2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start from command line
|
* Start from command line
|
||||||
*
|
*
|
||||||
|
@ -43,10 +43,10 @@ public class NamedDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized public void getReadLock() {
|
synchronized public void getReadLock() {
|
||||||
while((writersWaiting != 0)) {
|
while ((writersWaiting != 0)) {
|
||||||
try {
|
try {
|
||||||
wait();
|
wait();
|
||||||
} catch(InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readers++;
|
readers++;
|
||||||
@ -59,10 +59,10 @@ public class NamedDB {
|
|||||||
|
|
||||||
synchronized public void getWriteLock() {
|
synchronized public void getWriteLock() {
|
||||||
writersWaiting++;
|
writersWaiting++;
|
||||||
while(readers != 0 && writersWaiting != 1 ) {
|
while (readers != 0 && writersWaiting != 1) {
|
||||||
try {
|
try {
|
||||||
wait();
|
wait();
|
||||||
} catch(InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,8 +79,8 @@ public class NamedDB {
|
|||||||
* @throws ArrayIndexOutOfBoundsException when key does not exist
|
* @throws ArrayIndexOutOfBoundsException when key does not exist
|
||||||
*/
|
*/
|
||||||
public int idx(Object key) throws ArrayIndexOutOfBoundsException {
|
public int idx(Object key) throws ArrayIndexOutOfBoundsException {
|
||||||
for(int i = 0; i < index; i++) {
|
for (int i = 0; i < index; i++) {
|
||||||
if(key.equals(data[i][0])) {
|
if (key.equals(data[i][0])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,17 +100,17 @@ public class NamedDB {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
k = idx(key);
|
k = idx(key);
|
||||||
} catch(ArrayIndexOutOfBoundsException b) {
|
} catch (ArrayIndexOutOfBoundsException b) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
olddata = new Object[index + 2][2];
|
olddata = new Object[index + 2][2];
|
||||||
// copy to olddata, skipping 'k'
|
// copy to olddata, skipping 'k'
|
||||||
for(i = 0 , l = 0; l < index; i++, l++) {
|
for (i = 0, l = 0; l < index; i++, l++) {
|
||||||
if(i == k) {
|
if (i == k) {
|
||||||
l++;
|
l++;
|
||||||
didsomething++;
|
didsomething++;
|
||||||
}
|
}
|
||||||
for(j = 0; j < 2; j++) {
|
for (j = 0; j < 2; j++) {
|
||||||
olddata[i][j] = data[l][j];
|
olddata[i][j] = data[l][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,13 +132,13 @@ public class NamedDB {
|
|||||||
|
|
||||||
olddata = new Object[index + 2][2];
|
olddata = new Object[index + 2][2];
|
||||||
// copy to olddata
|
// copy to olddata
|
||||||
for(i = 0; i < index; i++) {
|
for (i = 0; i < index; i++) {
|
||||||
for(j = 0; j < 2; j++) {
|
for (j = 0; j < 2; j++) {
|
||||||
olddata[i][j] = data[i][j];
|
olddata[i][j] = data[i][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = olddata;
|
data = olddata;
|
||||||
data[index++] = new Object[] {key, val};
|
data[index++] = new Object[]{key, val};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,8 +149,8 @@ public class NamedDB {
|
|||||||
* @throws java.lang.RuntimeException
|
* @throws java.lang.RuntimeException
|
||||||
*/
|
*/
|
||||||
public Object get(Object key) throws RuntimeException {
|
public Object get(Object key) throws RuntimeException {
|
||||||
for(int i = 0; i < index; i++) {
|
for (int i = 0; i < index; i++) {
|
||||||
if(key.equals(data[i][0])) {
|
if (key.equals(data[i][0])) {
|
||||||
return data[i][1];
|
return data[i][1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,8 +164,8 @@ public class NamedDB {
|
|||||||
* @return true if an object exists, else returns false
|
* @return true if an object exists, else returns false
|
||||||
*/
|
*/
|
||||||
public boolean exists(Object key) {
|
public boolean exists(Object key) {
|
||||||
for(int i = 0; i < index; i++) {
|
for (int i = 0; i < index; i++) {
|
||||||
if(key.equals(data[i][0])) {
|
if (key.equals(data[i][0])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ public class NamedDB {
|
|||||||
* @throws java.lang.RuntimeException
|
* @throws java.lang.RuntimeException
|
||||||
*/
|
*/
|
||||||
public Object getnext(int i) throws RuntimeException {
|
public Object getnext(int i) throws RuntimeException {
|
||||||
if(i < index && i > -1) {
|
if (i < index && i > -1) {
|
||||||
return data[i][1];
|
return data[i][1];
|
||||||
}
|
}
|
||||||
throw new RuntimeException("No more data");
|
throw new RuntimeException("No more data");
|
||||||
|
@ -26,6 +26,7 @@ package net.i2p.BOB;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shove data from one stream to the other.
|
* Shove data from one stream to the other.
|
||||||
@ -36,7 +37,7 @@ public class TCPio implements Runnable {
|
|||||||
|
|
||||||
private InputStream Ain;
|
private InputStream Ain;
|
||||||
private OutputStream Aout;
|
private OutputStream Aout;
|
||||||
// private NamedDB info, database;
|
private AtomicBoolean lives;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -46,11 +47,10 @@ public class TCPio implements Runnable {
|
|||||||
*
|
*
|
||||||
* param database
|
* param database
|
||||||
*/
|
*/
|
||||||
TCPio(InputStream Ain, OutputStream Aout /*, NamedDB info , NamedDB database */) {
|
TCPio(InputStream Ain, OutputStream Aout, AtomicBoolean lives) {
|
||||||
this.Ain = Ain;
|
this.Ain = Ain;
|
||||||
this.Aout = Aout;
|
this.Aout = Aout;
|
||||||
// this.info = info;
|
this.lives = lives;
|
||||||
// this.database = database;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,24 +78,31 @@ public class TCPio implements Runnable {
|
|||||||
* --Sponge
|
* --Sponge
|
||||||
*
|
*
|
||||||
* Tested with 128 bytes, and there was no performance gain.
|
* 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
|
* --Sponge
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int b;
|
int b;
|
||||||
byte a[] = new byte[1];
|
byte a[] = new byte[8192];
|
||||||
boolean spin = true;
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
while (spin) {
|
while (lives.get()) {
|
||||||
b = Ain.read(a, 0, 1);
|
b = Ain.read(a, 0, 8192);
|
||||||
if (b > 0) {
|
if (b > 0) {
|
||||||
Aout.write(a, 0, b);
|
Aout.write(a, 0, b);
|
||||||
} else if (b == 0) {
|
} else if (b == 0) {
|
||||||
Thread.yield(); // this should act like a mini sleep.
|
// Will this die? We'll see.
|
||||||
if (Ain.available() == 0) {
|
while(Ain.available() == 0) {
|
||||||
Thread.sleep(10);
|
Thread.sleep(20);
|
||||||
}
|
}
|
||||||
|
// Thread.yield(); // this should act like a mini sleep.
|
||||||
|
// if (Ain.available() == 0) {
|
||||||
|
// Thread.sleep(10);
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
/* according to the specs:
|
/* according to the specs:
|
||||||
*
|
*
|
||||||
@ -105,9 +112,6 @@ public class TCPio implements Runnable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// System.out.println("TCPio: End Of Stream");
|
// System.out.println("TCPio: End Of Stream");
|
||||||
// Ain.close();
|
|
||||||
// Aout.close();
|
|
||||||
//return;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import java.net.Socket;
|
|||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
// import net.i2p.client.I2PSession;
|
// import net.i2p.client.I2PSession;
|
||||||
// import net.i2p.client.I2PSessionException;
|
// import net.i2p.client.I2PSessionException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import net.i2p.client.streaming.I2PServerSocket;
|
import net.i2p.client.streaming.I2PServerSocket;
|
||||||
import net.i2p.client.streaming.I2PSocketManager;
|
import net.i2p.client.streaming.I2PSocketManager;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@ -45,6 +46,7 @@ public class TCPlistener implements Runnable {
|
|||||||
public I2PSocketManager socketManager;
|
public I2PSocketManager socketManager;
|
||||||
public I2PServerSocket serverSocket;
|
public I2PServerSocket serverSocket;
|
||||||
private ServerSocket listener;
|
private ServerSocket listener;
|
||||||
|
private AtomicBoolean lives;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -53,22 +55,13 @@ public class TCPlistener implements Runnable {
|
|||||||
* @param database
|
* @param database
|
||||||
* @param _log
|
* @param _log
|
||||||
*/
|
*/
|
||||||
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
|
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log, AtomicBoolean lives) {
|
||||||
this.database = database;
|
this.database = database;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this._log = _log;
|
this._log = _log;
|
||||||
this.socketManager = S;
|
this.socketManager = S;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
this.lives = lives;
|
||||||
|
|
||||||
private void rlock() throws Exception {
|
|
||||||
database.getReadLock();
|
|
||||||
info.getReadLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runlock() throws Exception {
|
|
||||||
database.releaseReadLock();
|
|
||||||
info.releaseReadLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,47 +70,29 @@ public class TCPlistener implements Runnable {
|
|||||||
*/
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
boolean g = false;
|
boolean g = false;
|
||||||
boolean spin = true;
|
|
||||||
int conn = 0;
|
int conn = 0;
|
||||||
|
Socket server = null;
|
||||||
try {
|
try {
|
||||||
die:
|
try {
|
||||||
{
|
listener.setSoTimeout(50); // We don't block, we cycle and check.
|
||||||
try {
|
while (lives.get()) {
|
||||||
Socket server = new Socket();
|
try {
|
||||||
listener.setSoTimeout(50); // We don't block, we cycle and check.
|
server = listener.accept();
|
||||||
while (spin) {
|
server.setKeepAlive(true);
|
||||||
try {
|
g = true;
|
||||||
rlock();
|
} catch (SocketTimeoutException ste) {
|
||||||
} catch (Exception e) {
|
g = false;
|
||||||
break die;
|
}
|
||||||
}
|
if (g) {
|
||||||
try {
|
conn++;
|
||||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
// toss the connection to a new thread.
|
||||||
} catch (Exception e) {
|
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
|
||||||
try {
|
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
|
||||||
runlock();
|
t.start();
|
||||||
} catch (Exception e2) {
|
g = false;
|
||||||
break die;
|
|
||||||
}
|
|
||||||
break die;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
server = listener.accept();
|
|
||||||
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);
|
|
||||||
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
|
|
||||||
t.start();
|
|
||||||
g = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
|
||||||
}
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
|
@ -30,6 +30,7 @@ import java.io.OutputStream;
|
|||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.NoRouteToHostException;
|
import java.net.NoRouteToHostException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
import net.i2p.client.streaming.I2PSocketManager;
|
import net.i2p.client.streaming.I2PSocketManager;
|
||||||
@ -49,6 +50,7 @@ public class TCPtoI2P implements Runnable {
|
|||||||
private NamedDB info, database;
|
private NamedDB info, database;
|
||||||
private Socket sock;
|
private Socket sock;
|
||||||
private I2PSocketManager socketManager;
|
private I2PSocketManager socketManager;
|
||||||
|
private AtomicBoolean lives;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -57,11 +59,12 @@ public class TCPtoI2P implements Runnable {
|
|||||||
* param info
|
* param info
|
||||||
* param database
|
* param database
|
||||||
*/
|
*/
|
||||||
TCPtoI2P(I2PSocketManager i2p, Socket socket , NamedDB info, NamedDB database) {
|
TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database, AtomicBoolean lives) {
|
||||||
this.sock = socket;
|
this.sock = socket;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.database = database;
|
this.database = database;
|
||||||
this.socketManager = i2p;
|
this.socketManager = i2p;
|
||||||
|
this.lives = lives;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,8 +146,14 @@ public class TCPtoI2P implements Runnable {
|
|||||||
input = line.toLowerCase();
|
input = line.toLowerCase();
|
||||||
Destination dest = null;
|
Destination dest = null;
|
||||||
if (input.endsWith(".i2p")) {
|
if (input.endsWith(".i2p")) {
|
||||||
dest = I2PTunnel.destFromName(input);
|
try {
|
||||||
line = dest.toBase64();
|
dest = I2PTunnel.destFromName(input);
|
||||||
|
line = dest.toBase64();
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
// Could not find the destination!?
|
||||||
|
Emsg("Can't find destination: " + input, out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dest = new Destination();
|
dest = new Destination();
|
||||||
dest.fromBase64(line);
|
dest.fromBase64(line);
|
||||||
@ -157,19 +166,15 @@ public class TCPtoI2P implements Runnable {
|
|||||||
Iin = I2P.getInputStream();
|
Iin = I2P.getInputStream();
|
||||||
Iout = I2P.getOutputStream();
|
Iout = I2P.getOutputStream();
|
||||||
// setup to cross the streams
|
// setup to cross the streams
|
||||||
TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P
|
TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
|
||||||
TCPio conn_a = new TCPio(Iin, out /*, info, database */); // I2P -> app
|
TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
|
||||||
t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
|
t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
|
||||||
q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
|
q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
|
||||||
// Fire!
|
// Fire!
|
||||||
t.start();
|
t.start();
|
||||||
q.start();
|
q.start();
|
||||||
boolean spin = true;
|
while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
|
||||||
while (t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
|
|
||||||
Thread.sleep(10); //sleep for 10 ms
|
Thread.sleep(10); //sleep for 10 ms
|
||||||
rlock();
|
|
||||||
spin = info.get("RUNNING").equals(Boolean.TRUE);
|
|
||||||
runlock();
|
|
||||||
}
|
}
|
||||||
} catch (I2PException e) {
|
} catch (I2PException e) {
|
||||||
Emsg(e.toString(), out);
|
Emsg(e.toString(), out);
|
||||||
|
@ -78,26 +78,26 @@ public class UDPIOthread implements I2PSessionListener, Runnable {
|
|||||||
try {
|
try {
|
||||||
in = new DataInputStream(socket.getInputStream());
|
in = new DataInputStream(socket.getInputStream());
|
||||||
out = new DataOutputStream(socket.getOutputStream());
|
out = new DataOutputStream(socket.getOutputStream());
|
||||||
while(up) {
|
while (up) {
|
||||||
int c = in.read(data);
|
int c = in.read(data);
|
||||||
// Note: could do a loopback test here with a wrapper.
|
// Note: could do a loopback test here with a wrapper.
|
||||||
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
|
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
|
||||||
|
|
||||||
if(!ok) {
|
if (!ok) {
|
||||||
up = false; // Is this the right thing to do??
|
up = false; // Is this the right thing to do??
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
_log.error("Error running", ioe);
|
_log.error("Error running", ioe);
|
||||||
} catch(I2PSessionException ise) {
|
} catch (I2PSessionException ise) {
|
||||||
_log.error("Error communicating", ise);
|
_log.error("Error communicating", ise);
|
||||||
// } catch(DataFormatException dfe) {
|
// } catch(DataFormatException dfe) {
|
||||||
// _log.error("Peer destination file is not valid", dfe);
|
// _log.error("Peer destination file is not valid", dfe);
|
||||||
} finally {
|
} finally {
|
||||||
if(_session != null) {
|
if (_session != null) {
|
||||||
try {
|
try {
|
||||||
_session.destroySession();
|
_session.destroySession();
|
||||||
} catch(I2PSessionException ise) {
|
} catch (I2PSessionException ise) {
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,9 +116,9 @@ public class UDPIOthread implements I2PSessionListener, Runnable {
|
|||||||
byte msg[] = session.receiveMessage(msgId);
|
byte msg[] = session.receiveMessage(msgId);
|
||||||
out.write(msg);
|
out.write(msg);
|
||||||
out.flush();
|
out.flush();
|
||||||
} catch(I2PSessionException ise) {
|
} catch (I2PSessionException ise) {
|
||||||
up = false;
|
up = false;
|
||||||
} catch(IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
up = false;
|
up = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004 Ragnarok
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package addressbook;
|
|
||||||
|
|
||||||
import javax.servlet.GenericServlet;
|
|
||||||
import javax.servlet.ServletConfig;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for addressbook to allow it to be started as a web application.
|
|
||||||
*
|
|
||||||
* @author Ragnarok
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Servlet extends GenericServlet {
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
|
|
||||||
*/
|
|
||||||
public void service(ServletRequest request, ServletResponse response) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init(ServletConfig config) {
|
|
||||||
try {
|
|
||||||
super.init(config);
|
|
||||||
} catch (ServletException exp) {
|
|
||||||
}
|
|
||||||
String[] args = new String[1];
|
|
||||||
args[0] = config.getInitParameter("home");
|
|
||||||
DaemonThread thread = new DaemonThread(args);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.setName("Addressbook");
|
|
||||||
thread.start();
|
|
||||||
System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
|
|
||||||
System.out.println("INFO: config root under " + args[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -94,20 +94,21 @@ public class AddressBook {
|
|||||||
* @param proxyPort port number of proxy
|
* @param proxyPort port number of proxy
|
||||||
*/
|
*/
|
||||||
public AddressBook(Subscription subscription, String proxyHost, int proxyPort) {
|
public AddressBook(Subscription subscription, String proxyHost, int proxyPort) {
|
||||||
|
File tmp = new File(I2PAppContext.getGlobalContext().getTempDir(), "addressbook.tmp");
|
||||||
this.location = subscription.getLocation();
|
this.location = subscription.getLocation();
|
||||||
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
|
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
|
||||||
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, "addressbook.tmp", null,
|
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, tmp.getAbsolutePath(), null,
|
||||||
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
|
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
|
||||||
if (get.fetch()) {
|
if (get.fetch()) {
|
||||||
subscription.setEtag(get.getETag());
|
subscription.setEtag(get.getETag());
|
||||||
subscription.setLastModified(get.getLastModified());
|
subscription.setLastModified(get.getLastModified());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.addresses = ConfigParser.parse(new File("addressbook.tmp"));
|
this.addresses = ConfigParser.parse(tmp);
|
||||||
} catch (IOException exp) {
|
} catch (IOException exp) {
|
||||||
this.addresses = new HashMap();
|
this.addresses = new HashMap();
|
||||||
}
|
}
|
||||||
new File("addressbook.tmp").delete();
|
tmp.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,7 +193,8 @@ public class AddressBook {
|
|||||||
(! host.endsWith(".router.i2p")) &&
|
(! host.endsWith(".router.i2p")) &&
|
||||||
(! host.endsWith(".console.i2p")) &&
|
(! host.endsWith(".console.i2p")) &&
|
||||||
|
|
||||||
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AAAA")) ||
|
// null cert ends with AAAA but other zero-length certs would be AA
|
||||||
|
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AA")) ||
|
||||||
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
|
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
|
||||||
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
|
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
|
||||||
;
|
;
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -39,6 +39,9 @@ import java.util.Map;
|
|||||||
* Utility class providing methods to parse and write files in config file
|
* Utility class providing methods to parse and write files in config file
|
||||||
* format, and subscription file format.
|
* format, and subscription file format.
|
||||||
*
|
*
|
||||||
|
* TODO: Change file encoding from default to UTF-8?
|
||||||
|
* Or switch to the DataHelper loadProps/storeProps methods?
|
||||||
|
*
|
||||||
* @author Ragnarok
|
* @author Ragnarok
|
||||||
*/
|
*/
|
||||||
public class ConfigParser {
|
public class ConfigParser {
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -28,6 +28,8 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main class of addressbook. Performs updates, and runs the main loop.
|
* Main class of addressbook. Performs updates, and runs the main loop.
|
||||||
*
|
*
|
||||||
@ -37,6 +39,7 @@ import java.util.Map;
|
|||||||
public class Daemon {
|
public class Daemon {
|
||||||
public static final String VERSION = "2.0.3";
|
public static final String VERSION = "2.0.3";
|
||||||
private static final Daemon _instance = new Daemon();
|
private static final Daemon _instance = new Daemon();
|
||||||
|
private boolean _running;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the router and published address books using remote data from the
|
* Update the router and published address books using remote data from the
|
||||||
@ -124,12 +127,15 @@ public class Daemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run(String[] args) {
|
public void run(String[] args) {
|
||||||
|
_running = true;
|
||||||
String settingsLocation = "config.txt";
|
String settingsLocation = "config.txt";
|
||||||
String home;
|
File homeFile;
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
home = args[0];
|
homeFile = new File(args[0]);
|
||||||
|
if (!homeFile.isAbsolute())
|
||||||
|
homeFile = new File(I2PAppContext.getGlobalContext().getRouterDir(), args[0]);
|
||||||
} else {
|
} else {
|
||||||
home = ".";
|
homeFile = new File(System.getProperty("user.dir"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map defaultSettings = new HashMap();
|
Map defaultSettings = new HashMap();
|
||||||
@ -145,7 +151,6 @@ public class Daemon {
|
|||||||
defaultSettings.put("last_modified", "last_modified");
|
defaultSettings.put("last_modified", "last_modified");
|
||||||
defaultSettings.put("update_delay", "12");
|
defaultSettings.put("update_delay", "12");
|
||||||
|
|
||||||
File homeFile = new File(home);
|
|
||||||
if (!homeFile.exists()) {
|
if (!homeFile.exists()) {
|
||||||
boolean created = homeFile.mkdirs();
|
boolean created = homeFile.mkdirs();
|
||||||
if (created)
|
if (created)
|
||||||
@ -163,19 +168,21 @@ public class Daemon {
|
|||||||
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
|
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
|
||||||
} catch (InterruptedException ie) {}
|
} catch (InterruptedException ie) {}
|
||||||
|
|
||||||
while (true) {
|
while (_running) {
|
||||||
long delay = Long.parseLong((String) settings.get("update_delay"));
|
long delay = Long.parseLong((String) settings.get("update_delay"));
|
||||||
if (delay < 1) {
|
if (delay < 1) {
|
||||||
delay = 1;
|
delay = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
update(settings, home);
|
update(settings, homeFile.getAbsolutePath());
|
||||||
try {
|
try {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
wait(delay * 60 * 60 * 1000);
|
wait(delay * 60 * 60 * 1000);
|
||||||
}
|
}
|
||||||
} catch (InterruptedException exp) {
|
} catch (InterruptedException exp) {
|
||||||
}
|
}
|
||||||
|
if (!_running)
|
||||||
|
break;
|
||||||
settings = ConfigParser.parse(settingsFile, defaultSettings);
|
settings = ConfigParser.parse(settingsFile, defaultSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,4 +196,9 @@ public class Daemon {
|
|||||||
_instance.notifyAll();
|
_instance.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void stop() {
|
||||||
|
_instance._running = false;
|
||||||
|
wakeup();
|
||||||
|
}
|
||||||
}
|
}
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread that waits five minutes, then runs the addressbook daemon.
|
* A thread that waits five minutes, then runs the addressbook daemon.
|
||||||
@ -51,4 +51,9 @@ public class DaemonThread extends Thread {
|
|||||||
//}
|
//}
|
||||||
Daemon.main(this.args);
|
Daemon.main(this.args);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void halt() {
|
||||||
|
Daemon.stop();
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
96
apps/addressbook/java/src/net/i2p/addressbook/Servlet.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004 Ragnarok
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for addressbook to allow it to be started as a web application.
|
||||||
|
*
|
||||||
|
* This was a GenericServlet, we make it an HttpServlet solely to provide a hook
|
||||||
|
* for SusiDNS to wake us up when the subscription list changes.
|
||||||
|
*
|
||||||
|
* @author Ragnarok
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Servlet extends HttpServlet {
|
||||||
|
private DaemonThread thread;
|
||||||
|
private String nonce;
|
||||||
|
private static final String PROP_NONCE = "addressbook.nonce";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hack to allow susidns to kick the daemon when the subscription list changes.
|
||||||
|
* URL must be /addressbook/ with wakeup param set, and nonce param set from system property.
|
||||||
|
*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
|
||||||
|
*/
|
||||||
|
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
|
//System.err.println("Got request nonce = " + request.getParameter("nonce"));
|
||||||
|
if (this.thread != null && request.getParameter("wakeup") != null &&
|
||||||
|
this.nonce != null && this.nonce.equals(request.getParameter("nonce"))) {
|
||||||
|
//System.err.println("Sending interrupt");
|
||||||
|
this.thread.interrupt();
|
||||||
|
// no output
|
||||||
|
} else {
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
out.write("I2P addressbook OK");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) {
|
||||||
|
try {
|
||||||
|
super.init(config);
|
||||||
|
} catch (ServletException exp) {
|
||||||
|
System.err.println("Addressbook init exception: " + exp);
|
||||||
|
}
|
||||||
|
this.nonce = "" + Math.abs((new Random()).nextLong());
|
||||||
|
// put the nonce where susidns can get it
|
||||||
|
System.setProperty(PROP_NONCE, this.nonce);
|
||||||
|
String[] args = new String[1];
|
||||||
|
args[0] = config.getInitParameter("home");
|
||||||
|
this.thread = new DaemonThread(args);
|
||||||
|
this.thread.setDaemon(true);
|
||||||
|
this.thread.setName("Addressbook");
|
||||||
|
this.thread.start();
|
||||||
|
System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
|
||||||
|
//System.out.println("INFO: config root under " + args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
this.thread.halt();
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A subscription to a remote address book.
|
* A subscription to a remote address book.
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package addressbook;
|
package net.i2p.addressbook;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
@ -6,11 +6,17 @@
|
|||||||
<web-app>
|
<web-app>
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>addressbook</servlet-name>
|
<servlet-name>addressbook</servlet-name>
|
||||||
<servlet-class>addressbook.Servlet</servlet-class>
|
<servlet-class>net.i2p.addressbook.Servlet</servlet-class>
|
||||||
<init-param>
|
<init-param>
|
||||||
<param-name>home</param-name>
|
<param-name>home</param-name>
|
||||||
<param-value>./addressbook</param-value>
|
<param-value>./addressbook</param-value>
|
||||||
</init-param>
|
</init-param>
|
||||||
<load-on-startup>1</load-on-startup>
|
<load-on-startup>1</load-on-startup>
|
||||||
</servlet>
|
</servlet>
|
||||||
</web-app>
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>addressbook</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
</web-app>
|
||||||
|
@ -73,7 +73,7 @@ class AdminRunner implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reply(OutputStream out, String content) throws IOException {
|
private void reply(OutputStream out, String content) throws IOException {
|
||||||
StringBuffer reply = new StringBuffer(10240);
|
StringBuilder reply = new StringBuilder(10240);
|
||||||
reply.append("HTTP/1.1 200 OK\n");
|
reply.append("HTTP/1.1 200 OK\n");
|
||||||
reply.append("Connection: close\n");
|
reply.append("Connection: close\n");
|
||||||
reply.append("Cache-control: no-cache\n");
|
reply.append("Cache-control: no-cache\n");
|
||||||
@ -90,7 +90,7 @@ class AdminRunner implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void replyText(OutputStream out, String content) throws IOException {
|
private void replyText(OutputStream out, String content) throws IOException {
|
||||||
StringBuffer reply = new StringBuffer(10240);
|
StringBuilder reply = new StringBuilder(10240);
|
||||||
reply.append("HTTP/1.1 200 OK\n");
|
reply.append("HTTP/1.1 200 OK\n");
|
||||||
reply.append("Connection: close\n");
|
reply.append("Connection: close\n");
|
||||||
reply.append("Cache-control: no-cache\n");
|
reply.append("Cache-control: no-cache\n");
|
BIN
apps/i2psnark/_icons/application.png
Normal file
After Width: | Height: | Size: 464 B |
BIN
apps/i2psnark/_icons/book.png
Normal file
After Width: | Height: | Size: 593 B |
BIN
apps/i2psnark/_icons/cancel.png
Normal file
After Width: | Height: | Size: 587 B |
BIN
apps/i2psnark/_icons/cd.png
Normal file
After Width: | Height: | Size: 673 B |
BIN
apps/i2psnark/_icons/clock.png
Normal file
After Width: | Height: | Size: 882 B |
BIN
apps/i2psnark/_icons/compress.png
Normal file
After Width: | Height: | Size: 766 B |
BIN
apps/i2psnark/_icons/film.png
Normal file
After Width: | Height: | Size: 653 B |
BIN
apps/i2psnark/_icons/folder.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
apps/i2psnark/_icons/html.png
Normal file
After Width: | Height: | Size: 578 B |
BIN
apps/i2psnark/_icons/music.png
Normal file
After Width: | Height: | Size: 385 B |
BIN
apps/i2psnark/_icons/package.png
Normal file
After Width: | Height: | Size: 853 B |
BIN
apps/i2psnark/_icons/page.png
Normal file
After Width: | Height: | Size: 635 B |
BIN
apps/i2psnark/_icons/page_white.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
apps/i2psnark/_icons/page_white_acrobat.png
Normal file
After Width: | Height: | Size: 591 B |
BIN
apps/i2psnark/_icons/photo.png
Normal file
After Width: | Height: | Size: 589 B |
BIN
apps/i2psnark/_icons/plugin.png
Normal file
After Width: | Height: | Size: 591 B |
BIN
apps/i2psnark/_icons/tick.png
Normal file
After Width: | Height: | Size: 537 B |
@ -1 +1,7 @@
|
|||||||
|
# NOTE: This I2P config file must use UTF-8 encoding
|
||||||
|
#
|
||||||
|
# If you have a 'split' directory installation, with configuration
|
||||||
|
# files in ~/.i2p (Linux) or %APPDATA%\I2P (Windows), be sure to
|
||||||
|
# edit the file in the configuration directory, NOT the install directory.
|
||||||
|
#
|
||||||
i2psnark.dir=i2psnark
|
i2psnark.dir=i2psnark
|
||||||
|
17
apps/i2psnark/java/bmsg.sh
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#
|
||||||
|
# Update messages_xx.po and messages_xx.class files,
|
||||||
|
# from both java and jsp sources.
|
||||||
|
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
|
||||||
|
# zzz - public domain
|
||||||
|
#
|
||||||
|
|
||||||
|
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
|
||||||
|
## need to cd into our orignal path - where we call sh.exe from.
|
||||||
|
|
||||||
|
cd $CALLFROM
|
||||||
|
## echo $PWD
|
||||||
|
|
||||||
|
## except this everything is the same with bundle-message.sh
|
||||||
|
## walking - public domain :-D
|
||||||
|
|
||||||
|
source bundle-messages.sh $PARAS
|
@ -37,50 +37,72 @@
|
|||||||
</javac>
|
</javac>
|
||||||
</target>
|
</target>
|
||||||
<target name="jar" depends="builddep, compile">
|
<target name="jar" depends="builddep, compile">
|
||||||
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/*Servlet.class">
|
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class **/messages_*.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
|
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
|
||||||
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
||||||
</manifest>
|
</manifest>
|
||||||
</jar>
|
</jar>
|
||||||
</target>
|
</target>
|
||||||
<target name="war" depends="jar">
|
<!-- Ideally we would include
|
||||||
<war destfile="../i2psnark.war" webxml="../web.xml">
|
- only include the servlet, everything else is in the jar.
|
||||||
<classes dir="./build/obj" includes="**/*" />
|
- However, the wrapper.config classpath in existing installs
|
||||||
|
- does not include i2psnark.jar.
|
||||||
|
- So we must continue to duplicate everything in the war.
|
||||||
|
<classes dir="./build/obj" includes="**/I2PSnarkServlet*.class" />
|
||||||
|
-->
|
||||||
|
<target name="war" depends="jar, bundle">
|
||||||
|
<war destfile="../i2psnark.war" webxml="../web.xml" basedir="../" includes="_icons/*" >
|
||||||
|
<!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
|
||||||
|
<classes dir="./build/obj" includes="**/web/*.class" />
|
||||||
</war>
|
</war>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="bundle" depends="compile">
|
||||||
|
<!-- Update the messages_*.po files.
|
||||||
|
We need to supply the bat file for windows, and then change the fail property to true -->
|
||||||
|
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
|
||||||
|
<arg value="./bundle-messages.sh" />
|
||||||
|
</exec>
|
||||||
|
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
|
||||||
|
<arg value="./bundle-messages.sh" />
|
||||||
|
</exec>
|
||||||
|
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
|
||||||
|
<arg value="/c" />
|
||||||
|
<arg value="bundle-messages.bat" />
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="poupdate" depends="builddep, compile">
|
||||||
|
<!-- Update the messages_*.po files. -->
|
||||||
|
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
|
||||||
|
<arg value="./bundle-messages.sh" />
|
||||||
|
<arg value="-p" />
|
||||||
|
</exec>
|
||||||
|
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
|
||||||
|
<arg value="./bundle-messages.sh" />
|
||||||
|
<arg value="-p" />
|
||||||
|
</exec>
|
||||||
|
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
|
||||||
|
<arg value="/c" />
|
||||||
|
<arg value="bundle-messages.bat" />
|
||||||
|
<arg value="-p" />
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
<target name="standalone" depends="standalone_prep">
|
<target name="standalone" depends="standalone_prep">
|
||||||
<zip destfile="i2psnark-standalone.zip">
|
<zip destfile="i2psnark-standalone.zip">
|
||||||
<zipfileset dir="./dist/" prefix="i2psnark/" />
|
<zipfileset dir="./dist/" prefix="i2psnark/" />
|
||||||
</zip>
|
</zip>
|
||||||
</target>
|
</target>
|
||||||
<target name="standalone_prep" depends="war">
|
<target name="standalone_prep" depends="war">
|
||||||
<javac debug="true" deprecation="on" source="1.5" target="1.5"
|
|
||||||
destdir="./build" srcdir="src/" includes="org/klomp/snark/web/RunStandalone.java" >
|
|
||||||
<compilerarg line="${javac.compilerargs}" />
|
|
||||||
<classpath>
|
|
||||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
|
||||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
|
||||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
|
||||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
|
||||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
|
||||||
</classpath>
|
|
||||||
</javac>
|
|
||||||
|
|
||||||
<jar destfile="./build/launch-i2psnark.jar" basedir="./build/" includes="org/klomp/snark/web/RunStandalone.class">
|
|
||||||
<manifest>
|
|
||||||
<attribute name="Main-Class" value="org.klomp.snark.web.RunStandalone" />
|
|
||||||
<attribute name="Class-Path" value="lib/i2p.jar lib/mstreaming.jar lib/streaming.jar lib/commons-el.jar lib/commons-logging.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/javax.servlet.jar lib/org.mortbay.jetty.jar" />
|
|
||||||
</manifest>
|
|
||||||
</jar>
|
|
||||||
|
|
||||||
<delete dir="./dist" />
|
<delete dir="./dist" />
|
||||||
<mkdir dir="./dist" />
|
<mkdir dir="./dist" />
|
||||||
<copy file="./build/launch-i2psnark.jar" tofile="./dist/launch-i2psnark.jar" />
|
<copy file="../launch-i2psnark" todir="./dist/" />
|
||||||
<mkdir dir="./dist/webapps" />
|
<mkdir dir="./dist/webapps" />
|
||||||
<copy file="../i2psnark.war" tofile="./dist/webapps/i2psnark.war" />
|
<copy file="../i2psnark.war" tofile="./dist/webapps/i2psnark.war" />
|
||||||
<mkdir dir="./dist/lib" />
|
<mkdir dir="./dist/lib" />
|
||||||
|
<copy file="./build/i2psnark.jar" tofile="./dist/lib/i2psnark.jar" />
|
||||||
<copy file="../../../core/java/build/i2p.jar" tofile="./dist/lib/i2p.jar" />
|
<copy file="../../../core/java/build/i2p.jar" tofile="./dist/lib/i2p.jar" />
|
||||||
<copy file="../../jetty/jettylib/commons-el.jar" tofile="./dist/lib/commons-el.jar" />
|
<copy file="../../jetty/jettylib/commons-el.jar" tofile="./dist/lib/commons-el.jar" />
|
||||||
<copy file="../../jetty/jettylib/commons-logging.jar" tofile="./dist/lib/commons-logging.jar" />
|
<copy file="../../jetty/jettylib/commons-logging.jar" tofile="./dist/lib/commons-logging.jar" />
|
||||||
@ -92,7 +114,6 @@
|
|||||||
<copy file="../../streaming/java/build/streaming.jar" tofile="./dist/lib/streaming.jar" />
|
<copy file="../../streaming/java/build/streaming.jar" tofile="./dist/lib/streaming.jar" />
|
||||||
<copy file="../jetty-i2psnark.xml" tofile="./dist/jetty-i2psnark.xml" />
|
<copy file="../jetty-i2psnark.xml" tofile="./dist/jetty-i2psnark.xml" />
|
||||||
<copy file="../readme-standalone.txt" tofile="./dist/readme.txt" />
|
<copy file="../readme-standalone.txt" tofile="./dist/readme.txt" />
|
||||||
<mkdir dir="./dist/work" />
|
|
||||||
<mkdir dir="./dist/logs" />
|
<mkdir dir="./dist/logs" />
|
||||||
|
|
||||||
<zip destfile="i2psnark-standalone.zip">
|
<zip destfile="i2psnark-standalone.zip">
|
||||||
@ -104,11 +125,10 @@
|
|||||||
<delete dir="./build" />
|
<delete dir="./build" />
|
||||||
<delete file="../i2psnark.war" />
|
<delete file="../i2psnark.war" />
|
||||||
<delete file="./i2psnark-standalone.zip" />
|
<delete file="./i2psnark-standalone.zip" />
|
||||||
|
<delete dir="./dist" />
|
||||||
</target>
|
</target>
|
||||||
<target name="cleandep" depends="clean">
|
<target name="cleandep" depends="clean">
|
||||||
<ant dir="../../ministreaming/java/" target="distclean" />
|
|
||||||
</target>
|
</target>
|
||||||
<target name="distclean" depends="clean">
|
<target name="distclean" depends="clean">
|
||||||
<ant dir="../../ministreaming/java/" target="distclean" />
|
|
||||||
</target>
|
</target>
|
||||||
</project>
|
</project>
|
||||||
|
26
apps/i2psnark/java/bundle-messages.bat
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@echo off
|
||||||
|
set Callfrom=%cd%
|
||||||
|
set Paras=%1
|
||||||
|
|
||||||
|
rem before calling make sure you have msys and mingw 's "bin" path
|
||||||
|
rem in your current searching path
|
||||||
|
rem type "set path" to check
|
||||||
|
if not exist ..\locale\*.only goto updateALL
|
||||||
|
|
||||||
|
rem put a messages_xx.only(eg messages_zh.only) into locale folder
|
||||||
|
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
|
||||||
|
|
||||||
|
for %%i in (..\locale\*.only) do set PO=%%~ni
|
||||||
|
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
|
||||||
|
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
|
||||||
|
|
||||||
|
call sh --login %cd%\bmsg.sh
|
||||||
|
|
||||||
|
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:updateALL
|
||||||
|
call sh --login %cd%\bmsg.sh
|
||||||
|
|
||||||
|
:end
|
||||||
|
echo End of Message Bundling
|
85
apps/i2psnark/java/bundle-messages.sh
Executable file
@ -0,0 +1,85 @@
|
|||||||
|
#
|
||||||
|
# Update messages_xx.po and messages_xx.class files,
|
||||||
|
# from both java and jsp sources.
|
||||||
|
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
|
||||||
|
#
|
||||||
|
# usage:
|
||||||
|
# bundle-messages.sh (generates the resource bundle from the .po file)
|
||||||
|
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
|
||||||
|
#
|
||||||
|
# zzz - public domain
|
||||||
|
#
|
||||||
|
CLASS=org.klomp.snark.web.messages
|
||||||
|
TMPFILE=build/javafiles.txt
|
||||||
|
export TZ=UTC
|
||||||
|
|
||||||
|
if [ "$1" = "-p" ]
|
||||||
|
then
|
||||||
|
POUPDATE=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# add ../java/ so the refs will work in the po file
|
||||||
|
JPATHS="../java/src"
|
||||||
|
for i in ../locale/messages_*.po
|
||||||
|
do
|
||||||
|
# get language
|
||||||
|
LG=${i#../locale/messages_}
|
||||||
|
LG=${LG%.po}
|
||||||
|
|
||||||
|
if [ "$POUPDATE" = "1" ]
|
||||||
|
then
|
||||||
|
# make list of java files newer than the .po file
|
||||||
|
find $JPATHS -name *.java -newer $i > $TMPFILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -s build/obj/org/klomp/snark/web/messages_$LG.class -a \
|
||||||
|
build/obj/org/klomp/snark/web/messages_$LG.class -nt $i -a \
|
||||||
|
! -s $TMPFILE ]
|
||||||
|
then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$POUPDATE" = "1" ]
|
||||||
|
then
|
||||||
|
echo "Updating the $i file from the tags..."
|
||||||
|
# extract strings from java and jsp files, and update messages.po files
|
||||||
|
# translate calls must be one of the forms:
|
||||||
|
# _("foo")
|
||||||
|
# _x("foo")
|
||||||
|
# To start a new translation, copy the header from an old translation to the new .po file,
|
||||||
|
# then ant distclean poupdate.
|
||||||
|
find $JPATHS -name *.java > $TMPFILE
|
||||||
|
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\
|
||||||
|
--keyword=_ --keyword=_x \
|
||||||
|
-o ${i}t
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo 'Warning - xgettext failed, not updating translations'
|
||||||
|
rm -f ${i}t
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
msgmerge -U --backup=none $i ${i}t
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo 'Warning - msgmerge failed, not updating translations'
|
||||||
|
rm -f ${i}t
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
rm -f ${i}t
|
||||||
|
# so we don't do this again
|
||||||
|
touch $i
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Generating ${CLASS}_$LG ResourceBundle..."
|
||||||
|
|
||||||
|
# convert to class files in build/obj
|
||||||
|
msgfmt --java --statistics -r $CLASS -l $LG -d build/obj $i
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo 'Warning - msgfmt failed, not updating translations'
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -f $TMPFILE
|
||||||
|
# todo: return failure
|
||||||
|
exit 0
|
@ -7,7 +7,6 @@ package org.klomp.snark;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
|
||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
import net.i2p.client.I2PClient;
|
import net.i2p.client.I2PClient;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
|
@ -137,10 +137,11 @@ public class BitField
|
|||||||
return count >= size;
|
return count >= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
// Not very efficient
|
// Not very efficient
|
||||||
StringBuffer sb = new StringBuffer("BitField(");
|
StringBuilder sb = new StringBuilder("BitField(");
|
||||||
sb.append(size).append(")[");
|
sb.append(size).append(")[");
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
if (get(i))
|
if (get(i))
|
||||||
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.client.streaming.I2PServerSocket;
|
import net.i2p.client.streaming.I2PServerSocket;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
@ -36,7 +37,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class ConnectionAcceptor implements Runnable
|
public class ConnectionAcceptor implements Runnable
|
||||||
{
|
{
|
||||||
private Log _log = new Log(ConnectionAcceptor.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ConnectionAcceptor.class);
|
||||||
private I2PServerSocket serverSocket;
|
private I2PServerSocket serverSocket;
|
||||||
private PeerAcceptor peeracceptor;
|
private PeerAcceptor peeracceptor;
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
|
@ -4,7 +4,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -17,16 +16,19 @@ import net.i2p.I2PException;
|
|||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
import net.i2p.client.streaming.I2PServerSocket;
|
import net.i2p.client.streaming.I2PServerSocket;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
|
import net.i2p.client.streaming.I2PSocketEepGet;
|
||||||
import net.i2p.client.streaming.I2PSocketManager;
|
import net.i2p.client.streaming.I2PSocketManager;
|
||||||
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
||||||
import net.i2p.data.DataFormatException;
|
import net.i2p.data.DataFormatException;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
|
import net.i2p.util.ConcurrentHashSet;
|
||||||
import net.i2p.util.EepGet;
|
import net.i2p.util.EepGet;
|
||||||
import net.i2p.util.FileUtil;
|
import net.i2p.util.FileUtil;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.SimpleScheduler;
|
import net.i2p.util.SimpleScheduler;
|
||||||
import net.i2p.util.SimpleTimer;
|
import net.i2p.util.SimpleTimer;
|
||||||
|
import net.i2p.util.Translate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I2P specific helpers for I2PSnark
|
* I2P specific helpers for I2PSnark
|
||||||
@ -43,37 +45,39 @@ public class I2PSnarkUtil {
|
|||||||
private int _proxyPort;
|
private int _proxyPort;
|
||||||
private String _i2cpHost;
|
private String _i2cpHost;
|
||||||
private int _i2cpPort;
|
private int _i2cpPort;
|
||||||
private Map _opts;
|
private Map<String, String> _opts;
|
||||||
private I2PSocketManager _manager;
|
private I2PSocketManager _manager;
|
||||||
private boolean _configured;
|
private boolean _configured;
|
||||||
private Set _shitlist;
|
private final Set<Hash> _shitlist;
|
||||||
private int _maxUploaders;
|
private int _maxUploaders;
|
||||||
private int _maxUpBW;
|
private int _maxUpBW;
|
||||||
private int _maxConnections;
|
private int _maxConnections;
|
||||||
private File _tmpDir;
|
private File _tmpDir;
|
||||||
|
private int _startupDelay;
|
||||||
|
|
||||||
|
public static final int DEFAULT_STARTUP_DELAY = 3;
|
||||||
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
||||||
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
||||||
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
||||||
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
||||||
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
|
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
|
||||||
public static final int MAX_CONNECTIONS = 16; // per torrent
|
public static final int MAX_CONNECTIONS = 16; // per torrent
|
||||||
|
|
||||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||||
_context = ctx;
|
_context = ctx;
|
||||||
_log = _context.logManager().getLog(Snark.class);
|
_log = _context.logManager().getLog(Snark.class);
|
||||||
_opts = new HashMap();
|
_opts = new HashMap();
|
||||||
setProxy("127.0.0.1", 4444);
|
//setProxy("127.0.0.1", 4444);
|
||||||
setI2CPConfig("127.0.0.1", 7654, null);
|
setI2CPConfig("127.0.0.1", 7654, null);
|
||||||
_shitlist = new HashSet(64);
|
_shitlist = new ConcurrentHashSet();
|
||||||
_configured = false;
|
_configured = false;
|
||||||
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
||||||
_maxUpBW = DEFAULT_MAX_UP_BW;
|
_maxUpBW = DEFAULT_MAX_UP_BW;
|
||||||
_maxConnections = MAX_CONNECTIONS;
|
_maxConnections = MAX_CONNECTIONS;
|
||||||
|
_startupDelay = DEFAULT_STARTUP_DELAY;
|
||||||
// This is used for both announce replies and .torrent file downloads,
|
// This is used for both announce replies and .torrent file downloads,
|
||||||
// so it must be available even if not connected to I2CP.
|
// so it must be available even if not connected to I2CP.
|
||||||
// so much for multiple instances
|
// so much for multiple instances
|
||||||
_tmpDir = new File("tmp", "i2psnark");
|
_tmpDir = new File(ctx.getTempDir(), "i2psnark");
|
||||||
FileUtil.rmdir(_tmpDir, false);
|
FileUtil.rmdir(_tmpDir, false);
|
||||||
_tmpDir.mkdirs();
|
_tmpDir.mkdirs();
|
||||||
}
|
}
|
||||||
@ -83,6 +87,7 @@ public class I2PSnarkUtil {
|
|||||||
* host for no proxying)
|
* host for no proxying)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/*****
|
||||||
public void setProxy(String host, int port) {
|
public void setProxy(String host, int port) {
|
||||||
if ( (host != null) && (port > 0) ) {
|
if ( (host != null) && (port > 0) ) {
|
||||||
_shouldProxy = true;
|
_shouldProxy = true;
|
||||||
@ -95,6 +100,7 @@ public class I2PSnarkUtil {
|
|||||||
}
|
}
|
||||||
_configured = true;
|
_configured = true;
|
||||||
}
|
}
|
||||||
|
******/
|
||||||
|
|
||||||
public boolean configured() { return _configured; }
|
public boolean configured() { return _configured; }
|
||||||
|
|
||||||
@ -123,17 +129,23 @@ public class I2PSnarkUtil {
|
|||||||
_maxConnections = limit;
|
_maxConnections = limit;
|
||||||
_configured = true;
|
_configured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStartupDelay(int minutes) {
|
||||||
|
_startupDelay = minutes;
|
||||||
|
_configured = true;
|
||||||
|
}
|
||||||
|
|
||||||
public String getI2CPHost() { return _i2cpHost; }
|
public String getI2CPHost() { return _i2cpHost; }
|
||||||
public int getI2CPPort() { return _i2cpPort; }
|
public int getI2CPPort() { return _i2cpPort; }
|
||||||
public Map getI2CPOptions() { return _opts; }
|
public Map<String, String> getI2CPOptions() { return _opts; }
|
||||||
public String getEepProxyHost() { return _proxyHost; }
|
public String getEepProxyHost() { return _proxyHost; }
|
||||||
public int getEepProxyPort() { return _proxyPort; }
|
public int getEepProxyPort() { return _proxyPort; }
|
||||||
public boolean getEepProxySet() { return _shouldProxy; }
|
public boolean getEepProxySet() { return _shouldProxy; }
|
||||||
public int getMaxUploaders() { return _maxUploaders; }
|
public int getMaxUploaders() { return _maxUploaders; }
|
||||||
public int getMaxUpBW() { return _maxUpBW; }
|
public int getMaxUpBW() { return _maxUpBW; }
|
||||||
public int getMaxConnections() { return _maxConnections; }
|
public int getMaxConnections() { return _maxConnections; }
|
||||||
|
public int getStartupDelay() { return _startupDelay; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to the router, if we aren't already
|
* Connect to the router, if we aren't already
|
||||||
*/
|
*/
|
||||||
@ -185,18 +197,15 @@ public class I2PSnarkUtil {
|
|||||||
/** connect to the given destination */
|
/** connect to the given destination */
|
||||||
I2PSocket connect(PeerID peer) throws IOException {
|
I2PSocket connect(PeerID peer) throws IOException {
|
||||||
Hash dest = peer.getAddress().calculateHash();
|
Hash dest = peer.getAddress().calculateHash();
|
||||||
synchronized (_shitlist) {
|
if (_shitlist.contains(dest))
|
||||||
if (_shitlist.contains(dest))
|
throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are shitlisted");
|
||||||
throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are shitlisted");
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
I2PSocket rv = _manager.connect(peer.getAddress());
|
I2PSocket rv = _manager.connect(peer.getAddress());
|
||||||
if (rv != null) synchronized (_shitlist) { _shitlist.remove(dest); }
|
if (rv != null)
|
||||||
|
_shitlist.remove(dest);
|
||||||
return rv;
|
return rv;
|
||||||
} catch (I2PException ie) {
|
} catch (I2PException ie) {
|
||||||
synchronized (_shitlist) {
|
_shitlist.add(dest);
|
||||||
_shitlist.add(dest);
|
|
||||||
}
|
|
||||||
SimpleScheduler.getInstance().addEvent(new Unshitlist(dest), 10*60*1000);
|
SimpleScheduler.getInstance().addEvent(new Unshitlist(dest), 10*60*1000);
|
||||||
throw new IOException("Unable to reach the peer " + peer + ": " + ie.getMessage());
|
throw new IOException("Unable to reach the peer " + peer + ": " + ie.getMessage());
|
||||||
}
|
}
|
||||||
@ -205,7 +214,7 @@ public class I2PSnarkUtil {
|
|||||||
private class Unshitlist implements SimpleTimer.TimedEvent {
|
private class Unshitlist implements SimpleTimer.TimedEvent {
|
||||||
private Hash _dest;
|
private Hash _dest;
|
||||||
public Unshitlist(Hash dest) { _dest = dest; }
|
public Unshitlist(Hash dest) { _dest = dest; }
|
||||||
public void timeReached() { synchronized (_shitlist) { _shitlist.remove(_dest); } }
|
public void timeReached() { _shitlist.remove(_dest); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,7 +240,13 @@ public class I2PSnarkUtil {
|
|||||||
if (rewrite)
|
if (rewrite)
|
||||||
fetchURL = rewriteAnnounce(url);
|
fetchURL = rewriteAnnounce(url);
|
||||||
//_log.debug("Rewritten url [" + fetchURL + "]");
|
//_log.debug("Rewritten url [" + fetchURL + "]");
|
||||||
EepGet get = new EepGet(_context, _shouldProxy, _proxyHost, _proxyPort, retries, out.getAbsolutePath(), fetchURL);
|
//EepGet get = new EepGet(_context, _shouldProxy, _proxyHost, _proxyPort, retries, out.getAbsolutePath(), fetchURL);
|
||||||
|
// Use our tunnel for announces and .torrent fetches too! Make sure we're connected first...
|
||||||
|
if (!connected()) {
|
||||||
|
if (!connect())
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
EepGet get = new I2PSocketEepGet(_context, _manager, retries, out.getAbsolutePath(), fetchURL);
|
||||||
if (get.fetch()) {
|
if (get.fetch()) {
|
||||||
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
|
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
|
||||||
return out;
|
return out;
|
||||||
@ -327,6 +342,11 @@ public class I2PSnarkUtil {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param ot non-null */
|
||||||
|
public void setOpenTrackerString(String ot) {
|
||||||
|
_opts.put(PROP_OPENTRACKERS, ot);
|
||||||
|
}
|
||||||
|
|
||||||
public String getOpenTrackerString() {
|
public String getOpenTrackerString() {
|
||||||
String rv = (String) _opts.get(PROP_OPENTRACKERS);
|
String rv = (String) _opts.get(PROP_OPENTRACKERS);
|
||||||
if (rv == null)
|
if (rv == null)
|
||||||
@ -345,7 +365,7 @@ public class I2PSnarkUtil {
|
|||||||
while (tok.hasMoreTokens())
|
while (tok.hasMoreTokens())
|
||||||
rv.add(tok.nextToken());
|
rv.add(tok.nextToken());
|
||||||
|
|
||||||
if (rv.size() <= 0)
|
if (rv.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -390,4 +410,37 @@ public class I2PSnarkUtil {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String BUNDLE_NAME = "org.klomp.snark.web.messages";
|
||||||
|
|
||||||
|
/** lang in routerconsole.lang property, else current locale */
|
||||||
|
public String getString(String key) {
|
||||||
|
return Translate.getString(key, _context, BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translate a string with a parameter
|
||||||
|
* This is a lot more expensive than getString(s, ctx), so use sparingly.
|
||||||
|
*
|
||||||
|
* @param s string to be translated containing {0}
|
||||||
|
* The {0} will be replaced by the parameter.
|
||||||
|
* Single quotes must be doubled, i.e. ' -> '' in the string.
|
||||||
|
* @param o parameter, not translated.
|
||||||
|
* To tranlslate parameter also, use _("foo {0} bar", _("baz"))
|
||||||
|
* Do not double the single quotes in the parameter.
|
||||||
|
* Use autoboxing to call with ints, longs, floats, etc.
|
||||||
|
*/
|
||||||
|
public String getString(String s, Object o) {
|
||||||
|
return Translate.getString(s, o, _context, BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {0} and {1} */
|
||||||
|
public String getString(String s, Object o, Object o2) {
|
||||||
|
return Translate.getString(s, o, o2, _context, BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ngettext @since 0.7.14 */
|
||||||
|
public String getString(int n, String s, String p) {
|
||||||
|
return Translate.getString(n, s, p, _context, BUNDLE_NAME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,7 @@ class Message
|
|||||||
dos.write(data, off, len);
|
dos.write(data, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -30,6 +30,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.crypto.SHA1;
|
import net.i2p.crypto.SHA1;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@ -47,7 +48,7 @@ import org.klomp.snark.bencode.InvalidBEncodingException;
|
|||||||
*/
|
*/
|
||||||
public class MetaInfo
|
public class MetaInfo
|
||||||
{
|
{
|
||||||
private static final Log _log = new Log(MetaInfo.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(MetaInfo.class);
|
||||||
private final String announce;
|
private final String announce;
|
||||||
private final byte[] info_hash;
|
private final byte[] info_hash;
|
||||||
private final String name;
|
private final String name;
|
||||||
@ -345,6 +346,7 @@ public class MetaInfo
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "MetaInfo[info_hash='" + hexencode(info_hash)
|
return "MetaInfo[info_hash='" + hexencode(info_hash)
|
||||||
@ -362,7 +364,7 @@ public class MetaInfo
|
|||||||
*/
|
*/
|
||||||
private static String hexencode(byte[] bs)
|
private static String hexencode(byte[] bs)
|
||||||
{
|
{
|
||||||
StringBuffer sb = new StringBuffer(bs.length*2);
|
StringBuilder sb = new StringBuilder(bs.length*2);
|
||||||
for (int i = 0; i < bs.length; i++)
|
for (int i = 0; i < bs.length; i++)
|
||||||
{
|
{
|
||||||
int c = bs[i] & 0xFF;
|
int c = bs[i] & 0xFF;
|
||||||
@ -432,7 +434,7 @@ public class MetaInfo
|
|||||||
private byte[] calculateInfoHash()
|
private byte[] calculateInfoHash()
|
||||||
{
|
{
|
||||||
Map info = createInfoMap();
|
Map info = createInfoMap();
|
||||||
StringBuffer buf = new StringBuffer(128);
|
StringBuilder buf = new StringBuilder(128);
|
||||||
buf.append("info: ");
|
buf.append("info: ");
|
||||||
for (Iterator iter = info.entrySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = info.entrySet().iterator(); iter.hasNext(); ) {
|
||||||
Map.Entry entry = (Map.Entry)iter.next();
|
Map.Entry entry = (Map.Entry)iter.next();
|
||||||
|
@ -106,6 +106,7 @@ public class Peer implements Comparable
|
|||||||
/**
|
/**
|
||||||
* Returns the String representation of the peerID.
|
* Returns the String representation of the peerID.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
if (peerID != null)
|
if (peerID != null)
|
||||||
@ -125,6 +126,7 @@ public class Peer implements Comparable
|
|||||||
/**
|
/**
|
||||||
* The hash code of a Peer is the hash code of the peerID.
|
* The hash code of a Peer is the hash code of the peerID.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return peerID.hashCode() ^ (2 << _id);
|
return peerID.hashCode() ^ (2 << _id);
|
||||||
@ -134,6 +136,7 @@ public class Peer implements Comparable
|
|||||||
* Two Peers are equal when they have the same PeerID.
|
* Two Peers are equal when they have the same PeerID.
|
||||||
* All other properties are ignored.
|
* All other properties are ignored.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if (o instanceof Peer)
|
if (o instanceof Peer)
|
||||||
@ -385,6 +388,7 @@ public class Peer implements Comparable
|
|||||||
* Sets whether or not we are interested in pieces from this peer.
|
* Sets whether or not we are interested in pieces from this peer.
|
||||||
* Defaults to false. When interest is true and this peer unchokes
|
* Defaults to false. When interest is true and this peer unchokes
|
||||||
* us then we start downloading from it. Has no effect when not connected.
|
* us then we start downloading from it. Has no effect when not connected.
|
||||||
|
* @deprecated unused
|
||||||
*/
|
*/
|
||||||
public void setInteresting(boolean interest)
|
public void setInteresting(boolean interest)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ import java.io.OutputStream;
|
|||||||
import java.io.SequenceInputStream;
|
import java.io.SequenceInputStream;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
@ -41,7 +42,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class PeerAcceptor
|
public class PeerAcceptor
|
||||||
{
|
{
|
||||||
private static final Log _log = new Log(PeerAcceptor.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerAcceptor.class);
|
||||||
private final PeerCoordinator coordinator;
|
private final PeerCoordinator coordinator;
|
||||||
final PeerCoordinatorSet coordinators;
|
final PeerCoordinatorSet coordinators;
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ import java.util.List;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TimerTask that checks for good/bad up/downloader. Works together
|
* TimerTask that checks for good/bad up/downloader. Works together
|
||||||
* with the PeerCoordinator to select which Peers get (un)choked.
|
* with the PeerCoordinator to select which Peers get (un)choked.
|
||||||
@ -43,7 +45,7 @@ class PeerCheckerTask extends TimerTask
|
|||||||
this.coordinator = coordinator;
|
this.coordinator = coordinator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Random random = new Random();
|
private static final Random random = I2PAppContext.getGlobalContext().random();
|
||||||
|
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
@ -105,15 +107,15 @@ class PeerCheckerTask extends TimerTask
|
|||||||
peer.resetCounters();
|
peer.resetCounters();
|
||||||
|
|
||||||
_util.debug(peer + ":", Snark.DEBUG);
|
_util.debug(peer + ":", Snark.DEBUG);
|
||||||
_util.debug(" ul: " + upload/KILOPERSECOND
|
_util.debug(" ul: " + upload*1024/KILOPERSECOND
|
||||||
+ " dl: " + download/KILOPERSECOND
|
+ " dl: " + download*1024/KILOPERSECOND
|
||||||
+ " i: " + peer.isInterested()
|
+ " i: " + peer.isInterested()
|
||||||
+ " I: " + peer.isInteresting()
|
+ " I: " + peer.isInteresting()
|
||||||
+ " c: " + peer.isChoking()
|
+ " c: " + peer.isChoking()
|
||||||
+ " C: " + peer.isChoked(),
|
+ " C: " + peer.isChoked(),
|
||||||
Snark.DEBUG);
|
Snark.DEBUG);
|
||||||
|
|
||||||
// Choke half of them rather than all so it isn't so drastic...
|
// Choke a percentage of them rather than all so it isn't so drastic...
|
||||||
// unless this torrent is over the limit all by itself.
|
// unless this torrent is over the limit all by itself.
|
||||||
boolean overBWLimitChoke = upload > 0 &&
|
boolean overBWLimitChoke = upload > 0 &&
|
||||||
((overBWLimit && random.nextBoolean()) ||
|
((overBWLimit && random.nextBoolean()) ||
|
||||||
|
@ -23,11 +23,12 @@ package org.klomp.snark;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
class PeerConnectionIn implements Runnable
|
class PeerConnectionIn implements Runnable
|
||||||
{
|
{
|
||||||
private Log _log = new Log(PeerConnectionIn.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerConnectionIn.class);
|
||||||
private final Peer peer;
|
private final Peer peer;
|
||||||
private final DataInputStream din;
|
private final DataInputStream din;
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ class PeerConnectionIn implements Runnable
|
|||||||
din.readFully(bitmap);
|
din.readFully(bitmap);
|
||||||
ps.bitfieldMessage(bitmap);
|
ps.bitfieldMessage(bitmap);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Received bitmap from " + peer + " on " + peer.metainfo.getName() + ": size=" + (i-1) + ": " + ps.bitfield);
|
_log.debug("Received bitmap from " + peer + " on " + peer.metainfo.getName() + ": size=" + (i-1) /* + ": " + ps.bitfield */ );
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
piece = din.readInt();
|
piece = din.readInt();
|
||||||
|
@ -26,6 +26,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.SimpleScheduler;
|
import net.i2p.util.SimpleScheduler;
|
||||||
@ -33,7 +34,7 @@ import net.i2p.util.SimpleTimer;
|
|||||||
|
|
||||||
class PeerConnectionOut implements Runnable
|
class PeerConnectionOut implements Runnable
|
||||||
{
|
{
|
||||||
private Log _log = new Log(PeerConnectionOut.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerConnectionOut.class);
|
||||||
private final Peer peer;
|
private final Peer peer;
|
||||||
private final DataOutputStream dout;
|
private final DataOutputStream dout;
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ class PeerConnectionOut implements Runnable
|
|||||||
private boolean quit;
|
private boolean quit;
|
||||||
|
|
||||||
// Contains Messages.
|
// Contains Messages.
|
||||||
private List sendQueue = new ArrayList();
|
private final List sendQueue = new ArrayList();
|
||||||
|
|
||||||
private static long __id = 0;
|
private static long __id = 0;
|
||||||
private long _id;
|
private long _id;
|
||||||
@ -141,7 +142,7 @@ class PeerConnectionOut implements Runnable
|
|||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m == null && sendQueue.size() > 0) {
|
if (m == null && !sendQueue.isEmpty()) {
|
||||||
m = (Message)sendQueue.remove(0);
|
m = (Message)sendQueue.remove(0);
|
||||||
SimpleTimer.getInstance().removeEvent(m.expireEvent);
|
SimpleTimer.getInstance().removeEvent(m.expireEvent);
|
||||||
}
|
}
|
||||||
@ -151,7 +152,11 @@ class PeerConnectionOut implements Runnable
|
|||||||
{
|
{
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Send " + peer + ": " + m + " on " + peer.metainfo.getName());
|
_log.debug("Send " + peer + ": " + m + " on " + peer.metainfo.getName());
|
||||||
m.sendMessage(dout);
|
|
||||||
|
// This can block for quite a while.
|
||||||
|
// To help get slow peers going, and track the bandwidth better,
|
||||||
|
// move this _after_ state.uploaded() and see how it works.
|
||||||
|
//m.sendMessage(dout);
|
||||||
lastSent = System.currentTimeMillis();
|
lastSent = System.currentTimeMillis();
|
||||||
|
|
||||||
// Remove all piece messages after sending a choke message.
|
// Remove all piece messages after sending a choke message.
|
||||||
@ -159,9 +164,22 @@ class PeerConnectionOut implements Runnable
|
|||||||
removeMessage(Message.PIECE);
|
removeMessage(Message.PIECE);
|
||||||
|
|
||||||
// XXX - Should also register overhead...
|
// XXX - Should also register overhead...
|
||||||
if (m.type == Message.PIECE)
|
// Don't let other clients requesting big chunks get an advantage
|
||||||
state.uploaded(m.len);
|
// when we are seeding;
|
||||||
|
// only count the rest of the upload after sendMessage().
|
||||||
|
int remainder = 0;
|
||||||
|
if (m.type == Message.PIECE) {
|
||||||
|
if (m.len <= PeerState.PARTSIZE) {
|
||||||
|
state.uploaded(m.len);
|
||||||
|
} else {
|
||||||
|
state.uploaded(PeerState.PARTSIZE);
|
||||||
|
remainder = m.len - PeerState.PARTSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.sendMessage(dout);
|
||||||
|
if (remainder > 0)
|
||||||
|
state.uploaded(remainder);
|
||||||
m = null;
|
m = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class PeerCoordinator implements PeerListener
|
public class PeerCoordinator implements PeerListener
|
||||||
{
|
{
|
||||||
private final Log _log = new Log(PeerCoordinator.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class);
|
||||||
final MetaInfo metainfo;
|
final MetaInfo metainfo;
|
||||||
final Storage storage;
|
final Storage storage;
|
||||||
final Snark snark;
|
final Snark snark;
|
||||||
@ -61,7 +62,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
|
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
|
||||||
|
|
||||||
// synchronize on this when changing peers or downloaders
|
// synchronize on this when changing peers or downloaders
|
||||||
final List peers = new ArrayList();
|
final List<Peer> peers = new ArrayList();
|
||||||
/** estimate of the peers, without requiring any synchronization */
|
/** estimate of the peers, without requiring any synchronization */
|
||||||
volatile int peerCount;
|
volatile int peerCount;
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
private final byte[] id;
|
private final byte[] id;
|
||||||
|
|
||||||
// Some random wanted pieces
|
// Some random wanted pieces
|
||||||
private List wantedPieces;
|
private List<Piece> wantedPieces;
|
||||||
|
|
||||||
private boolean halted = false;
|
private boolean halted = false;
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// Install a timer to check the uploaders.
|
// Install a timer to check the uploaders.
|
||||||
// Randomize the first start time so multiple tasks are spread out,
|
// Randomize the first start time so multiple tasks are spread out,
|
||||||
// this will help the behavior with global limits
|
// this will help the behavior with global limits
|
||||||
Random r = new Random();
|
Random r = I2PAppContext.getGlobalContext().random();
|
||||||
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
|
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
public CoordinatorListener getListener() { return listener; }
|
public CoordinatorListener getListener() { return listener; }
|
||||||
|
|
||||||
// for web page detailed stats
|
// for web page detailed stats
|
||||||
public List peerList()
|
public List<Peer> peerList()
|
||||||
{
|
{
|
||||||
synchronized(peers)
|
synchronized(peers)
|
||||||
{
|
{
|
||||||
@ -134,8 +135,10 @@ public class PeerCoordinator implements PeerListener
|
|||||||
return storage.complete();
|
return storage.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** might be wrong */
|
||||||
public int getPeerCount() { return peerCount; }
|
public int getPeerCount() { return peerCount; }
|
||||||
|
|
||||||
|
/** should be right */
|
||||||
public int getPeers()
|
public int getPeers()
|
||||||
{
|
{
|
||||||
synchronized(peers)
|
synchronized(peers)
|
||||||
@ -236,16 +239,30 @@ public class PeerCoordinator implements PeerListener
|
|||||||
{
|
{
|
||||||
synchronized(peers)
|
synchronized(peers)
|
||||||
{
|
{
|
||||||
return !halted && peers.size() < _util.getMaxConnections();
|
return !halted && peers.size() < getMaxConnections();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce max if huge pieces to keep from ooming when leeching
|
||||||
|
* @return 512K: 16; 1M: 11; 2M: 6
|
||||||
|
*/
|
||||||
|
private int getMaxConnections() {
|
||||||
|
int size = metainfo.getPieceLength(0);
|
||||||
|
int max = _util.getMaxConnections();
|
||||||
|
if (size <= 512*1024 || completed())
|
||||||
|
return max;
|
||||||
|
if (size <= 1024*1024)
|
||||||
|
return (max + max + 2) / 3;
|
||||||
|
return (max + 2) / 3;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean halted() { return halted; }
|
public boolean halted() { return halted; }
|
||||||
|
|
||||||
public void halt()
|
public void halt()
|
||||||
{
|
{
|
||||||
halted = true;
|
halted = true;
|
||||||
List removed = new ArrayList();
|
List<Peer> removed = new ArrayList();
|
||||||
synchronized(peers)
|
synchronized(peers)
|
||||||
{
|
{
|
||||||
// Stop peer checker task.
|
// Stop peer checker task.
|
||||||
@ -257,8 +274,8 @@ public class PeerCoordinator implements PeerListener
|
|||||||
peerCount = 0;
|
peerCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (removed.size() > 0) {
|
while (!removed.isEmpty()) {
|
||||||
Peer peer = (Peer)removed.remove(0);
|
Peer peer = removed.remove(0);
|
||||||
peer.disconnect();
|
peer.disconnect();
|
||||||
removePeerFromPieces(peer);
|
removePeerFromPieces(peer);
|
||||||
}
|
}
|
||||||
@ -294,7 +311,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
peer.disconnect(false); // Don't deregister this connection/peer.
|
peer.disconnect(false); // Don't deregister this connection/peer.
|
||||||
}
|
}
|
||||||
// This is already checked in addPeer() but we could have gone over the limit since then
|
// This is already checked in addPeer() but we could have gone over the limit since then
|
||||||
else if (peers.size() >= _util.getMaxConnections())
|
else if (peers.size() >= getMaxConnections())
|
||||||
{
|
{
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
|
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
|
||||||
@ -325,9 +342,9 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// caller must synchronize on peers
|
// caller must synchronize on peers
|
||||||
private static Peer peerIDInList(PeerID pid, List peers)
|
private static Peer peerIDInList(PeerID pid, List peers)
|
||||||
{
|
{
|
||||||
Iterator it = peers.iterator();
|
Iterator<Peer> it = peers.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Peer cur = (Peer)it.next();
|
Peer cur = it.next();
|
||||||
if (pid.sameID(cur.getPeerID()))
|
if (pid.sameID(cur.getPeerID()))
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
@ -350,7 +367,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
peersize = peers.size();
|
peersize = peers.size();
|
||||||
// This isn't a strict limit, as we may have several pending connections;
|
// This isn't a strict limit, as we may have several pending connections;
|
||||||
// thus there is an additional check in connected()
|
// thus there is an additional check in connected()
|
||||||
need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
|
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
|
||||||
// Check if we already have this peer before we build the connection
|
// Check if we already have this peer before we build the connection
|
||||||
Peer old = peerIDInList(peer.getPeerID(), peers);
|
Peer old = peerIDInList(peer.getPeerID(), peers);
|
||||||
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
|
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
|
||||||
@ -378,7 +395,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
if (peer.isConnected())
|
if (peer.isConnected())
|
||||||
_log.info("Add peer already connected: " + peer);
|
_log.info("Add peer already connected: " + peer);
|
||||||
else
|
else
|
||||||
_log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
|
_log.info("Connections: " + peersize + "/" + getMaxConnections()
|
||||||
+ " not accepting extra peer: " + peer);
|
+ " not accepting extra peer: " + peer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -391,21 +408,21 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// linked list will contain all interested peers that we choke.
|
// linked list will contain all interested peers that we choke.
|
||||||
// At the start are the peers that have us unchoked at the end the
|
// At the start are the peers that have us unchoked at the end the
|
||||||
// other peer that are interested, but are choking us.
|
// other peer that are interested, but are choking us.
|
||||||
List interested = new LinkedList();
|
List<Peer> interested = new LinkedList();
|
||||||
synchronized (peers) {
|
synchronized (peers) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int unchokedCount = 0;
|
int unchokedCount = 0;
|
||||||
int maxUploaders = allowedUploaders();
|
int maxUploaders = allowedUploaders();
|
||||||
Iterator it = peers.iterator();
|
Iterator<Peer> it = peers.iterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
Peer peer = (Peer)it.next();
|
Peer peer = it.next();
|
||||||
if (peer.isChoking() && peer.isInterested())
|
if (peer.isChoking() && peer.isInterested())
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (uploaders < maxUploaders)
|
if (uploaders < maxUploaders)
|
||||||
{
|
{
|
||||||
if (!peer.isChoked())
|
if (peer.isInteresting() && !peer.isChoked())
|
||||||
interested.add(unchokedCount++, peer);
|
interested.add(unchokedCount++, peer);
|
||||||
else
|
else
|
||||||
interested.add(peer);
|
interested.add(peer);
|
||||||
@ -413,9 +430,9 @@ public class PeerCoordinator implements PeerListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (uploaders < maxUploaders && interested.size() > 0)
|
while (uploaders < maxUploaders && !interested.isEmpty())
|
||||||
{
|
{
|
||||||
Peer peer = (Peer)interested.remove(0);
|
Peer peer = interested.remove(0);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Unchoke: " + peer);
|
_log.debug("Unchoke: " + peer);
|
||||||
peer.setChoking(false);
|
peer.setChoking(false);
|
||||||
@ -460,10 +477,10 @@ public class PeerCoordinator implements PeerListener
|
|||||||
|
|
||||||
synchronized(wantedPieces)
|
synchronized(wantedPieces)
|
||||||
{
|
{
|
||||||
Iterator it = wantedPieces.iterator();
|
Iterator<Piece> it = wantedPieces.iterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
Piece p = (Piece)it.next();
|
Piece p = it.next();
|
||||||
int i = p.getId();
|
int i = p.getId();
|
||||||
if (bitfield.get(i)) {
|
if (bitfield.get(i)) {
|
||||||
p.addPeer(peer);
|
p.addPeer(peer);
|
||||||
@ -474,6 +491,13 @@ public class PeerCoordinator implements PeerListener
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be somewhat less than the max conns per torrent,
|
||||||
|
* but not too much less, so a torrent doesn't get stuck near the end.
|
||||||
|
* @since 0.7.14
|
||||||
|
*/
|
||||||
|
private static final int END_GAME_THRESHOLD = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns one of pieces in the given BitField that is still wanted or
|
* Returns one of pieces in the given BitField that is still wanted or
|
||||||
* -1 if none of the given pieces are wanted.
|
* -1 if none of the given pieces are wanted.
|
||||||
@ -490,11 +514,11 @@ public class PeerCoordinator implements PeerListener
|
|||||||
{
|
{
|
||||||
Piece piece = null;
|
Piece piece = null;
|
||||||
Collections.sort(wantedPieces); // Sort in order of rarest first.
|
Collections.sort(wantedPieces); // Sort in order of rarest first.
|
||||||
List requested = new ArrayList();
|
List<Piece> requested = new ArrayList();
|
||||||
Iterator it = wantedPieces.iterator();
|
Iterator<Piece> it = wantedPieces.iterator();
|
||||||
while (piece == null && it.hasNext())
|
while (piece == null && it.hasNext())
|
||||||
{
|
{
|
||||||
Piece p = (Piece)it.next();
|
Piece p = it.next();
|
||||||
if (havePieces.get(p.getId()) && !p.isRequested())
|
if (havePieces.get(p.getId()) && !p.isRequested())
|
||||||
{
|
{
|
||||||
piece = p;
|
piece = p;
|
||||||
@ -507,12 +531,17 @@ public class PeerCoordinator implements PeerListener
|
|||||||
|
|
||||||
//Only request a piece we've requested before if there's no other choice.
|
//Only request a piece we've requested before if there's no other choice.
|
||||||
if (piece == null) {
|
if (piece == null) {
|
||||||
|
// AND if there are almost no wanted pieces left (real end game).
|
||||||
|
// If we do end game all the time, we generate lots of extra traffic
|
||||||
|
// when the seeder is super-slow and all the peers are "caught up"
|
||||||
|
if (wantedPieces.size() > END_GAME_THRESHOLD)
|
||||||
|
return -1; // nothing to request and not in end game
|
||||||
// let's not all get on the same piece
|
// let's not all get on the same piece
|
||||||
Collections.shuffle(requested);
|
Collections.shuffle(requested);
|
||||||
Iterator it2 = requested.iterator();
|
Iterator<Piece> it2 = requested.iterator();
|
||||||
while (piece == null && it2.hasNext())
|
while (piece == null && it2.hasNext())
|
||||||
{
|
{
|
||||||
Piece p = (Piece)it2.next();
|
Piece p = it2.next();
|
||||||
if (havePieces.get(p.getId()))
|
if (havePieces.get(p.getId()))
|
||||||
{
|
{
|
||||||
piece = p;
|
piece = p;
|
||||||
@ -632,11 +661,11 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// Disconnect from other seeders when we get the last piece
|
// Disconnect from other seeders when we get the last piece
|
||||||
synchronized(peers)
|
synchronized(peers)
|
||||||
{
|
{
|
||||||
List toDisconnect = new ArrayList();
|
List<Peer> toDisconnect = new ArrayList();
|
||||||
Iterator it = peers.iterator();
|
Iterator<Peer> it = peers.iterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
Peer p = (Peer)it.next();
|
Peer p = it.next();
|
||||||
if (p.isConnected())
|
if (p.isConnected())
|
||||||
{
|
{
|
||||||
if (completed() && p.isCompleted())
|
if (completed() && p.isCompleted())
|
||||||
@ -648,7 +677,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
it = toDisconnect.iterator();
|
it = toDisconnect.iterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
Peer p = (Peer)it.next();
|
Peer p = it.next();
|
||||||
p.disconnect(true);
|
p.disconnect(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,8 +743,8 @@ public class PeerCoordinator implements PeerListener
|
|||||||
*/
|
*/
|
||||||
public void removePeerFromPieces(Peer peer) {
|
public void removePeerFromPieces(Peer peer) {
|
||||||
synchronized(wantedPieces) {
|
synchronized(wantedPieces) {
|
||||||
for(Iterator iter = wantedPieces.iterator(); iter.hasNext(); ) {
|
for(Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
|
||||||
Piece piece = (Piece)iter.next();
|
Piece piece = iter.next();
|
||||||
piece.removePeer(peer);
|
piece.removePeer(peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,8 +798,8 @@ public class PeerCoordinator implements PeerListener
|
|||||||
}
|
}
|
||||||
synchronized(wantedPieces)
|
synchronized(wantedPieces)
|
||||||
{
|
{
|
||||||
for(Iterator iter = wantedPieces.iterator(); iter.hasNext(); ) {
|
for(Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
|
||||||
Piece piece = (Piece)iter.next();
|
Piece piece = iter.next();
|
||||||
if (piece.getId() == savedRequest.piece) {
|
if (piece.getId() == savedRequest.piece) {
|
||||||
Request req = savedRequest;
|
Request req = savedRequest;
|
||||||
piece.setRequested(true);
|
piece.setRequested(true);
|
||||||
@ -795,9 +824,9 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// see if anybody else is requesting
|
// see if anybody else is requesting
|
||||||
synchronized (peers)
|
synchronized (peers)
|
||||||
{
|
{
|
||||||
Iterator it = peers.iterator();
|
Iterator<Peer> it = peers.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Peer p = (Peer)it.next();
|
Peer p = it.next();
|
||||||
if (p.equals(peer))
|
if (p.equals(peer))
|
||||||
continue;
|
continue;
|
||||||
if (p.state == null)
|
if (p.state == null)
|
||||||
@ -815,9 +844,9 @@ public class PeerCoordinator implements PeerListener
|
|||||||
// nobody is, so mark unrequested
|
// nobody is, so mark unrequested
|
||||||
synchronized(wantedPieces)
|
synchronized(wantedPieces)
|
||||||
{
|
{
|
||||||
Iterator it = wantedPieces.iterator();
|
Iterator<Piece> it = wantedPieces.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Piece p = (Piece)it.next();
|
Piece p = it.next();
|
||||||
if (p.getId() == piece) {
|
if (p.getId() == piece) {
|
||||||
p.setRequested(false);
|
p.setRequested(false);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
@ -12,7 +12,7 @@ import java.util.Set;
|
|||||||
* from it there too)
|
* from it there too)
|
||||||
*/
|
*/
|
||||||
public class PeerCoordinatorSet {
|
public class PeerCoordinatorSet {
|
||||||
private Set _coordinators;
|
private final Set _coordinators;
|
||||||
|
|
||||||
public PeerCoordinatorSet() {
|
public PeerCoordinatorSet() {
|
||||||
_coordinators = new HashSet();
|
_coordinators = new HashSet();
|
||||||
|
@ -107,6 +107,7 @@ public class PeerID implements Comparable
|
|||||||
/**
|
/**
|
||||||
* The hash code of a PeerID is the exclusive or of all id bytes.
|
* The hash code of a PeerID is the exclusive or of all id bytes.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return hash;
|
return hash;
|
||||||
@ -127,6 +128,7 @@ public class PeerID implements Comparable
|
|||||||
/**
|
/**
|
||||||
* Two PeerIDs are equal when they have the same id, address and port.
|
* Two PeerIDs are equal when they have the same id, address and port.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if (o instanceof PeerID)
|
if (o instanceof PeerID)
|
||||||
@ -171,6 +173,7 @@ public class PeerID implements Comparable
|
|||||||
* and address is the base64 dest (was the base64 hash of the dest) which
|
* and address is the base64 dest (was the base64 hash of the dest) which
|
||||||
* should match what the bytemonsoon tracker reports on its web pages.
|
* should match what the bytemonsoon tracker reports on its web pages.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
int nonZero = 0;
|
int nonZero = 0;
|
||||||
@ -190,7 +193,7 @@ public class PeerID implements Comparable
|
|||||||
{
|
{
|
||||||
boolean leading_zeros = true;
|
boolean leading_zeros = true;
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer(bs.length*2);
|
StringBuilder sb = new StringBuilder(bs.length*2);
|
||||||
for (int i = 0; i < bs.length; i++)
|
for (int i = 0; i < bs.length; i++)
|
||||||
{
|
{
|
||||||
int c = bs[i] & 0xFF;
|
int c = bs[i] & 0xFF;
|
||||||
|
@ -151,7 +151,7 @@ public interface PeerListener
|
|||||||
*
|
*
|
||||||
* @param state the PeerState for the peer
|
* @param state the PeerState for the peer
|
||||||
*/
|
*/
|
||||||
void savePeerPartial(PeerState state);
|
void savePeerPartial(PeerState state); /* FIXME Exporting non-public type through public API FIXME */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a peer has connected and there may be a partially
|
* Called when a peer has connected and there may be a partially
|
||||||
@ -161,7 +161,7 @@ public interface PeerListener
|
|||||||
*
|
*
|
||||||
* @return request (contains the partial data and valid length)
|
* @return request (contains the partial data and valid length)
|
||||||
*/
|
*/
|
||||||
Request getPeerPartial(BitField havePieces);
|
Request getPeerPartial(BitField havePieces); /* FIXME Exporting non-public type through public API FIXME */
|
||||||
|
|
||||||
/** Mark a peer's requested pieces unrequested when it is disconnected
|
/** Mark a peer's requested pieces unrequested when it is disconnected
|
||||||
* This prevents premature end game
|
* This prevents premature end game
|
||||||
|
@ -24,11 +24,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
class PeerState
|
class PeerState
|
||||||
{
|
{
|
||||||
private Log _log = new Log(PeerState.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
|
||||||
final Peer peer;
|
final Peer peer;
|
||||||
final PeerListener listener;
|
final PeerListener listener;
|
||||||
final MetaInfo metainfo;
|
final MetaInfo metainfo;
|
||||||
@ -152,7 +153,16 @@ class PeerState
|
|||||||
// XXX - Check for weird bitfield and disconnect?
|
// XXX - Check for weird bitfield and disconnect?
|
||||||
bitfield = new BitField(bitmap, metainfo.getPieces());
|
bitfield = new BitField(bitmap, metainfo.getPieces());
|
||||||
}
|
}
|
||||||
setInteresting(listener.gotBitField(peer, bitfield));
|
boolean interest = listener.gotBitField(peer, bitfield);
|
||||||
|
setInteresting(interest);
|
||||||
|
if (bitfield.complete() && !interest) {
|
||||||
|
// They are seeding and we are seeding,
|
||||||
|
// why did they contact us? (robert)
|
||||||
|
// Dump them quick before we send our whole bitmap
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Disconnecting seed that connects to seeds: " + peer);
|
||||||
|
peer.disconnect(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void requestMessage(int piece, int begin, int length)
|
void requestMessage(int piece, int begin, int length)
|
||||||
@ -186,6 +196,7 @@ class PeerState
|
|||||||
|
|
||||||
// Limit total pipelined requests to MAX_PIPELINE bytes
|
// Limit total pipelined requests to MAX_PIPELINE bytes
|
||||||
// to conserve memory and prevent DOS
|
// to conserve memory and prevent DOS
|
||||||
|
// Todo: limit number of requests also? (robert 64 x 4KB)
|
||||||
if (out.queuedBytes() + length > MAX_PIPELINE_BYTES)
|
if (out.queuedBytes() + length > MAX_PIPELINE_BYTES)
|
||||||
{
|
{
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
@ -512,8 +523,10 @@ class PeerState
|
|||||||
_log.debug(peer + " requests " + outstandingRequests);
|
_log.debug(peer + " requests " + outstandingRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts requesting first chunk of next piece. Returns true if
|
/**
|
||||||
// something has been added to the requests, false otherwise.
|
* Starts requesting first chunk of next piece. Returns true if
|
||||||
|
* something has been added to the requests, false otherwise.
|
||||||
|
*/
|
||||||
private boolean requestNextPiece()
|
private boolean requestNextPiece()
|
||||||
{
|
{
|
||||||
// Check that we already know what the other side has.
|
// Check that we already know what the other side has.
|
||||||
@ -545,6 +558,15 @@ class PeerState
|
|||||||
if (nextPiece != -1
|
if (nextPiece != -1
|
||||||
&& (lastRequest == null || lastRequest.piece != nextPiece))
|
&& (lastRequest == null || lastRequest.piece != nextPiece))
|
||||||
{
|
{
|
||||||
|
// Fail safe to make sure we are interested
|
||||||
|
// When we transition into the end game we may not be interested...
|
||||||
|
if (!interesting) {
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug(peer + " transition to end game, setting interesting");
|
||||||
|
interesting = true;
|
||||||
|
out.sendInterest(true);
|
||||||
|
}
|
||||||
|
|
||||||
int piece_length = metainfo.getPieceLength(nextPiece);
|
int piece_length = metainfo.getPieceLength(nextPiece);
|
||||||
//Catch a common place for OOMs esp. on 1MB pieces
|
//Catch a common place for OOMs esp. on 1MB pieces
|
||||||
byte[] bs;
|
byte[] bs;
|
||||||
|
@ -20,13 +20,20 @@ public class Piece implements Comparable {
|
|||||||
return this.peers.size() - ((Piece)o).peers.size();
|
return this.peers.size() - ((Piece)o).peers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (o == null) return false;
|
if (o instanceof Piece) {
|
||||||
try {
|
if (o == null) return false;
|
||||||
return this.id == ((Piece)o).id;
|
return this.id == ((Piece)o).id;
|
||||||
} catch (ClassCastException cce) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 5;
|
||||||
|
hash = 31 * hash + this.id;
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() { return this.id; }
|
public int getId() { return this.id; }
|
||||||
@ -36,6 +43,7 @@ public class Piece implements Comparable {
|
|||||||
public boolean isRequested() { return this.requested; }
|
public boolean isRequested() { return this.requested; }
|
||||||
public void setRequested(boolean requested) { this.requested = requested; }
|
public void setRequested(boolean requested) { this.requested = requested; }
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.valueOf(id);
|
return String.valueOf(id);
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,13 @@ class Request
|
|||||||
throw new IndexOutOfBoundsException("Illegal Request " + toString());
|
throw new IndexOutOfBoundsException("Illegal Request " + toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return piece ^ off ^ len;
|
return piece ^ off ^ len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if (o instanceof Request)
|
if (o instanceof Request)
|
||||||
@ -67,6 +69,7 @@ class Request
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "(" + piece + "," + off + "," + len + ")";
|
return "(" + piece + "," + off + "," + len + ")";
|
||||||
|
@ -28,7 +28,6 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@ -322,7 +321,7 @@ public class Snark
|
|||||||
// sixteen random bytes.
|
// sixteen random bytes.
|
||||||
byte snark = (((3 + 7 + 10) * (1000 - 8)) / 992) - 17;
|
byte snark = (((3 + 7 + 10) * (1000 - 8)) / 992) - 17;
|
||||||
id = new byte[20];
|
id = new byte[20];
|
||||||
Random random = new Random();
|
Random random = I2PAppContext.getGlobalContext().random();
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 9; i++)
|
for (i = 0; i < 9; i++)
|
||||||
id[i] = 0;
|
id[i] = 0;
|
||||||
@ -619,14 +618,14 @@ public class Snark
|
|||||||
command_interpreter = false;
|
command_interpreter = false;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if (args[i].equals("--eepproxy"))
|
//else if (args[i].equals("--eepproxy"))
|
||||||
{
|
// {
|
||||||
String proxyHost = args[i+1];
|
// String proxyHost = args[i+1];
|
||||||
String proxyPort = args[i+2];
|
// String proxyPort = args[i+2];
|
||||||
if (!configured)
|
// if (!configured)
|
||||||
util.setProxy(proxyHost, Integer.parseInt(proxyPort));
|
// util.setProxy(proxyHost, Integer.parseInt(proxyPort));
|
||||||
i += 3;
|
// i += 3;
|
||||||
}
|
// }
|
||||||
else if (args[i].equals("--i2cp"))
|
else if (args[i].equals("--i2cp"))
|
||||||
{
|
{
|
||||||
String i2cpHost = args[i+1];
|
String i2cpHost = args[i+1];
|
||||||
@ -735,7 +734,7 @@ public class Snark
|
|||||||
//if (debug >= INFO && t != null)
|
//if (debug >= INFO && t != null)
|
||||||
// t.printStackTrace();
|
// t.printStackTrace();
|
||||||
stopTorrent();
|
stopTorrent();
|
||||||
throw new RuntimeException("die bart die");
|
throw new RuntimeException(s + (t == null ? "" : ": " + t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +36,7 @@ public class SnarkShutdown extends I2PAppThread
|
|||||||
|
|
||||||
private final ShutdownListener listener;
|
private final ShutdownListener listener;
|
||||||
|
|
||||||
|
/* FIXME Exporting non-public type through public API FIXME */
|
||||||
public SnarkShutdown(Storage storage,
|
public SnarkShutdown(Storage storage,
|
||||||
PeerCoordinator coordinator,
|
PeerCoordinator coordinator,
|
||||||
ConnectionAcceptor acceptor,
|
ConnectionAcceptor acceptor,
|
||||||
@ -49,6 +50,7 @@ public class SnarkShutdown extends I2PAppThread
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
//Snark.debug("Shutting down...", Snark.NOTICE);
|
//Snark.debug("Shutting down...", Snark.NOTICE);
|
||||||
|
@ -46,7 +46,7 @@ public class Storage
|
|||||||
private final StorageListener listener;
|
private final StorageListener listener;
|
||||||
private I2PSnarkUtil _util;
|
private I2PSnarkUtil _util;
|
||||||
|
|
||||||
private BitField bitfield; // BitField to represent the pieces
|
private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces
|
||||||
private int needed; // Number of pieces needed
|
private int needed; // Number of pieces needed
|
||||||
private boolean _probablyComplete; // use this to decide whether to open files RO
|
private boolean _probablyComplete; // use this to decide whether to open files RO
|
||||||
|
|
||||||
@ -57,7 +57,8 @@ public class Storage
|
|||||||
|
|
||||||
/** The default piece size. */
|
/** The default piece size. */
|
||||||
private static final int MIN_PIECE_SIZE = 256*1024;
|
private static final int MIN_PIECE_SIZE = 256*1024;
|
||||||
public static final int MAX_PIECE_SIZE = 1024*1024;
|
/** note that we start reducing max number of peer connections above 1MB */
|
||||||
|
public static final int MAX_PIECE_SIZE = 2*1024*1024;
|
||||||
/** The maximum number of pieces in a torrent. */
|
/** The maximum number of pieces in a torrent. */
|
||||||
public static final int MAX_PIECES = 10*1024;
|
public static final int MAX_PIECES = 10*1024;
|
||||||
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
|
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
|
||||||
@ -190,6 +191,9 @@ public class Storage
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** FIXME we can run out of fd's doing this,
|
||||||
|
* maybe some sort of global close-RAF-right-away flag
|
||||||
|
* would do the trick */
|
||||||
private void fast_digestCreate() throws IOException {
|
private void fast_digestCreate() throws IOException {
|
||||||
// Calculate piece_hashes
|
// Calculate piece_hashes
|
||||||
SHA1 digest = new SHA1();
|
SHA1 digest = new SHA1();
|
||||||
@ -282,6 +286,50 @@ public class Storage
|
|||||||
return needed == 0;
|
return needed == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param file canonical path (non-directory)
|
||||||
|
* @return number of bytes remaining; -1 if unknown file
|
||||||
|
* @since 0.7.14
|
||||||
|
*/
|
||||||
|
public long remaining(String file) {
|
||||||
|
long bytes = 0;
|
||||||
|
for (int i = 0; i < rafs.length; i++) {
|
||||||
|
File f = RAFfile[i];
|
||||||
|
// use canonical in case snark dir or sub dirs are symlinked
|
||||||
|
String canonical = null;
|
||||||
|
if (f != null) {
|
||||||
|
try {
|
||||||
|
canonical = f.getCanonicalPath();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
f = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f != null && canonical.equals(file)) {
|
||||||
|
if (complete())
|
||||||
|
return 0;
|
||||||
|
int psz = metainfo.getPieceLength(0);
|
||||||
|
long start = bytes;
|
||||||
|
long end = start + lengths[i];
|
||||||
|
int pc = (int) (bytes / psz);
|
||||||
|
long rv = 0;
|
||||||
|
if (!bitfield.get(pc))
|
||||||
|
rv = Math.min(psz - (start % psz), lengths[i]);
|
||||||
|
int pieces = metainfo.getPieces();
|
||||||
|
for (int j = pc + 1; (((long)j) * psz) < end && j < pieces; j++) {
|
||||||
|
if (!bitfield.get(j)) {
|
||||||
|
if (((long)(j+1))*psz < end)
|
||||||
|
rv += psz;
|
||||||
|
else
|
||||||
|
rv += end - (((long)j) * psz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
bytes += lengths[i];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The BitField that tells which pieces this storage contains.
|
* The BitField that tells which pieces this storage contains.
|
||||||
* Do not change this since this is the current state of the storage.
|
* Do not change this since this is the current state of the storage.
|
||||||
@ -291,6 +339,18 @@ public class Storage
|
|||||||
return bitfield;
|
return bitfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base file or directory name of the data,
|
||||||
|
* as specified in the .torrent file, but filtered to remove
|
||||||
|
* illegal characters. This is where the data actually is,
|
||||||
|
* relative to the snark base dir.
|
||||||
|
*
|
||||||
|
* @since 0.7.14
|
||||||
|
*/
|
||||||
|
public String getBaseName() {
|
||||||
|
return filterName(metainfo.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates (and/or checks) all files from the metainfo file list.
|
* Creates (and/or checks) all files from the metainfo file list.
|
||||||
*/
|
*/
|
||||||
@ -416,13 +476,29 @@ public class Storage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final char[] ILLEGAL = new char[] {
|
||||||
|
'<', '>', ':', '"', '/', '\\', '|', '?', '*',
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes 'suspicious' characters from the give file name.
|
* Removes 'suspicious' characters from the given file name.
|
||||||
|
* http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
|
||||||
*/
|
*/
|
||||||
private static String filterName(String name)
|
private static String filterName(String name)
|
||||||
{
|
{
|
||||||
// XXX - Is this enough?
|
if (name.equals(".") || name.equals(" "))
|
||||||
return name.replace(File.separatorChar, '_');
|
return "_";
|
||||||
|
String rv = name;
|
||||||
|
if (rv.startsWith("."))
|
||||||
|
rv = '_' + rv.substring(1);
|
||||||
|
if (rv.endsWith(".") || rv.endsWith(" "))
|
||||||
|
rv = rv.substring(0, rv.length() - 1) + '_';
|
||||||
|
for (int i = 0; i < ILLEGAL.length; i++) {
|
||||||
|
if (rv.indexOf(ILLEGAL[i]) >= 0)
|
||||||
|
rv = rv.replace(ILLEGAL[i], '_');
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File createFileFromNames(File base, List names) throws IOException
|
private File createFileFromNames(File base, List names) throws IOException
|
||||||
@ -573,6 +649,9 @@ public class Storage
|
|||||||
if (rafs == null) return;
|
if (rafs == null) return;
|
||||||
for (int i = 0; i < rafs.length; i++)
|
for (int i = 0; i < rafs.length; i++)
|
||||||
{
|
{
|
||||||
|
// if we had an IOE in check(), the RAFlock may be null
|
||||||
|
if (RAFlock[i] == null)
|
||||||
|
continue;
|
||||||
try {
|
try {
|
||||||
synchronized(RAFlock[i]) {
|
synchronized(RAFlock[i]) {
|
||||||
closeRAF(i);
|
closeRAF(i);
|
||||||
|
@ -24,6 +24,8 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -31,6 +33,7 @@ import java.util.List;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
@ -42,7 +45,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class TrackerClient extends I2PAppThread
|
public class TrackerClient extends I2PAppThread
|
||||||
{
|
{
|
||||||
private static final Log _log = new Log(TrackerClient.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(TrackerClient.class);
|
||||||
private static final String NO_EVENT = "";
|
private static final String NO_EVENT = "";
|
||||||
private static final String STARTED_EVENT = "started";
|
private static final String STARTED_EVENT = "started";
|
||||||
private static final String COMPLETED_EVENT = "completed";
|
private static final String COMPLETED_EVENT = "completed";
|
||||||
@ -81,6 +84,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (stop) throw new RuntimeException("Dont rerun me, create a copy");
|
if (stop) throw new RuntimeException("Dont rerun me, create a copy");
|
||||||
super.start();
|
super.start();
|
||||||
@ -109,6 +113,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
return !stop && _util.connected();
|
return !stop && _util.connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
String infoHash = urlencode(meta.getInfoHash());
|
String infoHash = urlencode(meta.getInfoHash());
|
||||||
@ -121,13 +126,19 @@ public class TrackerClient extends I2PAppThread
|
|||||||
// followed by the secondary open trackers
|
// followed by the secondary open trackers
|
||||||
// It's painful, but try to make sure if an open tracker is also
|
// It's painful, but try to make sure if an open tracker is also
|
||||||
// the primary tracker, that we don't add it twice.
|
// the primary tracker, that we don't add it twice.
|
||||||
|
// todo: check for b32 matches as well
|
||||||
trackers = new ArrayList(2);
|
trackers = new ArrayList(2);
|
||||||
trackers.add(new Tracker(meta.getAnnounce(), true));
|
String primary = meta.getAnnounce();
|
||||||
|
if (isValidAnnounce(primary)) {
|
||||||
|
trackers.add(new Tracker(meta.getAnnounce(), true));
|
||||||
|
} else {
|
||||||
|
_log.warn("Skipping invalid or non-i2p announce: " + primary);
|
||||||
|
}
|
||||||
List tlist = _util.getOpenTrackers();
|
List tlist = _util.getOpenTrackers();
|
||||||
if (tlist != null) {
|
if (tlist != null) {
|
||||||
for (int i = 0; i < tlist.size(); i++) {
|
for (int i = 0; i < tlist.size(); i++) {
|
||||||
String url = (String)tlist.get(i);
|
String url = (String)tlist.get(i);
|
||||||
if (!url.startsWith("http://")) {
|
if (!isValidAnnounce(url)) {
|
||||||
_log.error("Bad announce URL: [" + url + "]");
|
_log.error("Bad announce URL: [" + url + "]");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -136,22 +147,29 @@ public class TrackerClient extends I2PAppThread
|
|||||||
_log.error("Bad announce URL: [" + url + "]");
|
_log.error("Bad announce URL: [" + url + "]");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (meta.getAnnounce().startsWith(url.substring(0, slash)))
|
if (primary.startsWith(url.substring(0, slash)))
|
||||||
continue;
|
continue;
|
||||||
String dest = _util.lookup(url.substring(7, slash));
|
String dest = _util.lookup(url.substring(7, slash));
|
||||||
if (dest == null) {
|
if (dest == null) {
|
||||||
_log.error("Announce host unknown: [" + url + "]");
|
_log.error("Announce host unknown: [" + url.substring(7, slash) + "]");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (meta.getAnnounce().startsWith("http://" + dest))
|
if (primary.startsWith("http://" + dest))
|
||||||
continue;
|
continue;
|
||||||
if (meta.getAnnounce().startsWith("http://i2p/" + dest))
|
if (primary.startsWith("http://i2p/" + dest))
|
||||||
continue;
|
continue;
|
||||||
trackers.add(new Tracker(url, false));
|
trackers.add(new Tracker(url, false));
|
||||||
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
|
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tlist.isEmpty()) {
|
||||||
|
// FIXME really need to get this message to the gui
|
||||||
|
stop = true;
|
||||||
|
_log.error("No valid trackers for infoHash: " + infoHash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long uploaded = coordinator.getUploaded();
|
long uploaded = coordinator.getUploaded();
|
||||||
long downloaded = coordinator.getDownloaded();
|
long downloaded = coordinator.getDownloaded();
|
||||||
long left = coordinator.getLeft();
|
long left = coordinator.getLeft();
|
||||||
@ -162,10 +180,10 @@ public class TrackerClient extends I2PAppThread
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!verifyConnected()) return;
|
if (!verifyConnected()) return;
|
||||||
boolean started = false;
|
boolean runStarted = false;
|
||||||
boolean firstTime = true;
|
boolean firstTime = true;
|
||||||
int consecutiveFails = 0;
|
int consecutiveFails = 0;
|
||||||
Random r = new Random();
|
Random r = I2PAppContext.getGlobalContext().random();
|
||||||
while(!stop)
|
while(!stop)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -178,7 +196,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
delay = r.nextInt(30*1000);
|
delay = r.nextInt(30*1000);
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
} else if (completed && started)
|
} else if (completed && runStarted)
|
||||||
delay = 3*SLEEP*60*1000 + random;
|
delay = 3*SLEEP*60*1000 + random;
|
||||||
else if (coordinator.trackerProblems != null && ++consecutiveFails < MAX_CONSEC_FAILS)
|
else if (coordinator.trackerProblems != null && ++consecutiveFails < MAX_CONSEC_FAILS)
|
||||||
delay = INITIAL_SLEEP;
|
delay = INITIAL_SLEEP;
|
||||||
@ -221,7 +239,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
Tracker tr = (Tracker)iter.next();
|
Tracker tr = (Tracker)iter.next();
|
||||||
if ((!stop) && (!tr.stop) &&
|
if ((!stop) && (!tr.stop) &&
|
||||||
(completed || coordinator.needPeers()) &&
|
(completed || coordinator.needPeers()) &&
|
||||||
(event == COMPLETED_EVENT || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
|
(event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -237,11 +255,11 @@ public class TrackerClient extends I2PAppThread
|
|||||||
tr.consecutiveFails = 0;
|
tr.consecutiveFails = 0;
|
||||||
if (tr.isPrimary)
|
if (tr.isPrimary)
|
||||||
consecutiveFails = 0;
|
consecutiveFails = 0;
|
||||||
started = true;
|
runStarted = true;
|
||||||
tr.started = true;
|
tr.started = true;
|
||||||
|
|
||||||
Set peers = info.getPeers();
|
Set peers = info.getPeers();
|
||||||
tr.seenPeers = peers.size();
|
tr.seenPeers = info.getPeerCount();
|
||||||
if (coordinator.trackerSeenPeers < tr.seenPeers) // update rising number quickly
|
if (coordinator.trackerSeenPeers < tr.seenPeers) // update rising number quickly
|
||||||
coordinator.trackerSeenPeers = tr.seenPeers;
|
coordinator.trackerSeenPeers = tr.seenPeers;
|
||||||
if ( (left > 0) && (!completed) ) {
|
if ( (left > 0) && (!completed) ) {
|
||||||
@ -252,6 +270,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
Iterator it = ordered.iterator();
|
Iterator it = ordered.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Peer cur = (Peer)it.next();
|
Peer cur = (Peer)it.next();
|
||||||
|
// FIXME if id == us || dest == us continue;
|
||||||
// only delay if we actually make an attempt to add peer
|
// only delay if we actually make an attempt to add peer
|
||||||
if(coordinator.addPeer(cur)) {
|
if(coordinator.addPeer(cur)) {
|
||||||
int delay = DELAY_MUL;
|
int delay = DELAY_MUL;
|
||||||
@ -296,7 +315,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
|
|
||||||
// we could try and total the unique peers but that's too hard for now
|
// we could try and total the unique peers but that's too hard for now
|
||||||
coordinator.trackerSeenPeers = maxSeenPeers;
|
coordinator.trackerSeenPeers = maxSeenPeers;
|
||||||
if (!started)
|
if (!runStarted)
|
||||||
_util.debug(" Retrying in one minute...", Snark.DEBUG);
|
_util.debug(" Retrying in one minute...", Snark.DEBUG);
|
||||||
} // *** end of while loop
|
} // *** end of while loop
|
||||||
} // try
|
} // try
|
||||||
@ -311,9 +330,9 @@ public class TrackerClient extends I2PAppThread
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// try to contact everybody we can
|
// try to contact everybody we can
|
||||||
// We don't need I2CP connection for eepget
|
// Don't try to restart I2CP connection just to say goodbye
|
||||||
// if (!verifyConnected()) return;
|
|
||||||
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
|
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
|
||||||
|
if (!_util.connected()) return;
|
||||||
Tracker tr = (Tracker)iter.next();
|
Tracker tr = (Tracker)iter.next();
|
||||||
if (tr.started && (!tr.stop) && tr.trackerProblems == null)
|
if (tr.started && (!tr.stop) && tr.trackerProblems == null)
|
||||||
doRequest(tr, infoHash, peerID, uploaded,
|
doRequest(tr, infoHash, peerID, uploaded,
|
||||||
@ -338,7 +357,11 @@ public class TrackerClient extends I2PAppThread
|
|||||||
+ "&uploaded=" + uploaded
|
+ "&uploaded=" + uploaded
|
||||||
+ "&downloaded=" + downloaded
|
+ "&downloaded=" + downloaded
|
||||||
+ "&left=" + left
|
+ "&left=" + left
|
||||||
+ ((event != NO_EVENT) ? ("&event=" + event) : "");
|
+ ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
|
||||||
|
if (left <= 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
|
||||||
|
s += "&numwant=0";
|
||||||
|
else
|
||||||
|
s += "&numwant=" + _util.getMaxConnections();
|
||||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||||
|
|
||||||
tr.lastRequestTime = System.currentTimeMillis();
|
tr.lastRequestTime = System.currentTimeMillis();
|
||||||
@ -368,25 +391,52 @@ public class TrackerClient extends I2PAppThread
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Very lazy byte[] to URL encoder. Just encodes everything, even
|
* Very lazy byte[] to URL encoder. Just encodes almost everything, even
|
||||||
* "normal" chars.
|
* some "normal" chars.
|
||||||
|
* By not encoding about 1/4 of the chars, we make random data like hashes about 16% smaller.
|
||||||
|
*
|
||||||
|
* RFC1738: 0-9a-zA-Z$-_.+!*'(),
|
||||||
|
* Us: 0-9a-zA-Z
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public static String urlencode(byte[] bs)
|
public static String urlencode(byte[] bs)
|
||||||
{
|
{
|
||||||
StringBuffer sb = new StringBuffer(bs.length*3);
|
StringBuilder sb = new StringBuilder(bs.length*3);
|
||||||
for (int i = 0; i < bs.length; i++)
|
for (int i = 0; i < bs.length; i++)
|
||||||
{
|
{
|
||||||
int c = bs[i] & 0xFF;
|
int c = bs[i] & 0xFF;
|
||||||
sb.append('%');
|
if ((c >= '0' && c <= '9') ||
|
||||||
if (c < 16)
|
(c >= 'A' && c <= 'Z') ||
|
||||||
sb.append('0');
|
(c >= 'a' && c <= 'z')) {
|
||||||
sb.append(Integer.toHexString(c));
|
sb.append((char)c);
|
||||||
|
} else {
|
||||||
|
sb.append('%');
|
||||||
|
if (c < 16)
|
||||||
|
sb.append('0');
|
||||||
|
sb.append(Integer.toHexString(c));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Tracker
|
/**
|
||||||
|
* @return true for i2p hosts only
|
||||||
|
* @since 0.7.12
|
||||||
|
*/
|
||||||
|
static boolean isValidAnnounce(String ann) {
|
||||||
|
URL url;
|
||||||
|
try {
|
||||||
|
url = new URL(ann);
|
||||||
|
} catch (MalformedURLException mue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return url.getProtocol().equals("http") &&
|
||||||
|
(url.getHost().endsWith(".i2p") || url.getHost().equals("i2p")) &&
|
||||||
|
url.getPort() < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Tracker
|
||||||
{
|
{
|
||||||
String announce;
|
String announce;
|
||||||
boolean isPrimary;
|
boolean isPrimary;
|
||||||
|
@ -23,6 +23,7 @@ package org.klomp.snark;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -37,6 +38,8 @@ public class TrackerInfo
|
|||||||
private final String failure_reason;
|
private final String failure_reason;
|
||||||
private final int interval;
|
private final int interval;
|
||||||
private final Set peers;
|
private final Set peers;
|
||||||
|
private int complete;
|
||||||
|
private int incomplete;
|
||||||
|
|
||||||
public TrackerInfo(InputStream in, byte[] my_id, MetaInfo metainfo)
|
public TrackerInfo(InputStream in, byte[] my_id, MetaInfo metainfo)
|
||||||
throws IOException
|
throws IOException
|
||||||
@ -68,11 +71,26 @@ public class TrackerInfo
|
|||||||
throw new InvalidBEncodingException("No interval given");
|
throw new InvalidBEncodingException("No interval given");
|
||||||
else
|
else
|
||||||
interval = beInterval.getInt();
|
interval = beInterval.getInt();
|
||||||
|
|
||||||
BEValue bePeers = (BEValue)m.get("peers");
|
BEValue bePeers = (BEValue)m.get("peers");
|
||||||
if (bePeers == null)
|
if (bePeers == null)
|
||||||
throw new InvalidBEncodingException("No peer list");
|
peers = Collections.EMPTY_SET;
|
||||||
else
|
else
|
||||||
peers = getPeers(bePeers.getList(), my_id, metainfo);
|
peers = getPeers(bePeers.getList(), my_id, metainfo);
|
||||||
|
|
||||||
|
BEValue bev = (BEValue)m.get("complete");
|
||||||
|
if (bev != null) try {
|
||||||
|
complete = bev.getInt();
|
||||||
|
if (complete < 0)
|
||||||
|
complete = 0;
|
||||||
|
} catch (InvalidBEncodingException ibe) {}
|
||||||
|
|
||||||
|
bev = (BEValue)m.get("incomplete");
|
||||||
|
if (bev != null) try {
|
||||||
|
incomplete = bev.getInt();
|
||||||
|
if (incomplete < 0)
|
||||||
|
incomplete = 0;
|
||||||
|
} catch (InvalidBEncodingException ibe) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +133,12 @@ public class TrackerInfo
|
|||||||
return peers;
|
return peers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPeerCount()
|
||||||
|
{
|
||||||
|
int pc = peers == null ? 0 : peers.size();
|
||||||
|
return Math.max(pc, complete + incomplete - 1);
|
||||||
|
}
|
||||||
|
|
||||||
public String getFailureReason()
|
public String getFailureReason()
|
||||||
{
|
{
|
||||||
return failure_reason;
|
return failure_reason;
|
||||||
@ -125,12 +149,15 @@ public class TrackerInfo
|
|||||||
return interval;
|
return interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
if (failure_reason != null)
|
if (failure_reason != null)
|
||||||
return "TrackerInfo[FAILED: " + failure_reason + "]";
|
return "TrackerInfo[FAILED: " + failure_reason + "]";
|
||||||
else
|
else
|
||||||
return "TrackerInfo[interval=" + interval
|
return "TrackerInfo[interval=" + interval
|
||||||
|
+ (complete > 0 ? (", complete=" + complete) : "" )
|
||||||
|
+ (incomplete > 0 ? (", incomplete=" + incomplete) : "" )
|
||||||
+ ", peers=" + peers + "]";
|
+ ", peers=" + peers + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,9 @@ public class BDecoder
|
|||||||
public BEValue bdecodeMap() throws IOException
|
public BEValue bdecodeMap() throws IOException
|
||||||
{
|
{
|
||||||
int c = getNextIndicator();
|
int c = getNextIndicator();
|
||||||
if (c != 'd')
|
if (c == '<')
|
||||||
|
throw new InvalidBEncodingException("Expected a .torrent metainfo file but found HTML? Check URL or file!");
|
||||||
|
else if (c != 'd')
|
||||||
throw new InvalidBEncodingException("Expected 'd', not '"
|
throw new InvalidBEncodingException("Expected 'd', not '"
|
||||||
+ (char)c + "'");
|
+ (char)c + "'");
|
||||||
indicator = 0;
|
indicator = 0;
|
||||||
|
@ -172,13 +172,14 @@ public class BEValue
|
|||||||
/** return the untyped value */
|
/** return the untyped value */
|
||||||
public Object getValue() { return value; }
|
public Object getValue() { return value; }
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
String valueString;
|
String valueString;
|
||||||
if (value instanceof byte[])
|
if (value instanceof byte[])
|
||||||
{
|
{
|
||||||
byte[] bs = (byte[])value;
|
byte[] bs = (byte[])value;
|
||||||
// XXX - Stupid heuristic...
|
// XXX - Stupid heuristic... and not UTF-8
|
||||||
if (bs.length <= 12)
|
if (bs.length <= 12)
|
||||||
valueString = new String(bs);
|
valueString = new String(bs);
|
||||||
else
|
else
|
||||||
|