goffi goffi

Parlons XMPP - épisode 10 - copie de fichiers et Jingle (suite)

pour lire les épisodes précédents, suivez l'étiquette correspondante

Maintenant que nous avons vu la copie de fichiers « classique » et ses défauts, abordons une technologie qui a fait beaucoup parler d'elle — et à raison — quand elle est arrivée : Jingle.

Pour la petite histoire, Jingle est une technologie qui résulte d'un effort commun entre des membres de la XSF et une équipe chez Google qui travaillait sur un protocole de voix sur IP (VoIP). La page Wikipédia retrace succinctement l'historique. La technologie Web « WebRTC » hérite et s'inspire de ce travail.

Jingle est souvent considéré à tort comme une technologie dédiée à la visioconférence. En réalité, c'est une technologie qui permet d'établir une session Pair à Pair (P2P) et de la contrôler de manière très souple. Elle a bien été pensée à l'origine pour la visioconférence, et la XEP-0167 s'appuie dessus à cet effet, mais toute application utilisant des connexions directes (et il y en a beaucoup !) peuvent profiter de Jingle : travail collaboratif, tableau blanc, jeux, chiffrement de bout en bout (en évitant ainsi le serveur), partage d'écran, etc. Nous allons nous intéresser plus particulièrement à une de ces applications : le transfert de fichiers.

Jingle fait une séparation claire entre l'application (ici le transfert de fichier), les transports (nous allons retrouver les connexions « in-band » et « SOCKS5 » mentionnées dans le dernier article), et la gestion de session.
Les applications et les transports sont décrits dans des extensions à part : la copie de fichiers est décrite dans la XEP-0234 « Jingle File Transfert ». Vous noterez qu'elle est toujours au statut « d'expérimental » : étant une pièce majeure du futur de XMPP, le travail est long pour obtenir quelque chose de solide et souple. Pour les transports, nous allons donc réutiliser les XEP-0047 et XEP-0065 décrites dans le dernier article, mais en utilisant respectivement les XEP-0261 et XEP-0260 pour les adapter à Jingle. Il faut donc utiliser pas moins de 6 XEPs pour la copie de fichiers avec Jingle (2 d'entre elles servant à la réutilisation d'anciennes), et il est probable que d'autres viennent étendre les possibilités par la suite, en particulier des nouveaux transports (*). Cela peut sembler un peu compliqué, mais c'est ce qui permet la souplesse de Jingle.

Il est possible de modifier ou remplacer à tout moment un transport ou une application, et c'est là la grande force du protocole. Une vidéo passe mal à cause d'une connexion trop faiblarde ? On change l'application pour avoir une vidéo en qualité dégradée. Une connexion SOCKS5 est impossible à établir ? On remplace le transport par un transport « in-band ». Ce dernier cas appelé « plan de secours » (fallback en anglais) était un des problèmes mentionné dans le dernier article, l'ancienne méthode n'indiquant pas comment changer de transport.

Voyons maintenant le fonctionnement. Encore une fois je ne vais pas entrer trop dans les détails, vous pouvez lire la XEP si vous souhaitez les connaître.

Une session Jingle se décide et contrôle à travers le flux XML de XMPP, pour établir une connexion P2P le plus souvent externe (c.-à-d. en dehors du flux XMPP). Une session propose des contenus (« contents »). Un contenu est composé d'une application (transfert de fichier, Vidéo via RTP, etc) et d'un transport (« in-band », « SOCKS5 », « ICE-UDP », etc). L'intérêt principal d'avoir plusieurs contenus est qu'ils sont liés dans la session : par exemple pour une visioconférence, un contenu peut s'occuper de la vidéo, et un autre de l'audio. Si un contenu dans le même logiciel mais non directement lié à la session est utilisé (par exemple un fichier est envoyé au cours de la conversation), on préférera créer une nouvelle session Jingle en parallèle plutôt qu'ajouter un contenu.

Au moment de la création de la session, nous avons 2 entités qui communiquent : l'initiateur (« initiator ») et le destinataire (« responder »). L'initiateur propose des paramètres et/ou une information pour l'application (par exemple des « codecs » pour une vidéo, ou des informations sur le fichier à transférer) ainsi que pour le transport (pour SOCKS5 les candidats par exemple). Si le destinataire accepte la session, il négocie les paramètres en retour pour l'application (par exemple les codecs proposés qu'il connaît) ou le transport (il indique ses propres candidats dans le cas de SOCKS5).

Quand la session est acceptée, elle est considérée « active », mais il n'est pas encore possible d'échanger des données pour autant : il faut d'abord terminer la négociation et accepter un transport (dans le cas de SOCKS5 ça signifie trouver le meilleur candidat, ou changer de transport, probablement pour « in-band »). Une fois tout en place on peut échanger les données, et éventuellement faire des changements en cours d'utilisation comme expliqué plus haut, ou donner des informations (par exemple indiquer qu'un correspondant a coupé le son (« mute »), ou qu'une sonnerie est en cours). Selon les applications, des cas plus compliqués peuvent apparaître, comme changer le sens de transmission de données, rediriger une session (d'un appareil vers un autre par exemple), etc.

Un autre point important avec Jingle, c'est qu'il est possible de demander une pré-condition de sécurité dans une session, par exemple on peut exiger qu'une session soit chiffrée de bout en bout.

Voici une petite liste non exhaustive des améliorations apportées par Jingle rien que pour le transfert de fichiers :

  • une vraie méthode de secours (« fallback »)
  • les XEP-0260 et XEP-261 adaptent les XEP-0065 et XEP-0047 en tirant vraiment profit de Jingle. Ainsi la XEP-0260 permet au destinataire de fournir ses propres candidats, s'inspirant d'une extension jamais standardisée de l'ancienne méthode (appelée « fast-mode »). C'est une grosse avancée, car dans l'ancienne méthode le destinataire doit accepter (et réussir à joindre) les candidats de l'initiateur sinon la connexion échoue. L'échec peut arriver dans de nombreux cas, et si l'initiateur n'a pas de proxy, mais le destinataire en a un, celui du destinataire ne peut pas être utilisé.
    Dans la méthode utilisée avec Jingle, le destinataire peut proposer son proxy, ou la connexion peut s'établir si l'initiateur est injoignable (derrière un NAT par exemple), mais pas le destinataire. L'échec est beaucoup plus rare
  • il est possible de fournir la somme de contrôle (« hash ») quand on le souhaite, et ainsi la calculer au fur et à mesure. Avec l'ancienne méthode c'est tout au début ou rien, ce qui risque de provoquer un ralentissement avant le transfert s'il faut faire le calcul pour un gros fichier
  • avec la XEP-0234, l'initiateur peut demander un fichier au destinataire, au lieu d'uniquement pouvoir lui en proposer un
  • la XEP-0234 permet aussi l'ajout de fichiers en cours de session
  • le chiffrement de bout en bout est possible et prévu, bien que non encore standardisé
  • « ICE-TCP » est en cours de standardisation et devrait arriver cette année (*), permettant de mieux traverser les NATs

Au final, il est quasiment impossible d'échouer un transfert de fichier via Jingle. Le principal cas que je vois est si un des serveurs a une politique interdisant un tel transfert. Cependant, la solution de secours via le flux XMPP « in-band » est gourmande en ressources et très lente, c'est pourquoi il y a du travail sur de nouveaux transports comme ICE-TCP. Ces nouveaux transports serviront à toute application basée sur Jingle : réutiliser l'existant est un des gros points forts de Jingle, et de XMPP en général.

Jingle est une excellente technologie, avec un gros potentiel. Avec PubSub, c'est probablement un des gros piliers du XMPP de demain.

J'en profite pour rappeler que ce blog vient de passer de Dotclear à Salut à Toi, autrement dit il est désormais entièrement basé sur XMPP. J'ai publié une petite série d'articles expliquant la mise en place d'un blog XMPP avec Libervia, son intégration dans une configuration Apache, l'import d'un blog Dotclear et enfin la publication de billets : à lire par ici.

Pour le prochain article, je ne suis pas décidé. Il est possible que je parle de chiffrement de bout en bout vu que c'est un domaine qui bouge en ce moment, ou que je continue sur la lancée Jingle avec les dépôts de fichiers. Cependant j'ai de moins en moins de temps libre, et je préfère consacrer le peu disponible au développement de SàT, le développement de la version bureau/mobiles promise en fin d'année dernière ayant commencé.

(*) cet article ayant été rédigé il y a plusieurs semaines, entre temps la XEP en question est sortie : XEP-0371

centralisé, décentralisé, P2P, mais c'est quoi tout ça ?

Une petite mise au point technique, parce que je vois qu'il y a beaucoup de confusion sur les termes « centralisé » (encore lui ça va), « décentralisé », « distribué », « fédéré », « pair à pair », etc.

Il faut dire que la confusion est assez normale, il n'y a pas vraiment de définition de ces termes, et ce que les gens entendent en les employant dépend de leurs lectures, leur compréhension, et leur sensibilité.

Commençons par le plus simple : centralisé. Un système centralisé c'est un système où tout le monde dépend d'une même autorité, un serveur a priori dans le cas informatique. Bien qu'un système centralisé soit beaucoup plus simple à faire sur le plan technique (facile de trouver des gens ou des informations quand ils sont tous au même endroit), il peut avoir ses propres problèmes : montée en charge en particulier ; il est plus difficile d'absorber des données quand il n'y a qu'un centre de traitement, les tuyaux peuvent rapidement se trouver trop petits, etc.

Un système de communication centralisé pose de nombreux problèmes : il est évident qu'il est plus facile d'espionner, censurer ou modifier des données quand elles sont dépendantes d'un seul point. Même sans intention malicieuse, on a un point unique de défaillance (ce que les anglophones appellent « single point of failure »), c.-à-d. qu'une panne, une attaque, une catastrophe naturelle ou pas provoque l'arrêt du service voire la perte des archives.
Dans les cas les plus gros, on prend un hangar et on le remplit d'ordinateurs, ce sont les fameux centres de données ou « data centers ».

Là où ça se complique un peu, c'est qu'un système centralisé peut être physiquement en plusieurs endroits, ou utiliser des systèmes de répartition/répétition des données. Le principe est d'éviter l'engorgement ou les risques de pannes cités plus haut, mais même si ces machines sont séparées et communiquent entre elles à distance, elles sont a priori toujours sous la même autorité.


http://repos.goffi.org/sat_docs/raw-file/tip/schemas/decentralisation/centralised_simple.png


Passons maintenant aux systèmes décentralisés/distribués/fédérés. Certains vont pousser les haut-cris que je mette tout ça ensemble, parce qu'il n'y pas vraiment de définition et que chacun se fait plus ou moins la sienne.

« dé-centralisé » veut dire qui n'a pas de centre, ni plus ni moins. L'idée pour un système de communication, c'est que toute entité (individu, association, organisation, etc) puisse être une partie d'un réseau qui n'a pas d'autorité principale, et que ces autorités puissent parler entre elles.

On essaye ainsi d'éviter les problèmes de la centralisation, mais on se retrouve avec tout un tas de nouveaux problèmes, techniques pour la plupart : il est beaucoup plus difficile de retrouver des données ou des gens en plusieurs endroits, de se mettre d'accord sur la « langue » à utiliser pour communiquer (surtout quand on a des logiciels ou des versions d'un même logiciel différents), ou encore d'être sûr que la donnée qu'on a est à jour (est-ce que le message a été modifié ou supprimé ?).

« fédéré » est généralement employé pour parler de systèmes différents (noms de domaines différents par exemple, voire logiciels différents) qui peuvent communiquer entre eux. Un système décentralisé est fédéré par nature, sinon on a affaire à plusieurs systèmes centralisés indépendants. Disons que si on veut être pointilleux, on peut dire qu'un système décentralisé peut communiquer avec seulement certaines entités (je communique avec les serveurs de mon entreprise internationale, mais pas avec le reste du monde), et que la fédération implique l'idée que c'est ouvert à tous (ou presque, il y a souvent des gens qu'on ne veut pas, les spammeurs par exemple).

« distribué » ne devrait pas être employé pour les systèmes de communication. Le terme est normalement utilisé pour le calcul : si votre ordinateur a plusieurs processeurs, il distribue la charge de calcul entre eux, ou dans le cas de très grosses demandes (recherche par exemple), on peut demander à plusieurs machines distantes de faire chacun une partie d'une grosse opération mathématique. Dans ce cas, l'organisation de la répartition est souvent contrôlé par une même autorité (par exemple le laboratoire qui veut faire cette opération).
Par extension, le terme est aussi utilisé pour les systèmes de fichiers, et certains l'emploient pour les logiciels de communication, mais cela ne veut pas dire autre chose que décentralisé.


http://repos.goffi.org/sat_docs/raw-file/tip/schemas/decentralisation/decentralised_simple.png


Enfin, il y a le terme P2P ou « pair à pair » (« peer to peer » en anglais). En fait une connexion pair à pair n'est rien d'autre qu'une connexion directe entre 2 ordinateurs, mais on l'associe souvent aux technologies plus ou moins apparentées qui ont commencé à apparaître à la fin des années 90/au début des années 2000 et qui servaient (et servent toujours) principalement à partager des fichiers.

Après Napster (lancé mi 1999) qui était un bête système centralisé qui mettait en relation des machines pour une connexion directe, il y a eu beaucoup d'essais et d'évolutions pour trouver un système qui permet de se passer de serveurs, l'idée étant principalement de permettre au réseau de fonctionner même si on lui coupe l'accès à une partie de lui-même.

Je vous passe toutes les techniques qui sont utilisées : c'est un domaine très pointu, très intéressant, et qui demanderait facilement un livre pour être expliqué. Ça part des systèmes de répartition par propagation de proche en proche à la Usenet, jusqu'aux récentes chaînes de blocs (blockchain), en passant par les tables de hachage distribuée (Distributed Hash Table), etc.

Ce qui fait principalement la différence entre un système « décentralisé » et « entièrement P2P », c'est la place du serveur. Un serveur, dans les grandes lignes, c'est ce qui permet à votre logiciel (le « client ») de contacter d'autres clients via d'autres serveurs. Il est là pour tout un tas de raisons : identifier les gens, donner les bonnes données aux bonnes personnes, garder
les fichiers à donner à un client actuellement hors ligne quand il sera disponible, etc.
Si on supprime le serveur, inévitablement c'est votre client (ou un autre) qui va devoir se charger de ce travail, ce qui aura un impact sur votre bande passante, la charge de travail pour votre processeur (et donc la durée de vie de votre batterie le cas échéant), et compliquera la tâche de votre logiciel (plus difficile de savoir à qui parler et à qui faire confiance quand on n'a pas de serveur comme référence).

http://repos.goffi.org/sat_docs/raw-file/tip/schemas/decentralisation/fully_P2P_simple.png

Pour transformer un système décentralisé avec serveurs en système entièrement P2P (c.-à-d. sans serveur), je vais vous donner une recette : vous mettez un seul client sur votre serveur, et vous mettez le serveur et le client sur la même machine.
Bien sûr si vous voulez être vraiment indépendant, il va falloir supprimer le besoin de points de références, et en particulier le système de noms de domaine ou « Domain Name System ». C'est ce qui associe le nom de votre serveur (par exemple « libervia.org ») à l'adresse « IP » qui permet de vous retrouver sur Internet. Il va falloir aussi être capable de retrouver les données ou les gens un peu partout, et là on se retrouve avec les technologies intéressantes mais complexes évoquées plus haut (« D.H.T. », « Blockchain », « SuperPeer », etc).
 

Et XMPP dans tout ça ?

Je vais quand même parler un peu de XMPP. XMPP est un système dit « hybride », c'est à dire qu'il fonctionne normalement sur un modèle client/serveur, mais il peut faire du P2P à la demande (pour transférer un fichier ou faire de la visioconférence par exemple).
Il est même possible de fonctionner sans serveur sur un réseau local (comme expliqué ici), et il peut parfaitement devenir à terme un système entièrement P2P comme expliqué dans le paragraphe précédent.

Ceci dit, même si l'approche entièrement P2P est séduisante, je pense que l'architecture décentralisée sur un modèle client/serveur est un compromis bien plus efficace : elle limite le travail de votre client, permet une meilleure optimisation du trafic ou du calcul, et facilite l'échange asynchrone (quand deux personnes ne sont pas connectées en même temps). Bref, c'est tout sauf un modèle du passé comme on peut le lire parfois, et bien qu'il y ait plusieurs recherches et options intéressantes pour des systèmes entièrement P2P, il ne faudrait pas jeter le bébé avec l'eau du bain.

SàT: Comment ça marche ?

Salut à vous,

En parallèle de la série d'articles sur XMPP, j'en commence une pour expliquer « Salut à Toi », notre logiciel à tout faire basé sur ce protocole. Il y a beaucoup de choses qui tournent autour de ce logiciel, sur son organisation technique, sa philosophie, et ce qu'on peut faire avec. Aussi je vais faire des articles plus ou moins techniques (plutôt moins), et je vais bientôt expliquer quelques cas concrets d'utilisation.

Ce premier article est un peu technique, puisque je vais expliquer l'organisation générale du logiciel, et ce qu'elle a de particulier.

Donc pour vous donner une idée, SàT c'est dans les grandes lignes ça:

http://ftp.goffi.org/media/pictures/schemas/sat_simplified_overview.png

C'est un client XMPP. Si vous avez lu mes articles, vous savez que XMPP ne signifie pas que « messagerie instantanée », mais beaucoup, beaucoup plus de choses. Le projet SàT essaye non seulement de faire le maximum de ces choses, mais aussi d'expérimenter de nouvelles.

La partie centrale  est la partie « d'arrière-plan » ou « backend » en anglais. C'est elle qui gère le plus gros du logiciel. La partie à droite  sont les « frontaux » (« frontends » en anglais) ou encore les interfaces homme/machine. C'est elles qui gèrent tout l'affichage des informations, ou la réception des commandes et autres messages.

Ce qui fait la force de cette architecture, c'est qu'il est très facile de faire un nouveau frontal, et que le tout représente un seul client. Autrement dit : si vous créez un profil (voir plus bas) sur un frontal, il sera disponible sur tous les autres, si vous envoyez un message d'un côté, il sera visible sur tous les frontaux connectés, l'historique est commun, les fonctionnalités aussi.
En effet, quand on ajoute une fonctionnalité (les messages de groupe par exemple, la copie de fichier, les blogs), c'est dans le « backend » que nous le faisons, et elle se retrouve ainsi disponible partout. Évidemment dans certains cas ça demande du développement particulier pour les interfaces : nous avons un jeu de Tarot par exemple, et on ne dessine pas les cartes de la même manière dans l'interface console (appelée Primitivus) et dans l'interface web (appelée Libervia).

Les interfaces (ou frontaux) disponibles aujourd'hui sont:

  • Libervia : interface web 
  • Primivus : interface de console (avec des fenêtres de type ncurses
  • jp: ligne de commande, permet d'automatiser des tâches facilement, d'envoyer un fichier sans parcourir des menus, d'écrire depuis Vim, etc 

Nous avions une autre interface pour le bureau, appelée « Wix », mais nous l'avons abandonnée, car elle était peu pratique et peu utilisée. Notre campagne de financement en cours permettra de remplacer cette interface et par la même occasion de porter le projet sur Android.

Cette architecture a un autre avantage : il est facile d'intégrer SàT dans des logiciels existants, et avec n'importe quel langage de programmation, mais laissons cela de côté pour le moment.

SàT a également une architecture modulaire via l'utilisation de greffons (ou « plugins » en anglais) au niveau du  sur le schéma : le cœur ne gère que l'essentiel (messages simples, liste de contacts, système de logs, gestion des profils, etc), et toutes les fonctionnalités avancées sont disponibles sous forme de greffons (messages de groupe, blog/microblogs, syntaxes avancées, etc). L'idée est d'une part de pouvoir désactiver les fonctionnalités qu'on ne veut pas, et d'autres part de permettre d'étendre facilement le logiciel : un greffon sera d'autant plus intéressant qu'il sera disponible pour toutes les interfaces. Ainsi un de nos greffons gère les marque-pages (c.-à-d. une liste de salons de discussions) : ils sont utilisables à la fois avec Primitivus (en texte), avec Libervia (graphiquement via le web) ou encore avec jp (en ligne de commande). À terme nous comptons faire un système de téléchargement automatisé de greffons, un peu comme les dépôts de logiciels.

Nous avons besoin de travailler un peu côté serveur, pour notre composant PubSub ou notre annuaire par exemple, nous avons donc aussi quelques travaux de ce côté.

Enfin les profils dont je parlais plus haut sont des comptes locaux associés à un compte XMPP. Ainsi j'ai un profil pour mon compte sur le serveur jabber.fr et un autre pour celui sur libervia.org, je peux utiliser l'un ou l'autre ou les 2 en même temps.

Voilà pour une première introduction, un peu technique parce que je voulais expliquer l'originalité de l'architecture. La prochaine fois je pense parler un plus spécifiquement de Libervia, et du système de blogs/microblogs décentralisé.

N'oubliez pas que nous avons une campagne de financement en cours, et nous avons grand besoin de soutien ! Merci.

Parlons XMPP - épisode 9 - copie de fichiers et Jingle

(pour lire les épisodes précédents, suivez l'étiquette correspondante)

Bien que déjà répété un certain nombre de fois, je le redis : XMPP fait bien plus que de la messagerie instantanée. Une des fonctionnalités qui est apparue rapidement est la copie de fichiers, voyons cela de plus près

Le problème : XMPP étant du XML, il n'est pas vraiment adapté aux données purement binaires comme des fichiers. La solution est de passer par l'extérieur, c'est à dire une autre connexion non XML, et d'utiliser le flux XML pour la gérer, on parle de connexion « out-band ». Malheureusement, parfois il n'est pas possible d'établir cette connexion, alors on passe tout par le flux XML : c'est lent, peu efficace, mais ça fonctionne presque toujours, on parle de connexion « in-band » (qu'on pourrait traduire par « interne »).
Il y a aussi des cas où il est plus simple et efficace de rester « in-band », enfin surtout un : si on envoie très peu de données, comme une petite image (un avatar par exemple).

Comme souvent dans le monde XMPP, plusieurs solutions ont été proposées, expérimentées, parfois adoptées puis dépréciées, jusqu'à ce qu'on trouve et garde celle qui semble convenir le mieux, et qui est a priori la meilleure techniquement.
Commençons par la solution courante, appelée « Stream Initiation » (initiation de flux), elle est définie par la XEP-0095, et la copie de fichier l'utilise via la XEP-0096.

La copie de fichiers est la seule application qui utilise la XEP-0095. Nous avons 2 personnes en jeu : celle qui veut envoyer le fichier, qu'on appellera « l'expéditeur » (« sender » en anglais) et celui qui veut le recevoir, qu'on appellera « le destinataire » (« receiver » en anglais).

La XEP-0096 défini ce qu'on appelle un « profil » pour l'initiation de flux, le profil « transfert de fichier ». Elle sert principalement à transmettre les métadonnées du fichier : une description, sa taille, son nom, sa date de dernière modification, et un « hash », c'est à dire une somme de contrôle pour vérifier que le fichier a été correctement copié. C'est l'algorithme MD5 qui est utilisé ici, pourtant connu pour avoir des failles, même si elles ne sont pas dramatiques dans le cadre d'un transfert de fichier (l'expéditeur étant déjà validé par ailleurs).

Il est également possible d'indiquer une fourchette (« range ») à copier, c'est à dire un point de départ (« offset ») dans le fichier et une longueur (« length »), pratique si un transfert a été interrompu en plein milieu, par une coupure de courant par exemple.

Le reste, c'est la XEP-0095 qui s'en occupe, il s'agit juste de négocier la méthode à utiliser, le destinataire accepte ou non le flux, et choisi une des méthodes. Il y a 2 méthodes principales : la première est le transfert en interne (« In-Band Bytestreams », XEP-0047) qui se contente de transcoder les données en base64.

La deuxième (la XEP-0065, « SOCKS5 Bytestreams ») est plus intéressante, elle utilise SOCKS v5 pour établir une connexion externe (« out-band ») et tenter une connexion directe ou via un « proxy » qui est un élément externe relayant les données. L'utilisation d'un proxy est moins efficace qu'une connexion directe bien entendu (les données passent par un 3ᵉ point), mais est parfois nécessaire si une connexion directe est impossible à cause d'un pare-feu ou d'un NAT par exemple. XMPP permet, grâce à disco (la XEP-0030) de savoir automatiquement si votre serveur propose un proxy.
C'est donc la XEP-0065 qui est à l'origine du nom « proxy65 » couramment utilisé.
Petit détail qui a son importance : dans le cas du transfert direct, la connexion se fait du destinataire vers l'expéditeur (qui a ouvert un port pour l'occasion), aussi la connexion peut échouer dans beaucoup de cas (par exemple l'expéditeur est derrière un NAT). Une méthode a été faite pour améliorer la situation, mais elle n'a jamais été standardisée, vous pouvez la trouver ici : http://delta.affinix.com/specs/stream.html.

Voilà pour la méthode actuelle. Elle pose de nombreux problèmes : c'est uniquement l'expéditeur qui doit proposer et le destinataire accepte ou refuse, il n'y a pas de vraie méthode de secours (appelée « fallback » en anglais), c.-à-d. de méthode pour passer de SOCKS5 (ou « s5b ») au transfert « in-band » (ou « ibb »), et il y a souvent des difficultés pour établir une connexion directe comme expliqué au paragraphe précédent. Bref, ça n'est pas satisfaisant. Mais le problème est assez complexe, il n'est pas si simple de faire une connexion directe, c'est à dire pair à pair (ou « peer to peer » en anglais).

Heureusement, une nouvelle méthode est apparue, et elle est beaucoup plus souple et efficace : Jingle. Mais cet article étant déjà long, j'en parlerai la prochaine fois.

J'en profite pour annoncer que je vais commencer une série d'articles pour expliquer l'architecture et ce qu'on peut faire concrètement avec « Salut à Toi ».

Je vous rappelle aussi que nous avons une campagne de financement participatif en cours pour porter « Salut à Toi » sur Android et faire une version de bureau, et que nous avons bien besoin de soutien ! http://www.arizuka.com/fr/projects/libervia
Merci :)

Parlons XMPP - épisode 8 - PubSub et PEP

(pour lire les épisodes précédents, suivez l'étiquette correspondante)

Aujourd'hui nous allons expliquer dans les grandes lignes comment fonctionnent « PubSub » et « PEP », et voir à quoi cela peut servir. Cet article va reprendre en partie ce que j'ai dit à la conférence « PubSub, microblogage et XMPP » en juillet dernier aux RMLL.

PubSub signifie « Publish/Subscribe » (Publication/Abonnement), c'est un mécanisme qui permet à une ou plusieurs personnes de publier toutes sortes d'informations sur un endroit connu (qu'on appelle un nœud) et aux personnes qui le désirent de s'abonner, c'est à dire d'avoir accès au contenu et d'être averti des modifications, le tout avec un système d'accès simple. Il s'agit du patron de conception « observateur/observable » décentralisé et appliqué à XMPP.

Le fonctionnement est expliqué dans la XEP-0060, c'est une des XEPs les plus longues de XMPP mais le principe est relativement simple à comprendre. Sans reprendre le long glossaire du document, expliquons quelques termes :

  • le service PubSub est l'entité qui gère le mécanisme de publication, d'autorisation, d'abonnement, de notification. C'est une entité XMPP et un jid y est donc associé, c'est à lui que vous faites toutes les requêtes pour un nœud donné.
  • le nœud est un espace associé à une publication. On peut associer ça à l'adresse d'un flux Atom.
  • un « item » (élément) est une publication dans un nœud. On peut associer ça à un article dans un flux Atom.
  • cet « item » contient un « payload » (charge utile), c'est à dire un contenu significatif qui dépend de la fonctionnalité utilisée. En effet la XEP-0060 décrit un mécanisme générique et souple, qui est ensuite utilisé dans des cas pratiques par d'autres extensions.

Un service PubSub est généralement un composant de votre serveur, mais ça peut-être n'importe quelle entité : votre serveur lui-même (c'est le cas avec PEP que nous allons voir ci-dessous), ou un client voire votre client lui-même (mais c'est assez rare – je n'ai jamais vu de client le faire –, car en général on utilise le service de son serveur).

Le mécanisme général est très simple et centré sur les nœuds : chaque entité (associée à un jid) à un rôle lié à ce nœud selon qu'elle l'ait créé, qu'elle soit publieur, abonné, banni ou sans lien avec le nœud. À ces rôles sont donnés des autorisations : le droit d'écrire (avec le « publish model » ou modèle de publication) et le droit en lecture (avec l'« access model » ou modèle d'accès).

Reprenons de manière un peu plus formelle. Les rôles dont nous avons parlé sont appelés « affiliations », et on peut avoir les suivantes:

  • owner (propriétaire): en général celui qui a créé le nœud
  • publisher (publieur): celui ou ceux (il peut y en avoir plusieurs) qui ont accès en écriture
  • publish-only (publication seulement): droit d'écriture mais pas de lecture, c'est un cas peu fréquent.
  • member (membre): quelqu'un qui est abonné au nœud
  • none (rien): l'entité n'a pas de lien avec le nœud
  • outcast (banni): l'entité a été explicitement interdite d'accès au nœud

La section 4.1 de la XEP-0060 fourni un tableau qui montre les autorisations selon l'affiliation. Ainsi on voit que le propriétaire peut publier ou configurer un nœud.

Les modèles d'accès (pour la lecture) définis dans la XEP-0060 sont les suivants:

  • open (ouvert, public): tout le monde peut lire le nœud
  • presence (présence – oui je traduis même pour un seul accent –) : si une entité est autorisée à voir la présence du publieur, alors elle peut accéder au nœud
  • roster (liste de contacts): si une entité est dans un groupe défini (dans la configuration du nœud) de la liste de contacts du service pubsub, elle a accès au nœud.
  • whitelist (liste blanche): des entités sont explicitement autorisées dans la configuration du nœud

Et rapidement les modèles de publication:

  • publishers (publieurs): quelqu'un qui a l'affiliation publieur peut écrire
  • subscribers (abonnés): n'importe quel abonné peut écrire
  • open (ouvert/libre): tout le monde peut écrire

Il faut bien noter une chose essentielle dans PubSub : quand la combinaison autorisation/abonnement/configuration le permet, on reçoit une notification immédiatement quand un élément est publié, modifié ou supprimé. Autrement dit on n'est plus du tout dans l'analogie avec un flux Atom – où on doit aller vérifier régulièrement qu'il n'y a rien de nouveau –, on est prévenu si nécessaire. Ceci est beaucoup plus efficace, rapide, et économe en ressources.

Voilà pour la base. La XEP défini d'autres choses qu'il n'est pas forcément pertinent d'expliquer ici, comme les métadonnées ou les inscriptions temporaires. On peut toutefois s'arrêter sur les collections, qui ne sont que mentionnées dans la XEP-0060 mais décrites en détails dans la XEP-0248. Elles permettent de faire des arbres de nœuds, et ainsi de représenter des données avec des relations entre elles. Des exemples valent parfois mieux qu'un long discours: les collections peuvent être utilisées pour représenter un système de fichiers sur un disque dur, ou un arbre généalogique.

Tout ceci est souple, générique, puissant, et relativement facile à utiliser par un client. Mais la XEP étant très longue, et l'implémentation de la partie service plus complexe, les implémentations ont mis du temps à arriver (et encore aujourd'hui elles sont très inégales). Comme PubSub peut être intéressant même sans tout le mécanisme, une version simplifiée est décrite dans la XEP-0163: « Personal Eventing Protocol » (Protocole d'évènements personels).

Cette dernière se base sur PubSub, mais définit les règles suivantes qui simplifient beaucoup :

  • 1 compte (jid) = 1 service : probablement la règle la plus importante, elle évite d'avoir à chercher un service PubSub associé à un jid, puisque le service est l'adresse canonique (« bare jid ») de l'entité. Ainsi pour la microblogage (XEP-0277), il suffit de connaître le jid de la personne – le nœud étant défini dans la XEP – pour retrouver ses publications.

  • 1 publieur par nœud : le propriétaire et le publieur sont le même, et il n'y a qu'un publieur par nœud. On se coupe ainsi de l'édition collaborative par souci de simplification, et il faudra utiliser PubSub pour ce genre d'applications.

  • accès par présence par défaut : sans rien toucher, il suffit d'avoir quelqu'un dans sa liste de contacts (et qui a accès à la présence) pour qu'il soit autorisé à voir nos publications

  • notifications filtrées sur l'intérêt exprimé : pour éviter d'être submergé de notifications, une entité/un client doit explicitement indiquer qu'il est intéressé par tel ou tel nœud

  • options par défaut au plus simple

PEP était utilisé au début pour des événements (sans grand intérêt à mon sens) comme l'humeur ou la musique en cours d'écoute, mais depuis son utilisation a évolué.

Voici, pour finir, quelques exemples d'utilisation de PubSub ou PEP:

  • enregistrement de données publiques ou semi-publiques (XEP-0222), par exemple une clef publique de chiffrement
  • enregistrement de données privées (XEP-0223), très utile pour n'importe quelle donnée de petite taille
  • les marque-pages (XEP-0048) utilisés pour les salons de discussions utilisent PEP (la XEP-0048 a été modifiée après l'apparition de PEP pour s'y adapter)
  • le microblogage bien entendu (XEP-0277), qui utilise PEP et utilise du Atom pour sa « charge utile » (« payload ») et un accès en général public. Les commentaires sont sur un nœud PubSub séparé, en général avec un modèle de publication par abonnement.
  • la XEP-0214 utilise PubSub et les collections pour faire un dépôt de fichiers
  • le futur protocole de discussions de groupe « MUC 2 » devrait se baser sur PubSub

PubSub pourrait aussi être utilisé pour placer des points sur une carte, faire un wiki, organiser des événements, ou encore gérer et surveiller une batterie de serveurs qui nous préviendraient en cas de problème.

Je reviendrai sûrement plus tard sur tout ça pour expliquer le microblogage ou d'autres extensions.

La prochaine fois, je pense vous parler de Jingle (mais pas de la partie vidéo-conférence). J'espère qu'à ce stade vous commencez à comprendre que XMPP n'est pas une technologie, mais un ensemble de technologies coordonnées et qui se réutilisent les unes les autres quand nécessaire.

J'ai un peu réduit le rythme des articles ces derniers temps car je travaille sur mon projet, et qu'une partie a été traduite en anglais avec l'aide de pas mal de monde (merci encore !), tout cela prend du temps.

Si vous venez à la fête de l'huma ce week-end, vous pourrez me trouver au village du libre, où Parinux me prête gentiment un bout de stand (merci aussi !). Je n'y serai pas en permanence, car je compte aussi profiter un peu de la fête :)

Let's talk XMPP - episode 4 - group conversations

This article was initially published in French, and it got some interest, so we started to translate the whole series in English. If you can read French, you can follow the whole series there: http://www.goffi.org/tag/parlons_xmpp

The translation to English was done thanks to: Poulet , Éfrit , Paco , mbarbarosa , Weyfonk and Chteufleur . The whole series is under CC By-SA , and any help would be appreciated to help with the translation of next articles.
(Follow the corresponding link to read the previous episodes).

In the software development field, and much in the libre software, group’s discussions are really common, mostly with IRC (Internet Relay chat).
This venerable protocol do what we ask it and XMPP is strongly inspired by it. Let’s see that closely.

Group’s discussions used nowadays are called MUC (Multi-User Chat) and are defined by XEP-0045. This one standardizes and extends the first solution called Groupchat. As all that comes from IRC, I’ll explain as they come the major differences between them.

It is possible to acces a chat room located on any server from any server (again, while it is not explicitly prohibited). Chat rooms do, as the users, have a jid, which has the pattern chat_room_name@service. For example, that of Salut à Toi is sat@chat.jabberfr.org:  “sat” is the chat room’s name, “chat.jabberfr.org” the service.

The resource is used for occupants of the chat room: sat@chat.jabberfr.org/goffi corresponds to the occupant “goffi” in the chat room sat@chat.jabberfr.org. Ah little detail that I forgot in previous articles: everything is unicode in XMPP, including jid. So you can use arabic or russian nickname. But beware: some unicode characters are strongly similar, therefore it is possible to get 2 words graphically similar mixed up, we name it “homoglyphs”. For example “gοffⅰ” looks like “goffi” but it uses different characters. This issue is mentioned in a unicode technical report: http://www.unicode.org/reports/tr36/. Also, do not rely exclusively on a nickname to identify someone (espcially that it is possible that it can be reused by someone else between two sessions).

The nickname is linked to the chat room and not to the service. You can have a nick “toto” in a chat room and “titi” in another one, and someone else can have “titi” on a third chat room. This is a big difference with IRC where we have only one nickname on a server that will be used in every chat room (channel on IRC).

To go in or go out a chat room, or to change nickname, we send an available (or not) presence directly to chat_room@example.net/desired_nick, but this is normaly managed by your client.

It is also possible to write directly to all chat room’s occupants (under the hood this is a “groupchat” message that is sent to the chat room’s bare jid), or to have a private chat with a member (we write to the full jid of the recipient).

A chat room can be public or hidden (it will not appear in the chat room list), not anonymous or semi-anonymous (in the first case everyone can see the occupant’s real jid, in the second case only moderators and administrators can), persistent or temporary, open or accessible only by white list or can be protected by password, moderated or not.

All those parameters are normally defined at the creation of the chat room, or they can be modified after with the suitable option of your client (on Gajim: right click on chat room tab => Manage Room => Configure Room). According to the service you use, you can configure more or less things, for example limit the occupant’s maximal number.

A feature often implemented is the history or “back log”: when you get in a chat room, the service sends you the last X messages, allowing you to understand the context of the current conversation.

Also, if a public archive of the chat room is kept (we say “logged” chat room), the service must warn you (it’s mandatory in the XEP), this is another good point compared to IRC. For sure, one has to remember that anyone in the room can keep a log and could publish it without your consent.

So far, so good, but a great strength of IRC is its simplicity: no need to create an account, you just have to pick a nick (unique), with a server, and that’s it! So, you won’t be disapointed, XMPP has exactly the same thing with connections called “anonymous”. No anonymity in terms of Tor here, but rather the possibility to get a temporary account, with a jid more or less random, for the connection time. This comes built-in but it must often be explicitly enabled in the server configuration, and most of the time, anonymous connections are limited to the local network, no communication with other servers (to avoid spam).

If you want to chat as with IRC in a simple and intuitive way, and if you like the console, I would strongly recommend Poezio which is an excellent XMPP client that is easy to use: initially, without changing the configuration, you will be anonymously connected to the MUC service of Poezio. It is inspired by Irssi/Weechat and use the same commands (and more generally those of IRC). Below the welcome message, without changing the configuration, we see the anonymous jid assigned for the session time.

Poezio screenshot

Well this episode is long enough, but I am not finished with MUC, therefore we will talk about it next time, probably with transports.

Parlons XMPP - épisode 7 - cas pratiques: SleekXMPP et SàT

(pour lire les épisodes précédents, suivez l'étiquette correspondante)

Comme cela a été demandé plusieurs fois, nous allons pour cet article faire un petit cas pratique avec deux bots XMPP.

SleekXMPP

c'est SleekXMPP que nous allons tester, que je n'avais jamais utilisé avant cet article. Il s'agit d'une bibliothèque Python qui se veut simple, avec peu de dépendances, et gérant tout avec des greffons. Vous pouvez aussi utiliser le fork (amical) fait pour Poezio, Slixmpp qui a réécrit le cœur de la bibliothèque pour tout gérer en asynchrone (sans thread) via le récent asyncio (aussi il faut une version de Python >= à 3.4, alors que SleekXMPP fonctionne avec Python 2 et 3).

Sans entrer trop dans les détails, que vous trouverez sur le site officiel avec plusieurs tutoriels (http://sleekxmpp.com/), faisons un simple bot qui répond à des commandes ad-hoc (aucun lien avec Tintin, voir plutôt l'épisode 6):

Ce script est une adaptation de l'exemple donné dans le dépôt officiel (voir sa licence). Des explications sont données après le script, et il devrait fonctionner avec Python 2.6 ou supérieur ou 3.1 ou supérieur.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sleekxmpp
from sleekxmpp import jid

JID="mon_super_bot@mon_super_server.tld"
PWD="mon_super_mot_de_passe"
ADMIN=jid.JID("mon_admin@mon_super_server.tld")
CMD_ENVOI = u'envoi message'
CMD_DECO = u'déconnexion'
CMD_ADMIN = u'gros bouton rouge'


class MonSuperBot(sleekxmpp.ClientXMPP):

    def __init__(self):
        sleekxmpp.ClientXMPP.__init__(self, JID, PWD)
        self.add_event_handler("session_start", self.session_start)
        # note 1
        self.register_plugin('xep_0030')
        self.register_plugin('xep_0004')
        self.register_plugin('xep_0050')
        self.register_plugin('xep_0199', {'keepalive': True, 'frequency':15})

    def session_start(self, event):
        # note 2
        self.send_presence()
        self.get_roster()
        self['xep_0050'].add_command(node='monbot',
                                     name=u'Commandes de monbot',
                                     handler=self._handle_commands)

    def _handle_commands(self, iq, session):
        form = self['xep_0004'].makeForm('form', 'bot')
        form['instructions'] = u'Choisissez une commande'
        options = [CMD_ENVOI, CMD_DECO]

        # note 3
        if session['from'].bare == ADMIN:
            options.append(CMD_ADMIN)

        form.addField(var='command',
                      label=u'commande',
                      ftype='list-single',
                      required=True,
                      options=options
                      )

        session['payload'] = form
        session['next'] = self._handle_command_complete
        session['has_next'] = False

        return session

    def _handle_command_complete(self, payload, session):
        form = payload
        command = form['values']['command']

        if command == CMD_ENVOI:
            self.send_message(mto=session['from'],
                              mbody="Message important !",
                              mtype='headline')
        elif command == CMD_DECO:
            self.disconnect(wait=True) # note 4
        elif command == CMD_ADMIN:
            # note 5
            if session['from'].bare == ADMIN:
                session['notes'] = [('warning', 'BOOM !')]
            else:
                raise ValueError("ce n'est pas un admin !")
        return session


if __name__ == '__main__':
    xmpp = MonSuperBot()
    if xmpp.connect(): # note 6
        print(r"\o/")
        xmpp.process(block=True)
    else:
        print(":(")

Explications

Après avoir importé sleekxmpp, nous utilisons quelques constantes (n'oubliez pas bien sûr de remplacer JID et PWD par des valeurs adaptées) pour simplifier, les exemples officiels permettent de manière plus élégante de préciser jid et mot de passe en ligne de commande.

Notre bot se comportera comme un client, nous héritons donc de sleekxmpp.ClientXMPP.

au niveau de la note 1 nous implémentons les greffons qui gèrent les XEPs qui nous intéressent :

  • disco (XEP-0030) pour annoncer ad-hoc, comme expliqué dans l'épisode 3
  • les formulaires de données (x-data, XEP-0004) et les commandes « ad-hoc » (commands, XEP-0050), expliquées dans l'épisode 6
  • la XEP-0199 permet d'envoyer et de répondre à des « pings », afin de s'assurer que la connexion et les logiciels sont toujours actifs.

À la note 2 nous envoyons notre présence et demandons la liste de contacts (« roster »), ce qui est requis par les RFCs, certains serveurs pouvant refuser de répondre si ce n'est pas fait.
Ensuite nous utilisons le greffon des commandes « ad-hoc » pour ajouter le point d'entrée à nos commandes.

Ce point d'entrée appellera la méthode « _handle_commands », et nous utilisons un formulaire (comme expliqué dans la XEP-0004) pour spécifier nos commandes. La liste « options » nous sert à indiquer nos commandes dans l'ordre voulu.

Au niveau de la note 3, nous profitons de l’identification forte de XMPP pour vérifier très simplement si le demandeur utilise l'adresse (jid) de notre compte privilégié, que nous avons indiqué dans la constante « ADMIN ». Nous aurons ainsi un jeu de commandes différent si nous utilisons le compte privilégié ou un autre.
Évidemment si vous voulez profiter de l'authentification forte, il faut vous assurer que tout est en ordre au niveau des certificats et du chiffrement (ce que fait a priori SleekXMPP de base, consultez la documentation pour plus d'informations).

L'ajout de commande se fait ici par une liste à choix unique (« list-single »), mais vous pouvez demander d'autres choses comme des mots de passe ou des jids, tout est expliqué dans la XEP-0004.

Quelques précisions sur ad-hoc : à chaque « page » vous pouvez effectuer une action:

  • cancel pour annuler
  • prev pour revenir en arrière
  • execute pour lancer une commande ou continuer la session
  • next pour passer à la page suivante
  • complete pour finir la sesssion

Ces actions sont gérées par sleekXMPP à travers le dictionnaire « session », la meilleure documentation que j'ai trouvée sur le sujet est le code lui-même : dans le fichier « sleekxmpp/plugins/xep_0050/adhoc.py » présent dans les sources.

Ad-hoc permet également d'indiquer un message, une « note », pour donner l'état de votre commande, elle peut avoir un type « info », « warn » (warning: attention) ou « error » (erreur).

Dans le code nous indiquons que nous avons notre dernière « page » par « session['has_next'] = False », et qu'il faut traiter la réponse dans « _handle_command_complete ». Oui c'est un peu contre-intuitif d’avoir à la fois has_next à False, et un next, mais ce dernier correspond à la réponse et non à une nouvelle page.

Passons à ces réponses. Nous regardons ce qui est dans le formulaire pour savoir quoi faire. Dans le premier cas nous envoyons un message manchette ou « headline » (voir l'épisode 2)

Dans le deuxième cas (au niveau de la note 4) on fait une déconnexion. Alors j'ai eu un problème ici avec SleekXMPP, que j'utilise pour la première fois comme indiqué plus haut : il faudrait pour faire propre terminer la session ad-hoc avant de déconnecter, mais je n'ai pas trouvé de moyen simple de le faire, vu que la déconnexion est immédiate et qu'il faut retourner le dictionnaire session pour terminer la séquence. Peut-être que je suis passé à côté de quelque chose, n'hésitez pas préciser en commentaire si vous avez une astuce.

Passons à la note 5: je refais une vérification du jid avant de lancer la commande privilégiée. La raison est simple: le formulaire est envoyé du client au bot par le serveur sans être vérifié par ce dernier, c'est au bot à le faire. Il est interdit d'ajouter une nouvelle commande, mais comme je doute que SleekXMPP conserve le formulaire d’origine pour vérifier qu'il n'y a rien de nouveau, un attaquant pourrait ajouter la commande privilégiée sans être admin. Cette vérification permet de l'éviter.

Pour faire propre il faudrait envoyer une réponse XMPP précisant que l'action est interdite, mais pour faire simple je me suis contenté d'une exception ici.

Enfin, au niveau de la note 6 on se connecte. Pour un serveur local de test, si vous n'avez pas de serveur DNS configuré comme il faut, vous pouvez spécifier l'adresse ip ou le nom de domaine local en dur, ainsi que le port (par exemple « self.connect(('localhost', 5222)) ». Si votre certificat n'est pas valide, vous pouvez aussi utiliser « use_tls=False » (pour les tests uniquement !). La documentation de SleekXMPP vous indiquera plus clairement comment gérer correctement les certificats.

Enfin, un autre problème que j'ai eu avec SleekXMPP: il ne semble pas possible avec ma version (1.3.1) d'indiquer de ne pas utiliser de commande « exécuter » ou de spécifier son équivalence (ce qui est pourtant possible avec la XEP-0050). Il faudrait qu'elle soit absente ou équivalent à « compléter ». Vous allez ainsi avoir un bouton qui sera inutile, et provoquera même une erreur. Là encore si quelqu'un plus habitué à la bibliothèque peut indiquer en commentaire comment corriger cela. Utilisez donc le bouton « compléter » (ou « finir ») et non « exécuter » de votre client.

Voilà la capture de notre bot piloté par Gajim:

bot piloté par Gajim

Salut à Toi

Pour indiquer les ajouts faits au code, nous utilisons un bot dénommé « Sabot ». Nous gérons les sources avec Mercurial (sur https://repos.goffi.org/). Celui-ci permet d'exécuter une commande via des crochets (« hooks »), dont un qui est lancé à chaque série de commits: incoming. Nous avons donc ceci dans notre hgrc:

[hooks]
incoming.sabot = /chemin/vers/hg_sabot_hook.sh

Pour le bot, nous profitons du côté multi-interfaces de SàT: SàT a une architecture qui permet pour un même client (et donc les mêmes profils, comptes, etc) d'avoir différentes interfaces (console, ligne de commande, bureau, web, etc).

Nous avons donc créé le compte comme un compte normal grâce à Primitivus, l'interface console (nous sommes sur un serveur sans interface graphique disponible). On peut joindre le salon désiré (ici sat@chat.jabberfr.org), et le mêttre en favori (grâce à la XEP-0048), ainsi que gérer l'entrée automatique (« autojoin »). Il ne reste plus qu'à envoyer le message quand le script hg_sabot_hook.sh est appelé, ce que nous faisons à l'aide de « jp », l'interface en ligne de commande:

#!/bin/sh

#on s'assure d'abord que D-Bus est lancé
eval `/chemin/vers/dbus-launch.sh`

REPOS_BASE="http://repos.goffi.org/sat"
PROJECT_FULL="Salut à Toi"
REPOS="$REPOS_BASE/rev/$HG_NODE"
MUC="sat@chat.jabberfr.org"

hg log -r $HG_NODE --template "Commit from {author|person} on $PROJECT_FULL\n{desc}\n$REPOS" | jp message -cp sabot $MUC

(le vrai script est un tout petit peu plus long puisqu'il gère aussi les noms des autres dépôts).

L'option « -c » indique de se connecter si ça n'est pas le cas, et « -p sabot » précise qu'il faut utiliser le profil « sabot »

Le script dbus-launch.sh s'assure juste que D-Bus est bien lancé et réutilisé entre les sessions de l'utilisateur:

#!/bin/sh
DBUS_PATH="/tmp/.dbus.`whoami`"
if [ ! -e $DBUS_PATH ]; then
        dbus-launch --sh-syntax > $DBUS_PATH
        chmod 400 $DBUS_PATH
fi
cat $DBUS_PATH

Voilà pour ces cas pratiques. La prochaine fois, je parlerai soit de PubSub, soit de Jingle.

Let's talk XMPP - episode 3 - core and extensions (part 2)

This article was initially published in French, and it got some interest, so we started to translate the whole series in English. If you can read French, you can follow the whole series there: http://www.goffi.org/tag/parlons_xmpp

The translation to English was done thanks to: Poulet, Éfrit, Paco, mbarbarosa, Weyfonk and Chteufleur. The whole series is under CC By-SA, and any help would be appreciated to help with the translation of next articles.
(Follow the corresponding link to read the previous episodes).
 
Some functionalities can be added to this central part, hence the X of XMPP (which stands for “eXtensible”).
 
Extensions are written using “XEP” (XMPP Extension Protocol) , following an idea taken from Python (if I am not mistaken). This is why the features supported by a server or a client are identified as XEP-0XXX. Obviously, no need to know this to use a XMPP client, but it can be useful to read an extension (you can find them at  https://xmpp.org/xmpp-protocols/xmpp-extensions/) to understand correctly the utility of a functionality. Two parts are particularly useful without the need to enter in the implementation details: the “abstract” part (summary) in the top that indicates what the XEP is doing, and the “introduction” section (the very first section) that provides further details about the cause of the extension and its use cases.
 
XEP-0045 abstract
 
An XEP can describe a feature, a process (for instance the XEP-0001 explains the life cycle of the XEPs themselves), a historical legacy (related to something created before the XMPP Standard Foundation), information (like good practices), even a joke (yes, there are also lousy jokes in the XEPs!). It can have several statuses, detailed in the XEP-0001. It is interesting to note that a lot of XEPs are “experimental” and so technically not (yet) standards, but often implemented anyway. Such XEPs can be widely modified before they get the “Draft” status and eventually become a standard.
 
Why am I talking about all this? For you to get one thing loud and clear: XMPP is not only about instant messaging!
 
Some interesting examples of extensions:
 
  • Extended Stanza Addressing (XEP-0033): to send messages to several recipients at once, or to do carbon copies, as well as blind carbon copies (as the… yes, yes you see what I mean).
  • Multi-User Chat (XEP-0045): IRC-like group chat.
  • Ad-Hoc Commands (XEP-0050): a generic system to handle any kind of commands. Related to users' permissions, it is a great tool!
  • vcard-temp (Business cards, temporary version, XEP-0054): The legacy way to manage electronic business cards, which are a kind of public profile. A new extension will eventually replace it (XEP-0292).
  • Jabber Search (XEP-0055): used to search for jid, mostly used by directories.
  • Publish/Subscribe (XEP-0060): a big piece, used to publish all kinds of information, and its recovery based on permissions, with a notification system in real time.
  • XHTML-IM (XEP-0071): to publish with an XHTML subset, which enables formatting (to write bold text or include a picture for example).
  • Gateway Interaction (XEP-0100): to manage gateways, i.e. links to external networks.
  • Personal Eventing Protocol (XEP-0163): a kind of simplified Publish/Subscribe system.
  • Jingle (XEP-0166): Peer-to-peer session establishment with a wide range of possible applications, the most well-known being video conference.
  • Serverless Messaging (XEP-0174): unsurprisingly used to communicate without servers.
  • Message Archive Management (XEP-0313): to recover messages or other objects (works with Publish/Subscribe as well) following criteria such as a date. In particular, used to get a conversation history on a server, which is useful to access it from all your clients.
 
Keep in mind that we’ve barely scratched the surface here.
 
Further details will be provided about some of these extensions in future articles.
Please note that extensions can be referred by using short names, for instance “MAM” for “Message Archive Management”. Such names are usually mentioned at the end of the related XEPs, in the “Document Information” appendices.
 
This may lead to situations where clients and servers don’t support the same extensions subsets… How to make both parties agree on which one to use? This problem is solved through another extension (though so essential and widely implemented that it could nearly be considered as a main standard): “Service Discovery”, aka XEP-030, short name: “disco”.
 
The idea is simple: each client, server or component discloses who it is, what it can do, or associated items. A component is a service that plugs itself into a server, see below.
 

who it is

An XMPP address (or jid) can be used by all kinds of elements, be it a server, a client, a gateway, or a bot for instance. The latter is a robot, i.e. a program that automates tasks, and is often used to behave like a client.
 
When a client or another element sees a jid, it may need to know what kind of element is associated to that jid, for instance to render it in a special way in the user interface. This is how clients and gateways are shown in distinct ways in your contacts list.
 
Disco’s identity provides this through a category (“client” or “server” for instance), a type (e.g. a client can be “bot”, “web”, “game”…), and a free name (eg “ejabberd”). A list of categories and their associated types can be found on  https://xmpp.org/registrar/disco-categories.html.
 

what it can do

 
XMPP’s extensibility makes it very feature-rich, therefore knowing what the software we are talking to is able to do is mandatory. Disco provides a list of such supported features, which is why you may see disabled buttons or icons (e.g. for video conference) while talking to someone. This means the client you are talking to indicates that it does not support this feature, or more accurately: it does not reveal that it supports it.
 
These features are linked to namespaces that are mentioned in the related XEPs. A list of XEPs based on namespaces is available here: https://xmpp.org/resources/schemas.
 

associated items

 
Beside its identity and available features, an XMPP entity can have associated elements. They can be servers indicating where to find chat rooms, or gateways to other networks.

 

Let's try

Let’s make this clear with an example. Salut à Toi’s command line interface “jp” can retrieve an entity’s disco using the command “jp info disco”, see below with jabber.fr:
 
 
% jp info disco jabber.fr
Features:
 
http://jabber.org/protocol/commands
http://jabber.org/protocol/disco#info
http://jabber.org/protocol/disco#items
http://jabber.org/protocol/stats
iq
jabber:iq:register
jabber:iq:time
jabber:iq:version
msgoffline
presence
presence-invisible
urn:xmpp:time
vcard-temp
--
Identities:
 
ejabberd (server/im)
--
Extensions:
 
http://jabber.org/network/serverinfo
 
--
Items:
 
[chat.jabberfr.org]
[irc.jabberfr.org]
[j2j]
[presence.jabberfr.org]
[proxy.jabberfr.org]
[users.jabberfr.org]
 
 
As we can see, jabber.fr supports legacy vCards management (vCard-temp, XEP-0054) as well as ad-hoc commands (http://jabber.org/protocol/commands, XEP-0050), and the server (server/im) used for instant messaging is called “ejabberd”. We can also notice that various services are available, one of them being char.jabberfr.org. Let’s take a closer look:
 
% jp info disco chat.jabberfr.org
Features:
 
http://jabber.org/protocol/disco
http://jabber.org/protocol/muc
http://jabber.org/protocol/muc#unique
jabber:iq:browse
jabber:iq:last
jabber:iq:register
jabber:iq:time
jabber:iq:version
urn:xmpp:ping
vcard-temp
--
Identities:
 
Public Chatrooms (conference/text)
--
Items:
 
[...]
JabberFR (13) [jabberfr@chat.jabberfr.org]
[...]
 
 
We see that we are dealing with a chat rooms service (conference/text), which use the protocol “Multi-User Chat” (http://jabber.org/protocol/muc). It is at the moment the only one which is available for groups’ discussions (we will talk about it later). “Items” elements contain rooms’ list, with the name, the occupiers’ number with the corresponding JID. I shorten the list which was very long.
 
In jabber.fr’s information, you may have noticed the “extensions” section, it is the XEP-0128 which allow to extend disco for all kind of information. In the case of ejabberd here, it is to give contact addresses of server, but they aren’t indicated for jabber.fr
 
Below the disco’s window of Gajim:
 
Gajim disco
The first time I used XMPP, with Psi in the early 2000s, I was a bit intimidated by the “service discovery” menu, which shows near directly all information we just saw. This kind of menu is often, at my opinion, showed too abruptly in XMPP clients: using disco directly (that is all except what is automated by the client) is already advanced use.
 
 
Furthermore, I will quickly mention the “software version” extension (XEP-0092) which allows, as indicated by its name, to know to which software we are talking to, and the operating system used. jp allows to show these information with “jp info version”, let’s try on jabber.fr:
 
% jp info version jabber.fr
Client name: ejabberd
Client version: 2.1.13
Operating System: unix/linux 3.2.0
 
We now know the ejabberd version that is used. Useful when we know if a feature is supported or if a bug is fixed. And this work with every entity which implement the XEP, not only servers.
 
% jp info version chat.jabberfr.org
Client name: MU-Conference
Client version: 0.9-svn (Jan 27 2014)
Operating System: Linux 3.2.0-4-amd64
 
That’s it. Knowing about the extensions allows to truly know what we can do with a client or a server. Next time I think I will explain groups’ discussions and see what changed in relation to IRC.

Let's talk XMPP - episode 2 - core and extensions

This article was initially published in French, and it got some interest, so we started to translate the whole series in English. If you can read French, you can follow the whole series there: http://www.goffi.org/tag/parlons_xmpp

The translation to English was done thanks to: Poulet, Éfrit, Paco and mbarbarosa and Weyfonk. The whole series is under CC By-SA, and any help would be appreciated to help with the translation of next articles.

Now that we know what we’re talking about, let’s see what the core of the protocol looks like.
 
Originally, XMPP is defined by 3 (previously 2) RFCs: RFC 6120, RFC 6121, and RFC 6122 (there are others, but these 3 are the main ones). They explain the core of the system, such as sending messages, presence information, statuses and so on.
 
Without getting too much into details related to developers, we can quickly explain that XMPP is based on 3 element types, or “stanzas”:
  • <presence/> to primarily indicate… our presence information (sometimes, we also add other things like our avatars, our capabilities, but let’s stay focused). The presence is broadcast by the server to all the people that you have given permission to (see below).
    We can associate a state and a message to our presence. The state can be one of the following (names can change depending on the client):
    • available (default): you’re online.
    • away: you’re away for a short period
    • chat: you want to talk
    • dnd (do not disturb): you’re occupied (often called “busy” in clients)
    • xa (eXtended Away): you’re away for a long while.
    The status messages allow you to specify your availability in a clear language (for example: “I’m watching a movie, do not disturb”), even though, in practice, it is used for any kind of message (a lot of people use a quote, for example).
  • <message/> A message’s sending of type “send and forget”. There are 5 types of messages::
    • chat: the most well-known message, used for simple instant messaging;
    • error: this one is usually managed directly by client software. It is often shown by means of a notification window in your client, indicating that something wrong occurred;
    • groupchat: as “chat”, but for discussion with multiple people. In practice the difference concerns only developers and it should be transparent in the client;
    • headline: an important message, an announcement. Normally, these messages aren’t kept offline, so if you aren’t connected while the message is sent, you shouldn’t receive it. These messages don’t expect answers. A typical example is an announcement for an imminent server maintenance;
    • normal: a little known yet interesting type. It is a message which generally has a subject, but outside of an instant conversation. Yes, exactly like an email! It is more or less its XMPP equivalent.
    Conversation threads are managed as well, but we’ll talk about it another time.
  • <IQ/> (Info/Query): used for everything that works on a question/answer pattern (it is mandatory to provide an answer to an request, even if you need to reply with an error). This is used mainly by developers, as it serves as a basis for most of the features you need. Using it is like saying "I need to know or edit this information".
 
I don't want to delve into technical details, but it seems essential for a user to know different message and presence types to understand their client.
 
One should note that there is an excellent feature that is largely underused in XMPP: it natively knows how to handle different languages because of its inheritance from XML (xml:lang). In other words, you can specify a normal or status message in French, German and Slovak at the same time. This is a major asset that we intend to use in Libervia.
 
Now let's talk about another essential part: the contact list.
 
It is called "roster" in the XMPP world. You can assign 0, 1 or several groups ("family", "friends", etc.), a name (which is an alias chosen by yourself, not by your contact), and subscription information to every contact you add to your roster.
 
Subscription lets you know whether you have allowed your contact to see your presence information and whether you are allowed to see theirs. Therefore, every time someone adds you to their contact list, your client (e.g. Gajim) asks you whether you wish to grant them access to your presence information. Note that these permissions don't need to be symmetrical: a contact may have been allowed to see your contact information without enabling you to see theirs, and vice versa. It might even be possible that neither of you can see each other's presence information (but I think most clients remove the contact from the roster in that case).
 
Groups are dependent on contacts, not the other way around (it's not a list of groups which contains the contacts): this explains why having an empty group (i.e. without any contact) isn't possible. In my opinion, groups too are underused in the XMPP world, but we'll get back to this.
 
 
That's it for today. I opted to keep the part on extensions for the next post to keep this one lighter.

Let's talk XMPP - episode 1 - the basics

This article was initially published in French, and it got some interest, so we started to translate the whole series in English. If you can read French, you can follow the whole series there: http://www.goffi.org/tag/parlons_xmpp


The translation to English was done thanks to: Poulet, Éfrit, Paco and mbarbarosa. The whole series is under CC By-SA, and any help would be appreciated to help with the translation of next articles.

G'day,
 
Well, as it’s a shame that XMPP is not well known or understood, I decided to start a series of articles to explain what it is.
 
These articles are for a technical audience, but not necessarily for developers, and I hope it will help you to understand the advantages of this protocol and to use your software in a better way.
 
Being a developer of the “Salut à Toi” project, I’ll probably give examples with it quite often.
 
So let’s start with basis.
 
What’s XMPP? It’s a standard message and presence protocol, and extensible (XMPP means « eXtensible Message and Presence Protocol », that is it’s documented and used as a reference (validated by standards organization: the IETF). It allows all software which use it to speak the same language, and so to be interoperable. It’s a libre protocol, that is you can get the documentation and use it for free, without any legal or technical restrictions, and you can improve or modify it (but if you divert and don’t suggest your modifications, you risk to lose the compatibility with other software).
 
XMPP is decentralized and federated, that is you can have servers anywhere, they could (if they don’t forbid it explicitly in their configuration) communicate with each other.
 
It’s a popular protocol, many software allow to use it: for servers, there are Prosody, Ejabberd, Openfire, Tigase, Mongooselm, Metronome, etc. For clients: Gajim, Poezio, Pidgin, Psi, Swift, Jappix, Movim and of course Libervia/Salut à Toi (I let you find the official websites by yourself). A complete list (servers, clients and libraries) is available here: https://xmpp.org/xmpp-software/.
 
If you cannot install your server at home, many public ones are available: in France one can cite those of APINC ((jabber.fr, im.apinc.org, etc), of the Quadrature du Net, etc. A small list (it’s not up-to-date, don’t hesitate to contribute) is available here in French,, if not you can check on https://xmpp.net/directory.php or http://www.jabberes.org/servers (yes, there are a lot!). But I strongly suggest you to install your own server or to go meet a local organization that you can contact easily: on the one hand if you install it by yourself you’ll have a better control on your own data and on the other hand if you want a specific feature you’ll be able to ask admins for an update.
 
Knowing all that, let’s try to install an account.
 
Once the server installed or a public server chosen, you can create an account. You’ll have then an address, a “JID” (Jabber ID, “Jabber” is the former name of the protocol, this name is now owned by a private company and is kept here for historical reasons).
 
This address is on the form of local_name@domain.tld/resource, or in canonical form (or what is called “bare JID”) local_name@domain.tld. For example, mine is goffi@jabber.fr. Does it sound familiar? Yes, it really looks like email addresses!
 
So what is this resource? The resource is linked with the client software that you use to connect: XMPP has been designed from the beginning to allow several clients to connect at once (10 years ago, a few messaging protocols were able to do that, and connecting again from a different place was often resulting in the disconnection of the first client) and this resource is used to identify them. In other words, you have a resource only once connected, and it will be a different one for each client that you are using: if I connect with Libervia, Gajim and Movim, I’ll have 3 different resources.
 
It used to be several strategies to name the resource, sometimes it was used to show the connection location (“home”, “work”), clients often used their names as default value (“gajim”, “psi”). Today, it’s well accepted that it’s better to have a resource that we cannot guess, as somebody can know if you are online or not (even if you don’t want this information to be public) by doing a request to this resource. The best way is to let the server choose the resource for you.
 
Finally, the resource is linked with a priority: it allows to indicate, if several resources are available, which one will get the message. But we’ll see that later.
 
In the next episode, I'll talk about extensions an features discovery
 
That’s it. Let me know if you are interested in this series, if it seems too technical for you, or if you have any comment or fix to suggest. Everything is under the license CC By-SA, so don't hesitate to re-use, share or modify !
Powered by Salut à Toi
Subscribe to this news feed Atom feed