Transfert de fichiers
CE PASSE EST DEPRÉCÉTée: LIRE développeur/groupe:transfert de fichiers
Comment l’utiliser?
Android
Lorsque vous parlez à quelqu’un sur Android, vous avez la possibilité d’envoyer une photo sur votre appareil ou de prendre une photo avec ces boutons:
Je suis en train de faire une vidéo de mon blog.
Remarque: lorsque vous envoyez un fichier, l’autre doit l’accepter.
Je suis en train de faire une vidéo de mon blog.
Comment ça marche?
Comment ça marche
Introduction
Jami est une application distribuée et doit fonctionner sans connectivité Internet. Donc, le transfert de fichiers aussi! fondamentalement, nous utilisons la même méthode pour effectuer le transfert de fichiers et les appels, mais en TCP. Pour résumer comment cela fonctionne, nous pouvons imaginer une situation où Alice (A) veut transférer un fichier à Bob (B).
Premièrement, Alice demandera une connexion à Bob. Pour ce faire, Jami utilise ICE (RFC 6544), un protocole utilisé pour négocier des liens entre pairs. Alice enverra, dans un paquet crypté via le DHT, l’IP de son appareil. Ainsi, lorsque Bob recevra les ips d’Alice, ils seront en mesure de négocier un transport où Bob sera en mesure d’envoyer des paquets à Alice. La négociation peut être réussie, mais si elle échoue, un serveur TURN (celui configuré dans les paramètres) sera utilisé pour effectuer le transfert. Si la négociation réussit, Bob enverra ses ips à Alice pour effectuer la négociation dans l’autre direction. Notez que le lien n’est toujours pas envoyé, donc Bob enverra les ips via le DHT dans un message crypté. Si la deuxième négociation échoue, le TURN sera utilisé comme une rétroaction.
Maintenant que le lien TCP bidirectionnel est ici, la prochaine étape sera de négocier un TLS 1.3 (généralement un (TLS1.3)-DHE-FFDHE8192)-RSA-PSS-RSAE-SHA384)-AES-256-GCM) entre Alice et Bob, puis Alice commencera à transférer le fichier.
La première partie sera une petite en-tête pour décrire le contenu du fichier.
Processus
Envoyer un dossier
La méthode suivante est utilisée:
1. Un client appellera DataTransferFacade::sendFile()
. DataTransferFacade
est la classe correspondant à l’API exposée pour les clients. Il est utilisé pour gérer une vue des transferts de fichiers (les classes correspondantes sont DataTransfer
, IncomingFileTransfer
, OutgoingFileTransfer
et SubOutgoingFileTransfer
). Cette méthode demandera au JamiAccount
lié de demander une connexion.
[Diagramme: diagramme de classe de transfert de données] images/file-transfer-data-transfer-class-diagram.png)
2. La méthode DhtPeerConnector: requestConnection()
est activée et crée une connexion entre tous les appareils connectés du pair (trouvés sur le DHT). DhtPeerConnector
est utilisé pour gérer la boucle d’événements principaux qui gèrent les connexions.
3. Cette méthode est utilisée pour initialiser le transport ICE et mettre un PeerConnectionMsg (qui contient le message SDP, voir ci-dessous) sur le DHT et attendre une réponse (DhtPeerConnector::Impl::onResponseMsg
).
4. Ensuite, une réponse est reçue du DHT, qui contient des adresses publiques du périphérique de pair. Nous pouvons maintenant négocier un lien TLS (directement via ICE, ou via TURN comme une rétroaction). Ce TlsSocketEndpoint
est donné à l’objet PeerConnection
comme une sortie et le transfert peut commencer.
5.\ Lorsque la prise TLS est prête, l’appel de retour DataTransferFacade::Impl::onConnectionRequestReply
est appelé, et un OutgoingFileTransfer
est lié au PeerConnection
comme entrée. Ce OutgoingFileTransfer
contient une liste de SubOutgoingFileTransfer
(un par appareil) où chaque sous-transfer est un transfert vers un appareil. Nous faisons cela pour pouvoir fournir la vue la plus optimiste du transfert (si un contact comme 3 appareils, où le contact annule le transfert sur un appareil, mais accepte le transfert sur les deux autres, le transfert le plus avancé sera affiché).
6. Le SubOutgoingFileTransfer
transfère d’abord l’en-tête du fichier, attend l’acceptation par les pairs (un message « GO\n » sur la prise) et envoie ensuite le fichier.
7. Si une annulation est reçue du peer ou du client ou si le transfert de fichier est terminé, la connexion sera fermée via un message CANCEL
sur le DhtPeerConnector::eventLoop()
et les ressources seront libérées.
Réception d’un dossier
La même structure est utilisée pour recevoir des fichiers, mais la méthode change un peu:
La classe
JamiAccount
est utilisée pour recevoir des messages du DHT, car la première chose reçue sera la demande DHT.Ensuite, ce message est transmis à
DhtPeerConnector: onRequestMessage()
via l’événementLoop.Le
DhtPeerConnector::Impl::answerToRequest
tentera de se connecter au serveur TURN (si ce n’est pas connecté) et d’initialiser le transport ICE. Cette méthode ouvre 2 connexions de contrôle à un serveur TURN (une pour autoriser les pairs IPv4, une autre pour les pairs IPv6, en raison de RFC 6156) si elle n’est pas déjà ouverte et permet aux adresses publiques de pairs de se connecter.Une fois que les liens sont prêts, comme l’expéditeur, un lien TLS est négocié et donné à la
PeerConnection
donné à laIncomingFileTransfer
comme entrée.
Re- demande pour un transfert de fichier précédent
Comme spécifié dans developer/swarm:Other mime types, les interactions de transfert de données sont désormais synchronisées et stockées dans des conversations. Ainsi, un appareil peut facilement détecter si un fichier a été téléchargé ou non.
Pour ce faire, l’appareil enverra un json avec le type mime: application/data-transfer-request+json
contenant conversation
(id de la conversation), interaction
(interaction liée), deviceId
l’appareil recevant le fichier.
L’expéditeur vérifie maintenant si l’appareil est un appareil de l’annonceur et que l’appareil est un membre de la conversation, et peut envoyer le fichier via un transfert de fichier classique.
Le récepteur peut maintenant accepter le premier transfert entrant, télécharger le fichier et vérifier que la somme sha3 est correcte.
Schéma
[Diagramme: schéma principal]
SDP envoyé par le 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
Où 0d04b932
est l’ufrag et 7c33834e7cf944bf0e367b47
le mot de passe de la session ICE. 2130706431
et 1694498815
sont la priorité des candidats. 192.168.0.126 42751 type hôte tcptype passif
est un candidat hôte passif et 1694498815 X.X.X.X 42751 type srflx tcptype passif
un hôte passif reflétant l’IP public (mappé par exemple via UPnP).
Des appareils multiples
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.
Première approche
La première approche consistait à envoyer une demande via le DHT à tous les appareils et les premiers appareils qui répondent obtiennent le fichier à transférer.
Approche actuelle
Maintenant, nous envoyons toujours une demande à tous les appareils. La différence est que tous les appareils auront la notification de recevoir un fichier et peuvent accepter/rejeter le transfert. La plupart du code pour cela est dans 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.
Dans data_transfer.cpp nous définissons la classe OptimisticMetaOutgoingInfo qui représente la vue optimiste à montrer au client. C’est optimiste parce que si un contact accepte un transfert sur un appareil et refuse sur d’autres, cette classe affichera le transfert de fichier en cours. Et il ne montrera une erreur que si tous les appareils refusent le transfert.
Cette classe est liée à SubOutgoingFileTransfer qui représentent l’état d’un transfert avec un seul appareil. Les clients auront la possibilité d’afficher un transfert sous-optimisé plus tard (voir liste TODO).
Utilisation d” un autre serveur 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 tourne-serveur -a -v -n -u utilisateur: mot de passe -r « realm »
Then, you can configure the TURN server in the advanced settings of the app.
Remarque: cela nécessite des connaissances techniques. En outre, le serveur TURN devrait voir la même adresse IP de votre nœud que le nœud de destination ou la connexion partagée échouera (car l’autorisation sera incorrecte)
Liste de TODO
Use libtorrent?
Afficher l’état des sous-transférences pour les fichiers sortants