Torrent-файл. Что же у него внутри?

    Введение


    image
    Добрый день.
    Использую, как и многие, крупный торрент-трекер — rutracker.org, однако есть одна особенность которая меня раздражает.
    Это добавление в список трекеров адреса ix*.rutracker.net, который служит для непонятных мне целей. Однако который часто (у меня — практически всегда) выдаёт ошибки (502 Bad Gateway и 0 No Response). Торрент-клиент (у меня Transmission) помечает торрент сломанным. Что само собой довольно сильно мне мешает. Особенно если учесть особенность Transmission — она задаёт статус торрента по последнему ответу трекера. То есть опрашиваем ix*, он возвращает ошибку, торрент помечается как Broken, через n минут/секунд опрашивается следующий трекер из списка — bt*.rutracker.org или retracker.local, которые возвращают успешный код и торрент снова становится нормальным. Такая чехарда не особо меня радует.

    Решение банально — убрать этот нехороший адрес из списка. Однако файлов у меня много, из каждого вручную вырезать совсем не хочется, да и дополнительное действие при добавлении нового торрента выполнять тоже не было никакого желания. Поэтому принял решение разобраться в формате и автоматизировать удаление трекера из списка.

    Bencode



    Именно так называется формат кодирования данных в .torrent-файлах. Больше он почти нигде и не используется, мне попадался он на глаза так же в формате хранения resume-информации в Transmission.
    Для большинства актуальных языков написаны библиотеки для работы с этим форматом, но не для C++, да, конечно, есть такая штука, но это чистый Си и кроме того форма представления мне не показалась удачной, поэтому написал простенький свой велосипед, ибо формат крайне прост.

    Описываются 4 типа данных — массив байт, число, список, ассоциативный массив.

    Пойдем по порядку:
    • Числа задаются в форме i<последовательность цифр>e, <последовательность цифр> — это цифры в ascii представлении, то есть 1 задаётся как '1' или 0x31. Заметно что так мы можем задавать огромные числа, которые не влезут ни в long, ни в long long, однако большинство пренебрегают отсутствием лимита и используют 64-битные числа.
    • Массив байт — <длина массива>:<сам массив>. Длина массива так же формируется неограниченной последовательностью цифр.
    • Список — l<элемeнты списка>e. Элементом может являться любой из типов данных. В том числе и вложенный список. Конец, как видно из формата, отмечается литералом 'e'.
    • Ассоциативный массив — d<элемeнты массива>e. Каждый элемент массива выглядит таким образом — <массив байт><элемент>. Массив байт — это имя записи в форме из пункта 2. Элемент опять же может быть любым — список, массив, ассоциативный массив, число.


    Это всё. Сам файл это последовательность таких записей. Поэтому декодирование крайне просто выполняется:
    void CTorrentFile::ReadBencElement(ifstream & fin, tree <BencElement>::pre_order_iterator & parent, 
                                       string name)
    {
        BencElement el;
        char c = fin.get();
        el.name = name;
        if (c == 'i')
        {
            el.type = BencInteger;
            fin >> el.integer;
            m_tree.append_child(parent, el);
        } else if (c == 'l')
        {
            int l = fin.peek();
            el.type = BencList;
            tree <BencElement>::pre_order_iterator it = m_tree.append_child(parent, el);
            while (l != 'e')
            {
                ReadBencElement(fin, it, string(""));
                l = fin.peek();
            }
            fin.seekg(1, ios_base::cur);
        } else if (c == 'd')
        {
            int l = fin.peek();
            el.type = BencDict;
            tree <BencElement>::pre_order_iterator it = m_tree.append_child(parent, el);
            while (l != 'e')
            {
                string name;
                int len;
                fin >> len;
                fin.seekg(1, ios_base::cur);
                while (len--)
                {
                    char s = fin.get();
                    name += s;
                }
                ReadBencElement(fin, it, name);
                l = fin.peek();
            }
            fin.seekg(1, ios_base::cur);
        } else if (c >= '0' && c <= '9')
        {
            fin.seekg(-1, ios_base::cur);
            int len;
            el.type = BencString;
            fin >> len;
            el.bstr.len = len;
            // skip ':'
            fin.seekg(1, ios_base::cur);
            el.bstr.byteStr = new char[len + 1];
            for (int i = 0; i < len; i++)
            {
                char s = fin.get();
                el.bstr.byteStr[i] = s;
            }
            el.bstr.byteStr[el.bstr.len] = 0;
            m_tree.append_child(parent, el);
        }
    }


    Кодирование тоже несложно:
    void CTorrentFile::WriteBencElement(std::ofstream & fout, tree <BencElement>::sibling_iterator & el)
    {
        tree <BencElement>::sibling_iterator it;
        switch (el->type)
        {
            case BencInteger:
                fout << 'i' << el->integer << 'e';
                break;
            case BencString:
                fout << el->bstr.len << ':';
                fout.write(el->bstr.byteStr, el->bstr.len);
                break;
            case BencList:
                fout << 'l';
                it = m_tree.child(el, 0);
                for (size_t i = 0; i < m_tree.number_of_children(el); i++, ++it)
                    WriteBencElement(fout, it);
                fout << 'e';
                break;
            case BencDict:
                fout << 'd';
                tree <BencElement>::sibling_iterator it = m_tree.child(el, 0);
                for (size_t i = 0; i < m_tree.number_of_children(el); i++, ++it)
                {
                    fout << it->name.length() << ':' << it->name.c_str();
                    WriteBencElement(fout, it);
                }
                fout << 'e';
                break;
        }
    }


    Структура .torrent-файла.



    Как я уже писал выше для кодирования используется Bencode.
    Стоит добавить что если массив байт может быть интерпретирован как строка (имена элементов в ассоциативном массиве, просто строковые поля), то используется кодировка utf-8.

    Содержимое является одним большим ассоциативным массивом со следующими полями:
    • info — вложенный ассоциативный массив который собственно и описывает файлы, которые передаёт торрент.
    • announce — URL для трекера. Наряду с info является обязательным полем, всё остальное — опционально.
    • announce-list — список трекеров, если их несколько. В Bencode-виде — список списков.
    • creation date — дата создания. UNIX Timestamp.
    • comment — текстовое описание торрента. rutracker.org хранит здесь ссылку на тему форума.
    • created by — говорит нам о том, кем создан данный торрент.


    Необходимо упомянуть то, что файлы представлены в протоколе кусками. То есть файлы содержащиеся в торренте объединены в единый массив, и затем этот массив разделили на относительно небольшие кусочки. В таком виде данные обрабатывает BitTorrent-протокол.

    Ассоциативный массив info состоит из:
    • piece length — размер одного кусочка — 512 килобайт, 1 метр, и так далее. Слишком большое число кусков будет «раздувать» .torrent-файл.
    • pieces — строка, которая содержит конкатенацию SHA1-хешей, описывающих каждый кусочек. Длина этой строки равна 20 * количество кусков.
    • name — рекомендательное имя файла (если файл один) или директории. Увы многие торрент-клиенты воспринимают это как аксиому.
    • length — если файл один, то будет задано это поле, которое содержит длину файла.
    • files — если файлов несколько, то появится список ассоциативных массивов.


    Формат элементов списка files:
    • length — длина файла.
    • path — список из строк, которые задают путь. Каждая строка — элемент пути, относительно корневой директории торрента. Для пути a/b/c/d.jpg будет 4 строки в данном списке — ['a', 'b', 'c', 'd.jpg'].


    В общем-то это всё.
    Нам в данный момент нужно только одно поле — announce-list. Пробегаясь по этому списку находим неугодный трекер и вырезаем его:
    int CTorrentFile::RemoveTracker(const char * mask)
    {
        int deletedCount = 0;
        tree <BencElement>::pre_order_iterator root = m_tree.child(m_tree.begin(), 0);
        tree <BencElement>::sibling_iterator it = m_tree.child(root, 0);
        for (size_t i = 0; i < m_tree.number_of_children(root); i++, ++it)
        {
            if (it->type == BencString && !it->name.compare("announce") && it->bstr.len > 0 && 
                it->bstr.byteStr)
            {
                if (wildcardMatch(it->bstr.byteStr, mask))
                {
                    it->bstr.len = 0;
                    it->bstr.byteStr[0] = 0;
                    deletedCount++;
                }
            } else if (it->type == BencList && !it->name.compare("announce-list"))
            {
                tree <BencElement>::sibling_iterator trackerList = m_tree.child(it, 0);
                for (size_t j = 0; j < it.number_of_children(); j++)
                {
                    if (trackerList->type != BencList)
                    {
                        ++trackerList;
                        continue;
                    }
                    tree <BencElement>::sibling_iterator tracker = m_tree.child(trackerList, 0);
                    for (size_t k = 0; k < trackerList.number_of_children(); k++)
                    {
                        if (tracker->type != BencString || tracker->bstr.len <= 0 || 
                            !tracker->bstr.byteStr)
                        {
                            ++tracker;
                            continue;
                        }
                        if (wildcardMatch(tracker->bstr.byteStr, mask))
                        {
                            tracker = m_tree.erase(tracker);
                            deletedCount++;
                        } else
                            ++tracker;
                    }
                    if (trackerList.number_of_children() == 0)
                        trackerList = m_tree.erase(trackerList);
                    else
                        ++trackerList;
                }
            }
        }
        return deletedCount;
    }


    Скомпонуем всё в один исходник:
    Скачать — кроссплатформенный (win + *nix), нужен boost::filesystem.

    Пользоваться просто:
    torrentEditor <имя_файла> <шаблон>, где шаблон — это wildcard-строка ('*' и '?'), для моего случая — http://ix*rutracker.net/*
    Если в качестве имени файла подставить имя директории, то будет совершен рекурсивный обход по этой директории и модификация *.torrent файлов.
    Бэкап для <имя>.torrent сохраняется в <имя>.old.

    Демоны и watch-directory.



    Таким образом мы можем пробежаться по существующим .torrent-файлам и вырезать трекер, однако что делать с новыми файлами?
    Я использую удобную штуку — watch directory. Кидаем туда .torrent и клиент обнаружив его в этой папке, сам автоматически добавит его к себе.
    Однако мне совсем не хочется предварительно вырезать трекер, а желаю автоматизировать это дело.
    Поэтому написал простенький демон, который мониторит собственную watch directory, удаляет трекер и кидает файл в watch directory торрент-клиента.
    Для меня как пользователя абсолютно ничего не поменялось, кидаю файлы в ту же папку, получаю на выходе торрент в клиенте.

    Демона пишем на Си с использованием замечательной штуки — inotify,
        notifyDesc = inotify_init();
        if (notifyDesc < 0)
            exit(EXIT_FAILURE);
        watchDesc = inotify_add_watch(notifyDesc, argv[1], IN_CREATE);
        if (watchDesc < 0)
            exit(EXIT_FAILURE);
        // endless loop
        while (1)
        {
            processEvents(notifyDesc, argv[2], argv[3], argv[1]);
        }


    Инициализируем модуль с помощью inotify_init(), затем добавляем директорию для слежения inotify_add_watch(), нас интересует только создание файла, поэтому указываем флажок IN_CREATE. А затем крутим бесконечный цикл слежения за директорией.
    static void processEvents(int wd, char * moveDir, char * pattern, char * watchDir)
    {
        #define BUF_SIZE    ((sizeof(struct inotify_event) + FILENAME_MAX) * 10)
    
        int len, i = 0;
        char buf[BUF_SIZE];
        
        // blocked read, we wake up when directory changed
        len = read(wd, buf, BUF_SIZE);
        while (i < len)
        {
            struct inotify_event * ev;
            
            ev = (struct inotify_event *)&buf[i];
            processNewFile(ev->name, moveDir, pattern, watchDir);
            i += sizeof(struct inotify_event) + ev->len;
        }
    }

    Блокирующий вызов read() вернёт нам управление как только произойдут нужные нам изменения в одной из директорий, за которыми следим. Таким образом мы абсолютно не грузим процессор во время ожидания.
    Сама обработка файла не представляет из себя ничего интересного — пара вызовов rename() и один вызов system().

    Демонизация тоже стандартна:
        // create child-process
        pid = fork();
        // error?
        if (pid < 0)
            exit(EXIT_FAILURE);
        // parent?
        if (pid > 0)
            exit(EXIT_SUCCESS);
        // new session for child
        sid = setsid();
        if (sid < 0)
            exit(EXIT_FAILURE);
        // change current directory
        if (chdir("/") < 0)
            exit(EXIT_FAILURE);
        // close opened descriptors
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);


    Исходник.
    Поделиться публикацией
    Комментарии 56
      +24
      Помоему пропущен важный шаг: выяснить, что это за адрес, зачем туда стучится клиент, и к каким последствия приведет его вырезание.
        0
        Последствий никаких, без него качается нормально. Один из адресов должен использоваться внутри локальной сети для поиска локальных пиров, но не во всех сетях есть такие трекеры. А что делает другой адрес — для меня осталось загадкой, возможно это дублирующий трекер, на случай подения первого.
          +9
          Все должны помнить историю с отбиранием домена torrents.ru
          Помню даже была тема по массовому добавлению анонса bt*.rutracker.org ко всем раздаваемым торрентам, чтоб трекер работал и учитывал отдачу.

          Так вот, два анонс урла в зонах .org и .net нужны чтобы при проблемах с одним из них, по второму бы все уже скаченные и раздаваемые торренты работали бы.
            0
            А разве поиск локальных пиров идет не через retracker.local/announсe?
              +8
              retracker.local — это ретрекер, который используется для поиска локальных пиров (разумеется, при условии, что в вашей локальной сети поднят некий ретрекер, и на DNS-сервере в локальной сети поднята зона local и в ней прописана запись retracker.local, которая указывает на этот сервер с ретрекером).

              А ix*retracker.net, как я понял, это тоже ретрекер, но он используется, как и сам трекер bt*.retracker.org, для поиска внешних пиров в инете. В отличие от трекера он не учитывает статистику файлообмена, а просто помогает пирам найти лруг-друга. В мирное время он просто разгружает сам трекер. А в случае блокировки регистратором доменного имени (как было с torrents.ru) позволит пирам продолжать файлообмен.
                0
                Спасибо за объяснение.
                0
                Я про него и говорил, рутрекер отдает 3 трекера в раздаче — главный, ix и локальный.
                  +46
                  Кстати, по поводу имени retracker.local и соответственно DNS-зоны .local на DNS-сервере в локальной сети.
                  Я категорически против, чтобы для внутрилокальных bittorrent-ретрекеров в torrent-файл добавлялся такой announce-URL. Т.е. я не против добавления туда URL ретрекера вообще, но просто имя (а точнее зону) для этого универсального локального ретрекера следовало выбрать другое. Сделали бы имя в некой зоне bittorrent (например, retracker.bittorrent) или в зоне retracker (bittorrent.retracker) или ещё в какой-то уникальной нигде не зарезервированной зоне. Но имя в зоне .local выбрали совершенно напрасно.

                  И очень жаль, что администраторы rutracker.org (torrents.ru) повелись на это предложение. А глядя на них администраторы ряда других трекеров сделали так же, а администраторы локальных сетей создали зону .local с этой записью в локальных DNS.

                  Проблема в том, что зона .local в протоколах разрешения имён уже была ранее зарезервирована совсем для других целей.
                  В реализациях технологии Zeroconf от Apple (Bonjour) и в реализациях этой технологии, используемой в Linux/BSD, (Avahi) для разрешения имён хостов и сервисов в локальной сети без DNS-сервера используется связка протоколов mDNS (multicast DNS) и DNS-SD. И в протоколе mDNS как раз зарезервировано, что имена хостов в некой псевдо-зоне .local должны разрешаться клиентами не через классические запросы к DNS-серверу, а именно мультикастом по протоколу mDNS. И клиенты с Mac OS X, Linux и *BSD именно так и поступают, если у них установлена поддержка Bonjour (Mac OS X) или Avahi (у всех десктопных дистрибутивов Linux она точно есть).

                  В итоге получается явный конфликт. С одной стороны записи *.local прописаны на DNS-серверах в локальной сети и администраторы сети предполагают, что эти имена будут разрешаться именно через DNS. А с другой стороны ряд клиентов в сети используют протокол mDNS, который предполагает разрешение имён *.local мультикастовыми mDNS-запросами, а вовсе не через DNS-сервер.

                  И чтобы Linux-клиенты научились разрешать имена хостов вида *.local не только через mDNS, но и через обычные DNS-запросы к DNS-серверу, во многих Linux-дистрибутивах (в частности Ubuntu и openSUSE) приходится делать ручные манипуляции по редактированию конфиг-файла /etc/nsswitch.conf и удалению оттуда фрагмента [NOTFOUND=return] в строке hosts:. Только после этого эти Linux-клиенты начинают находить в локальной сети сервер retracker.local, прописанный в torrent-файлах и на внутрисетевом DNS-сервере в зоне .local.

                  Windows-клиентам на этот конфликт с использованием зоны .local, конечно, насрать. У Microsoft, как обычно, своя реализация технологии Zeroconf, называемая APIPA (Automatic Private IP Addressing), а для разрешения имён там используется не mDNS, а свой протокол LLMNR (Link-local Multicast Name Resolution), в котором не зарезервирована зона .local для разрешения имён локальных хостов. Поэтому для Windows нет конфликта, связанного с использованием зарезервированной зоны .local.

                  Но всё же при принятии решения о выборе универсального имени для локальных ретрекеров следовало учесть не только Windows-клиентов, но и прочие реализации и зарезервированные для них зоны.
                    +2
                    Спасибо.
                      +2
                      Ага, у меня ubuntu каждый раз при загрузке напоминает об отключении службы avahi из-за зоны .local.
                        +6
                        > А глядя на них администраторы ряда других трекеров сделали так же, а администраторы локальных сетей создали зону .local с этой записью в локальных DNS.

                        Такие администраторы локальных сетей — идиоты. Создавать надо не хост retracker в зоне local, а сразу _зону_ retracker.local., тогда она не будет конфликтовать с Zeroconf/Avahi
                          +2
                          Я, помню, еще когда торрентс.ру это вводили, писал на форуме про это. Что придумали имя, не подумав головой, положив болт на всех, кроме Windows. Комментарии были в стиле «macos? linux? что это? вот еще, греть голову из-за нескольких %%».

                          От души пожелал им, чтобы в одно прекрасное утро к их винде приехал update, после которого windows-клиенту тоже понадобится зона .local :)

                          Причем писал ведь и про то, что надо хотя бы инструкцию поправить, для тех админов, которые не включают голову, а будут тупо копипастить. Чтобы, как пишут выше, создавалась в fake dns не зона .local и в ней хост retracker. А сразу зона rettracker.local с доменной A записью. Тогда хоть убунты не станут ругаться при каждом логине и т.п.

                          Пофигу. Деревянные.
                          +5
                          > А разве поиск локальных пиров идет не через retracker.local/announсe?

                          Также можно добавить, что поиск локального bittorrent-трекера/ретрекера (а потом через него и пиров в локальной сети) возможен и без добавления announce-URL этого ретрекера во все torrent-файлы.
                          Существует расширение BitTorrent-протокола BEP-0022, которое позволяет автоматически искать адрес локального bittorrent-ретрекера в DNS через специальную SRV-запись, созданную там. Для этого bittorrent-клиент должен поддерживать эту фичу, а также администратор локального DNS-сервера должен добавить туда соответствующую SRV-запись для локального ретрекера.

                          Ну и всякие механизмы DHT, Local Peer Discovery и Peer Exchange, которым для поиска/получения списка пиров не нужен ни локальный ретрекер, ни DNS.
                        0
                        Есть предположение что это резервный домен, на случай если rutracker.org «умрет».
                        В случае «утери» домена rutracker.org не составит труда поднять трекер на rutracker.net. В раздачах он уже вбит, значит с сидерами после смены домена, проблем не будет.
                        0
                        В единственном треде на форуме что я нашёл — rutracker.org/forum/viewtopic.php?t=2833412, ничего нет информативного.
                        Ошибки есть у всех, у кого я узнавал, поэтому моё мнение таково, что что-то планировали сделать, но не срослось, и сейчас сервис не функционирует.
                          0
                          > Это добавление в список трекеров адреса ix*.rutracker.org, который служит для непонятных мне целей.

                          А вы ничего не путаете?
                          У меня у torrent-файлов, скачанных с rutracker.org в качестве трекера указан либо
                          http://bt*.rutracker.org/ 
                          либо
                          http://ix*.rutracker.net/

                          Домены-то разные (.net и .org). И тот и другой трекер работают в битторрент-клиенте без ошибок.
                            0
                            Ошибка в статье, именно про ix*.rutracker.net я и говорю.
                            У меня оба этих трекера присутствуют в каждом скачанном .torrent-файле.
                              0
                              Ну т.е. в торрентах прописаны-то оба трекера, просто иногда в разном порядке. И любой из них откликается, и не даёт ошибок в bittorrent-клиенте.
                              +21
                              А просто добавить запись в hosts, указываюшую на rutracker?
                                +3
                                думал об этом, но есть несколько причин почему отказался:
                                1. Изучение протокола позволит решать ряд других задач, например, автоматизация смены трекера (torrents.ru -> rutracker.org), или добавление нового. Поэтому в плане опыта лучше разобраться что к чему.
                                2. Не знаю как вы, но я нередко забываю о модификациях hosts/dns, и поэтому возможно множество факапов в дальнейшем — например, банальная смена пасскея.
                                3. Я не знаю механизмов работы торрент-клиента, поэтому вполне возможно что он будет посылать в 2 раза больше запросов, чем нужно.

                                Возможно это напоминает — «давайте потратим 8 часов сейчас, что бы когда-нибудь сэкономить 2 раза по 5 секунд». Но надеюсь что это не так :)
                                  0
                                  или в конфиг dnsmasq
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    То есть, если взять ресурс типа isohunt, где в каждом терренте прописано много трекеров, и некоторые всегда оказываются недоступны, transmission будет его всегда помечать сломанным?
                                      –1
                                      Помечает и еще мигать начинает, нормальный-сломанный. Так делают многие клиенты, тот же uTorrent, но продолжают качать через работающие источники, например DHT.
                                        +12
                                        странно, utorrent обычно вполне доволен и молча качает, если хотя бы один трекер из списка работает.
                                        0
                                        не всегда, где-то примерно (60 * count of unavailable)/count of trackers процентов времени.
                                        +9
                                        Или вариант №2 — исправить transmission
                                          0
                                          Что то я никогда за transmission такого не замечал (по крайней мере в мак версии), а под линуксом я таких проблем сроду не видел, сколько не сижу и не качаю :) Может лучше баг-репорт разрабам послать? Это будет выглядеть логичнее мне кажется.
                                            –1
                                            я не считаю что это баг.
                                            имхо, правильно помечать то что торрент сломан, когда хотя бы один из трекеров вернул ошибку.
                                            По-крайне мере если трекеров 2 — URL источника (bt*.rutracker.org, например) + retracker.local.
                                            То при возникновении ошибки (например Unregistered torrent), мы сразу увидим это.
                                              0
                                              Я вообще если честно слабо понимаю о чём речь. Я этого никогда не наблюдал. Вот что у меня делюг например говорит
                                              Status:
                                              rutracker.org: Анонс успешен
                                              Трекер:
                                              bt3.rutracker.org/ann?uk=1NP1VrIWfC
                                              Пока я в редактор трекеров не залезу я и не знаю что их там 3 штуки вообще.
                                                0
                                                image
                                                image
                                                  +3
                                                  Ну 2 из 3 трекера работают — что ему панику то наводить? ИМХО баг
                                                    0
                                                    если бы он панику не наводил то отслеживать _реальные_ проблемы с трекером было бы сложно.
                                                      +6
                                                      Остальные 2 работают? Информацию передают? Всё качается, статистика учитывается? Значит всё ок — пусть молчит.
                                                        0
                                                        а если в списке окажется только retrecker.local?
                                                        а остальные 2 отвалятся?
                                                        ну или retrecker.local + ix*, который не учитывает статистику.
                                                        Технически практически нереально определить «важность» трекера. Поэтому вывод из строя любого из списка должен сигнализировать, ибо вдруг этот вышедший и является самым главным, а остальные, рабочие, — просто заглушки.
                                                          0
                                                          Должен сигнализировать, но не тем же способом, что и в случае отказа всех. Оранжевым цветом, дополнительным значком и т.д.
                                                    +1
                                                    Вас тоже касается =)
                                                      +1
                                                      черт, кто-то уже скачал «Покемон: Возвращение Мьюту» и «Китай изнутри» :)
                                                    +3
                                                    Товарищ KorP у тебе щас паскей стырят! :)
                                                    Вот он твой 1NP1VrIWfC

                                                    Как возьму и скачаю что-нить от твоего аккаунта, будешь знать! :)
                                                      0
                                                      Можно очень сильно не переживать, это ж рутрекер, а не порнолаб :)
                                                        0
                                                        Это мой не основной аккаунт просто. Этим аккаунтом только мой сервак пользуется :) А за счёт того что я его натренировал самостоятельно следить за обновляемыми раздачами, которые мне интересны — он при обновлении торрента оказывается всегда в первой десятке раздающих, отсюда высокий рейтинг и никаких переживаний :)
                                                          0
                                                          На рутрекере фрилич
                                                          0
                                                          Вы сейчас спалили свой passkey (uk=). Теперь можно добавить на скачку любой торрент с рутрекера, в редактировании трекеров указать ваш passkey, и всё скачанное будет засчитываться вам. Вы можете зайти в профиль на рутрекере и сгенерировать новый паскей. В старых раздачах в торренте придётся его тоже сменить.
                                                            0
                                                            Да мне в общем то и не жалко :) Там рейтинг большой, убить его будет крайне сложно
                                                              0
                                                              На рутрекере сейчас фрилич же
                                                        0
                                                        > Bencode
                                                        > Именно так называется формат кодирования данных в .torrent-файлах.
                                                        > Больше он почти нигде и не используется,

                                                        Он используется для кодирования всех пакетов BitTorrent.

                                                        Кстати формат .torrent-файла указан слишком примитивно, в нём часто можно встретить дополнительные хеши файлов и другую опциональную информацию.
                                                          +1
                                                          Мне кажется или Вы копирайт на картинке замазали?
                                                            +4
                                                            тема о торрентах, к чёрту копирайты! :)
                                                              0
                                                              сам не замазывал, думал что копирайт, это название сайта, а на нём так и было.
                                                              +3
                                                              Когда год назад torrents.ru стал rutracker.org, я написал питоновский скрипт, правящий announce-list в торрент файлах. Использовал готовые функции работы с bencode из BitTorrent/BitTornado и не изобретал лишних сущностей :-)
                                                              +1
                                                              Для решения этой задачи не достаточно ли было внести изменения в файл hosts,
                                                              подставив для имени ix*.rutracker.net IP адрес от retracker.local?
                                                                0
                                                                Дада, я такие проблемы всегда решаю методом #gedit /etc/hosts
                                                                0
                                                                Автору зачёт. Но в качестве альтернативы можно использовать BEncode Editor
                                                                forum.utorrent.com/viewtopic.php?id=31306
                                                                  0
                                                                  Любопытная статейка. Хотя сишить это костыль :) хоть и автору респект. Есть де куча вменяемых либ, на базе того де python.

                                                                  Автоматизирую ка я для себя с учетом, что качать могу на лине и на макоси.
                                                                    0
                                                                    Если файлы ты кидаешь копированием, то IN_CREATE неправильно использовать в данном случае. Данные код будет отлавливать только мув-ы и линк-и. С копированием будут ошибки, тк ты будешь открывать недозаписанный файл.

                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                    Самое читаемое