diff options
-rw-r--r-- | misc/analiza.txt | 1 | ||||
-rw-r--r-- | misc/manjka_piece_layers.txt | 138 | ||||
-rw-r--r-- | src/dht.c | 87 | ||||
-rw-r--r-- | src/main.c | 7 | ||||
-rw-r--r-- | www/index.php | 3 | ||||
-rwxr-xr-x | www/insert.php | 132 | ||||
-rw-r--r-- | www/stanje.php | 6 |
7 files changed, 336 insertions, 38 deletions
diff --git a/misc/analiza.txt b/misc/analiza.txt new file mode 100644 index 0000000..ac2ef30 --- /dev/null +++ b/misc/analiza.txt @@ -0,0 +1 @@ +cd www; find .. -maxdepth 2 -name *.torrent | parallel ./insert.php 'mysql:host=tranzistor:3306\;dbname=travnik\;charset=utf8' travnik $TRAVNIK_DB_PASSWORD {} | tee ../tmp/insert.txt; ocd diff --git a/misc/manjka_piece_layers.txt b/misc/manjka_piece_layers.txt new file mode 100644 index 0000000..65524c8 --- /dev/null +++ b/misc/manjka_piece_layers.txt @@ -0,0 +1,138 @@ +449de98d537033333b8b906f173aeca358db2934 +44b84847f7d829225c788e161017e484526e5259 +44b2ee5bbe4c0abcc1b089d511e0aa90bdbb9d3f +449ee63fa8a383a59b2a98d7d8851c7e160674b3 +4490221a4cb0d2bcf21ff2feb011f0aaf29f47c1 +472eca9914ca5c91a435644d0e03065deaaff388 +ef1b17e8e84cb09ba0c4642c3e401d5afaf6c116 +a3838eca4a8d377946db68eb0c68e0e7fa60b6f0 +58b66fde563352e87b4a9edda7f6303fb3d51af6 +8a51ff72f85a542141ac4d5031e0d5d33e3dc552 +ca3bf9975e7fc9f3e1d28bfce1463c6590058af0 +449aae0961adca0ed412903314ec0a2268d28ae1 +b0104173e4f57a7b8f22453a616e6c07eea7e498 +8674ae9dadac02b84f79240c5d8c15b7e2754abb +20ca3b531663a6560ce4bf298270722ebd8056f5 +8aee4dac68d5890e86d926aac7a5e57191572881 +76ef0dcfcbcd4fc6eb041ec86bcbc9b84a04248f +e40fc02287941ef2b27bff81829a272e040f61bb +e5a8b4f3df8c7544b614b7e568490859ce462781 +e945fd776f2c563e8d3854033d5e71a1c344beae +e96193c0e90533a386ca103f4d893b39f7e0e604 +e92db52764d5d32425d1255cfe1bc14c17e700e4 +3b92af49f505a8d45c6e81cab6ab1ce5e9c9def2 +3dd437e15c0db9f45688e093cfa569641f5fbc86 +3ddafd52547600a28de6efc4408ae73c63742072 +a132644ccdcf09dcc3812e784165ea129720b93a +e56c512dcecd07aac2043c014c61bec934f29875 +4c85dea3d00d041f3a66e12a0ae015bc9ab8010c +3a95d8b80cad8bd441ce867ff6365046dffddc0a +3a8ccb5c5f59d491a3cc18646a83b90090606da6 +48e289b6efcc67d49b7819a1e8327fe24be08435 +5115e0b09978ba0ddd6a30a6a92fc503ae644f1d +880d2a5b3446f3bb914facbb04c9d513ec5da89e +b47fbe20899b8ef182e45f58a62edddc3bb78863 +d4b3eb8944074e1491c49a132827de6f6b4a8e97 +9690551f4adb023ba4f80d6a1df795baccc196f8 +2a6644871d12fd0c6808ee3e6501027da62a2f07 +98e1eb3e9430f0f20230bcd64deeed68181bd9d8 +b65dc2866dd108c724e84e8983560130ced8e18f +f85c7bd79be33309177eb253aa10c3ef1347eadc +b61456fe7b7ae74e9d805e584955775cbb784202 +b64abd382e298d086c4bd7a0b00ef1f11dfeccfc +7afb5e79530c742b4501b54cc71b0ab1d97f2f95 +ecabe733b93d14637d2aed1dfb0f4eb59bdb048b +efed72ead6e6fcebea4baf1ee2d19bca5be44142 +eea0ee9d789104bb5808fd69cb0555391f2b4f50 +8d0eb365a521ad9bf9156a43eddcf0ed8a689b13 +f1a61d828983a124d487acee4f2ce7e8386b718e +de4443fe31894dfd55b17e70096c1613a9a4bb9c +f274529b213f19557fa6ecfcf3cfb53c5154e526 +678a109563a19cc9ffa21708d9abc458e1d8906c +9c5d033dea8f9a3382a20c99218c7a431dfaaf6e +19e66c53c722a13cd6a82879c9e85bf88c66735a +404eb209c11aa3947d6c81300b2d29f2d26efa4f +799cf2575769406187e9e014c99a5e7f485c2a83 +319d369388f27c4c14e0259663728e8ba2e688b9 +14dec98f148ec2e6444073ae640640507381afa0 +6f9ec668b5d83d298c56682000817e33ec757b78 +bdc393a39f4e51964bf71cbaa5ac3e237928db8a +562a762c2009b0fe6726b9b5cefc141bc42a46f9 +c2c4250cb585b8a2fa71bf072ec46dcf80c88e4d +41e05f5273ccc219d36d34efb9b40e6b6a909a44 +3bf800aaf4bc9f42829af7ab5eaaa8a6d9e46469 +2713ba902590bd7e239aaffc43dc6af94c1f4ac1 +e5dfcc39b252356c4a873937abcb56be9f6988ae +4f269d8aefd647ee270842d53ec98aebd23a4afe +4e719332c00cd72d141765108d18f07311caed9d +796f60fb8cf4a5c9558df26aec62fd4b45506dcf +8d12b862405ca6e816ab59281afaba7c3b8c6381 +50e2170b4f789e248e2fc76ae5450966431fa9d1 +bd9e5ba75c9148be7adaea38034c9bb4957a3b79 +d1aefb69ec959bf839c35cd120b5c744eb1c7b1e +2c71f6db3da8086b9ad4413d325780f346052a56 +ca4e193754e04ebe9326d6de2c440a46044f48e9 +c17e87eed256ff71cb6cdd3573276a70692f3530 +bfb0310f7f3ee5221d7f64658b48e1e1e1720f5a +b235c3d96069927fd49ec099254462bb9e37a683 +7eb532b5138be534d6be4bedce93982ffb9b7358 +93aec420aa7e874668fa728ce8a7b41a177c15a4 +93a31efd4809ee94b1ace992a3538e3af0399361 +93b6f1ca54f643404f675489591f60f1f4ed7694 +e62e4b5e8be88b1be082b1f79806d283181b0335 +dd0342632a055f91560d0242717069091fb7ab9d +dcc28f5758ae29a50ed2d8c93bb8135004a1b63e +135637767239366c6781d9a31aea0040f2155f89 +506dce309921b2fa47f24a9b007f732157de00fc +63f641c833ef83759163560a3ff21d7c6ff88380 +2c3c9c5aeaa72cb9819dc6da2ba90b39047acc9d +2f898f0b36ab12e7334570080b68e6ad51cbefb9 +2dc120a7ae1032d8c70bba2b6056c5ab3f2c7fc6 +9a9488e52389eb437040bcadd3677f9eb80cae61 +88733aee0983c6c7609f17afe1378531b84660a2 +c93c8b7fe9f0bfd76a4140e65b86e5fc6a3764fe +87e90db19588e3b07d551cceb50cafe1a3a89c2a +434d5e2790bc70f97a847cadaf1fdc2a1fbc175d +2b0d7c905f2690fbc4a33d55b686382f8a8ec6ed +22ebd378d449033a2e51fdd059f8a9e0e42c55d3 +00089ff950ab5204d9e5f0d91ada337029fe3706 +23efe29e8597d103d10d1a974b6399232f14272c +006349aef773b05109fa75a2b5ce07f28883c2fa +a6f5cf3896734e455db5f2659c00c655d63db6af +89cc95b6286b5d75956d6fb182c6f34e34076e0e +59f38783e5c15ad3a2c8973de7f03fe98544898f +ac1a7de4089600b407335699d6a9623808cff54e +cf91ecc307d1edf48d3c06c3db01f952d1b6c2d1 +272888f1ff5b133518559ec10a2b7057aabeaf63 +236f4a8ae458e682f019dce0c10f87cde6f1eee8 +3ab4922c732f09b7fa242a9b21385d2bc3dd06ae +71e5bf7db68bbd172bdb52beee1a802804b62621 +7afed744cb29e68c153a49967ec9bb40059fba1f +b6e9226e972d6b3d42860efcb3b5eac64ff122cf +16952e1ca004b33cbc25857c511909fe3293ca37 +874bbb81db303ed84aa818a26adb1785184eb9c5 +91df1fa1f456a2f85efa3ff78e8a521a5e2348d7 +827044521071f0c8e26477a1f45b17456eca1ef4 +668fa7077df73b1997345bd545131e831a4e87d9 +ac045dbf9e0eb6de3061efc2021cd89eceb19bb0 +8e297385ed9f65354b7ba1691be87f1f134e881d +5303a10cfa37eb1d98cdaf391ab69cad10f4fc7e +1452653134c1f4d93ca076123452ef04b25fcb56 +ad97aadba73952b610022f4c57eb6c8aa293dfd1 +ae14bcbd9ec2c58c59a312458a91a43045061b42 +21360976daa61cd99cadde5a399a64db90f9e3d3 +2030742d6cb6c1367894cc33d32a1131953e445d +393423c857a161908a8ed6b93716c5fc1ac1079a +d38ec4a7f86831b4fc827dd7c594779efc24f0f7 +d4149bb6f1cd576c348c449ff55b10679c810499 +044376eaf3db326f077178ecff0b62d2404e7c12 +116ca329507f249bb2f2d392a1c33e321228bd5a +a156421412df34a5f0241b029ec2930e758729c0 +a1d968842cef01b80cd2b7446a5bdfe617f873f9 +acca049a0221e6ccf8b3c3a9cd213b0b5018f664 +a6a2b2d6a157f6c2fd0ca222ad475fdb2f9328f1 +a4a05eb30ccdcfad604e92cd6bb4fa945c14c81e +a4841947e26645520694e7be64d44493a7075a5b +c533c91993741c38fab0d088c14c823b2706167b +a4978bf8ffb82c45eee68bf393a7968e882f9618 +a4a377a1f4fb73f2a019ab3ca3cb53175ecc238e @@ -794,6 +794,8 @@ struct dht * dht_init (const struct bencoding * c) { #pragma GCC diagnostic pop goto e; } +#define TOOMUCH 32727 + unsigned pinged = 0; if (c) { const struct bencoding * id = bpath(c, "id"); if (id && id->type & string && id->valuelen == 20) @@ -811,7 +813,7 @@ struct dht * dht_init (const struct bencoding * c) { .sin6_family = AF_INET6, .sin6_port = htons(atoi(++port)) }; - if (inet_pton(AF_INET6, remote, addr.sin6_addr.s6_addr) == 1) + if (inet_pton(AF_INET6, remote, addr.sin6_addr.s6_addr) == 1 && pinged++ < TOOMUCH/2) ping_node(d, &addr); } } @@ -2172,6 +2174,30 @@ d: } // do not log, it may have been a bencoded reply } +/** + * delete all but first bucket in ll, used in refresh on both lls (v4 and v6) in case of sybil + * + * @param b [in] first bucket in ll + */ + +void delete_buckets (struct bucket * b) { + struct node * n = b->nodes; + while (n) { + struct node * old = n; + n = n->next; + node_free(old); + } + b->nodes = NULL; + memset(b->id, '\0', 20); + struct bucket * del = b->next; + b->next = NULL; + while (del) { + struct bucket * old = del; + del = del->next; + bucket_free(old); + } +} + #define PERIODIC 10 /** @@ -2214,33 +2240,10 @@ int refresh (struct dht * d, int fam) { if (buckets > 64) { // sybil attack - node is broken - clear whole routing table, keeping one bucket dht_print(d->log, d); L(disagreement, d, "@@@@@@ SYBIL ATTACK - CLEARING ROUTING TABLE @@@@@@"); - int keep_first = rand() % 2; // should we even keep one bucket? the sybil node has a 1/2 - if (keep_first) { // chance of having stared in the bucket farthest away, so it's stored there ... - memset(d->buckets->id, '\0', 20); - b = d->buckets->next; - d->buckets->next = NULL; - while (b) { - bucket_free(b); - b = b->next; - } - } else { - b = d->buckets; - while (b->next) { - struct bucket * old = b; - b = b->next; - bucket_free(old); - } - d->buckets = b; - memset(d->buckets->id, '\0', 20); - } + delete_buckets(d->buckets); + delete_buckets(d->buckets6); if (getrandom(d->id, 20, GRND_NONBLOCK) == -1) // changing our ID. note that this might make - L(std_fail, d, "getrandom: %s", strerror(errno)); // existing nodes hate us - switch (fam) { - case AF_INET: - return node_count(d->buckets6->nodes); - case AF_INET6: - return node_count(d->buckets6->nodes); - } + L(std_fail, d, "getrandom: %s", strerror(errno)); // existing nodes hate us, though we'll probably have no existing nodes return 0; } return nrgood; @@ -2337,25 +2340,36 @@ void periodic (struct dht * d) { if (t->type & (peers | announce)) { struct node * n = t->nodes; int sent = 0; - while (n) { - sent++; + int c = node_count(n); + if (c) + c = rand() % c; + while (n && c--) + n = n->next; + if (n && sent < 3) { // we pick some consecutive at random and ping them. + sent++; // increase to more than this if desired ... idk this is shit if (!n->unanswered) n->last_sent = seconds(); n->unanswered++; get_peers(d, &n->addr, t->hash); n = n->next; + if (!n && !t->nodes->unanswered) // if unanswered, we already sent it + n = t->nodes; } - if (sent < 1) { + if (sent < 2) { #define RTGP(buckets) {struct bucket * b = d->buckets; \ find(t->hash, &b, NULL); \ struct node * n = b->nodes; \ - while (sent < 1 && n) { \ + int c = node_count(n); \ + if (c) \ + c = rand() % c; \ + while (n && c--) \ + n = n->next; \ + if (n) { \ sent++; \ if (!n->unanswered) \ n->last_sent = seconds(); \ n->unanswered++; \ get_peers(d, &n->addr, t->hash); \ - n = n->next; \ }} RTGP(buckets); RTGP(buckets6); @@ -2364,13 +2378,17 @@ void periodic (struct dht * d) { struct bucket * b = d->buckets; while (sent < 1 && b) { n = b->nodes; - while (sent < 1 && n) { + int c = node_count(n); + if (c) + c = rand() % c; + while (n && c--) + n = n->next; + if (sent < 1 && n) { sent++; if (!n->unanswered) n->last_sent = seconds(); n->unanswered++; get_peers(d, &n->addr, t->hash); - n = n->next; } b = b->next; } @@ -2435,7 +2453,6 @@ void periodic (struct dht * d) { t = t->next; } L(debug, d, "txqp=%u rxrp=%u rxqp=%u txrp=%u", d->txqp, d->rxrp, d->rxqp, d->txrp); -#define TOOMUCH 32727 if (d->txqp > TOOMUCH || d->rxrp > TOOMUCH || d->rxqp > TOOMUCH || d->txrp > TOOMUCH) { dht_print(stdout, d); raise(SIGABRT); @@ -45,7 +45,7 @@ void found_torrent (struct dht * d __attribute__((unused)), const unsigned char L(debug, d, "%s%s", buf, t ? " stored" : " new"); if (t) { if (!t->type) - t->ttl = seconds()+128; + t->ttl = seconds()+256; t->type |= info | peers; } else { if (last_added + 1 > seconds()) { @@ -56,7 +56,7 @@ void found_torrent (struct dht * d __attribute__((unused)), const unsigned char t = torrent_init(); memcpy(t->hash, h, 20); t->type |= info | peers; - t->ttl = seconds()+128; + t->ttl = seconds()+256; add_torrent(d, t); } } @@ -135,6 +135,7 @@ int main (int argc, char ** argv) { struct torrent * torrent = torrent_init(); memcpy(torrent->hash, "\xdd\x82\x55\xec\xdc\x7c\xa5\x5f\xb0\xbb\xf8\x13\x23\xd8\x70\x62\xdb\x1f\x6d\x1c", 20); torrent->type = /* (useless, since we have no listening system yet) announce | */ peers | info; + torrent->ttl = seconds()+128; /**< idk, enough to bootstrap i guess */ add_torrent(dht, torrent); periodic(dht); // alarm(PERIODIC); @@ -143,6 +144,7 @@ w: if (sigusr1) { sigusr1 = 0; dht_print(stdout, dht); + fflush(stdout); goto w; } if (periodično) { @@ -160,6 +162,7 @@ w: if (sigusr1) { sigusr1 = 0; dht_print(stdout, dht); + fflush(stdout); goto w; } if (periodično) { diff --git a/www/index.php b/www/index.php index e37fe7f..96f0f8f 100644 --- a/www/index.php +++ b/www/index.php @@ -5,8 +5,9 @@ ?> <meta charset=UTF-8 /> <meta name=viewport content='width=device-width, initial-scale=1.0'> -<h1>število datotek: <?= shell_exec("find .. -name '*.torrent' | wc -l") ?></h1> +<h2>število datotek: <?= shell_exec("find .. -name '*.torrent' | wc -l") ?></h2> <h2><a href=list.php>seznam</a></h2> +<h2><a href=stanje.php>stanje</a></h2> <h2>iskalnik</h2> <form> <input name=i value="<?= !empty($_REQUEST["i"]) ? htmlspecialchars($_REQUEST["i"]) : "" ?>" /> diff --git a/www/insert.php b/www/insert.php new file mode 100755 index 0000000..4fa8e59 --- /dev/null +++ b/www/insert.php @@ -0,0 +1,132 @@ +#!/usr/bin/php +<?php +require_once "vendor/autoload.php"; +use Rhilip\Bencode\TorrentFile; +use Rhilip\Bencode\ParseException; +if ($argc != 5) { + echo "uporaba: $argv[0] 'mysql:host=tranzistor:3306;dbname=travnik;charset=utf8' travnik " . '$TRAVNIK_DB_PASSWORD datoteka.torrent' . PHP_EOL; + exit(1); +} +$t = TorrentFile::load($argv[4]); +$c = new PDO($argv[1], $argv[2], $argv[3]); +$c->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +try { + $s = $c->prepare("SELECT COUNT(1) FROM torrenti WHERE zgoščena_vrednost=:z"); + $s->bindParam(":z", $zgoščena_vrednost); + $zgoščena_vrednost = $t->getInfoHashV1(true); + $s->execute(); +} catch (PDOException $e) {} +if ($s->fetchColumn()) { + echo "torrent je že shranjen v podatkovni zbirki" . PHP_EOL; + exit(0); +} +try { + $c->exec("CREATE TABLE IF NOT EXISTS torrenti ( + zgoščena_vrednost BINARY(20) NOT NULL PRIMARY KEY, + " /* . "id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL COMMENT 'samo za lažje ročno navigiranje po podatkovni zbirki, pravi ključ je zgoščena vrednost', " */ . " + pridobljeno TIMESTAMP NOT NULL, + velikost_metainfo INT UNSIGNED NOT NULL COMMENT 'sem se štejejo tudi informacije, ki jih doda travnik, recimo created by, datum izdelave, vir in odjemalec. to ni le velikost info slovarja, vendar je striktno večja, saj je velikost celotne torrent datoteke.', + velikost_koščka INT UNSIGNED NOT NULL, + izvor VARBINARY(4096), + ime VARBINARY(4096), + ip BINARY(16) NOT NULL, + vrata SMALLINT UNSIGNED NOT NULL, + odjemalec VARCHAR(4096) + )"); + $c->exec('CREATE TABLE IF NOT EXISTS datoteke ( + id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + torrent BINARY(20) NOT NULL, + FOREIGN KEY (torrent) REFERENCES torrenti (zgoščena_vrednost), + pot VARBINARY(4096) NOT NULL, + velikost BIGINT NOT NULL + )'); + $c->beginTransaction(); // glej php.net/manual/en/pdo.begintransaction.php + $s = $c->prepare("INSERT INTO torrenti ( + zgoščena_vrednost, + pridobljeno, + velikost_metainfo, + velikost_koščka, + izvor, + ime, + ip, + vrata, + odjemalec + ) VALUES ( + :z, + :pridobljeno, + :velikost_metainfo, + :v, + :izvor, + :ime, + INET6_ATON(:ip), + :vrata, + :odjemalec + )"); + $s->bindParam(":z", $zgoščena_vrednost); + $s->bindParam(":pridobljeno", $pridobljeno); + $s->bindParam(":velikost_metainfo", $velikost_metainfo); + $s->bindParam(":v", $velikost_koščka); + $s->bindParam(":izvor", $izvor); + $s->bindParam(":ime", $ime); + $s->bindParam(":ip", $ip); + $s->bindParam(":vrata", $vrata); + $s->bindParam(":odjemalec", $odjemalec); + $pridobljeno = date("Y-m-d H:i:s", $t->getCreationDate()); + $velikost_metainfo = filesize($argv[4]); + $velikost_koščka = $t->getPieceLength(); + $izvor = $t->getSource(); + if (strlen($izvor) > 4096) + echo "$argv[4] izvor $izvor daljši od 4096"; + $ime = $t->getName(); + if (strlen($ime) > 4096) + echo "$argv[4] ime $ime daljše od 4096"; + if (!isset($t->getRootData()["source"])) { + echo "$argv[4] nima source ključa" . PHP_EOL; + exit(4); + } + $ip = explode("/", $t->getRootData()["source"]["ip"])[0]; + $vrata = intval(explode("/", $t->getRootData()["source"]["ip"])[1]); + if (isset($t->getRootData()["source"]["v"])) + $odjemalec = $t->getRootData()["source"]["v"]; + $s->execute(); + function p ($k, $v, $p) { + global $c, $zgoščena_vrednost; + // if (preg_match("/padding.file/i", $k)) + // return; + if (is_array($v)) { + foreach ($v as $ke => $va) + p($ke, $va, $p . $k . "/"); + } else { + $s = $c->prepare("INSERT INTO datoteke ( + torrent, + pot, + velikost + ) VALUES ( + :torrent, + :pot, + :velikost + )"); + $s->bindParam(":torrent", $zgoščena_vrednost); + $s->bindParam(":pot", $pot); + $s->bindParam(":velikost", $velikost); + $pot = $p . $k; + if (strlen($pot) > 4096) + echo "$argv[4] pot $pot daljša od 4096"; + $velikost = $v; + $s->execute(); + } + } + try { + foreach ($t->getFileTree() as $k => $v) + p($k, $v, ""); + } catch (ParseException $e) { + echo "neveljaven metainfo $argv[4]: " . $e->getMessage() . PHP_EOL; + exit(5); + } + $c->commit(); +} catch (PDOException $e) { + echo "sql napaka pri $argv[4]: " . $e->getMessage() . PHP_EOL; + $c->rollback(); + exit(2); +} +$c = null; diff --git a/www/stanje.php b/www/stanje.php new file mode 100644 index 0000000..da429e1 --- /dev/null +++ b/www/stanje.php @@ -0,0 +1,6 @@ +<pre> +<?php + shell_exec("echo > ../tmp/stanje.txt && sleep 1 && pkill -sigusr1 travnik"); + sleep(1); + echo file_get_contents("../tmp/stanje.txt"); +?> |