Cliente BitTorrent implementado do zero
(github.com/piyushgupta53)- Este projeto open source é um cliente BitTorrent implementado em Go, com a lógica básica de download de arquivos desenvolvida internamente
- Faz o processamento de codificação/decodificação Bencode diretamente e inclui recursos robustos de validação de erros
- Oferece suporte abrangente a recursos centrais como parsing de arquivos
.torrent, cálculo de info hash e comunicação entre peers - Inclui funcionalidades que aumentam a utilidade prática, como downloads simultâneos, montagem de arquivos e gerenciamento de armazenamento em nível de bloco
- Em comparação com outros projetos open source de BitTorrent, se destaca pela simplicidade do Go, clareza da estrutura do código e modularização
Visão geral
Este projeto implementa diretamente um cliente BitTorrent em Go
Ele oferece, de forma própria, a funcionalidade de download de arquivos usando o protocolo BitTorrent
No centro da implementação estão os recursos de parsing de arquivos torrent, descoberta de peers e download de arquivos
Principais recursos
-
Codificação/decodificação Bencode
- Suporte a todos os tipos de Bencode, como strings, inteiros, listas e dicionários
- Aplicação de tratamento de erros robusto e validação de dados
-
Processamento de arquivos torrent
- Faz parsing de torrents de arquivo único e de múltiplos arquivos
- Extrai o info hash e os hashes de cada piece, com suporte a todos os campos padrão
-
Descoberta de peers e comunicação
- Suporte a trackers HTTP
- Implementação do protocolo de handshake entre peers
- Execução do protocolo de mensagens BitTorrent e gerenciamento de conexões entre peers
-
Funcionalidades de download
- Gerenciamento em nível de piece e bloco
- Processamento de downloads simultâneos
- Rastreamento do progresso do download e montagem de arquivos
- Eficiência por meio de gerenciamento de armazenamento em nível de bloco
Estrutura do projeto
- cmd/ : interface de linha de comando e executáveis
- internal/
- bencode/ : funcionalidades de codificação e decodificação Bencode
- torrent/ : parsing e processamento de arquivos torrent
- tracker/ : implementação do protocolo de tracker
- peer/ : funcionalidades de comunicação entre peers
- download/ : funcionalidades de gerenciamento de download
- pkg/ : conjunto de pacotes que podem ser expostos externamente
Requisitos
- Requer Go 1.21 ou superior
Como usar
- No momento, o projeto está em estágio inicial de desenvolvimento, e as instruções de uso serão adicionadas depois
Status do desenvolvimento e planos
- O desenvolvimento está em andamento de forma ativa
- As etapas detalhadas do desenvolvimento estão registradas no arquivo
checkpoint.md - Planos futuros:
- Suporte a links Magnet
- Protocolo de troca de metadados
- Suporte a DHT (tabela hash distribuída)
Documentação de referência
- Especificação do protocolo BitTorrent
- Especificação do Bencode
Importância e pontos fortes do projeto
- Este projeto aproveita a sintaxe simples e a concorrência características do Go para implementar os elementos complexos de um cliente BitTorrent de forma claramente modularizada
- Sua estrutura clara oferece vantagens tanto para aprendizado quanto para aplicação prática em termos de extensibilidade e manutenibilidade
- Mesmo estando em um estágio relativamente inicial, já concretizou rapidamente funcionalidades centrais do protocolo BitTorrent
1 comentários
Comentários do Hacker News
Foi sugerido limitar o tamanho das alocações dinâmicas de memória no decodificador de bencode. Como os valores recebidos do arquivo torrent ou do announce não são confiáveis, uma entrada maliciosa pode solicitar uma alocação muito grande e causar negação de serviço (DoS). Na análise de strings, um limite superior adequado pode ser definido como o tamanho restante da entrada, já que um torrent válido não pode ter uma string maior que o restante do arquivo
O projeto parece limpo e simples, o que é ótimo. Seria bom adicionar um exemplo de uso em uma linha no README. Recomendaram incluir uma frase mostrando algo como
./go-torrent My-Linux-Distro-Wink-ISO.torrent. Se também adicionar a funcionalidadetorrent.ParseFromUrl, melhor ainda. Todo mundo deveria passar por esse tipo de experiência em sua própria “jornada espiritual”Foi apresentado um desafio parecido oferecido pela codecrafters. Nesse curso eles ajudam com o andamento do processo e com testes, e a pessoa experimentou por um mês grátis e achou bem divertido
https://app.codecrafters.io/courses/bittorrent/overview
Alguém que não é desenvolvedor Go perguntou por que está sendo usada a versão antiga Go 1.21. Quis saber se havia algum motivo específico para insistir em uma versão antiga. Pesquisando, viu que o suporte já foi encerrado há 10 meses
É por causa do suporte ao Windows 7. Projetos escritos com Go 1.21.4 ou inferior funcionam em quase todo Windows e em praticamente qualquer computador desde 2009, mas ao usar 1.21.5 ou superior eles só funcionam em computadores mais novos com Windows 10 ou 11, sem nenhuma vantagem especial
https://github.com/golang/go/issues/64622
O README provavelmente foi escrito por IA. No arquivo real
go.mod, a versão de Go está definida como 1.23.1, então no fim das contas é necessário 1.23.1 ou superiorhttps://github.com/piyushgupta53/go-torrent-client/blob/6130f4e/go.mod#L3 https://go.dev/doc/modules/gomod-ref#go-notes
Projeto realmente incrível. Na faculdade, isso foi o trabalho final de uma disciplina de redes no Georgia Tech; o código se perdeu, mas as lições aprendidas ficaram para a vida toda. Esse tipo de projeto é uma ótima forma de aprender uma linguagem nova
Perguntaram se há suporte a magnet links.
Edit: descobriram que é um recurso planejado para o futuro
Perguntaram como isso foi feito. Se a pessoa leu diretamente a especificação do protocolo ou se consultou outras implementações. Sempre existe curiosidade sobre como implementar algo assim do zero
https://www.bittorrent.org/beps/bep_0003.html
As extensões adicionais estão em
https://www.bittorrent.org/beps/bep_0000.html
É importante dividir o trabalho em partes bem pequenas e ir verificando os resultados por conta própria. Por exemplo, comecei analisando arquivos
.torrente tive que implementar bencoding manualmente. Ao baixar um.torrentdo Arch Linux, percebi que ele tinha um formato inesperado e apareciam chaves comourl-list. Fui investigar o que era e descobri que estava relacionado ao bep_0019. No fim, consegui analisar com sucesso um arquivo.torrentdo Debian LinuxDepois disso implementei a requisição HTTP de announce do tracker e também o protocolo entre peers. O protocolo entre peers foi bem difícil, e uma postura experimental ajudou bastante. Removi a URL de announce do torrent do Debian para que ele ficasse sem peers, depois adicionei manualmente meu cliente no KTorrent para observar as mensagens trocadas, e com base nisso ajustei meu código. Houve muita tentativa e erro, além de muito debugging
Alguns detalhes do protocolo simplesmente não apareciam de forma clara na documentação oficial, então às vezes recorri ao ChatGPT para dúvidas pequenas, e como cada cliente implementa certas partes de forma um pouco diferente, os algoritmos detalhados não ficam muito claros. Coisas como qual bloco receber, com qual peer se conectar e como choke/unchoke funciona não estão bem documentadas. Pesquisar na web ajuda muito
Além disso, o site https://wiki.theory.org/Main_Page também tem informações úteis
Neste momento já estou em uma etapa em que downloads/uploads completos com o KTorrent funcionam. Daqui para frente ainda falta desenvolver o algoritmo para obter peers do tracker, selecionar os blocos para baixar e gravá-los no arquivo
Se quiser saber mais detalhes sobre o processo, pergunte à vontade
Perguntaram quão difícil seria adicionar uma GUI. A pessoa comentou que não vê muitos exemplos de GUI em Go
Pessoalmente, prefiro o wrapper de ImGui https://github.com/AllenDang/giu
O mais completo em recursos parece ser o unison, mas não sei o quanto ele é realmente usado na prática, e imagino que a documentação seja bem fraca https://github.com/richardwilkes/unison
Gio é um framework de GUI com uma abordagem nova, usado pelo Tailscale e pelo gotraceui https://gioui.org
Wails é fácil de aprender se você tem experiência com desenvolvimento web https://wails.io
As bindings de GTK4 também parecem boas https://github.com/diamondburned/gotk4
Cogent Core também parece interessante, mas eu só usei brevemente antes de migrar do Go para a linguagem Odin https://www.cogentcore.org/core
Fyne, pessoalmente, me deu muitos problemas de desempenho em vários computadores e sistemas operacionais, mas ainda assim é o framework de GUI mais conhecido https://fyne.io
A pessoa comentou que sempre teve interesse em projetos assim e pensou em tentar fazer um. Perguntou o quão difícil é, qual o nível de completude da implementação e se recursos complexos como DHT, Magnet e NAT traversal já foram implementados. Também disse que nem sabe ao certo quais recursos são necessários para cobrir quase todos os torrents disponíveis, já que há muitos protocolos relacionados a torrent e é difícil até saber a lista completa e a função de cada um
O nível de dificuldade varia muito conforme experiência, domínio da linguagem e postura experimental. Como exemplo, a própria pessoa começou na semana passada a fazer um cliente Bittorrent em Go e em uma semana chegou a algo como 80% do projeto mostrado aqui. Como já tinha bastante conhecimento de Go, protocolos e redes, além do hábito de experimentar, avançou rápido
A especificação oficial do Bittorrent em si é realmente curta, então em cerca de uma hora dá para ler e entender https://www.bittorrent.org/beps/bep_0003.html
Mas existem muitas extensões em volta do protocolo, e o nível de suporte varia entre clientes. Por exemplo, muitos tentam primeiro usar criptografia de protocolo (que na prática é mais ofuscação) e, se não der certo, voltam ao protocolo normal
Se a intenção for apenas baixar distribuições Linux a partir de arquivos
.torrentoficiais, a dificuldade cai bastante. Em geral é um único arquivo, com tracker presente e peers que usam protocolo padrão, então mesmo atrás de NAT costuma funcionar bem sem abrir portas internasClaro, se quiser lidar com torrents mais gerais (especialmente os da zona cinzenta), aí vai precisar adicionar aos poucos parsing de magnet links, DHT para descoberta de peers e UPnP para mapeamento automático de portas. Ainda assim, tudo isso pode ser implementado passo a passo, recurso por recurso. Quanto mais funcionalidades, mais peers você consegue encontrar e com mais sucesso consegue trocar dados
Foi bem desafiador, e levou quase um mês para aprender o protocolo, entender bencoding, montar a arquitetura inteira na cabeça e então escrever o código. Magnet e DHT ainda não são suportados
Perguntaram se v2 e mutable torrents foram implementados. Também pediram fortemente que mutable torrents sejam implementados