BitTorrent

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

BitTorrent (букв. англ. «битовый поток») — пиринговый (P2P) сетевой протокол для кооперативного обмена файлами через Интернет.

Файлы передаются частями, каждый torrent-клиент, получая (скачивая) эти части, в то же время отдаёт (закачивает) их другим клиентам, что снижает нагрузку и зависимость от каждого клиента-источника и обеспечивает избыточность данных.

Протокол был создан Брэмом Коэном, написавшим первый torrent-клиент BitTorrent на языке Python, 4 апреля 2001 года. Запуск первой версии состоялся 2 июля 2001 года.

Существует множество программ-клиентов для обмена файлами по протоколу BitTorrent.

Файл метаданных[править | править код]

Файл метаданных является словарём в bencode формате с расширением .torrent — содержит информацию о раздаче (файлах, трекерах и др.)

Принцип работы протокола[править | править код]

Принцип работы BitTorrent: нагрузка на распространителя файла уменьшается благодаря тому, что клиенты начинают обмениваться данными сразу же, даже если файл не докачан ими до конца

Перед началом скачивания клиент подсоединяется к трекеру по адресу, указанному в торрент-файле, сообщает ему свой адрес и хеш-сумму торрент-файла, на что в ответ клиент получает адреса других клиентов, скачивающих или раздающих этот же файл. Далее клиент периодически информирует трекер о ходе процесса и получает обновлённый список адресов. Этот процесс называется объявлением (англ. announce).

Клиенты соединяются друг с другом и обмениваются сегментами файлов без непосредственного участия трекера, который лишь хранит информацию, полученную от подключённых к обмену клиентов, список самих клиентов и другую статистическую информацию. Для эффективной работы сети BitTorrent необходимо, чтобы как можно больше клиентов были способны принимать входящие соединения. Неправильная настройка NAT или брандмауэра могут этому помешать.

При соединении клиенты сразу обмениваются информацией об имеющихся у них сегментах. Клиент, желающий скачать сегмент (личер), посылает запрос и, если второй клиент готов отдавать, получает этот сегмент. После этого клиент проверяет контрольную сумму сегмента. Если она совпала с той, что записана в торрент-файле, то сегмент считается успешно скачанным, и клиент оповещает всех присоединённых пиров о наличии у него этого сегмента. Если же контрольные суммы различаются, то сегмент начинает скачиваться заново. Некоторые клиенты банят тех пиров, которые слишком часто отдают некорректные сегменты.

Таким образом, объём служебной информации (размер торрент-файла и размер сообщений со списком сегментов) напрямую зависит от количества, а значит, и размера сегментов. Поэтому при выборе сегмента необходимо соблюдать баланс: с одной стороны, при большом размере сегмента объём служебной информации будет меньше, но в случае ошибки проверки контрольной суммы придётся заново скачивать больше информации. С другой стороны, при малом размере ошибки не так критичны, так как необходимо заново скачать меньший объём, но зато размер торрент-файла и сообщений об имеющихся сегментах становится больше.

Алгоритм обмена данными[править | править код]

Каждый клиент имеет возможность временно блокировать отдачу другому клиенту (англ. choke). Это делается для более эффективного использования канала отдачи. Кроме того, при выборе — кого разблокировать, предпочтение отдаётся пирам, которые сами передали этому клиенту много сегментов. Таким образом, пиры с хорошими скоростями отдачи поощряют друг друга по принципу «ты — мне, я — тебе».

Обмен сегментами ведётся по принципу «ты — мне, я — тебе» симметрично в двух направлениях. Клиенты сообщают друг другу об имеющихся у них сегментах при подключении и затем — при получении новых сегментов, и поэтому каждый клиент может хранить информацию о том, какие сегменты есть у других подключённых пиров. Порядок обмена выбирается таким образом, чтобы сначала клиенты обменивались наиболее редкими сегментами: таким образом повышается доступность файлов в раздаче. В то же время выбор сегмента среди наиболее редких — случаен, и поэтому можно избежать ситуации, когда все клиенты начинают скачивать один и тот же самый редкий сегмент, что негативно бы отразилось на производительности.

Обмен данными начинается, когда в нём заинтересованы обе стороны, то есть, каждая из сторон имеет сегменты, которых нет у другой. Количество переданных сегментов подсчитывается, и если одна из сторон обнаруживает, что передаёт в среднем больше, чем принимает, она блокирует (англ. choke) на некоторое время отдачу другой стороне. Таким образом в протокол заложена защита от личеров.

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

Режим End game[править | править код]

Когда скачивание почти завершено, клиент входит в особый режим, называемый end game. В этом режиме он запрашивает все оставшиеся сегменты у всех подключённых пиров, что позволяет избежать замедления или полного «зависания» почти завершённой закачки из-за нескольких медленных клиентов.

Спецификация протокола не определяет, когда именно клиент должен войти в режим «end game», однако существует набор общепринятых практик. Некоторые клиенты входят в этот режим, когда не осталось незапрошенных блоков, другие — пока количество оставшихся блоков меньше количества передающихся и не больше 20. Существует негласное мнение, что лучше поддерживать количество ожидаемых блоков низким (1 или 2) для минимизации избыточности, и что при случайном запрашивании меньший шанс получить дубликаты одного и того же блока[1][2].

Сидирование[править | править код]

При получении полного файла клиент переходит в специальный режим работы, в котором он только отдаёт данные (становится сидом). Далее сид периодически информирует трекер об изменениях в состоянии торрентов (закачек) и обновляет списки IP-адресов.

Общие особенности[править | править код]

  • Отсутствие очередей на скачивание.
  • Файлы закачиваются небольшими фрагментами; чем менее доступен фрагмент, тем чаще он будет передаваться. Таким образом, присутствие в сети «сидера» с полным файлом для загрузки необязательно — система распределяет сегменты между «пирами», чтобы в последующем они могли обмениваться недостающими сегментами.
  • Клиенты (пиры) обмениваются сегментами непосредственно между собой, по принципу «ты — мне, я — тебе».
  • Скачанные фрагменты становятся немедленно доступны другим клиентам.
  • Контролируется целостность каждого фрагмента.
  • На фрагменты разбиваются не отдельные файлы, а вся раздача целиком, поэтому у «личера», пожелавшего скачать лишь некоторые файлы из раздачи, для поддержания целостности фрагментов нередко будет храниться также небольшой объём избыточной (для него) информации.
  • В качестве объекта раздачи могут выступать несколько файлов (например, содержимое каталога).

Протоколы и порты[править | править код]

Клиенты соединяются с трекером по протоколу TCP. Наиболее часто используемый входящий порт трекера: 6969. Наиболее часто используемый диапазон входящих портов клиентов: 6881—6889.

Номера портов не фиксированы в спецификации протокола и могут изменяться при необходимости. В данный момент большинство трекеров использует HTTP-порт 80, а для клиентов рекомендуется выбрать случайный входящий порт. Более того, некоторые трекеры не допускают использования портов клиентов из стандартного диапазона 6881—6889, так как некоторые провайдеры запрещают использование этого диапазона портов.

DHT-сеть в BitTorrent-клиентах использует протокол UDP.

Кроме того, протокол UDP используется UDP-трекерами[en] (поддерживается не всеми клиентами и не является официальной частью протокола) и для соединения клиентов друг с другом через UDP NAT Traversal (используется только в клиенте BitComet и не является официальной частью протокола).

Трекер[править | править код]

Трекер (англ. tracker; /ˈtɹækə(ɹ)/) — специализированный сервер, работающий по протоколу HTTP. Трекер нужен для того, чтобы клиенты могли найти друг друга. Фактически, на трекере хранятся IP-адреса, входящие порты клиентов и хеш-суммы, уникальным образом идентифицирующие объекты, участвующие в закачках. По стандарту, имена файлов на трекере не хранятся, и узнать их по хеш-суммам нельзя. Однако на практике трекер часто помимо своей основной функции выполняет и функцию небольшого веб-сервера. Такой сервер хранит файлы метаданных и описания распространяемых файлов, предоставляет статистику закачек по разным файлам, показывает текущее количество подключённых пиров и пр.

Работа без трекера[править | править код]

В новых версиях протокола были разработаны бестрекерные (англ. trackerless) системы, которые решают некоторые из предыдущих проблем. Отказ трекера в таких системах не приводит к автоматическому отказу всей сети.

Начиная с версии 4.2.0 официального клиента, выпущенной в конце 2015 года, реализована функция бестрекерной работы, базирующаяся на DHT Kademlia. В такой реализации трекер доступен децентрализовано на клиентах в форме распределённой хеш-таблицы.

На данный момент не все клиенты используют совместимый друг с другом протокол. Совместимы между собой BitComet, µTorrent, Deluge, KTorrent, Transmission, qBittorrent и официальный клиент BitTorrent. Vuze (Azureus) также имеет режим бестрекерной работы, но его реализация отличается от официальной, вследствие чего он не может работать через DHT с вышеперечисленными клиентами[3]. Однако, для Vuze существует поддержка стандартного DHT через плагин Mainline DHT.

Работа без трекера также возможна при использовании мультипротокольных клиентов, поддерживающих BitTorrent. Shareaza через сеть Gnutella2 обменивается хешами и адресами пиров других поддерживаемых сетей, в том числе BitTorrent. В GreyLink 6.0 планируется поддержка BitTorrent, при этом сеть Direct Connect может использоваться не только для преобразования в TTH, но и для поиска пиров.

Работа без торрент-клиента[править | править код]

Для того чтобы брать и раздавать файлы в торрент-сетях, не обязательно пользоваться специальными программами. Существует несколько сервисов, которые позволяют скачивать файлы, используя только браузер[4].

Наличие в файлах метаданных дополнительной информации, такой, как дополнительные источники и опциональные хеши, позволяет использовать файл метаданных .torrent аналогично форматам Metalink, MAGMA, Список файлов (Direct Connect). Клиент Shareaza использует опциональные хеши для поиска альтернативных источников в других сетях.

Web-сиды[править | править код]

Одним из вариантов использования является так называемое web-сидирование. Иногда на сервере по разным причинам нельзя запустить полноценный торрент-клиент. В этом случае в качестве источника раздачи выступает сервер, работающий по протоколу HTTP. Как правило, клиенты отдают предпочтение другим BitTorrent клиентам и обращаются к web-сиду только по необходимости. Следует знать, что реализован этот вариант использования как минимум тремя способами: BEP0017 BitTornado style webseeding, BEP0019 GetRight style webseeding и External Sourcing, каждый из которых отличается в деталях реализации.

Впервые был создан Джоном «TheSHAD0W» Хоффманом, который создал BitTornado[5]. Начиная с версии 5.0 клиент BitTorrent поддерживает веб-сиды и загрузки с веб-сайтов, был создан простой инструмент, который создаёт публикации веб-сидов торрентов. В μTorrent добавлена поддержка для получения веб-сидов в версии 1.7. В BitComet добавлена поддержка для получения веб-сидов в версии 1.14.

BTIH (BitTorrent Info Hash)[править | править код]

Это SHA-1-хеш поля Info из файла метаданных. Данный хеш используется в магнет-ссылках, а также для идентификации на трекере и между клиентами. При загрузке на трекер файла метаданных его Info Hash может измениться, так как трекер может изменить поле info, установив флаг закрытой раздачи private или изменив/добавив поля внутри info. Поэтому необходимо снова скачать файл метаданных (файл .torrent) с трекера и добавить его в клиент[6].

BTC-ссылка[править | править код]

Указывается в виде:

btc://[Адрес]: [Порт]/[Peer ID]/[ BTIH ]

Ссылка такого вида ссылается на раздачу и на её источник. Поддерживается в Shareaza.

Недостатки и ограничения[править | править код]

Недоступность раздачи[править | править код]

В случае, если раздача непопулярна, то может возникнуть ситуация, когда нет ни одного сида, а данных у присутствующих пиров не хватает, чтобы завершить скачивание. В таком случае необходимо ждать появления либо сида, либо пира, имеющего сегменты, отсутствующие у остальных. Можно также использовать копии файлов, полученные другим путём. Раздача, которая не имеет ни одного сида долгое время, называется «мёртвой».

Для поощрения раздач даже был создан BitTorrent-токен[7].

Отсутствие анонимности и персонализации[править | править код]

Принцип работы BitTorrent-протокола подразумевает, что каждому клиенту известны IP-адреса как минимум других клиентов, полученные от сервера. Использование разнообразных расширений протокола в некоторых случаях позволяет узнать также и адреса других пиров из роя. Поэтому:

  • Пользователи незащищённых систем и клиентов с известными уязвимостями могут быть подвергнуты атаке.
  • Возможно узнать адреса пользователей, передающих или принимающих определённый файл.

Проблема с анонимностью может быть решена при помощи использования Tor[8]. BitTorrent-клиент Vuze имеет встроенную программную поддержку этой анонимной сети. Но данный метод не является стопроцентно эффективным[9].

С другой стороны, протокол не предполагает использование ников. Отсутствует чат между пирами. Невозможно просмотреть список файлов пира (в поисках других файлов, которые могли бы заинтересовать). Большинство этих функций реализовано в других протоколах (например, Direct Connect).

Проблема личеров[править | править код]

Некоторые пользователи, особенно на трекерах, не требующих регистрации, не поддерживают раздачу после завершения скачивания, что ведёт к уменьшению общей производительности, поэтому некоторые торрент-трекеры учитывают и количество скачанного/отданного, и выдают разрешение на скачивание в зависимости от размера отданных клиентом данных.

Отсутствие точного учёта трафика[править | править код]

В отличие от многих коммерческих протоколов дистрибуции медиаконтента, архитектура протокола не предусматривает точного механизма учёта и контроля трафика между точками сети. Всё, что есть — поля downloaded и uploaded, в которых клиенты передают при анонсе трекеру количество байт, учтённых при скачивании/загрузке данных с момента предыдущего анонса. Однако не контролируясь никем, кроме как клиентом, они могут быть легко подменены. Для этого пользователи статично прописывают значения этих полей в URI трекера, пользуются патчами для клиентов или же отдельными программами (RatioMaster, GiveMeTorrent, GreedyTorrent и т. д.), либо просто удаляют из клиента запись о трекере сразу же после получения с трекера списка точек сети. Всё это позволяет обходить искусственные ограничения, создаваемые администрацией многих частных и публичных трекеров.


Терминология[править | править код]

  • Анонс (англ. announce) — обращение клиента к трекеру посредством HTTP-GET-запроса. При каждом анонсе клиент передаёт на трекер информацию об объёмах им скачанного и отданного, a трекер передаёт клиенту список адресов других клиентов. Обращение клиента к трекеру происходит через определённые интервалы времени, которые определяются настройками клиента и трекера.
  • Веб-сид — HTTP или FTP-сервер, используемый в качестве источника данных наравне с обычными сидами
  • Доступность (англ. availability, англ. distributed copies — распространённые копии) — количество полных копий файла, доступных клиенту. Каждый сид добавляет 1,0 к этому числу; личеры увеличивают доступность в зависимости от количества скачанного, которого нет у других личеров. К примеру, если на раздаче есть один сид и два личера, скачавшие по 50 % файла (скачанные части равны между собой), то доступность равна 1,50.
  • Заглохший (англ. choked — заглохший, придушенный) — клиент, обмен данными с которым заглох. Либо его канал на выход забит полностью и он не может ничего передать (достиг max_uploads), либо он является сидом и ему ничего не нужно получать.
  • Заинтересованный (англ. interested) — участник, желающий получить куски файла, имеющиеся у другого участника. Например, если у клиента А нет каких-то частей, которые есть у клиента Б, считается, что клиент А заинтересован в обмене с клиентом Б.
  • Излишки — данные, которые были посланы пиром или сидом, но получатель в них не нуждается. К излишкам также относятся ошибки хеша.
  • Индекс (англ. index) — это список .torrent-файлов (обычно включающий описания и другую информацию), управляемый веб-сайтом (индексатором) и доступный для поиска. Индексирующий сайт часто ошибочно называют трекером.
Личер и его рой
  • Лич, иногда личер (англ. leech — пиявка) — пир, не имеющий пока всех сегментов, то есть продолжающий скачивание. Термин часто употребляется и в негативном смысле, который он имеет в других файлообменных сетях: пользователь, который отдаёт гораздо меньше, чем скачивает.
  • Отравление торрент-файла — ситуация, когда часть пиров раздаёт повреждённые либо специально сфальсифицированные сегменты.
  • Пир (англ. peer — соучастник) — клиент, участвующий в раздаче в любой файлообменной сети.
  • Пренебрегающий (англ. snubbed) — клиент, подключённый к получателю, но не посылавший ему данные уже более 60 секунд.
  • Раздача (англ. seeding) — процесс распространения файла по протоколу BitTorrent.
  • Рейтинг (англ. share ratio) — отношение отданного к скачанному.
  • Рой (англ. swarm) — совокупность всех пиров, участвующих в раздаче.
  • Сегмент (англ. part — часть) — все файлы для передачи делятся на небольшие куски — сегменты, которые затем передаются по сети в произвольном порядке для оптимизации обмена.
  • Сид, иногда сидер (англ. seeder — сеятель) — пир, имеющий все сегменты распространяемого файла, то есть либо начальный распространитель файла, либо уже скачавший весь файл и оставшийся на раздаче.
  • Scrape-запрос (англ. scrape — скрести, царапать) — дополнительный протокол запроса клиента к трекеру, при котором трекер сообщает клиенту общее количество сидов и пиров на раздаче. В отличие от анонсирования, запрос scrape не имеет прямого отношения к скачиванию раздачи, является необязательным и отнимает меньше ресурсов у клиента и трекера. Он может запрашиваться и для остановленных в клиенте заданий, а также позволяет одним запросом получить информацию сразу по нескольким торрентам (multi-scrape). Клиент с помощью scrape-запроса может получить точное количество сидов и пиров на каждом задании, включая остановленные. Некоторые клиенты, например Azureus, также могут с помощью scrape-запроса раньше узнать о том, что на раздаче появились дополнительные участники, и сделать внеочередной announce для получения их адресов, и автоматически останавливать и запускать сидирование заданий в зависимости от числа сидов и пиров, в результате сидируя там, где это нужнее.
  • Супер-сидирование — специальный режим раздачи в некоторых BitTorrent-клиентах, пытающийся минимизировать количество данных, которое отдаст раздающий до появления первого скачавшего. Суперсид предлагает каждому пиру скачать только один сегмент файла, которого ещё нет у других пиров. Затем сид не даёт этому пиру следующих сегментов, пока не получит от других пиров подтверждения, что они тоже получили этот сегмент. Таким образом, суперсид пытается избежать повторной отдачи одних и тех же сегментов, и старается отдавать сегменты только тем пирам, которые активно передают их другим.
  • Хеш (англ. hash) — SHA1 отдельных сегментов оригинальных файлов, перечисленных в словаре «info» .torrent-файла. Каждая часть после получения сначала проверяется на совпадение хеша. Если проверка не удалась, данные отбрасываются и запрашиваются ещё раз. Также в протоколе используется хеш самого словаря «info»(«инфохеш»), выступающий в роли идентификатора конкретной раздачи при обращении к трекеру, к другим точкам сети и при составлении magnet-ссылок (он содержат Base32-представление инфохеша).
  • Passkey — аутентификатор пользователя на неанонимных трекерах. Содержится в скачиваемом torrent-файле. Таким образом, если кто-то получит доступ к torrent-файлу (например, пользователь по неосторожности расшарил его), он сможет работать с трекером от имени этого пользователя. Трекер может изменить passkey по запросу пользователя, но при этом необходимо будет перескачать все прошлые torrent-файлы (или вручную отредактировать их), чтобы иметь возможность и дальше раздавать скачанные файлы.
  • URL анонса (англ. announce URL) — адрес трекера, к которому клиент делает анонс. Во многих клиентах называется «Tracker URL». Может включать «passkey» — уникальный код, назначаемый трекером для аккаунта пользователя, помогающий идентифицировать его на трекере (добавляется к URL анонса в самом *.torrent-файле при скачивании).

BitTorrent v2[править | править код]

Работа над BitTorrent протоколом второй версии ведётся с 2008 года. В протоколе осуществлён уход от использования алгоритма SHA-1, имеющего проблемы с подбором коллизий, в пользу SHA-2 256. Инфо-хеш второй версии применяется как для контроля целостности блоков данных, так и для записей в индексах (info-dictionary), что нарушает совместимость в коммуникации по сети DHT новых и необновившихся клиентов, и трекеров (длина v2 хеша 32 байта, а v1 — 20 байт). Для магнитных ссылок на торренты с хэшами SHA2-256 предложен новый префикс «urn:btmh:» (для SHA-1 и гибридных торрентов используется «urn:btih:»).

Разработка спецификации BitTorrent v2 изначально велась без оглядки на обратную совместимость и в состав были приняты другие существенные улучшения, такие как использование хеш-дерева Меркла в индексах для сокращения размера torrent-файлов и проверки загруженных данных на уровне блоков.

Из изменений в BitTorrent v2 также выделяется переход к привязке отдельных хэш-деревьев к каждому файлу и применение выравнивания файлов по частям (без добавления добавочного заполнения после каждого файла), что позволяет избавиться от дублирования данных при наличии одинаковых файлов и упрощает выявление разных источников для файлов. Тем самым решается потребность скачивания полного размера части, для проверки целостности отдельных файлов, экономя пространство и трафик. Торрент-файл содержит значения коренных хешей файлов, которые отличаются от стандартного SHA2-256 файла, эти хеши могут также быть показаны на трекерах. Это даёт возможность поиска торрентов по значению хешей файлов, что упрощает нахождение торрентов с нужными файлами, восстанавливания умирающих раздач. Они также могут быть извлечены из .torrent файлов, с помощью пользовательских программ[10]. Повышена эффективность кодирования структуры каталогов (уходом от повторения полного пути для каждого файла), уменьшая размер .torrent файла.

Для сглаживания сосуществования BitTorrent v1 и BitTorrent v2 реализована возможность создания гибридных torrent-файлов, которые включают, помимо структур с хэшами SHA-1, также индексы с SHA2-256. Гибридные торренты могут использоваться клиентами, без поддержки BitTorrent v2. Так как данные обоих протоколов вшиты в info-раздел гибридного .torrent файла, то клиенты с дополнительной поддержкой BitTorrent v2, автоматически подцепляют поддержку v2 протокола через DHT пиров (клиенты которых могут даже его не поддерживать), при этом руководствуясь только v1 хешом в магнитной ссылке. Протокол BEP-47 (выравнивание файлов по частям файлами заполнения во мнимой папке .pad) обязателен для гибридных файлов. Для решения несовместимости пользователям на первое время рекомендуется пользоваться гибридами[11]. Также ведётся разработка для поддержки протокола WebTorrent, работающего в браузерах[12].

Примечания[править | править код]

  1. BitTorrent Specification: End Game. Дата обращения: 14 февраля 2010. Архивировано 14 декабря 2006 года.
  2. [1]Архивная копия от 17 февраля 2012 на Wayback Machine HAL — INRIA:: [inria-00000156, version 3] Understanding BitTorrent: An Experimental Perspective
  3. What is DHT?//Torrent FAQ Архивировано 8 июля 2007 года.
  4. Качаем торренты без клиента: Bitlet, Torrent2exe, httpTorrents. Интернетные штучки. Архивировано 13 декабря 2009 года.
  5. HTTP-Based Seeding Specification (TXT). Дата обращения: 9 мая 2006. Архивировано из оригинала 22 августа 2011 года.
  6. [rutracker.org/forum/viewtopic.php?t=215520 Как начать раздачу (на примере клиента µTorrent 1.8.3.)]. Дата обращения: 2 марта 2010. Архивировано 25 марта 2014 года.
  7. BitTorrent Token (BTT) | Tokenizing Decentralized File Sharing (англ.). Дата обращения: 22 сентября 2021. Архивировано 27 сентября 2021 года.
  8. Making BitTorrent Safe to Use Over Tor. Дата обращения: 31 июля 2013. Архивировано 16 мая 2013 года.
  9. Bittorrent over Tor isn’t a good idea. Дата обращения: 31 июля 2013. Архивировано 13 октября 2016 года.
  10. TMRR. github.com. kovalensky. Дата обращения: 9 апреля 2023. Архивировано 9 апреля 2023 года.
  11. Arvid Nordberg. Introducing BitTorrent v2 (амер. англ.). Дата обращения: 7 августа 2023. Архивировано 30 октября 2020 года.
  12. Выпуск libtorrent 2.0 с поддержкой протокола BitTorrent 2. www.opennet.ru. Дата обращения: 13 ноября 2020. Архивировано 7 ноября 2020 года.

Ссылки[править | править код]