Cliente de BitTorrent implementado directamente desde cero
(github.com/piyushgupta53)- Este proyecto de código abierto es un cliente de BitTorrent implementado en Go que desarrolla por cuenta propia la lógica básica de descarga de archivos
- Maneja directamente la codificación/decodificación Bencode e incluye funciones sólidas de validación de errores
- Ofrece soporte integral para funciones clave como parseo de archivos
.torrent, cálculo del info hash y comunicación entre peers - Incluye funciones que mejoran su utilidad real, como descargas concurrentes, ensamblado de archivos y gestión de almacenamiento por bloques
- Frente a otros proyectos open source de BitTorrent, destaca por la simplicidad de Go, la claridad de la estructura del código y la modularidad
Resumen general
Este proyecto implementa directamente un cliente de BitTorrent en Go
Proporciona una implementación propia de la funcionalidad de descarga de archivos usando el protocolo BitTorrent
Se enfoca principalmente en el parseo de archivos torrent, el descubrimiento de peers y la descarga de archivos
Funciones principales
-
Codificación/decodificación Bencode
- Soporta todos los tipos de Bencode, como cadenas, enteros, listas y diccionarios
- Aplica manejo robusto de errores y validación de datos
-
Procesamiento de archivos torrent
- Puede parsear tanto torrents de un solo archivo como de múltiples archivos
- Extrae el info hash y los hashes de cada pieza, con soporte para todos los campos estándar
-
Descubrimiento y comunicación con peers
- Soporte para trackers HTTP
- Implementación del protocolo de handshake entre peers
- Ejecuta el protocolo de mensajes de BitTorrent y la gestión de conexiones entre peers
-
Funcionalidad de descarga
- Gestión por piezas y bloques
- Procesamiento de descargas concurrentes
- Seguimiento del progreso de descarga y ensamblado de archivos
- Gestión de almacenamiento por bloques para mayor eficiencia
Estructura del proyecto
- cmd/ : interfaz de línea de comandos y ejecutables
- internal/
- bencode/ : funciones de codificación y decodificación Bencode
- torrent/ : parseo y procesamiento de archivos torrent
- tracker/ : implementación del protocolo de tracker
- peer/ : funciones de comunicación entre peers
- download/ : funciones de gestión de descargas
- pkg/ : colección de paquetes que pueden exponerse externamente
Requisitos
- Requiere Go 1.21 o superior
Uso
- Actualmente el proyecto se encuentra en una etapa inicial de desarrollo, por lo que la guía de uso se agregará más adelante
Estado del desarrollo y planes
- El desarrollo está avanzando activamente en este momento
- Las etapas detalladas del desarrollo están registradas en el archivo
checkpoint.md - Planes futuros:
- Soporte para enlaces Magnet
- Protocolo de intercambio de metadatos
- Soporte planeado para DHT (tabla hash distribuida)
Documentación de referencia
- Especificación del protocolo BitTorrent
- Especificación de Bencode
Importancia y fortalezas del proyecto
- Este proyecto aprovecha la sintaxis simple y la concurrencia propias de Go para implementar los elementos complejos de un cliente de BitTorrent con una modularización clara
- Su estructura clara aporta ventajas tanto para aprendizaje como para uso práctico en términos de escalabilidad y mantenibilidad
- Aunque está en una etapa relativamente temprana, ya ha materializado rápidamente funciones clave del protocolo BitTorrent
1 comentarios
Comentarios en Hacker News
Sugieren que sería buena idea limitar el tamaño de las asignaciones dinámicas de memoria en el decodificador de bencode. Como no se puede confiar en los valores de entrada que llegan desde el archivo torrent o desde
announce, una entrada maliciosa podría pedir una asignación enorme y provocar una denegación de servicio (DoS). En el parseo de strings, un límite superior adecuado puede ser la longitud restante de la entrada, ya que un torrent válido no puede tener una cadena más larga que lo que queda del archivoEl proyecto se ve limpio y simple, y eso gusta. Sería bueno agregar al Readme un ejemplo de uso en una sola línea. Recomiendan añadir una frase como
./go-torrent My-Linux-Distro-Wink-ISO.torrentpara mostrar cómo se usa. Si además se agrega la funcióntorrent.ParseFromUrl, todavía mejor. Todo el mundo debería pasar por una experiencia así como parte de su propia “travesía espiritual”Presentan un reto parecido ofrecido por codecrafters. En ese curso te ayudan con el avance del proceso y las pruebas; lo probaron gratis durante un mes y estuvo bastante entretenido
https://app.codecrafters.io/courses/bittorrent/overview
Desde la perspectiva de alguien que no desarrolla en Go, preguntan por qué se usa una versión antigua como Go 1.21. Quieren saber si hay algún motivo especial para insistir en una versión vieja. Revisaron y vieron que el soporte terminó hace 10 meses
Es por el soporte para Windows 7. Los proyectos escritos con Go 1.21.4 o anterior funcionan en casi cualquier Windows y en prácticamente cualquier computadora desde 2009, pero si usas 1.21.5 o superior, solo funcionan en computadoras modernas con Windows 10 u 11, sin ofrecer una ventaja especial
https://github.com/golang/go/issues/64622
Es muy probable que el README haya sido escrito por IA. El archivo real
go.modfija la versión de Go en 1.23.1, así que en la práctica se requiere 1.23.1 o superiorhttps://github.com/piyushgupta53/go-torrent-client/blob/6130f4e/go.mod#L3 https://go.dev/doc/modules/gomod-ref#go-notes
Es un proyecto realmente genial. En la universidad hicieron esto como proyecto final en una clase de redes de Georgia Tech; ya perdieron el código, pero las lecciones aprendidas se les quedaron para toda la vida. Proyectos así son una muy buena forma de aprender un lenguaje nuevo
Preguntan si soporta enlaces magnet.
Edit: se enteraron de que es una función planeada para más adelante
Preguntan cómo hizo algo así. Si revisó directamente la especificación del protocolo o si tomó otras implementaciones como referencia. Siempre les da curiosidad cómo se implementa algo así desde cero
https://www.bittorrent.org/beps/bep_0003.html
Las extensiones adicionales están en
https://www.bittorrent.org/beps/bep_0000.html
Lo importante es dividir el trabajo en partes muy pequeñas e ir verificando uno mismo cada resultado. Por ejemplo, empecé parseando archivos
.torrent, para lo cual tuve que implementar bencoding por mi cuenta. Al descargar un.torrentde Arch Linux, vi que tenía un formato inesperado y aparecían claves comourl-list. Investigando qué era eso, resultó estar relacionado con bep_0019. Al final logré parsear correctamente un archivo.torrentde Debian LinuxDespués implementé la solicitud HTTP de
announceal tracker y también el protocolo entre peers. El protocolo entre peers fue bastante difícil, y una actitud experimental ayudó muchísimo. Quité la URL deannouncedel torrent de Debian para dejarlo sin peers por completo, luego agregué manualmente mi cliente en KTorrent para observar los mensajes que se intercambiaban, y con base en eso fui ajustando mi código. Hubo muchísimo ensayo y error y bastante depuraciónAlgunos detalles del protocolo simplemente no aparecían en la documentación oficial, así que en ocasiones le pregunté a ChatGPT cosas puntuales, y como cada cliente lo implementa un poco distinto, los algoritmos detallados no están del todo claros. No está bien documentado qué bloque pedir, con qué peer conectarse, ni cómo funcionan
chokeyunchoke, por ejemplo. Buscar en la web ayuda bastanteAdemás, el sitio https://wiki.theory.org/Main_Page también tiene información útil
En este momento ya está en una etapa en la que puede descargar y subir completamente con KTorrent. Lo que queda es desarrollar el algoritmo para obtener peers desde el tracker, elegir qué bloques descargar y guardarlos en el archivo
Si te interesa conocer el proceso con más detalle, pregunta con confianza
Preguntan qué tan difícil sería agregar una GUI. Dicen que no han visto muchos casos de interfaces gráficas hechas en Go
Personalmente prefiero https://github.com/AllenDang/giu, que es un wrapper de ImGui
El que parece tener más funciones es unison, aunque no sé qué tanto se use en la práctica y probablemente tenga muy poca documentación https://github.com/richardwilkes/unison
Gio es un framework de GUI con un enfoque nuevo, y lo usan Tailscale y gotraceui https://gioui.org
Wails es fácil de aprender si ya tienes experiencia en desarrollo web https://wails.io
Los bindings para GTK4 también se ven bien https://github.com/diamondburned/gotk4
Cogent Core también se ve interesante, aunque yo solo lo usé brevemente antes de pasarme al lenguaje Odin en lugar de Go https://www.cogentcore.org/core
Fyne, en lo personal, me dio muchos problemas de rendimiento en varias computadoras y sistemas operativos, pero aun así es el framework de GUI más conocido https://fyne.io
Les interesa este tipo de proyectos y habían pensado en intentar uno. Preguntan qué tan difícil es, qué tan completo lo considera, y si implementó funciones complejas como DHT, Magnet o NAT traversal. Dicen que ni siquiera tienen claro cuál es la lista de funciones realmente necesarias para cubrir casi todos los torrents que hay en circulación. Como hay tantos protocolos relacionados con torrents, ni siquiera saben cuál es la lista completa ni qué hace cada uno
El nivel de dificultad cambia mucho según la experiencia, el dominio del lenguaje y la disposición a experimentar. Por ejemplo, yo también empecé la semana pasada a hacer un cliente de Bittorrent en Go, y en una semana ya llegué a más o menos el 80% del proyecto que se publicó aquí. Como ya tengo mucho conocimiento de Go, de protocolos y de redes, y además estoy acostumbrado a experimentar, avancé rápido
La especificación oficial de Bittorrent en sí es realmente corta; se puede leer y entender en alrededor de una hora https://www.bittorrent.org/beps/bep_0003.html
Pero hay muchísimos protocolos de extensión alrededor, y cada cliente tiene un nivel de soporte distinto. Por ejemplo, muchos intentan primero usar cifrado del protocolo —que en realidad es más bien ofuscación— y, si no funciona, siguen con el protocolo normal
Si solo quieres descargar usando archivos
.torrentoficiales, como los de distribuciones de Linux, la dificultad baja bastante. Normalmente es un solo archivo, hay tracker y la mayoría de los peers usan protocolos estándar, así que incluso detrás de NAT puede funcionar bien sin abrir puertos internosClaro, si quieres manejar torrents más generales —sobre todo los de la zona gris— entonces vas a tener que ir sumando parseo de enlaces magnet, DHT para descubrimiento de peers y UPnP para mapeo automático de puertos. Aun así, también se puede implementar paso a paso, función por función. Mientras más funciones tengas, más peers podrás encontrar y más intercambios exitosos podrás hacer
Fue bastante desafiante, y me tomó casi un mes aprender el protocolo y bencoding, imaginar toda la estructura en la cabeza y después escribir el código. Magnet y DHT todavía no están soportados
Preguntan si ya están implementados v2 y mutable torrents. También expresan el deseo de que, por favor, sí se implementen los mutable torrents