| 1 |
#!/opt/bin/perl |
| 2 |
|
| 3 |
BEGIN { |
| 4 |
$ENV{http_proxy} = |
| 5 |
$ENV{https_proxy} = "http://127.0.0.1:8118"; # privoxy |
| 6 |
} |
| 7 |
|
| 8 |
use common::sense; |
| 9 |
use Compress::LZF; |
| 10 |
use EV; |
| 11 |
use AnyEvent::HTTP; |
| 12 |
use BDB; |
| 13 |
use Coro; |
| 14 |
use Coro::BDB; |
| 15 |
use AnyEvent::DNS; |
| 16 |
use Set::IntSpan; |
| 17 |
use CBOR::XS; |
| 18 |
use Compress::Zlib (); |
| 19 |
use Compress::Raw::Zlib (); |
| 20 |
use AnyEvent::TLS; |
| 21 |
|
| 22 |
BDB::min_parallel 8; |
| 23 |
|
| 24 |
#our @TPB = qw(https://thepiratebay.org); |
| 25 |
#our @TPB = qw(https://baypirateproxy.org); |
| 26 |
our @TPB = qw(http://uj3wazyk5u4hnvtk.onion); |
| 27 |
our $TPB = $TPB[0]; |
| 28 |
|
| 29 |
our $TODAY = int time / 86400; |
| 30 |
|
| 31 |
#our $TPB_SWITCHER = AE::timer 1, 0.02, sub { |
| 32 |
# state $i; |
| 33 |
# $TPB = $TPB[++$i % @TPB]; |
| 34 |
#}; |
| 35 |
|
| 36 |
############################################################################# |
| 37 |
|
| 38 |
$AnyEvent::HTTP::MAX_PER_HOST = |
| 39 |
$AnyEvent::HTTP::MAX_PERSISTENT_PER_HOST = 400; |
| 40 |
|
| 41 |
our %stat; |
| 42 |
|
| 43 |
our $statprint = AE::timer 1, 1, sub { |
| 44 |
syswrite STDOUT, "\r" . (join " ", map "$_=$stat{$_}", sort keys %stat) . " " |
| 45 |
if $ENV{VERBOSE}; |
| 46 |
}; |
| 47 |
|
| 48 |
our @DICTIONARY = (do { |
| 49 |
open my $fh, "<:perlio", "dictionary0" |
| 50 |
or die "dictionary0: $!"; |
| 51 |
local $/; |
| 52 |
<$fh> |
| 53 |
}); |
| 54 |
|
| 55 |
############################################################################# |
| 56 |
|
| 57 |
our $db_env = db_env_create; |
| 58 |
|
| 59 |
$db_env->set_flags (BDB::AUTO_COMMIT | BDB::TXN_WRITE_NOSYNC, 1); |
| 60 |
$db_env->log_set_config (BDB::LOG_AUTO_REMOVE); |
| 61 |
#$db_env->set_cachesize (0, 8 * 1024 * 1024); |
| 62 |
$db_env->set_cachesize (0, 512 * 1024); |
| 63 |
$db_env->set_lk_max_lockers (20480); |
| 64 |
$db_env->set_lk_max_locks (20480); |
| 65 |
$db_env->set_lk_max_objects (20480); |
| 66 |
|
| 67 |
mkdir "db", 0777; |
| 68 |
db_env_open |
| 69 |
$db_env, |
| 70 |
"db", |
| 71 |
BDB::INIT_LOCK | BDB::INIT_LOG | BDB::INIT_MPOOL |
| 72 |
| BDB::INIT_TXN | BDB::RECOVER | BDB::REGISTER | BDB::USE_ENVIRON | BDB::CREATE, |
| 73 |
0666; |
| 74 |
|
| 75 |
our %DB; |
| 76 |
|
| 77 |
sub table($) { |
| 78 |
my $db = $DB{$_[0]} = db_create $db_env; |
| 79 |
db_open $db, undef, $_[0], undef, BDB::BTREE, BDB::AUTO_COMMIT | BDB::CREATE, 0666; |
| 80 |
die if $!; |
| 81 |
$db |
| 82 |
} |
| 83 |
|
| 84 |
our $db_state = table "state"; # global state |
| 85 |
our $db_info = table "info"; # per torrent state |
| 86 |
|
| 87 |
our $TXN; |
| 88 |
|
| 89 |
sub get($$) { |
| 90 |
db_get $_[0], $TXN, $_[1], my $data, 0; |
| 91 |
$data # will be undef on error |
| 92 |
} |
| 93 |
|
| 94 |
sub put($$$) { |
| 95 |
db_put $_[0], $TXN, $_[1], $_[2], 0; |
| 96 |
} |
| 97 |
|
| 98 |
sub del($$) { |
| 99 |
db_del $_[0], $TXN, $_[1], 0, sub { }; |
| 100 |
} |
| 101 |
|
| 102 |
sub sget($) { |
| 103 |
get $db_state, $_[0] |
| 104 |
} |
| 105 |
|
| 106 |
sub sput($$) { |
| 107 |
put $db_state, $_[0], $_[1]; |
| 108 |
} |
| 109 |
|
| 110 |
sub iget($) { |
| 111 |
my $data = get $db_info, $_[0]; |
| 112 |
length $data ? decode_cbor $data : [] |
| 113 |
} |
| 114 |
|
| 115 |
sub iput($$) { |
| 116 |
put $db_info, $_[0], encode_cbor $_[1]; |
| 117 |
} |
| 118 |
|
| 119 |
our $syncer = AE::timer 5, 60, sub { |
| 120 |
db_env_txn_checkpoint $db_env, 0, 0, 0, sub { }; |
| 121 |
}; |
| 122 |
|
| 123 |
sub dbsync() { |
| 124 |
db_env_txn_checkpoint $db_env; |
| 125 |
} |
| 126 |
|
| 127 |
sub dbflush { |
| 128 |
return if $::dbflush_called++; |
| 129 |
db_env_txn_checkpoint $db_env, sub { }; |
| 130 |
BDB::set_sync_prepare undef; |
| 131 |
db_close $_ for values %DB; |
| 132 |
db_env_txn_checkpoint $db_env; |
| 133 |
db_env_close $db_env; |
| 134 |
} |
| 135 |
|
| 136 |
END { |
| 137 |
dbflush; |
| 138 |
} |
| 139 |
|
| 140 |
sub quit { |
| 141 |
EV::unloop; |
| 142 |
#exit 1; |
| 143 |
}; |
| 144 |
|
| 145 |
our $sigint = AE::signal INT => \&quit; |
| 146 |
our $sigterm = AE::signal TERM => \&quit; |
| 147 |
|
| 148 |
sub dic_compress($$) { |
| 149 |
my $d = new Compress::Raw::Zlib::Deflate |
| 150 |
-Level => 9, |
| 151 |
-WindowBits => -15, |
| 152 |
-Dictionary => $DICTIONARY[$_[0]], |
| 153 |
-AppendOutput => 1, |
| 154 |
; |
| 155 |
|
| 156 |
my $o; |
| 157 |
|
| 158 |
$d->deflate ($_[1], $o); |
| 159 |
$d->flush ($o); |
| 160 |
|
| 161 |
$o |
| 162 |
} |
| 163 |
|
| 164 |
sub dic_decompress($$) { |
| 165 |
my $i = new Compress::Raw::Zlib::Inflate |
| 166 |
-WindowBits => -15, |
| 167 |
-Dictionary => $DICTIONARY[$_[0]], |
| 168 |
-AppendOutput => 1, |
| 169 |
-ConsumeInput => 0, |
| 170 |
; |
| 171 |
|
| 172 |
$i->inflate ($_[1], my $o, 1); |
| 173 |
|
| 174 |
$o |
| 175 |
} |
| 176 |
|
| 177 |
############################################################################# |
| 178 |
|
| 179 |
############################################################################# |
| 180 |
|
| 181 |
sub GET { |
| 182 |
my ($data, $hdr); |
| 183 |
|
| 184 |
for (1..50) { |
| 185 |
http_get $_[0], |
| 186 |
#proxy => undef, |
| 187 |
recurse => 0, |
| 188 |
headers => { |
| 189 |
"user-agent" => "Mozilla/5.0 (X11; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0 Iceweasel/20.0", |
| 190 |
"referer" => undef, |
| 191 |
}, |
| 192 |
Coro::rouse_cb; |
| 193 |
($data, $hdr) = Coro::rouse_wait; |
| 194 |
|
| 195 |
$hdr->{Status} = 404 |
| 196 |
if $data =~ /You're looking for something that does not, has not, will not, might not or must not exist/; |
| 197 |
|
| 198 |
$hdr->{Status} = 580 |
| 199 |
if $data =~ /^(?:Upgrading software|Could not connect to caching server|Database maintenance, please check back in 10 minutes)/; |
| 200 |
|
| 201 |
$hdr->{Status} = 581 |
| 202 |
unless length $data; |
| 203 |
|
| 204 |
$data = Compress::Zlib::memGunzip $data |
| 205 |
if $hdr->{"content-encoding"} eq "gzip"; |
| 206 |
|
| 207 |
last |
| 208 |
if $hdr->{Status} < 500; |
| 209 |
|
| 210 |
Coro::AnyEvent::sleep 1.5 if $hdr->{Satus} == 503; |
| 211 |
Coro::AnyEvent::sleep 9.5 if $hdr->{Satus} == 580; |
| 212 |
|
| 213 |
Coro::AnyEvent::sleep 0.5; |
| 214 |
++$stat{"retry-$hdr->{Status}"}; |
| 215 |
|
| 216 |
# use Data::Dump; ddx $hdr;#d# |
| 217 |
} |
| 218 |
|
| 219 |
++$stat{$hdr->{Status}}; |
| 220 |
($data, $hdr) |
| 221 |
} |
| 222 |
|
| 223 |
1 |
| 224 |
|