Trunk smack - pubsub support - not quite there w/ ejabberd server?

Referring to an earlier thread, which was mistakenly posted under Spark,

http://www.igniterealtime.org/community/message/201318#201318

I have taken rcollier’s advice and switched to smack trunk. I have made some progress getting pub/sub subscription working with that code. However, there are some gotchas which may be specific to ejabberd server (I am using ejabberd-2.0.5-8.el5 on Centos5 from EPEL).

rcollier, has this had much testing against ejabberd 2.x? Specifically it seems like the IQ reply from the discover done by getNode() is not parseable, leading to a ClassCastException later on (from Packet to DiscoverReply).

It seems to be falling into one of the parser fail paths in PacketParserUtils.parseIQ()

(I could be wrong though; I am not exactly a Java debugging expert.)

The same issue occurs in Node.subscribe() (i.e. the Packet returned is not parsed as expected, causing a ClassCastException).

I have brutally hacked these two cases for now, but there is a more fundamental issue.

Please see attached file for packet text and corresponding debug console views.

In the debugging console, I see the correct messages heading to subscribers, but Smack is not calling my ItemEventListener. This may be related to the fact that the All Packets view shows a mangled version of the packet. This parse problem also apparently prevented su smack from processing these incoming messages.

Is this another ejabberd incompatibility?

I wonder if it’s related to this report: Re: PubSub and

Message was edited by: Toby Thain
pkt.txt.zip (418 Bytes)


I tested against OpenFire, although I believe it was also tested against ejabberd by by @squaremo, since he contacted me about modifying the test cases so they would work with ejabberd’s node naming restrictions. I have no idea what version that may have been though.

That being said, I can see why the second item (from your png) doesn’t work. It isn’t a valid pubsub event. It doesn’t contain any of the valid elements within the the event. Unfortunately, I cannot tell you more with this limited amount of information. What is the ClassCastException you are seeing?

Do you know what version of the pubsub spec is supported by that version of ejabberd?

Can you post the stacktrace?

Node naming hasn’t been a problem — I use “/home/server/jid/blah” — but it is necessary to pass the 2nd argument when constructing PubSubManager(conn, “pubsub.server”).

The ClassCastExceptions occur when the object is one of the anonymous classes derived from IQ, which are created on a failed parse in PacketParserUtils.parseIQ(), e.g. line 304 happens to be the class created in my tests.

First exception is in PubSubManager.getNode(). SyncPacketSend.getReply() returns the anonymous class instead of the DiscoverReply required by the cast in getNode() line 161.

The 2nd is in Node.subscribe(). sendPubsubPacket() also returns the anonymous class and not the PubSub object required by the cast in subscribe() on line 151.

These can be hacked around to keep my project moving forward, but I have no traction on the other problem (mangled xml) shown in the screenshots yet.

rcollier wrote:

I can see why the second item (from your png) doesn’t work. It isn’t a valid pubsub event. It doesn’t contain any of the valid elements within the the event.

Right, the parsed version logged in All Packets doesn’t, but the raw message logged in All Received Packets appears to be complete and correct, to me. I also observed this when trying to use su smack, which might help explain why su smack’s event listeners never worked for me.

Not only are the elements missing, but so are most of my own XML elements originally shipped inside .

ejabberd 2.0.5 claims to support

Pub-Sub (XEP-0060), PEP (XEP-0163)

More details.

I can see, on an incoming event message, that parsePacketExtension() finds no extension provider. It therefore proceeds to parse the tag as a DefaultPacketExtension (line 738, PacketParserUtils.java).

It recognises as a start tag at line 742.

Now… here is a nasty bug:

— The next parser ‘event’ is pulled at line 750. (causing to be ignored)

— The if() on the following line expects a TEXT event, but the parser event is a new START_TAG ().

— the loop is continued, without further processing, ignoring and pulling a new tag at line 743 (the parser is now looking at part of my payload: the tag).

— again, not being TEXT, loop continues, ignoring start tag

— pulls start tag at line 743

— again, not TEXT, ignores

— pulls a TEXT event at line 743, but the test on line 742 expects a start tag, and so this text is ignored (the contents of element)

— pulls an end tag at line 743

— recognises the end tag at line 757

— this element name (time) does not match elementName (event) and so the loop continues

— pulls another start tag at line 743 ()

— pulls a TEXT event at line 750

— recognises it in the if at line 751

— extension.setValue(“print”, “…text of print element…”) at line 753

— eventually it pops enough END TAGs to match at line 757+758 and finally exit the loop.

…and that is how we end up with a single, bogus, “print” element.

So that parser logic seems to need fixing, as it is missing the tag, getting out of sync, and ploughing into the payload, leaving the Packet without a useful extension.

XEP-0060 has as a child of and as a child of , but parsePacketExtension() is not prepared to handle a structure of this form:

Rather, it expects:

{TEXT{}}

terminating when /TAG matches the extension tag name (event).

Worse, it only attaches extension data which is in the form of element text content. XML inside does not conform to this expectation.

Message was edited by: Toby Thain

I am not sure why it is occuring, but the basic problem seems to be that the proper extension provider is not being found. There are specific ones for all stanzas from the pubsub set of namespaces. As you said, the provider is not being found, which of course will fail proper parsing and not produce the appropriate class for the PubSub API.

I just checked trunk and the smack.providers file still seems to be correct. As long as the correct namespace and element is included the ItemsProvider extension provider should be parsing the stream.

Any hints on how I can investigate why the provider isn’t being loaded? This is a pretty generic smack trunk setup, I am running from within Eclipse.

Is there any chance you could look into the ClassCastException issues in getNode() and subscribe(), or is it unlikely you’d be able to test against ejabberd? Since I use ejabberd, I can probably look at these further once my urgent solution is running.

OK, found the solution.

I needed to add smack/build/resources directory to my Build Path as a Class Folder, then Smack located the resources (smack-config.xml and smack.providers) at startup.

rcollier, thanks for the help!