Archive for the ‘XMPP’ Category

Serveur Jabber en ligne

En fait, non. Je l’ai coupé. Je le remettrais un jour.

En attendant pour me joindre via XMPP : cstar chez ohmforce point com

(Celui d’Ohm Force, s’il tombe, je me fais taper sur les doigts).

Advertisements

mini Auth CAS on Yaws

Yaws, c’est le serveur web écrit en erlang, célèbre pour ce graphe qui montre comment Yaws met sa pâté à Apache.

Voici le client minimal permettant de s’authentifier sur un serveur CAS.

A sauver dans un fichier cas.yaws à mettre dans le /var/yaws (document root par défaut).

N’oubliez pas d’adapter CASHOST et SERVICE à votre configuration.

<erl>
-define(CASHOST, "http://localhost:8080/cas/").
-define(SERVICE, "service=http%3A%2F%2Flocalhost%3A5224%2Fcas.yaws").
-include_lib("xmerl/include/xmerl.hrl").

out(A)->
    H = A#arg.headers,
    C = H#headers.cookie,
    inets:start(),
    case yaws_api:find_cookie_val("casuser", C) of
        []->
            check_auth(A);
        Cookie ->
            {ok, Username} = yaws_api:cookieval_to_opaque(Cookie),
            {html, "Authentified as "++Username}
    end.

check_auth(A)->
    case queryvar(A,"ticket") of
        {ok, Ticket}->
            case verify_ticket(Ticket) of
                {ok, Username} ->
                    Cookie = yaws_api:new_cookie_session(Username),
                    CO = yaws_api:setcookie("casuser",Cookie,"/"),
                    [{html, "Authentified as "++Username}, CO];
                {error, Reason} ->
                    [{status, 403},{html, "Unauthorized : "++Reason}]
            end;
        undefined ->
            {redirect, ?CASHOST ++ "login?" ++ ?SERVICE }
        end.

verify_ticket(Ticket) ->
    inets:start(),
    Url =?CASHOST++"proxyValidate?"++?SERVICE++"&ticket="++Ticket,
    {ok, {_Status, _Headers, Body}} =
          http:request(Url),
    { Xml, _Rest } = xmerl_scan:string(Body),
    inets:stop(),
    case xmerl_xpath:string("//cas:user/text()",Xml) of
        [ #xmlText{value=Username} ] ->
            {ok, Username};
        [] ->
            {error, "invalid ticket " ++ Url}
        end.
</erl>

Tant qu’on est sur le sujet, il y a un article très intéressant sur le REST dans Yaws chez InfoQ.

Auth me on Jabber

CAS est un service très populaire permettant de mettre en place le Single Sign On, avec des librairies clientes pour la plupart des langages.

On peut facilement rajouter des handlers d’authentification.

En voici un très rapide, permettant de s’authentifier sur un service Jabber.

Installation :

Uniquement compatible CAS v3.

Installez ce bout de xml dans le deployerConfigContext, dans la liste des AuthHandlers :


<bean class="com.ohmforce.cas.JabberAuthenticationHandler">
 <property name="jabberHostname" value="DOMAIN"/>
</bean>

Copiez jabber-cas.jar.zip et la jar de Smack, relancez la webapp CAS et c’est tout.

Pour se logger sur vos applications CASifiées, vos utilisateurs utiliserons leur compte défini dans sur le domaine indiqué par jabberHostname, le mal nommé.

Le code

Y en a tellement peu que ca tient ici.


package com.ohmforce.cas;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

final public class JabberAuthenticationHandler extends
        AbstractUsernamePasswordAuthenticationHandler {
    private String jabberHostname;
    @Override
    protected boolean authenticateUsernamePasswordInternal(
            UsernamePasswordCredentials credentials)
            throws AuthenticationException {
        XMPPConnection conn = new XMPPConnection(jabberHostname);
        try {
            conn.connect();
            conn.login(credentials.getUsername(), credentials.getPassword());
        } catch (XMPPException e) {
            log.error("Failed", e);
            return false;
        }
        finally{
            conn.disconnect();
        }
        return true;
    }

public void setJabberHostname(String server)
{
    jabberHostname=server;
}
public String getJabberHostname()
{
    return jabberHostname;
}

}

Ping me on Jabber

Je suis en train de faire migrer Ohm Force d’IRC à full Jabber.

Ca marche bien, mais il manque une fonctionnalité indispensable :

Que ca bippe le client quand dans une chatroom, on cite mon nickname.

Ni iChat ni Spark ne l’ont.

iChat

Pour iChat, c’est facile avec AppleScript:


using terms from application "iChat"
    on chat room message received theMessage from theBuddy for theChat
        set theUser to "VOTRE NICKNAME"
        if theMessage contains theUser then
            say theUser
        end if
    end chat room message received
end using terms from

Tout ça dans le script editor, on enregistre dans le rep ~/Library/Scripts/iChat sous le nom de beep.scpt et ensuite on configure comme ça :

Configuration d'iChat

Spark

Pour Spark, j’ai du écrire un plugin. Rapide, j’ai passé plus de temps à trouver comment le compiler qu’à l’écrire.

J’ai pris le son bell.wav de Spark, et je l’ai embarqué dedans.

Pour le télécharger, c’est ici :
beep.jar.zip

Il faut dézipper, et glisser la jar dans le répertoire plugins de Spark.

Sur Mac et Linux, cherchez dans le répertoire Spark à la racine de votre compte. Sur Windows … j’en sais rien.

C’est dans la même licence que Spark, et si vous voulez le code source, contactez-moi.

(oui, je dois toujours configurer mon serveur SVN pour l’accès public)

Pour finir :

Une fonctionnalité qui complémente bien celle-ci est l’autocomplétion des nicknames. Mais c’est beaucoup plus de travail, donc c’est pour plus tard !

Pour l’instant, dites à vos amis de choisir des nicknames plus courts.

mod_rpc : Jabber-RPC within ejabberd

What is mod_rpc ?

mod_rpc is an ejabberd module which will handle rpc queries … in a modular way.

It is is easily extensible, and is designed to access the mnesia database from XMPP clients.

It plugs in the access control list to allow or prevent access to the rpc modules.

Installing mod_rpc

Download the mod_rpc.erl file and copy it over your ejabberd src/ directory.
make ejabberd.

Do not restart yet, we have some configuration to do !

Using mod_rpc

Let’s say you want to publish two functions, echo and mult. The code would go as follow :

rpc_test.erl :


-module(rpc_test).
-export([handle/2]).

handle(_State, {call, echo, [A]}) -> {response, [A]};
handle(_State, {call, mult, [A, B]}) -> {response, [A*B]};

Copy into your ejabberd source directory and make.

Now you need to configure access to your functions.
In

ejabberd.cfg


% 2 groups : admins, and the rest.
{access, rpc_admin, [{allow, admin}]}.
{access, rpc_all, [{allow, all}]}.
%...

%... in modules configuration
%...
  {mod_register,   [{access, register}]},
  {mod_rpc, [{access, [{rpc_test, rpc_admin}] }]}, % only admins can call echo and mult
  {mod_roster,     []},
%....

Now start ejabberd. (of course you could do the hot code stuff if you want)

From now on I have rpc_test@rpc.localhost answering to my rpc queries.

Let’s test from ruby using xmpp4r. Get the SVN version for jabber-RPC support.


require 'xmpp4r'
require 'xmpp4r/rpc/helper/client'
require 'xmpp4r/rpc/helper/server'
include Jabber
jid = JID::new('cstar@localhost') #this one is admin !
cl = Client::new(jid)
cl.connect
cl.auth("PASS")
rpc= RPC::Client.new(cl, 'rpc_test@rpc.localhost')
puts rpc.call("echo", 'Test string') # outputs Test string
puts rpc.call("mult", 2,4) # outputs ... 8

If you try with a non-admin user, you’d get

Jabber::AuthenticationFailure: not-authorized

About Groovy Jabber-RPC

I have been playing with it, and it does not work directly out of the box. The groovy lib will try to see if rpc_test@rpc.localhost is in the user roster.

Patching to making it work is quite simple ;
In file xmlrpc-groovy/src/main/java/groovy/net/xmlrpc/JabberRPCServerProxy.java

Just replace : request.setTo(getId(connection.getRoster(), this.to)); (line 102)

with : request.setTo(this.to);

And the following will work :


import groovy.net.xmlrpc.*
import org.jivesoftware.smack.XMPPConnection

def clientConnection = new XMPPConnection("localhost")
clientConnection.connect()
clientConnection.login("cstar", "PASS")
def serverProxy = new JabberRPCServerProxy(clientConnection, "rpc_test@rpc.localhost")
serverProxy.echo("test")
clientConnection.disconnect()

Necessary caveats

This is my first foray in developping a module in ejabberd, I still have to check how this actually scales. I only have one process handling all queries, which is not very concurrency oriented programming 🙂

Thanks

The guys from ejabberd, for making software really easy to use and extend 😉

Download :

mod_rpc.erl

Feedback

I really welcome enhancements and fixes (especially regarding the concurrency stuff!)

License

Don’t sue me, don’t remove copyright/name kind of license.

From ejabberd xml to xmerl and back – XEP-009

Those last days I was busing implementing an ejabberd module responding to Jabber-RPC (a.k.a XEP-009).

I used the xmlrpc module shipped with erlang to do the parsing. But that was tricky. xmlrpc uses xmerl for parsing and representing XML but ejabberd does not. It a simpler xml module handling the parsing.

To make a long story short, to get ejabberd’s xml understood by xmlrpc, here’s the thing :

% ....
xmlrpc_decode:payload(xmerl_ucs:to_utf8(
            xml:element_to_string(xml:get_subtag(SubEl, "methodCall")))),
% ....

SubEl being the sub_el field of an iq packet.

The complex part is that you need to call xmerl_ucs:to_utf8/1 else the module will crash.

For returning the resulting XML to the client, you need to call xml_stream:parse_element (ejabberd’s internal XML parser) to get the XML structure right for handling by ejabberd.

case xmlrpc_encode:payload(handle(State,Decoded)) of % handle is the xmlrpc method
 {ok, EncodedPayload} ->
    Res = IQ#iq{type = result,
        sub_el = [{xmlelement, "query", [{"xmlns", ?NS_RPC}],
        [ xml_stream:parse_element(EncodedPayload) ]
               }]
    },
%....

That’s not very optimal of course, as data is converted at nearly every step :

XML -> ejabberd -> XML -> xmerl -> XML -> ejabberd -> XML.

But developper time is more expensive than machine time, right ?

So now I can call methods on the server directly from Groovy using Groovy Jabber-RPC (using XMPPPool, of course).

If there is any interest, I’ll release the code, but for the time being it is very crude. I’ll like to “componentize” a bit more, and hook up ACLs for specific RPC handlers.

[UPDATED] XMPPPool : XMPP Connection Pooling for Tomcat and Grails/Jetty

Release 0.3 of XMPPPool

[Update : also added support for Grails Jetty]

[Update 2 : Simplified the API a lot. It is now basically invisible …]

About

It provides XMPP connection pooling for Tomcat, configured as a resource in the $TOMCAT_HOME/conf/server.xml.

The main use case to use Groovy Jabber-RPC, with the webapp acting as a client :

  • You fetch a XMPPConnection from the pool,
  • call an RPC method,
  • get the result,
  • return the XMPPConnection to the pool.

Of course you can use the code to write XMPP “servers”/bots, but you’ll have to manage the lifecycle of the connection (i.e. launch a separate thread)

How it works

A pool is created, with connections to the XMPP server. All connections use the same XMPP account, but each have a unique resource.

Rule 10.5 of RFC 3920 (XMPP Core) means that is a stanza is sent to a JID with a specific resource, it MUST be delivered to this resource or it MUST fail.
However if a stanza is sent to a jid without any resource identifier, it SHOULD be sent to at least one of the resources.

So make sure that the code answering to a query coming from an XMPPPool managed connection sends it to a specific JID.

Quick install guide for Tomcat

Download XMPPPool-0.3.0-jar-with-dependencies.jar.zip and copy it in your $TOMCAT_HOME/common/lib.
Then in server.xml, configure your source as follow :


<Resource auth="Container" maxActive="10" maxIdle="5" maxWait="10000"
  factory="com.ohmforce.xmpp.XMPPSourceFactory" type="com.ohmforce.xmpp.XMPPConnectionPool" name="xmpp/connection"
  username="username" password="pass" service="localhost" port="5222"/>

The pooling code is using commons-pool from Apache. All the usual options are available. port is optional and defaults to 5222.

Now restart your container.

Quick install guide for Grails/Jetty

First you need to patch Grails as per this report (which should be implemented soon in Grails). Don’t forget to add the jars to $GRAILS_HOME/lib!

Also unzip and add XMPPPool-0.3.0-jar-with-dependencies.jar in GRAILS_HOME/lib

Then add a jetty-env.xml file in WEB-INF/ directory (of your Grails app)


<Configure class="org.mortbay.jetty.webapp.WebAppContext">
  <New id="xmpp" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>xmpp/connection</Arg>
    <Arg>
    <New class="com.ohmforce.xmpp.XMPPSourceFactory">
     <Set name="properties">
       <New class="java.util.Properties">
         <Put name="username">username</Put>
         <Put name="password">pass</Put>
         <Put name="service">localhost</Put>
       </New>
      </Set>
   </New>
 </Arg>
   </New>
</Configure>

Start the grails app : grails -Denable.jndi=true run-app

Now inside a grails controller you can connect to a Jabber-RPC service :

Using from Grails :

Now inside a grails controller you can connect to a Jabber-RPC service :


import javax.naming.InitialContext;
import groovy.net.xmlrpc.*
class HelloController{
def hello = {
        def p =new InitialContext().lookup("java:comp/env/xmpp/connection")
        def serverProxy = new JabberRPCServerProxy(p, "cstar@localhost")
        def s = serverProxy.add(2,6)
        def e = serverProxy.echo("toto")
        flash.message = "${s} and ${e}"
        p.disconnect() // does not actually disconnect, but returns connection in pool
    }
}

The server code (slightly modified from the examples on the Groovy website. fixed typos and updated to latest Smack version) :


import groovy.net.xmlrpc.*
import org.jivesoftware.smack.XMPPConnection
def server = new JabberRPCServer()
server.echo = {return it+"toto"}
server.add = {i,j -> return i+j}
def serverConnection = new XMPPConnection("localhost")
serverConnection.connect()
serverConnection.login("user", "pass")
server.startServer(serverConnection)

Using the datasource in a servlet


try{
    InitialContext ctx = new InitialContext();
    XMPPConnection conn = (XMPPConnection) ctx.lookup("java:/comp/env/xmpp/connection");
    // Do things here
    conn.disconnect(); // does not actually disconnect, but returns connection in pool
}
catch(Exception e){
    e.printStackTrace();
}

For actually using the connection, please refer to the Smack developper guide

Building the source code

The project is built with Maven.

mvn assembly:assembly

cp target/XMPPPool-0.3.0-jar-with-dependencies.jar $TOMCAT_HOME/common/lib/

And you’re set.

Bugs ? Patches ?

  • mail : eric at ohmforce dot com
  • xmpp : cstar at cestari dot info

Known issues

  • Only one pool can be configured on a given tomcat instance (Although that should fit most use cases)

Todo

  • Better error reporting, I guess 🙂

License

Apache 2.0 license, the same as Smack and others libs XMPPPool is built upon. Free to use, as long as you don’t sue me or remove my name from the code …

Download

Des bots XMPP avec Smack

J’ai écrit il y a quelques temps deux bots qui communiquent entre eux. j’utilise la librarie Smack Java.

Le code : chatbots.zip. C’est un projet Eclipse 3.1, avec toutes les jars nécessaires.

Pour l’utiliser, vous allez devoir créer deux comptes sur le serveur Jabber, et modifier la méthode main.

Mais que font-ils ?

Il y a deux bots : sessioncreator et sessionbot.
Pour créer une chatroom, il faut envoyer un message à sessioncreator sous cette forme :

create MaChatRoom <liste de personnes a inviter separes par des espaces>

A ce moment-là, sessioncreator :

  • crée la chatroom et met le sessionbot en owner de la chatroom.
  • invite le sessionbot, avec le nom listener
  • envoie les invitations au demandeur, et à la liste des personnes à inviter.
  • quitte la chatroom un fois que le sessionbot a rejoint la chatroom.

Le sessionbot, lui travaille beaucoup moins :

  • Il accepte les invitations à rejoindre les chatrooms
  • Il kick toutes les personnes qui disent FORBIDDEN.

NB : le sessioncreator a deux hooks canCreate et canJoin qui permettent de vérifier si un utilisateur peut créer ou joindre la chatroom (avec une vérification en BDD, par exemple).

NB2 : Vous pouvez utiliser/modifier mon code source sans restriction. Pour les jars de Smack, vous devez respecter leur licence (mais bon c’est du Open Source Apache, ce qui est assez tranquille).

Libraries et clients XMPP

Le post précédent était trop long. J’espère que vous avez tenu.

Indispensable pour développer des applications XMPP, le client Psi . Permet d’afficher le trafic depuis et vers le client, la possibilité de composer en brut les stanzas (paquets) XMPP, connexions multiples, bref idéal pour développer et débugger.

  • Pour causer :

    Il y aussi iChat sur les Mac, GAIm et le WengoPhone .
    Un client plutôt sympa : Coccinella . Avec une fonctionnalité de whiteboard en SWF. Malheureusement l’interface utilisateur est plutôt maladroite.
    La page des clients sur Jabber.org

  • Pour développer :

    Les APIs que j’ai testée sont en général basé sur un modèle événementiel, ce qui colle plutôt bien 🙂
    Il y a Smack dont je parle dans le post précédent qui gère tout le support de XMPP-Core, et entre autres, la connexion au serveur de discussion, et les data-forms (envoi de formulaires à la HTML).

    C’est une librairie Java, et elle semble la plus avancée dans ce langage.
    Par contre, pas de développement de composants, il faut utiliser Whack , qui n’est curieusement pas documenté du tout sur le site IgniteRealtime.

    J’ai testé XMPP4R, mais pas longtemps. J’ai joué avec les exemples, remarqué que la couverture de XMPP Core et des Extensions est large, et y a des helpers pour développer des Multi-User Chatrooms (MUC) en composant assez facilement. Par contre j’ai eu des problèmes curieux pendant le développement de mes bots, et par flemme (?) j’ai basculé mon développement sur Smack en Java.
    Les librairies XMPP sur Jabber.org

.
.
. Enough pour aujourd’hui.

Vers Erlang via XMPP

XMPP , né Jabber, m’occupe depuis maintenant quelques mois.
Ce protocole s’occupe de la messagerie instantanée, et se cache derrière le réseau GoogleTalk.
Une de ses grosses forces est l’ouverture et l’interopérabilité entre les serveurs XMPP.
Il faut imaginer le réseau XMPP comme le réseau de routage des emails. L’utilisateur est indentifié via son jid (Jabber ID) : eric@cestari.info . Ca ressemble à une adresse mail, et pour cause. Un ami, Olivier, est sur GoogleTalk. Son jid est of@gmail.com . Lorsque je souhaite envoyer un message, il est routé par mon serveur (cestari.info) vers le serveur gmail.com qui délivre enfin le message à Olivier.

Intégré aussi, le système de chatroom, de publication/abonnement, annuaire, etc.

Bref, le protocole de messagerie instantanée qui finira par gagner :).
Je voulais installer un serveur XMPP sur mon serveur, pour jouer avec et écrire une version custom du module MUC (multi-user chat, les chatrooms).
Parmi les serveurs XMPP les plus répandus, j’en ai testé 2 et gardé 1.
OpenFire : Ecrit en Java, administré via http. Respecte les principales XEP (extensions de XMPP). Dimensionné pour 5000 utilisateurs simultanés, avec la possibilité d’utiliser des connecteurs pour augmenter la capacitée.
J’ai eu un problème de connexion S2S (Server to Server) vers d’autres serveurs comme GoogleTalk. J’ai arrêter de creuser dessus, bien que Java soit le langage que je connaisse le mieux.
ejabberd : Ecrit en Erlang (on y arrive !), très bonne couverture du protocole et de ses extensions. Et ensuite, les trucs mortels :

  • Mise en cluster : J’ai besoin de plus de puissance ? j’ajoute un serveur avec une nouvelle instance d’ejabberd que je connecte en 30 secondes, sur la première.

  • Possibilité de mettre à jour le code sans interruption : Je compile, je me connecte à la console du serveur, je lui dit que le code d’un module a été mis à jour, et les requêtes suivantes seront traités par la nouvelle version.

  • Scalabilité incroyable : on peut lui balancer des utilisateurs … Il existe des installations d’ejabberd qui gèrent des centaines de milliers d’utilisateurs et des dizaines de milliers d’utilisateurs simultanéments. Un simple PIII 1,5GHz gère 2000 messages par seconde et 7000 utilisateurs connectés !

Toutes ses fonctionnalités arrivent avec un coût. Tout est écrit en erlang . Langage inventé par les suédois d’Ericsson, pour avoir un outil adapté au développement de leurs produits télécom. Ce petit film indépendant très cheesy présente les avantages d’Erlang. Avant de cliquer sur ce lien, n’oubliez pas qu’il s’agit des concepteurs du langage eux-même qui s’occupent de la présentation.

Je regarde un peu le code source d’ejabberd, et je comprends initialement que dalle. Regardez plutôt.

Interlude Java ….

Pendant la phase de réflexion, je m’oriente vers des bots XMPP qui répondrait aux requêtes. J’utilise la librairie Smack , par Jive Software. (oui ceux derrière OpenFire !). C’est du Java, je connais. En quelques heures et 300 lignes de code j’ai deux bots qui se connectent à mon serveur, qui causent entre eux et gèrent des chatrooms.

Mais ca ne me plaît pas. Même si l’informatique distribué, c’est toujours marrant, le côté mystérieux et “best kept secret” m’intrigue.

En effet, les avantages d’ejabberd sont directement des avantages du langage et de l’environnement Erlang. Il fonctionne sur une machine virtuelle comme Java.

Du coup, je creuse. Je tombe sur des blogs : Tenerife Skunkworks , Joel Armstrong (l’un des concepteurs, justement) et Yariv’s Blog , qui parlent causent erlang.

Des PDF intéressants :
Getting started with Erlang
La thèse de Joel Armstrong

Et comme par hasard, ce dernier vient de publier chez Pragmatic Programmers , Programming Erlang .

J’achète le PDF (des bouts sont dispos sur la page du livre). Pas le temps d’attendre la livraison, et avec un dollar aussi bas … c’est cadeau.

Et finalement, petit à petit, le code source de ejabberd commence à prendre sens.

Après 2 jours de travail, et une dizaine de programmes de test, et une première bidouille sur un module d’ejabberd, je sens que je peux vous parler de manière plus informée de ce langage.

Les caractérisques notable d’Erlang :

  • Langage fonctionnel, comme Lisp et OCaml
  • Donc largement basé sur les closures et fonctions anonymes, ce qui rend la programmation événementielle très pratique à utiliser.
  • La communication se fait uniquement par passage de message d’un processus à l’autre, il n’y a pas d’état global
  • Les processus sont complètement isolés, donc pas de synchronisation à faire. Chaque processus a une boite à message qu’il relève avec receive. Les processus sur des noeuds (instances) séparés peuvent communiquer très simplement.
  • La création d’un processus, et le changement de contexte ne coûtent rien. Un petit script qui va créer 20000 processus créera chacun d’eux en 2,5 ms.
  • Le pattern matching et les variantes de fonctions permettent d’exprimer la gestion des cas particuliers :

 -module(testblog).
 -export([hello/1]).

 hello({hello, eric}) ->
     io:format("Bonjour Eric~n"),
     ok;
 hello({hello, Name}) ->
     io:format("Bonjour, ~w~n", [Name]),
     ok;

 hello({Action, Name}) ->
     io:format("action : ~p pour : ~p~n", [Action, Name]),
     ok.

Le tuple (le truc entre {}) passé en paramètre sera testé sur chacun des prototypes en partant du haut. Les mots commençant par une minuscule sont des atomes (utilisés entre autres comme clés. hello represente un truc qui s’appelle hello et qui peut être identifié par hello.) Les mots commençant par une majuscule sont des variables.

Donc :

  • testblog:hello({hello, eric}) appelera la première version.
  • testblog:hello({hello, marc}) ne sera pas matché par la première version, car marc est différent de eric. On teste sur la deuxième. Le premier élément est l’atome hello, et le deuxième est une variable, que je peux matcher avec n’importe quoi (donc marc). Il n’y a pas d’autres éléments dans le tuple, donc cette version de la fonction convient. C’est donc celle-ci qui est exécuté.
  • testblog:hello({bonjour, eric}). Seule la troisième version de la fonction accepte un premier paramètre différent de 0.

Enfin bref, ce billet n’est pas un tutorial sur Erlang, c’est un truc qui peut vous donner envie de l’utiliser.

Une fois qu’on sait lire la syntaxe du langage (ce qui ne prend que quelques heures), on commence à apprécier la clarté compacte qu’elle engendre.

Du coup, je me suis livré à une étude non-scientifique sur la complexité relative d’un gros projet entre Java et Erlang, en regardant le nombre de lignes entre ejabberd et OpenFire.
Alors que OpenFire compte à peu près 200 000 lignes , ejabberd n’en compte que 80 000 , avec plus de fonctionnalités.

Damn !

Un autre exemple, comparaison des performances entre Apache et yaws (serveur web écrit en erlang). Le benchmark s’attache au nombre de connexions simultanée.
Apache lâche autour de 4000 connexions simultanées. Yaws fonctionne toujours à 80 000 connexions simultanées.

Duh !

Pour démarrer, Process One, le sponsor de ejabberd maintient CEAN (Comprehensive Erlang Archive Network), le CPAN d’Erlang. Avec des packages pour démarrer .

J’en re-parlerais très bientôt. Pour l’heure, il est samedi, et Martin veut jouer avec son papa.