Este informe documenta la implementación exitosa de LINK CHAT, una aplicación de mensajería y transferencia de archivos diseñada para operar exclusivamente en la Capa de Enlace (Capa 2 del modelo OSI) dentro de una Red de Área Local (LAN). El proyecto se realizó bajo la estricta limitación de no utilizar información de capas de red superiores (IP, TCP, UDP) ni bibliotecas externas al stack estándar del lenguaje.
Se define un formato de frame estilo Ethernet (cabecera + datos + CRC)
El código crea una clave a partir de dos cadenas (MACs) usando SHA-256. Luego cifra/descifra datos aplicando XOR con un bloque SHA-256 derivado de la clave + salt de 4 bytes (salt incluida en el ciphertext).
Para enviar mensajes, la aplicación coloca los datos en la cola to_send, donde el hilo sender_thread los procesa. Este hilo cifra el mensaje con xor_encrypt, construye una trama Ethernet personalizada usando tools.build_frame y la envía directamente por el socket RAW. Así, los mensajes viajan entre nodos sin necesidad de protocolos superiores como TCP o UDP.
El hilo receiver_thread escucha continuamente en el socket y, al recibir una trama, la descifra y analiza su tipo (texto, archivo, ACK o descubrimiento). Dependiendo del contenido, la información se guarda en la cola to_receive o en estructuras dedicadas para reconstruir archivos. Este proceso permite que los nodos intercambien datos de forma directa y segura a nivel de enlace.
El metodo selective_repeat_manager se encarga de controlar la retransmisión confiable de fragmentos (frames) de archivos en la aplicación P2P. Funciona como un gestor automático que revisa constantemente qué fragmentos no han sido confirmados (ACK) por el receptor y decide si deben reenviarse.
Para hacerlo, recorre todos los archivos pendientes, selecciona los frames sin confirmar dentro de una ventana de transmisión limitada y verifica si ha pasado suficiente tiempo desde el último envío. Si un frame tarda demasiado sin recibir respuesta, lo reenvía por el socket y actualiza su tiempo y contador de reintentos. Cuando todos los frames de un archivo son confirmados, el archivo se elimina de la lista de pendientes. En cambio, si algún frame supera el número máximo de reintentos permitidos, el sistema marca el archivo como fallido y lo descarta.
En mi aplicación, el descubrimiento de dispositivos se realiza automáticamente mediante el envío periódico de mensajes de broadcast. Cada 30 segundos, un hilo envía un paquete tipo 4 que anuncia la presencia del dispositivo en la red local. Los demás nodos que reciben este mensaje responden con un paquete tipo 5, indicando que están activos. Al recibir estas respuestas, la aplicación registra o actualiza la información de cada peer, guardando su nombre y el momento en que fue visto por última vez. Además, un hilo de limpieza se encarga de eliminar los dispositivos que no han respondido en más de dos minutos, manteniendo actualizada la lista de peers disponibles.
En mi aplicación, cuando se envía un archivo, este primero se lee completamente en bytes y se divide en fragmentos de 1400 bytes. Cada fragmento se cifra con una clave generada a partir de las direcciones MAC del emisor y receptor, y luego se empaqueta en una trama con información como el número de fragmento, el total y un identificador único del archivo. Todos los fragmentos se registran en una lista de espera de confirmaciones (ACK) para asegurar su correcta recepción. Finalmente, se envía un mensaje inicial notificando al receptor que comenzará la transferencia del archivo.
Para enviar una carpeta, la aplicación primero la comprime en un archivo temporal con formato .tar, conservando su estructura interna. Luego, ese archivo comprimido se envía utilizando el mismo proceso de fragmentación, cifrado y empaquetado que en el envío de archivos normales. Una vez completada la transferencia, el archivo temporal se elimina automáticamente para liberar espacio.
