Entity Caps and PEP

I’ve been testing my User Gaming via PEP on a locally installed copy of openfire and things are looking pretty good until I tried on jabber.org. Suddenly none of my packets are getting through. Upon further investigation, I found that you must advertise what information you are publishing and what info you are interested in before jabber.org will forward your PEP packets or route others PEP packets to you. This is in keeping with the PEP specs. Surprise, surprise. And the way this information is published is using a method call Entity Capabilties (XEP-0115).

Here is roughly how it works. When you come online, you Jabber client will send out a presence packet like so

<presence id=”N2ttf-4″/>

However XMPP clients with entity caps sends presences packet looks something like this

<presence id=”N2ttf-6″>
   <c xmlns=”http://jabber.org/protocol/caps&#8221; hash=”sha-1″
         node=”http://www.igniterealtime.org/projects/smack&#8221;
         ver=”FqngNglmgiLwmdc3F7/O7kMua0E=”/>

</presence>

Note the additional <c> fragment (formatted for readability) and inparticular the ver attribute. As you might have guess this is entity caps and the ver is a hash of your entity’s, in this case your JID, capabilities. This is typically what features your client support. I use JID and clients here interchangeably; a client is a XMPP client like Pidgin and JID is what you use to get on say jabber.org.

Now remember the presence packet is going out from the entity who has just come online; as an example and in keeping with most XMPP literature, when romeo@jabber.org comes online it will send out a presences packet to every one in his roster. Juliet (juliet@jabber.org) happens to be in his roster, so Juliet Jabber client receives this packet. Juliet’s client notices that Romeo’s presence packet has a entity cap hash string but does not know what that is. So the client sends a IQ to query Romeo. The following packet goes out to romeo@jabber.org

<iq id=”purple2686f3a5″ to=”romeo@jabber.org/games” from=”juliet@jabber.org/pidgin” type=”get”>
   <query xmlns=”http://jabber.org/protocol/disco#info&#8221;
         node=”http://www.igniterealtime.org/projects/smack#FqngNglmgiLwmdc3F7/O7kMua0E=“/>
</iq>

Romeo’s client then respond to this query with a list of the features that the hash represents them

<iq id=”purple2686f3a5″ to=”juliet@jabber.org/pidgin” type=”result”>
   <query xmlns=”http://jabber.org/protocol/disco#info&#8221;
         node=”http://www.igniterealtime.org/projects/smack#FqngNglmgiLwmdc3F7/O7kMua0E=“>
      <identity category=”client” name=”Smack” type=”pc”/>
      <feature var=”http://jabber.org/protocol/caps”/&gt;
      <feature var=”http://jabber.org/protocol/xhtml-im”/&gt;
      <feature var=”http://jabber.org/protocol/muc”/&gt;
      <feature var=”http://jabber.org/protocol/bytestreams”/&gt;
      <feature var=”http://jabber.org/protocol/commands”/&gt;
      <feature var=”urn:xmpp:gaming:0″/>
      <feature var=”urn:xmpp:gaming:0+notify”/>
   </query>
</iq>

Juliet’s client will now cache the hash string against these features. The next time she sees the same hash string, her client will know exactly what those features are without ever sending an IQ.

So what has this to do with PEP? Simple PEP leverages entity caps to tell other what it is interested in receiving and what it is publishing.

Smack do not support entity cap. However there is a project on github that adds this support. You can find it here. I’ve made a fork of this since mine works with the stock Smack rather than a fork version of Smack as the original did. You can find my implementation here and I’ll be using this for the rest of the article.

The following code snippet shows how you publish your entity cap in your presence

//Create a connection, connection and login
XMPPConnection connection = …
connection.connect();
connection.login(“juliet”, “act2scene2”, “balcony”);

//Get an instance of EntityCapsManager
EntityCapsManager capsManager = EntityCapsManager.getInstanceFor(connection);

//Eg. want to support user gaming (XEP-0196) through PEP (XEP-0163)
capsManager.addFeature(“urn:xmpp:gaming:0”);
capsManager.addFeature(“urn:xmpp:gaming:0+notify”);

//Republish our presence so that it will include our entity caps
connection.sendPacket(new Presence(Presence.Type.available));

//Now publish or receive data

Once you have created a connection, use the connection to retrieve an instance of EntityCapsManager.  Then what you do is now add the namespace XEP-0196 (urn:xmpp:gaming:0) as our feature. Note that there are two lines. The first indicates that we are publishing user gaming data and the second with a +notify appended indicates that we are interested in receiving user gaming data published by others. You can continue adding features here. Once you are done, you now resend your presences. The presence will now include an entity cap fragment with the latest hash code of all your features, including those supported by the client by default.

One important thing to remember is that if you want a feature or extended info to be included in the hash value of your entity caps, use addFeature(), removeFeature(), setExtendedInfo() and removeExtendedInfo() from EntityCapsManager. Do not use those the 4 corresponding methods from ServiceDiscoveryManager. Wherever you add or remove a feature or extended info, don’t forget to republish your presence.

jabber.org is one public servers I’ve tried that supports PEP. To find out what other public servers supports PEP, issue a disco#info to the JID (your login) or and look for the following

<identity category=”pubsub” name=”null” type=”pep“/>

In Smack that would be

XMPPConnection conn = … //Create a connection and login
ServiceDiscoveryManager mgr = ServiceDiscoveryManager.getInstanceFor(conn);
DiscoverInfo discoInfo = mgr.discoverInfo(conn.getUser());
Iterator<DiscoverInfo.Identity> iter = discoInfo.getIdentities();
while (iter.hasNext()) {
   DiscoveryInfo.Identity id = iter.next();
   if (“
pubsub“.equals(id.getCategory() && “pep“.equals(id.getType()))
      //Eureka! our server supports PEP!
}

Advertisements

14 Responses to Entity Caps and PEP

  1. Alex Vishnev says:

    Is it possible to get the source of your XEP-0115 implementation. i get an java.lang.NullPointerException in EntityCapsManager capsManager = EntityCapsManager.getInstanceFor(xmppConnection); I am actually using asmack package which is a clone of smack but for android. this is most likely creating an issue.

  2. Alex Vishnev says:

    I tried to clone the repository with hg, but could not find the correct path. Can you provide instructions on how to download xep-0115 project from your repository

  3. Jaya Krishna says:

    Hi,

    Thanks for the article about CAPS presence implementation.

    I’ve gone through your project jar file and tried implementing using the same, but it is resulting an error while creating an instance of EntityCapsManager.

    Following error I’m seeing in my eclipse:

    Cannot resolve name org.jivesoftware.smack.Connection

    Please note that I’ve included all the required Jars in my build path. Also, if you see the example you have provided above in the article, it is taking XMPPConnection as input argument where as the signature of EntityCapsManager accepts only Connection.

    Please throw some light here.

    Regards,
    Jaya Krishna

  4. Jaya Krishna says:

    I could solve this issue when I re-opened my project and deployed.

    Now, I’m facing the below issue when using xep0115.jar:

    Exception in thread “main” java.lang.NoSuchMethodError: javax.xml.stream.XMLInputFactory.newFactory()Ljavax/xml/stream/XMLInputFactory;
    at org.jivesoftware.smackx.caps.CapsHelpers.extractFeature(CapsHelpers.java:28)
    at org.jivesoftware.smackx.caps.CapsHelpers.extractFeatureAsString(CapsHelpers.java:50)
    at org.jivesoftware.smackx.caps.EntityCapsManager.cloneDiscoverInfo(EntityCapsManager.java:205)
    at org.jivesoftware.smackx.caps.EntityCapsManager.access$200(EntityCapsManager.java:67)
    at org.jivesoftware.smackx.caps.EntityCapsManager$CapsNodeInformationProvider.(EntityCapsManager.java:563)
    at org.jivesoftware.smackx.caps.EntityCapsManager.renewEntityCapsVersion(EntityCapsManager.java:172)
    at org.jivesoftware.smackx.caps.EntityCapsManager.(EntityCapsManager.java:110)
    at org.jivesoftware.smackx.caps.EntityCapsManager.getInstanceFor(EntityCapsManager.java:552)

  5. Jaya Krishna says:

    Hi,

    Perhaps, I’m seeing this issue because the jdk version I’m using is 1.5. If the xep0115.jar is built using jdk1.6 then, could you please send me the jar which supports jdk1.5?

    Regards,
    Jaya Krishna

  6. Jaya Krishna says:

    Hi,

    I could get rid of above error by adding stax.1.2.0.jar file into my source lib.

    Now, I’m able to send my presence packet to a specific JID I’m interested with.

    But, my only question here is, I’m asked to send a feature set for the HASH code I have sent with earlier presence packet.

    How to respond back to the incoming disco#info request with the list of corresponding available features?

    Please help me out here with your thoughts.

    Regards,
    Jaya Krishna

  7. Jaya Krishna says:

    Hi,

    Sorry for the confusion I’m creating in this thread. But, when I add PacketWriterListener to my connection, I could see the response packet with the list of features being submitted.

    But, I have a question here, for the corresponding feature I’m subscribing, the JID should send me a <message> stanza. I’m not sure if I’m getting this or not.

    Should I add any other listener to capture <message> stanza?

    Please help me out here.

    Regards,
    Jaya Krishna

  8. Jaya Krishna says:

    To add, I have PacketListener also implemented in my code to capture any incoming packets.

    But, I’m not seeing any packet of kind ‘message’. Should I do any change in order to make my JID to send message packets to my client?

  9. Nitish says:

    How to discover receiver’s capability if it does not support XEP-0115 ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: