<exploring:xmpp/>Jack Moffitt
Why XMPP?
HTTP APIs are great
HTTP polling sucks
Real time is different
XMPP is real time
XMPP basics
XMPP network
XMPP addressing
example.com
XMPP protocol
XML
XML streams
XML stanzas
<message/>
<presence/>
<iq/>
<message/>
<messagefrom=’[email protected]/home’to=’[email protected]’type=’chat’>
<body>Wherefore art thou, Romeo?
</body></message>
<messagefrom=’[email protected]/home’to=’[email protected]’type=’chat’>
<body>Wherefore art thou, Romeo?
</body></message>
<messagefrom=’[email protected]/home’to=’[email protected]’type=’chat’>
<body>Wherefore art thou, Romeo?
</body></message>
<messagefrom=’[email protected]/home’to=’[email protected]’type=’chat’>
<body>Wherefore art thou, Romeo?
</body></message>
<messagefrom=’[email protected]/home’to=’[email protected]’type=’chat’>
<body>Wherefore art thou, Romeo?
</body></message>
<presence/>
<presence><show>away</show><status>At Codebits</status>
</presence>
<presencetype=’available’>
<show>away</show><status>At Codebits</status>
</presence>
<presencetype=’available’>
<show>away</show><status>At Codebits</status>
</presence>
<presencetype=’available’>
<show>away</show><status>At Codebits</status>
</presence>
<iq/>
<iqto=’sapo.pt’type=’get’id=’disco:1’>
<query xmlns=’disco#info’/></iq>
<iqto=’sapo.pt’type=’get’id=’disco:1’>
<query xmlns=’disco#info’/></iq>
<iqto=’sapo.pt’type=’get’id=’disco:1’>
<query xmlns=’disco#info’/></iq>
<iqto=’sapo.pt’type=’get’id=’disco:1’>
<query xmlns=’disco#info’/></iq>
<iqto=’sapo.pt’type=’get’id=’disco:1’>
<query xmlns=’disco#info’/></iq>
<iqto=’[email protected]/home’from=’sapo.pt’type=’result’id=’disco:1’>
<query xmlns=’disco#info’><identity category='server' type='im'
name='ejabberd'/><feature var='vcard-temp'/>
</query></iq>
<iqto=’[email protected]/home’from=’sapo.pt’type=’result’id=’disco:1’>
<query xmlns=’disco#info’><identity category='server' type='im'
name='ejabberd'/><feature var='vcard-temp'/>
</query></iq>
<iqto=’[email protected]/home’from=’sapo.pt’type=’result’id=’disco:1’>
<query xmlns=’disco#info’><identity category='server' type='im'
name='ejabberd'/><feature var='vcard-temp'/>
</query></iq>
<iqto=’[email protected]/home’from=’sapo.pt’type=’result’id=’disco:1’>
<query xmlns=’disco#info’><identity category='server'type='im'name='ejabberd'/>
<feature var='vcard-temp'/></query>
</iq>
The application
example
contrived
Server monitoring
Goodbye SNMP
XMPP APIs
Features
Collection hub
Collectors are XMPP bots
Controlled via client
Presence
Discovery
Commands
Notification
No processing
Presence
Communicates status
Subscribing
<presence type=’subscribe’ to=’[email protected]’/>
<presence type=’subscribed’ from=’xmpp@mon...’ to=’client@mon...’/>
Rosters
<iq type=’get’ id=’roster1’> <query xmlns=’jabber:iq:roster’/></iq>
<iq type=’result’ id=’roster1’> <query xmlns=’jabber:iq:roster’> <item jid=’xmpp@mon...’ subscription=’to’/> </query></iq>
Initial presence
<presence/>
Starting up
<presence from=’xmpp@mon...’/>
Dead server
<presence type=’unavailable’ from=’xmpp@mon...’/>
Busy server
<presence type=’available’> <show>away</show> <status> Overloaded. Can’t take more jobs. </status></presence>
Discovery
Meta information
Disco info
<iq id=’disco1’ type=’get’ to=’xmpp@mon...’> <query xmlns=’.../disco#info’/></iq>
<iq ...> <query xmlns=’.../disco#info’> <identity name=’XMPP Monitor’ category=’monitor’ type=’server’/> </query></iq>
Statistics available
Disco items
<iq id=’disco2’ type=’get’ to=’xmpp@mon...’> <query xmlns=’.../disco#items’/></iq>
<iq ...> <query xmlns=’.../disco#items’> <item name=’CPU Load’ jid=’xmpp@mon...’ node=’cpu’/> ... </query></iq>
<iq ...> <query xmlns=’.../disco#items’> <item name=’CPU Load’ jid=’xmpp@mon...’ node=’cpu’/> ... </query></iq>
<iq ...> <query xmlns=’.../disco#items’> <item name=’CPU Load’ jid=’xmpp@mon...’ node=’cpu’/> ... </query></iq>
Gathering statistics
Disco info again
With a node
<iq id=’disco3’ type=’get’ to=’xmpp@mon...’> <query xmlns=’.../disco#info’ node=’cpu’/></iq>
<iq ...> <query xmlns=’.../disco#info’ node=’cpu’> <statisic xmlns=’codebits’ name=’5-min’ value=’0.4’/> </query></iq>
<statistic/>
Extended stanza
Create your own
Namespace
<iq ...> <query xmlns=’.../disco#info’ node=’cpu’> <statisic xmlns=’codebits’ name=’5-min’ value=’0.4’/> </query></iq>
Commands
Ad-hoc commands
RPC
Input and output
Data forms
<x xmlns='jabber:x:data' type='...'> <field type='hidden' var='FORM_TYPE'> <value>jabber:bot</value> </field> <field type='text-single' var='botname'> <value>Awesome Bot</value> </field></x>
<x xmlns='jabber:x:data' type='...'> <field type='hidden' var='FORM_TYPE'> <value>jabber:bot</value> </field> <field type='text-single' var='botname'> <value>Awesome Bot</value> </field></x>
<x xmlns='jabber:x:data' type='...'> <field type='hidden' var='FORM_TYPE'> <value>jabber:bot</value> </field> <field type='text-single' var='botname'> <value>Awesome Bot</value> </field></x>
<x xmlns='jabber:x:data' type='...'> <field type='hidden' var='FORM_TYPE'> <value>jabber:bot</value> </field> <field type='text-single' var='botname'> <value>Awesome Bot</value> </field></x>
<x xmlns='jabber:x:data' type='...'> <field type='hidden' var='FORM_TYPE'> <value>jabber:bot</value> </field> <field type='text-single' var='botname'> <value>Awesome Bot</value> </field></x>
Reboot command
<iq ...> <command xmlns=’.../commands’ node=’reboot’ action=’execute’/></iq>
<iq ...> <command xmlns=’.../commands’ node=’reboot’ action=’execute’/></iq>
<iq ...> <command xmlns=’.../commands’ node=’reboot’ action=’execute’/></iq>
<iq ...> <command xmlns=’.../commands’ node=’reboot’ status=’completed’/></iq>
Stats reset
Shell commands
Notifications
Important events
Limits exceeded
Publish subscribe
Pubsub
Nodes
Node hierarchy
Leaves
Collections
Bots publish
Client subscribes
PEP
Personal eventing protocol
Profile of pubsub
Simple
Presence
Every JID is a pubsub node
Subscriptions are automatic
Publishing
<iq ...> <pubsub xmlns=’.../pubsub’> <publish node=’codebits’> <item> <rebooted xmlns=’codebits’/> </item> </publish> </pubsub></iq>
<iq ...> <pubsub xmlns=’.../pubsub’> <publish node=’codebits’> <item> <rebooted xmlns=’codebits’/> </item> </publish> </pubsub></iq>
<iq ...> <pubsub xmlns=’.../pubsub’> <publish node=’codebits’> <item> <rebooted xmlns=’codebits’/> </item> </publish> </pubsub></iq>
<iq ...> <pubsub xmlns=’.../pubsub’> <publish node=’codebits’> <item> <rebooted xmlns=’codebits’/> </item> </publish> </pubsub></iq>
<iq ...> <pubsub xmlns=’.../pubsub’> <publish node=’codebits’> <item> <rebooted xmlns=’codebits’/> </item> </publish> </pubsub></iq>
Subscribing
Automatic
Entity capabilities
Caps
Caps extend presence
<presence> <c xmlns=’.../caps’ node=’codebits’ hash=’sha-1’ ver=’...hash...’/></presence>
<presence> <c xmlns=’.../caps’ node=’codebits’ hash=’sha-1’ ver=’...hash...’/></presence>
<presence> <c xmlns=’.../caps’ node=’codebits’ hash=’sha-1’ ver=’...hash...’/></presence>
Interpreted via disco
<feature var=’codebits’/><feature var=’codebits+notify’/>
Events
<message ...> <event xmlns=’.../pubsub’> <items node=’codebits’> <item> <rebooted xmlns=’codebits’/> </item> </items> </event></message>
Just add code
http://www.xmpp.org
http://metajack.im