Saturday, July 24, 2010

The gen_client v0.9: new design and features

The gen_client underwent a lot of changes over the past few months.  The most significant are:
  • Plugin framework added;
  • Startup options introduced. The ones that work now are:
  1. "presence" - allows to specify if presence should be send after logging in;
  2. "reconnect" - auto-reconnect,
  3.  "script" - arbitrary function to call right after the connection was established; the default is exmpp:login/1
Other options coming soon: mechanisms (i.e  BASIC, PLAIN etc), connection types (i.e. TCP, BOSH, SSL).
  • Dynamic handlers implementation was switched to gen_event;
  • The code can now be built with faxien, in addition to Emakefile.
I have to mention that API was changed almost entirely, just in case you did use previous versions. 
Check out the example of using API in test_gen_client:test/0. There are 2 Jabber account that I opened at jabber.ru in order to make it easier to try it live. That's what is happening:
  1. The first account signs in, announces the presence and adds "disco" plugin with user-defined content (implemented in test_disco module).
  2. The second  account signs in, announces presence and sends two synchronous requests to the first account to retrieve "disco_info" and "disco_items".
test_gen_client:test() output
Below is a code for test/0:

test() ->
 {ok, Client1} = gen_client:start("gen_client@jabber.ru", "jabber.ru", 5222, "test", 
                  [{debug, true}, {presence, {true, "I'm online."}}, {reconnect, 15000}]), 
 gen_client:add_plugin(Client1, disco_plugin, [test_disco, []]),
  %% Log in with 2nd client and send discovery request to 1st client
 {ok, Client2} = gen_client:start("gen_client2@jabber.ru", "jabber.ru", 5222, "test", 
                  [{debug, true}, {presence, {true, "I'm online."}}, {reconnect, 15000}]),

 %% We want to know what resource the first client was assigned, as disco requests should be sent to a particular resource
 Jid1 = gen_client:get_client_jid(Client1),
 %% We need to convert it to string to comply with exmpp_client_disco calls 
 Jid1Str = exmpp_jid:to_list(Jid1),
 {ok, Info} = gen_client:send_sync_packet(Client2, exmpp_client_disco:info(Jid1Str), 10000),
 io:format("Disco info from gen_client:~p~n", [gen_client:get_xml(Info)]),
 {ok, Items} = gen_client:send_sync_packet(Client2, exmpp_client_disco:items(Jid1Str), 10000),
 io:format("Disco items from gen_client:~p~n", [gen_client:get_xml(Items)]), 
 ok.

The gen_client code can be obtained here.

Coming soon: adhoc commands plugin with examples.