Vue d'ensemble du système Jabber

Ce document offre une courte introduction à l'architecture et au protocole du système Jabber.

Sommaire


Introduction

La première application de la technologie Jabber est un système de messagerie instantanée et de présence qui a été conçu et continue à être développé par la communauté open-source. Jabber se distingue des autres système de MI existants sur plusieurs points :

Ce document fournit une vue d'ensemble de l'architecture de Jabber, il se concentre particulièrement sur la conception du serveur, qui en est maintenant à la version 1.4. Pour plus d'information concernant le protocole XML de Jabber, référez-vous svp au document : Vue d'ensemble du protocole de Jabber.

(note: Vous trouverez la version originale en langue anglaise de ce document sur le site de Peter Saint-Andre


Bases

Jabber a été conçu dans une large mesure sur le modèle du système de transmission de messages le plus réussi d'Internet, c'est a dire : l'E-mail. Les communications s'établissent au travers d'un réseau distribué de serveurs qui emploient un protocole commun. Les clients se connectent sur ce réseau pour pouvoir envoyer et recevoir des messages des autres utilisateurs.

Alors que l'E-mail est un système de transfert et d'enregistrement de messages, Jabber lui, transfert des messages instantanés. Les serveurs Jabber (et, par extention, les autres utilisateurs de Jabber) savent en permanence lorsqu'une personne particuliere est en ligne. Cette information de disponibilité, s'appelle "la présence" et est l'élément essentiel de tout systeme de messagerie instantanée. Jabber combine cette caractéristiques de MI standard avec deux autres caractéristiques qui rendent Jabber unique. La premiere est un protocole ouvert qui permet l'interopérabilité avec les autres systèmes de MI. La seconde est un protocole basé sur XML, cela rend possible la communication non seulement entre des utilisateurs humains, mais également entre des applications logiciel.

Client/Server

Jabber s'appuie sur une architecture de type client/serveur, et non de type client/client comme le font d'autres systèmes de MI. Cela signifie que tous les messages et données qui transitent d'un client vers un autre, passent par un ou plusieurs serveurs. N'importe quel client peut ensuite négocier une connexion directe avec un autre client, mais ces connexions sont spécifiques à certains besoins, comme par exemple pour le transfert de fichiers. Ces connexions particulières sont néanmoins initialisées dans le contexte de l'architecture client/serveur de Jabber.

Réseau Distribué

Le réseau Jabber est bâti sur le modèle de l'E-mail. Donc, chaque utilisateur dispose de son serveur local de qui il reçoit toutes les informations, et les serveurs se transfèrent entre eux les différents messages et informations de présences. Il peut exister, toutes sortes de serveurs Jabber acceptant ou non les communications avec d'autres clients connectés sur d'autres serveurs. Chaque serveur fonctionne indépendamment des autres, et maintient sa propre liste d'utilisateurs. N'importe quel serveur Jabber peut communiquer avec n'importe quel autre serveur pourvu qu'il soit connecté sur Internet. Un utilisateur particulier est associé à un serveur particulier qui peut être public ou privé (comme par exemple au sein d'une entreprise). Les adresses Jabber sont de la même forme que les adresses E-mail, par exemple : stpeter@jabber.org. Les adresses Jabber sont détaillées ici.

Serveur Modulaire

Le serveur Jabber joue deux rôles principaux :

Le serveur Jabber est modulaire, chaque module gère des fonctionnalités telles que l'authentification utilisateur, le stockage de données (messages, préférences, messages en attentes), et autres. En outre, le serveur peut être étendu par des services additionnels, tels que la sécurité intégrée, les connexions avec des clients alternatifs, et les passerelles vers d'autres systèmes de MI.

L'échange de messages et d'information de présence entre Jabber et un autre système de MI non-Jabber, donne un bon exemple de cette modularitée. Ce type de communication est rendu possible grâce à une couche de "transport" indépendante, qui traduit les flux XML de Jabber en protocole étranger. Cette couche "transport" ne fait pas partie du noyau du serveur. Au lieu de cela, ce sont des programmes modulaires qui peuvent être ajoutés facilement au serveur pour fournir la fonctionnalité demandée.

Clients Simples

Un des critères de conception du système Jabber était qu'il puisse supporter des clients simples (quelque chose d'aussi simple par exemple, qu'une connexion Telnet). En effet, l'architecture de Jabber impose très peu de restrictions aux clients. Les seuls dispositifs qu'un client doit pouvoir supporter sont :

Le choix de conception de Jabber a été de déplacer la complexité des clients vers le serveur. Ceci permet d'écrire des clients, relativement facilement, (noter la grande variété disponible de clients Jabber) mais aussi d'ajouter de nouvelles fonctionnalités au système, sans obliger les utilisateurs à installer de nouveaux logiciels clients. Les clients Jabber communiquent avec le serveur grâce à des flux XML, encapsulés dans des sockets TCP, sur le port 5222, et ne communiquent pas directement entre eux. Dans la pratique, plusieurs des fonctions de bas niveau du client (par exemple, l'analyse XML et la compréhension des balises Jabber, comme : <message/>, <presence/>, et <iq/>) sont manipulées par des bibliothèques, cela permet aux programmeurs de clients, de se concentrer sur l'interface utilisateur.

Format De Données XML

XML est une caractéristique essentielle du système Jabber. Il est très important que l'architecture soit fondamentalement extensible et puisse contenir toutes sortes de données structurées. (plus spécifiquement, Jabber utilise des flux XML pour la communication avec le serveur, et de serveur à serveur. Le flux de paquets XML est toujours initialisé par le client vers le serveur, et la "vie" du flux XML est directement associée à la durée de la session de cet utilisateur.)

Bien que Jabber soit fortement lié à XML, il est en même temps, indépendant du média de livraison : il n'y a aucune restriction inhérente au système de livraison, et aucune connaissance dans l'architecture du système de livraison n'est nécessaire. Cela doit permettre, entre autres, de bâtir un système de communication qui puisse rendre transparent l'échange de messages avec des services tiers (comme par exemple : IRC, ICQ, AIM). Vous trouverez plus d'informations sur le protocole XLM de Jabber dans ce document : Vue d'ensemble du protocole de Jabber


Vue générale de l'architecture du serveur

Le serveur Jabber se compose de modules multiples qui gèrent les différentes fonctions du système. Au coeur des modules du serveur, quatre composants ont pour unique fonction de diriger et de livrer les paquets XML d'un composant de bas niveau à un autre. Ces quatre composants sont : accept, connect, exec, et load. Chacun de ces composants de base, décode en entrée le paquet XML, le livre aux autres composants qui le réencodent en XML à destination des composants de plus bas nivaux. Voici un schéma de l'architecture :

Lors du démarrage du serveur, les modules sont chargés selon leurs degrés de priorité par rapport au noyau (ces degrés sont définis dans le fichier de configuration), les modules manipulent ensuite les données selon ces priorités (définissant de cette manière, la logique de livraison). Le noyau du serveur Jabber, grâce aux modules, gère les tâches courantes suivantes :

De plus, le noyau du serveur peut être étendu par des modules additionnels capables de gérer différents protocoles non-Jabber (voir Modules de transports pour plus de détails). Actuellement, les protocoles supportés sont les suivants :

note : D'autres modules de transports seront intégrés au fur et à mesure de leurs créations, comme par exemple, le module qui gérera le futur protocole de l'IMUnified.


Flux de messages

Suivre le cheminement d'un message au sein du serveur Jabber, est, une bonne introduction à son architecture. Bien que l'élément XML <message> soit seulement l'un des trois éléments principaux du protocole de Jabber, il en est l'élément essentiel : c'est lui qui transporte l'information d'un point à un autre.

Voici un diagramme de ce flux :

Le serveur Jabber (ici nommé "jabberd", abréviation le "démon Jabber") attend des paquets de type <message> contenu dans une socket TCP sur le port 5222 (ou sur le port 5223 si le SSL est autorisé et en service). Si une session n'existe pas, le "jabberd" lancera la procédure d'authentification décrite ci-dessous. Si une session existe, les paquets seront envoyés au "Jabber Session Manager" (JSM).

Voici un exemple de paquet XML :

<message
    to='psaintandre@aim.jabber.org'
    type='chat'>
  <body>Hey, the AIM transport is working great!</body>
</message>

Ensuite, le JSM vérifie le "hostname" du serveur de destination dans la liste de noms de serveurs contenus dans son fichier de configuration. Souvent cet "hostname" y sera défini. Par exemple, aim.jabber.org est défini dans le fichier de configuration du serveur jabber.com pour se diriger vers le module de transport de AIM (qui pourrait être sur une autre machine). Si cet "hostname" n'est pas défini dans le dossier de configuration, le composant "dnsrv" devra "résoudre" cet "hostname", composé d'une adresse IP et d'un port. De l'une ou de l'autre manière, le paquet message sera ensuite expédié au composant de communication de serveur-à-serveur (le "s2s") puis au serveur concerné, qui sera dans notre exemple : jabber.org. Le module "s2s" expédiera donc le message au serveur ou à un module de transport de ce serveur. Dans notre exemple, la destination exacte du paquet message est : aim.jabber.org, donc le paquet sera envoyé au module de transport AIM sur jabber.org pour être finalement transmis à un utilisateur d'AOL (voir Modules de transports ci-dessous). Dans tout les cas, le message a transité d'un client vers un serveur, puis vers un autre serveur ou vers un autre systeme de MI.


Authentification

Comme mentionné précédemment à propos des flux de paquets, les messages et les informations de présence transitent dans le contexte d'une architecture client/serveur. Dans le protocole Jabber, cette session est initialisée au moyen de deux flux XML. L'un allant du client vers le serveur et l'autre du serveur vers le client. Voici un exemple de flux XML lors d'une ouverture de session :

SEND:<stream:stream
SEND:to='jabber.org'
SEND:xmlns='jabber:client'
SEND:xmlns:stream='http://etherx.jabber.org/streams'>

RECV:<stream:stream
RECV:xmlns:stream='http://etherx.jabber.org/streams'
RECV:id='39ABA7D2'
RECV:xmlns='jabber:client'
RECV:from='jabber.org'>
SEND:<iq id='1' type='set'>
SEND:<query xmlns='jabber:iq:auth'>
SEND:<username>stpeter</username>
SEND:<resource>Gabber</resource>
SEND:<digest>f1e881517e9917bb815fed112d81d32b4e4b3aed</digest>
SEND:</query>
SEND:</iq>
RECV:<iq id='6' type='result'/>
(XML for user session goes here)
SEND:</stream:stream>
RECV:</stream:stream>

Cependant, pour que le serveur puisse ouvrir une session, il doit auparavant authentifier l'utilisateur. Le schéma suivant décrit, le flux des paquets nécessaires a l'authentification :

La procédure d'authentification démarre lorsque le client se connecte au serveur et lui envoi un paquet XML. Immédiatement, les modules de contrôles du serveur se mettent dans l'attente d'un paquet de type <iq> (abréviation de info/query) contenant un sous-élément <query> possédant un attribut de type : xmlns="jabber:iq:auth". Ce paquet XML, devra contenir les informations d'authentification de l'utilisateur, ou le cas échéant, les données nécessaires a l'enregistrement d'un nouveau compte pour cet utilisateur. Ces informations se composent d'un nom (ou "login") et d'un mot de passe, le mot de passe est crypté grâce à l'algorithme SHA1 (ceci correspond au schéma d'authentification standard).

Dés que cette information est reçue, le parseur XML passe la main au "deliver", qui commencera à surveiller le tampon d'entrée au cas où le client continuerait à envoyer des paquets sans avoir été parfaitement authentifier. Le serveur (généralement le JSM) passera alors le paquet d'authentification au composant "xdb". Le composant "xdb" (moteur de base de données Xml) enverra le paquet aux autres sous-composant abonnés à ce type de paquet : par exemple, la correspondance des paquets d'authentification décryptés pourrait être recherchée dans le système de fichier XML en utilisant le sous-composant "xbd_file", tandis que la correspondance des paquets d'authentification crypté pourraient être recherchée dans le LDAP en utilisant le sous-composant "xdb_ldap". Le rôle du JSM se limite juste à transmettre le paquet d'authentification au composant "xdb", qui se chargera lui-même de l'envoyer au sous-composant approprié. De plus, pour accélérer la rapidité d'exécution, le composant "xdb_ldap" possède sa propre réserve de threads.

Le composant "xdb" retournera le résultat de la requête d'authentification au serveur (le JSM). Si l'authentification échoue, le serveur renverra au client le code d'erreur 401 et n'ouvrira pas de session. Si l'authentification réussie, le JSM ouvrira une session (et libérera le "delivrer"). Désormais, tous les paquets "presence", "message", et "iq", transiteront dans le cadre de cette session; Jusqu'à ce que le client ou le serveur termine la session en envoyant une balise de flux fermante : </stream>.


Jabber Session Manager

Voici le schéma d'activité du JSM :

Comme mentionné, le "JSM" gère les paquets de type message, présence, et IQ, d'un client connecté au serveur. Cependant, le JSM manipulera également les paquets destinés à un utilisateur momentanément absent. Par exemple, imaginons que vous m'envoyez un message (stpeter@jabber.org) et que je ne sois pas en ligne. Le JSM devra stocker ce message sur le serveur jusqu'à ce que je sois de nouveau en ligne.

Le JSM distingue les utilisateurs en ligne et hors ligne en se basant sur la "ressource" de l'adresse du paquet XML (la "ressource" est le dispositif, le logiciel client, ou l'endroit d'où vous vous connectez. Par exemples : "laptop", "Gabber", ou "à la maison"). Normalement, un utilisateur est absent si le paquet XML ne contient pas de ressource. Cependant, il arrive parfois que la ressource soit absente par erreur, alors, le JSM vérifie si l'utilisateur est réellement hors ligne avant d'envoyer le paquet au module "d'absence", qui pourrait (par exemple) stocker le message ou rechercher une "vCard".

Si l'utilisateur est en ligne, le message, l'information de présence, ou le paquet "iq" n'est pas envoyé au module "d'absence" mais est géré par le JSM. Un tel paquet ne peut avoir que deux états possibles : ou il doit être livré à l'utilisateur ou il est envoyé par l'utilisateur. Ainsi le JSM possède deux contrôleurs en attente des paquets "to" ou "from" de l'utilisateur, puis les dirige vers le module approprié. Une fois que le module a manipulé le paquet, il est a nouveau retourné aux contrôleurs pour une autre manipulation par d'autres composant ou, si tout le traitement est achevé, l'expédier à/de l'utilisateur.

Voici un exemple : imaginons que je reçoive un message de foobar@jabber.org. Je suis en ligne, donc le message est envoyé au JSM. Le contrôleur stoppe ce paquet qui m'est destiné, et envoie un appel aux modules qui sont abonnés au JSM. Le premier module a répondre, est un "mod_filter" qui trie les messages entrants selon des critères définis par l'utilisateur. Dans ce cas-ci (puisque je n'ai semble-t-il jamais obtenu de critiques désagréable de notre ami foobar), j'ai configuré le "mod_filter" pour rediriger tous les messages venant de foobar@jabber.org dans ma boîte aux lettre en utilisant le protocole smtp (en cours de réalisation). Donc le "mod_filter" restructure le message de telle sorte que l'adresse de destination initialement jabber.org devienne maintenant smtp.jabber.org, puis réexpédit le paquet au contrôleur. Un nouvel appel est fait aux autres modules abonnés au JSM, mais comme aucun d'eux ne répond, le paquet est finalement expédié a stpeter@smtp.jabber.org, où le message sera directement transféré dans ma boite aux lettre.

ce qu'il est important de noter, c'est que ce processus est itératif, c'est a dire que de multiples modules peuvent manipuler un paquet avant qu'il soit finalement envoyé à/de l'utilisateur. Ceci donne au JSM beaucoup de flexibilité et d'extensibilité, puisque la nouvelle fonctionnalité peut être ajoutée au serveur en lui rajoutant un module sans avoir à modifier le JSM ou les modules existants.


Threading

Le JSM utilise les threads (processus) multiples pour accélérer l'exécution des tâches. Lors du démarrage du serveur, un certain nombre de threads sont assignés à la réserves de threads (ce nombre est défini dans le fichier de configuration). Lorsque que des paquets de messages sont transmis au JSM par le module d'entrée, le JSM extrait dynamiquement des threads inutilisés de la réserve et les affecte aux ports d'entrée et de sortie de messages. (Le "port de message" est une structure de donnée qui gère une connexion avec un client.) Si aucun thread n'est disponible dans la réserve, le JSM peut (mais n'est pas obligé) créer un nouveau thread et l'associer au port de message approprié. Voici un schéma du processus :


Systeme de livraison

Le module de livraison est le coeur du serveur, puisqu'il est chargé de transporter les données d'un composant bas vers un autre. Voici le schéma du système de transfert des données à ce niveau :

Une fois qu'un paquet est livré à l'un des composants bas (accep, connect, exec, ou load), il peut être envoyé à un sous-composant tel que le "jpolld" ou le "xdb_ldap" pour une transformation ultérieure.

Un exemple de condition préalable pourrait être le résultat d'une interrogation "xdb" (obtenu d'une base de données). Un exemple d'état de processus pourrait être l'addition d'un "namespace" de destination qui sera utilisé par le JSM, et un exemple de transformation de paquet pourrait être un changement de format de message avant livraison en transformant l'adresse de destination.


Modules de transports

Bien que le but principal du projet Jabber soit la réalisation d'un système de messagerie instantanée robuste basé sur XML, un second objectif important est l'interopérabilité entre les différents systèmes de MI existants. Fondamentalement, le projet de Jabber y contribue en rendant son protocole complètement ouvert. Cependant, il y contribue également en permettant la communication entre le format XML de Jabber et les nombreux autres formats non-Jabber par l'utilisation de ce qui dans le monde de Jabber s'appelle une couche "transport".

Quand un utilisateur de Jabber envoie un message à un utilisateur d'un système étranger, l'adresse de livraison de ce message contient les éléments du transport. Le client Jabber de l'utilisateur envoie son message au module dédié au protocole étranger, accompagné d'une identification Jabber qui contient le nom du système étranger (par exemple, psaintandre@aim.jabber.org). Le serveur Jabber expédie alors les données au module de transport approprié. Si le module de transport est local (tournant sur la même machine), le JSM le transfère directement, si le module de transport fonctionne à distance (sur une autre machine), alors le serveur local passe le paquet au serveur distant; qui le passera lui-même au module approprié. Une fois que le module reçoit le paquet XML, il "transforme" le message (ou des instructions) en paquet étranger, compréhensible par l'autre réseau de MI, et le serveur l'expédie sur ce réseau.

Voici un schéma général de la couche transports de Jabber :

Essentiellement, un module de transport met en application un modèle de procuration. La plupart des modules de transports contiennent leur propre petit JSM, dans lequel sera traduit le XML de Jabber en protocole "étranger" pour la présence, les messages, et l'interrogation "iq". En général, le module de transport affecte un thread par utilisateur pour gérer ses communications.

Dans certains cas la traduction du protocole de Jabber est assez facile, par exemple lorsque le protocole étranger est bien documenté (ex : IRC ou AIM). Dans d'autres cas, la traduction est rendue plus difficile par la nature propriétaire ou non documentée du protocole étranger (ex : Yahoo). On peut espérer que l'initiative d'IMUnified (http://www.imunified.org) parvienne a ouvrir certains protocoles aujourd'hui fermés, ou parvienne a créer un protocole commun.

Bien que la plupart des modules de transports servent à communiquer avec des services non-Jabber, il y a des exceptions à cette règle. Par exemple, le module de "Groupchat" permet de dialoguer avec plusieurs autres utilisateurs dans une salle de discutions, comme le protocole IRC. Ce module "Groupchat" sert de serveur de réflexion à tous les utilisateurs connectés, en renvoyant chaque nouveau message reçu à tous les autres membres. Il créera et détruira également les salles selon les besoins. C'est à dire, que si je rejoins une salle qui n'existe pas, le module créera cette salle, et si je suis la dernière personne à quitter une salle, le module se chargera de la détruire. Une salle est désignée comme ceci : groupname@groupchatserver, et chaque participant est identifié par une ressource unique représentant son surnom. Par exemple, le "groupchat" des sorcières dans Macbeth de Shakespeare pourrait avoir lieu dans une salle dont l'adresse est cauldron@conference.witches.org, et les sorcières pourraient être identifiées comme cauldron@conference.witches.org/firstwitch et ainsi de suite. Voici ce qu'elles pourraient voir :


Abonnement

Une entité de Jabber peut s'abonner à la présence de n'importe quelle autre entité (c'est a dire, a une "Jabber ID"). Un abonnement est essentiellement un accord de l'utilisateur a qui est faite la demande d'abonnement, d'envoyer ses informations de présences a l'abonné. Cet accord est stocké dans les préférences de l'utilisateur. Quand je m'authentifie et crée une session sur le serveur, mon information de présence est stockée par le JSM. A chaque fois que mes informations de présences changent, le serveur consulte mes préférences, et expédie les informations de présence à toutes les entités Jabber qui sont abonnées à ma présence.

Voici les différentes relations de présences possibles, stockées dans les préférences utilisateurs :

L'entité envoyant ses informations de présence n'est pas forcement un autre utilisateur Jabber, mais peut être un service extérieur tel qu'une source de données ou un système de MI non-Jabber. Dans ce dernier cas, les abonnements aux utilisateurs du système non-Jabber sont gérés par le module de transport, et l'utilisateur Jabber s'inscrit au module de transport correspondant (par exemple, icq.jabber.org). Une fois que l'utilisateur Jabber s'est enregistré avec succès, chaque changement de présences du propriétaire provoque envoi d'une demande d'information de présence au module. Un paquet de présence spécial est envoyé avec l'attribut "from" produit par le module, avec les données correspondantes du protocole étranger.

Le serveur Jabber maintient une liste des abonnements de chaque utilisateur (par exemple, dans une base de données). Cette liste nommée "liste de contacts" est semblable à ce qui dans d'autres systèmes de MI s'appelle une "liste de copain". Les préférences dans Jabber sont stockées sur le serveur et sont ainsi disponible de n'importe ou sur le réseau. Le serveur Jabber gère automatiquement les préférences selon les différents types d'abonnement. Les préférences, peuvent également contenir d'autres informations, comme par exemple les "nicknames" de cet utilisateur ou les "groupe" auxquels il appartient. Ces informations peuvent être exploitées par le logiciel client pour les présenter dans une interface appropriée.


Jabber ID

Dans Jabber il y a beaucoup de différentes entités qui doivent communiquer entre elles. Ces entités peuvent représenter des modules de transports, des salles de "groupchat", ou bien, un simple utilisateur Jabber. Des identifications Jabber sont employées extérieurement et expriment intérieurement les informations de propriété ou de cheminement. Voici les principales caractéristiques des identifications Jabber :

Chaque identification Jabber (ou "JID") contient un ensemble d'éléments. Les JID sont constitués d'un domaine, d'un noeud, et d'une ressource dans le format suivant :

node@domain/resource

Les éléments d'identification de Jabber sont définis comme suit :

Un utilisateur Jabber se connecte toujours au serveur au moyen d'une ressource particulière et a donc une adresse de la forme node@domain/resource. Cependant, puisque la ressource est facultative, l'adresse de l'utilisateur peut être de la forme node@domain (par exemple : juliet@capulet.com), ce qui est plus facile a retenir, puisqu'il est de la même forme que les adresses d'E-mail).

En général, les messages sont expédiés à une ressource spécifique, et un message destiné à juliet@capulet.com est transformé par le serveur Jabber pour que son adresse de destination correspondre a une ressource précise. Ainsi, si un message est envoyé à juliet@capulet.com (c'est a dire sans indiquer de ressource), le message est dirigé vers la ressource qui a la priorité la plus élevée, par exemple : juliet@capulet.com/balcony.


Server Dialback

Le serveur 1.2 a ajouté un dispositif appelé le "dialback". Ce dispositif est conçu pour décourager le "spoofing", ceci rajoute une mesure de sécurité supplémentaire aux communications de serveur à serveur. Vous trouverez de la documentation sur ce sujet ici : http://docs.jabber.org/draft-proto/html/dialback.html.


Conclusion

Ce document a fourni une vue d'ensemble sur l'architecture de Jabber. Si vous avez d'autres questions au sujet de ce document, contacter son auteur (Peter Saint-André) par l'intermédiaire du courrier électronique ou de Jabber : stpeter@jabber.org

Vous pouvez également contacter (en français) le traducteur de ce document : Yvon Le Gal ou yvozin@jabber.org


Copyright Information

This document is copyright 2001 by Peter Saint-Andre.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation, with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a copy of the GNU Free Documentation License from the Free Software Foundation by visiting http://www.fsf.org/ or by writing to:

The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307 USA