Transferencia de archivos
ESTA PÁGINA ESTÁ OBSOLETA: LEER File transfer
¿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
When you send a file, the other has to accept it. At this moment you will see “awaiting peer”:
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
¿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).
First, Alice will request a connection to Bob. To do that, Jami is using ICE (RFC 6544), a protocol used to negotiate links between peers. Alice will send, into an encrypted packet via the DHT the IP address of its device. So, when Bob receives the IP addresses of Alice, they will be able to negotiate a transport where Bob will be able to send packets to Alice. The negotiation can be successful, but if it fails, a TURN server will be used (the one configured into the settings) to perform the transfer. If the negotiation succeeds, Bob will send its IP addresses to Alice to perform the negotiation in the other direction. Note that the link is still not secure, so Bob will send the IP addresses through the DHT network in an encrypted message. If the second negotiation fails, the TURN will be used as a fallback.
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:
A client will call
DataTransferFacade::sendFile()
.DataTransferFacade
is the class corresponding to the API exposed for the clients. It is used to manage a view of the file transfers (the corresponding classes areDataTransfer
,IncomingFileTransfer
,OutgoingFileTransfer
andSubOutgoingFileTransfer
). This method will ask the linkedJamiAccount
to request a connection.The method
DhtPeerConnector: requestConnection()
is triggered and creates a connection between all connected devices of the peer (found on the DHT).DhtPeerConnector
is used to manage the main event loop which manage connections. When a device is found, the event loop will create aClientConnector
(which manage the connection for one device) and launch theprocess()
method.This method is used to initialize the ICE transport and put a PeerConnectionMsg (which contains the SDP message, see below) on the DHT and waits for a response (
DhtPeerConnector::Impl::onResponseMsg
).Then a response is received from the DHT, which contains public addresses of the peer device. We can now negotiate a TLS link (directly via ICE, or via TURN as a fallback). This
TlsSocketEndpoint
is given to thePeerConnection
object as an output and the transfer can start.When the TLS socket is ready, the callback
DataTransferFacade::Impl::onConnectionRequestReply
is called, and aOutgoingFileTransfer
is linked to thePeerConnection
as an input. ThisOutgoingFileTransfer
contains a list ofSubOutgoingFileTransfer
(one per device) where each sub transfer is a transfer to one device. We do that to be able to furnish the most optimistic view of the transfer (if a contact as 3 devices, where the contact cancel the transfer on one device, but accepted the transfer on the two others, the most advanced transfer will be shown).The
SubOutgoingFileTransfer
will first transfer the header of the file, wait the peer acceptance (A «GO\n» message on the socket) and then will send the file.If a cancel is received from the peer or the client or if the file transfer finish, the connection will be closed via a
CANCEL
message on theDhtPeerConnector::eventLoop()
and the resources will be released.
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
Recibir un archivo
La misma estructura se utiliza para recibir archivos, pero el método cambia un poco:
La clase
JamiAccount
se utiliza para recibir mensajes del DHT, porque lo primero que se recibirá será la solicitud del DHT.Luego, este mensaje se le da a
DhtPeerConnector: onRequestMessage()
a través del eventLoop.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).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 laIncomingFileTransfer
como entrada.
Re-pedir una transferencia de archivos anterior
Como se especifica en Other mime types, las interacciones de transferencia de datos ahora se sincronizan y almacenan en conversaciones. Por lo tanto, un dispositivo puede detectar fácilmente si un archivo se descargó o no. De lo contrario, puede solicitar a todos los miembros de la conversación que transmitan el archivo nuevamente.
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
Where 0d04b932
is the ufrag and 7c33834e7cf944bf0e367b47
the password of the ICE session.
2130706431
and 1694498815
are the priority of the candidates.
192.168.0.126 42751 typ host tcptype passive
is a passive host candidate and 1694498815 X.X.X.X 42751 typ srflx tcptype passive
a passive host reflecting the public IP address (mapped via UPnP for example).
Dispositivos múltiples
Un usuario puede vincular su cuenta a varios dispositivos. Entonces, necesitamos implementar la transferencia cuando un usuario envía un archivo a un contacto que tiene varios dispositivos vinculados a esta cuenta.
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.
Ahora (desde https://review.jami.net/c/jami-daemon/+/9327), cuando un usuario envíe un archivo, solicitará una Conexión entre pares con todos los dispositivos entre pares. Y para todas las conexiones, adjuntamos un nuevo flujo de entrada para tener la capacidad de aceptar/rechazar/cancelar cada transferencia por separado.
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"
Luego, puede configurar el servidor TURN en la configuración avanzada de la aplicación.
Nota
This needs some technical knowledge. Moreover, the TURN server should see the same IP address of your node as the destination node, or the peer connection will fail (because the authorization will be incorrect).
Lista de todos
¿Usas libtorrent?
Muestre el estado de las subtransferencias para archivos salientes