Transferencia de archivos

Este PAJINA SE DEPRECATÓ: LEER desarrollador/grupo:transferencia de archivos

¿Cómo usarlo?

Android

Cuando estás hablando con alguien en Android, tienes la posibilidad de enviar una foto en tu dispositivo o tomar una foto con estos botones:

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡

Nota: cuando envías un archivo, el otro tiene que aceptarlo. En este momento verás “esperando a un compañero”:

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡

¿Cómo funciona?

Cómo funciona

Introducción

Jami es una aplicación distribuida y tiene que funcionar sin conectividad a Internet. Así que, transferencia de archivos también! Básicamente, usamos el mismo método para realizar transferencias de archivos y llamadas, pero en TCP. Para resumir cómo funciona, podemos imaginar una situación en la que Alice (A) quiere transferir un archivo a Bob (B).

Para ello, Jami está utilizando ICE (RFC 6544), un protocolo utilizado para negociar enlaces entre pares. Alice enviará, a un paquete cifrado a través del DHT, el IP de su dispositivo. Así, cuando Bob reciba los ips de Alice, podrán negociar un transporte donde Bob podrá enviar paquetes a Alice. La negociación puede ser exitosa, pero si falla, se utilizará un servidor TURN (el configurado en las configuraciones) para realizar la transferencia. Si la negociación tiene éxito, Bob enviará sus ips a Alice para realizar la negociación en la otra dirección.

Ahora que el enlace TCP bidireccional está aquí, el siguiente paso será negociar un TLS 1.3 (generalmente un (TLS1.3)-(DHE-FFDHE8192)-(RSA-PSS-RSAE-SHA384)-(AES-256-GCM) cuando escriba estas líneas) entre Alice y Bob, entonces Alice comenzará a transferir el archivo.

La primera parte será un pequeño encabezado para describir el contenido del archivo.

Proceso

Enviando un archivo

Se utiliza el siguiente método:

1. Un cliente llamará DataTransferFacade::sendFile() . DataTransferFacade es la clase correspondiente a la API expuesta para los clientes. Se utiliza para administrar una vista de las transferencias de archivos (las clases correspondientes son DataTransfer, IncomingFileTransfer, OutgoingFileTransfer y SubOutgoingFileTransfer). Este método pedirá a la JamiAccount vinculada a solicitar una conexión.

¡[Diagrama: Diagrama de clase de transferencia de datos]images/file-transfer-dataatransfer-class-diagram.png)

2. El método DhtPeerConnector: requestConnection() se activa y crea una conexión entre todos los dispositivos conectados del peer (que se encuentran en la DHT). DhtPeerConnector se utiliza para administrar el bucle principal de eventos que gestionan las conexiones. Cuando se encuentra un dispositivo, el bucle de eventos creará un ClientConnector (que gestiona la conexión para un dispositivo) y lanzará el método proceso) .

3. Este método se utiliza para iniciar el transporte ICE y colocar un PeerConnectionMsg (que contiene el mensaje SDP, véase más adelante) en el DHT y esperar una respuesta (DhtPeerConnector::Impl::onResponseMsg).

4. Luego se recibe una respuesta del DHT, que contiene direcciones públicas del dispositivo de pares. Ahora podemos negociar un enlace TLS (directamente a través de ICE, o a través de TURN como una retroceso). Este TlsSocketEndpoint se da al objeto PeerConnection como salida y se puede iniciar la transferencia.

Cuando el socket TLS está listo, se llama la llamada de regreso DataTransferFacade::Impl::onConnectionRequestReply, y un OutgoingFileTransfer se vincula a la PeerConnection como entrada. Este OutgoingFileTransfer contiene una lista de SubOutgoingFileTransfer (uno por dispositivo) donde cada subtransfer es una transferencia a un dispositivo. Lo hacemos para poder proporcionar la visión más optimista de la transferencia (si un contacto como 3 dispositivos, donde el contacto cancela la transferencia en un dispositivo, pero aceptó la transferencia en los otros dos, se mostrará la transferencia más avanzada).

6. El SubOutgoingFileTransfer primero transferirá el encabezado del archivo, esperará la aceptación por pares (un mensaje «GO\n» en el socket) y luego enviará el archivo.

7. Si se recibe una cancelación del peer o del cliente o si la transferencia de archivos termina, la conexión se cerrará a través de un mensaje CANCEL en el DhtPeerConnector::eventLoop() y se liberarán los recursos.

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡

Recibir un archivo

La misma estructura se utiliza para recibir archivos, pero el método cambia un poco:

  1. La clase JamiAccount se utiliza para recibir mensajes del DHT, porque lo primero que se recibirá será la solicitud del DHT.

  2. Luego, este mensaje se le da a DhtPeerConnector: onRequestMessage() a través del eventLoop.

  3. El DhtPeerConnector::Impl::answerToRequest intentará conectarse al servidor TURN (si no está conectado) e iniciar el transporte ICE. Este método abrirá 2 conexiones de control a un servidor TURN (una para autorizar pares IPv4, otra para pares IPv6, debido a RFC 6156) si ya no está abierto y permite que las direcciones públicas de pares se conecten. Luego, si el SDP recibido no contiene candidatos ICE, utilizará el TURN y elaborará la respuesta SDP para esperar al pares. Si el SDP contiene candidatos ICE, el método intentará negociar el enlace (o retroceder en el TURN) y luego responder al SDP (con candidatos ICE o no).

  4. Una vez que los enlaces están listos, como el remitente, se negocia un enlace TLS y se le da a la PeerConnection dado a la IncomingFileTransfer como entrada.

Re-pedir una transferencia de archivos anterior

Como se especifica en developer/swarm:Other mime types, las interacciones de transferencia de datos se sincronizan y se almacenan en conversaciones. Así, un dispositivo puede detectar fácilmente si un archivo se descargó o no. Si no, puede pedir a todos los miembros de la conversación que transmitan el archivo de nuevo.

Para ello, el dispositivo enviará un json con el tipo de mime: application/data-transfer-request+json que contiene conversation (id de la conversación), interaction (interacción relacionada), deviceId el dispositivo que recibe el archivo.

El remitente ahora verifica si el dispositivo es un dispositivo del compañero anunciado y que el dispositivo es un miembro de la conversación, y puede enviar el archivo a través de una transferencia de archivos clásica.

El receptor ahora puede aceptar la primera transferencia entrante, descargar el archivo y verificar que la sha3sum es correcta.

Esquema

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡

SDP enviado por el DHT
0d04b932
7c33834e7cf944bf0e367b47
H6e6ca682 1 TCP 2130706431 2607:fad8:4:6:9eb6:d0ff:dead:c0de 50693 typ host tcptype passive
H6e6ca682 1 TCP 2130706431 2607:fad8:4:6:9eb6:d0ff:dead:c0de 9 typ host tcptype active
H42c1b577 1 TCP 2130706431 fe80::9eb6:d0ff:fee7:1412 50693 typ host tcptype passive
H42c1b577 1 TCP 2130706431 fe80::9eb6:d0ff:fee7:1412 9 typ host tcptype active
Hc0a8007e 1 TCP 2130706431 192.168.0.123 42751 typ host tcptype passive
Hc0a8007e 1 TCP 2130706431 192.168.0.123 9 typ host tcptype active
Sc0a8007e 1 TCP 1694498815 X.X.X.X 42751 typ srflx tcptype passive
Z.Z.Z.Z:YYYY
A.A.A.A:YYYY

Donde 0d04b932 es el ufrag y 7c33834e7cf944bf0e367b47 la contraseña de la sesión ICE. 2130706431 y 1694498815 son la prioridad de los candidatos. 192.168.0.126 42751 tipo de anfitrión tcptype pasivo es un anfitrión pasivo candidato y 1694498815 X.X.X 42751 tipo srflx tcptype pasivo un anfitrión pasivo que refleja la ip pública (mapeado a través de UPnP por ejemplo).

Dispositivos múltiples

A user can link its account to several devices. So, we need to implement the transfer when a user send a file to a contact who have multiple devices linked to this account.

Primero enfoque

El primer enfoque fue enviar una solicitud a través del DHT a todos los dispositivos y los primeros dispositivos que respondieron obtienen el archivo para transferir.

Enfoque actual

Ahora, todavía enviamos una solicitud a todos los dispositivos. La diferencia es que todos los dispositivos tendrán la notificación para recibir un archivo y pueden aceptar / rechazar la transferencia. La mayor parte del código para eso está en data_transfer.cpp.

Now (since https://review.jami.net/c/jami-daemon/+/9327), when a user send a file, it will request a PeerConnection with all peer devices. And for all connections, we attach a new input stream to have the ability to accept/refuse/cancel each transfer separately.

En data_transfer.cpp definimos la clase OptimisticMetaOutgoingInfo que representa la vista optimista para mostrar al cliente. Es optimista porque si un contacto acepta una transferencia en un dispositivo y se niega en otros, esta clase mostrará la transferencia de archivos en curso. Y solo mostrará un error si todos los dispositivos rechazan la transferencia.

Esta clase está vinculada a SubOutgoingFileTransfer que representan el estado de una transferencia con un dispositivo. Los clientes tendrán la capacidad de mostrar una subtransferencia en lugar de la optimista más adelante (ver lista TODO).

Usando otro servidor TURN

Actually the default TURN server is turn.jami.net. But you can host your own TURN server. For example by running a coturn server.

sudo turnserver -a -v -n -u usuario: contraseña -r "realm"

Then, you can configure the TURN server in the advanced settings of the app.

Nota: esto requiere algunos conocimientos técnicos. Además, el servidor TURN debe ver la misma dirección IP de su nodo que el nodo de destino o la conexión de pares fallará (porque la autorización será incorrecta)

Lista de todos

  1. Use libtorrent?

  2. Muestre el estado de las subtransferencias para archivos salientes