Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#11819 closed defect (fixed)

XMPP presence and chatstatus with bare JIDs

Reported by: dimakcgs Owned by: deryni
Milestone: 2.7.1 Component: XMPP
Version: 2.6.6 Keywords: presence aggregation JID CommuniGate
Cc:

Description

When the Pidgin client starts an IM chat to a client connected to CommuniGate? Pro server, it sends out "typing" messages (<composing/>, <paused />, etc. in the "http://jabber.org/protocol/chatstates" namespace). But as soon as the client connected via CommuniGate? Pro sends any <message> stanza back, Pidgin stops sending out these "chatstates" messages, EVEN if the received <message /> stanza contains some "chatstates" data, indicating the remote client support for this protocol.

CommuniGate? Pro developers believe that the reason for this may be following: the libpurlpe library keeps the "capability" information about remote contact account, and its resources (clients currently connected to that remote contact account). It builds a new element in its internal storage, and updates it when needed. For example, if it receives a message stanza with "http://jabber.org/protocol/chatstates" data from some remote resource, it marks the resource element internally as supporting this "chatstates" feature.

When a remote client is connected via CommuniGate? Pro, it does not send its presence information outside. Instead, the CommuniGate? Pro server aggregates all that information from all clients, and sends it out in the aggregated form. As a result, Pidgin gets all the <presence > stanza with a bare JID (without a resource specification) from="user@domain" attribute, not from="user@domain/client-resource" attribute.

It looks like in this case, libpurple does not build the internal "resource" elements in its database, and thus it cannot process such clients correctly. In this case - stops sending the "chatstate" messages altogether.

It would be excellent if Pidgin/libpurple is prepared to handle this situation.

Attachments (1)

purple-debug.log (4.0 KB) - added by dimakcgs 9 years ago.
Log to show the lack of "chatstates" messages

Download all attachments as: .zip

Change History (8)

comment:1 Changed 9 years ago by darkrain42

  • Status changed from new to pending

Pidgin (at least in the most recent version, are you using 2.6.6?) should handle the case you've described correctly (I've personally only done limited testing of this, though). Presences received from a bare JID are treated as coming from a "NULL" resource (we track resources by name, and that one is a NULL pointer), and libpurple should notice the typing notification in an incoming message from a bare JID, too.

Arguably, I don't think Pidgin handles this as strictly as it should (in the cases where Pidgin receives presence both from a bare JID and resources, but based on your description, I don't think that's the issue here).

Would you please attach the Help->Debug Window output from when this occurs?

Changed 9 years ago by dimakcgs

Log to show the lack of "chatstates" messages

comment:2 Changed 9 years ago by dimakcgs

  • Status changed from pending to new

Attachment (purple-debug.log) added by ticket reporter.

comment:4 Changed 9 years ago by darkrain42

The reason Pidgin doesn't show typing notifications from Psi is because Pidgin isn't receiving any typing notifications after the first ones (lines 19 and 21). I believe this is unrelated to Pidgin not generating typing notifications, as all of Pidgin's message stanzas (including the last one, on line 27) include, at the least, an <active/> child (so I don't see why Psi would think it shouldn't send typing notifications).

Okay, so the issue with Pidgin here really is that Communigate brokenly sends presence from the bare JID and messages from full JIDs (ugh) (re-reading your description, you did describe it that way, though the debug log is helpful, thanks). Communigate really shouldn't be doing what it's doing (if it wants to strip a bunch of identifying information like status messages or entity caps out of presences, fine, but either it should support resources fully or it shouldn't use them at all) </rant>

So it seems like the best way to workaround this is to send typing notifications to unknown (i.e. haven't received presence from them) resources of buddies who are subscribed to the user's presence. I'm not going to make this change for 2.7.0, but I'll try it out shortly after the release.

comment:5 follow-up: Changed 9 years ago by dimakcgs

Here's what our senior developer suggests:

First of all, presence and IM are different protocols within XMPP, though many clients (and sometimes server) do provide some sort of "integration" between the two.

But in this case, we really do not see why there should be a link between the presence and IMing. We are talking about the IM session behaviour. The <message> stanza are exchanged between your client and "something" on the other end.

That something may or may not have a resource. In our case, it does have a resource name in it. When your client starts the session itself, it does not know anything about the resource on the other end, so it sends all <message > stanza to bare JID.

It ASSUMES that the other end understands the "chatstates" protocol, so it sends the <composing />, <paused />, etc. messages - all the bare JID. So far so good.

Now, it gets a reply from the "other end". And, most likely, it gets the resource name in that reply. Here you client can make a smart decision: if the other end does not support the "chatstates" namespace, it can stop sending its own state - as it's simply waste of the traffic.

AND - if we read the libpurple source code right, it does EXACTLY THAT. If an incoming <message /> stanza contains any <xxxxx xmlns="http://jabber/protocol/chatstates"> element, then you assume that the "other" end supports this protocol, otherwise - that it does not support it.

BUT: somwhere along these lines (we guess outside the libpruple code) your client also tries to check the information it go from the same resource in the latest <presence /> stanze. And it does not find it (as all <presence > stanzas come agrregated by the other end). AND here - we think - is the problem: in this situation your client does not IGNORE the <presence /> data when it's absent, but treats it as "the other end does not support anything". This, it deletes the just-collected information about the xmlns="http://jabber/protocol/chatstates" support.

We think it's not the best method to handle the situation, and if you change it so that lack of <presence /> from the same resource does not OVERRIDE the already collected information about this resource (collected from the incomding <message /> stanzas), it would solve many problems.

Finally - we do not think that the simple algorithm we saw in libpurple processing of the <message /> stanza is the best one. If you do see a xmlns="http://jabber/protocol/chatstates" element, you can safely assume that the other end supports this protocol. But if you do not see it, it's quite risky to assume that it does not: it can be service <message /> stanza delliverying any other info. Our suggestion would be to have the flag for that option set to "unknown", "supported", "unsupported" (you already have it there), and set the flag to "unknown" initially. Then, you always set to to "supported" when you see a xmlns="http://jabber/protocol/chatstates" element, but you set it to "unsupported" ONLY if you get a <message /> stanza without xmlns="http://jabber/protocol/chatstates" element AND the flag is currently "unknown" AND the <message /> stanza contains a <body /> or an <html /> element.

This way if you see xmlns="http://jabber/protocol/chatstates" once from the client, you will not reset it if it sends some service <message /> later. And at the beginning, if the client has not sent any xmlns="http://jabber/protocol/chatstates" with or before a "real" <message /> (i.e. one delivering some text), then you may assume that this client does not support the xmlns="http://jabber/protocol/chatstates".

But - it's just a suggestion, we do not have any problem with libpurple using the curreny simple yes/no algorithm, it's just an iprovement suggestion.

But the problem with linking of IM and presence data when the presence from this particular resource has never been received - this is a serious problem for our customers now.

Thank you for your cooperation.

comment:6 Changed 9 years ago by darkrain42@…

  • Milestone set to 2.7.0
  • Resolution set to fixed
  • Status changed from new to closed

(In b721192f0b7c409b2f6d8829fc79087ee7587bfb):
jabber: Send typing notifications to a buddy when it can see our presence

This allows us to send typing notifications to a resource which we haven't seen presence from (because there's a product out there that coalesces presence to bare JID, but exposes resources for messaging, which I think is stupid). Should Fixes #11819

comment:7 Changed 9 years ago by darkrain42

  • Milestone changed from 2.7.0 to 2.7.1

comment:8 in reply to: ↑ 5 Changed 9 years ago by darkrain42

  • Keywords XMPP removed

I shouldn't really argue (but feel like I should anyway, since it lets off steam). Fair warning. :P

For clarity, the core issue is that coalescing presence information to the bare JID while sending messages from full JIDs is stupid and counter-productive. There are a number of XEPs (and frankly, I bet rfc3921(bis?) does, but I'm lazy) that make the assumption that two parties communicating SHOULD (and often DO) exchange presence (this is one of the great things about XEP-0115 Entity Capabilities), as well that if we have a subscription to a buddy (and we get a presence either from a bare JID or from resources, we've gotten all the presences from all of those resources (there's a MUST in rfc3921 about broadcasting initial presence with a 'from' of the full JID).

Coalescing presence also breaks the ability to enable/disable features based on what the remote client will support (because we don't know which client we're talking to!), not to mention the ability of a power user to specifically address messages to a particular resource that he sees ("Oh, I don't want to bother Joe with this at the office, selects Home resource".) It's made impractical if resource-presence aren't advertised. (Ignore the fact Pidgin can't easily direct messages to specific resources)

Replying to dimakcgs:

Here's what our senior developer suggests:

But in this case, we really do not see why there should be a link between the presence and IMing. We are talking about the IM session behaviour. The <message> stanza are exchanged between your client and "something" on the other end.

I disagree that they can be totally separated (and see above for the ways in which there are links between presence and IMing -- various XEPs also talk about "discovering support" based off Entity Capabilities/Disco#info?)

Now, it gets a reply from the "other end". And, most likely, it gets the resource name in that reply. Here you client can make a smart decision: if the other end does not support the "chatstates" namespace, it can stop sending its own state - as it's simply waste of the traffic.

AND - if we read the libpurple source code right, it does EXACTLY THAT. If an incoming <message /> stanza contains any <xxxxx xmlns="http://jabber/protocol/chatstates"> element, then you assume that the "other" end supports this protocol, otherwise - that it does not support it.

The issue is(was) actually that the XMPP prpl tracks whether or not an entity supports chat states on a per-resource basis (it's stored in the JabberBuddyResource struct), and those structs are created/destroyed when libpurple receives presence from a JID (that's the cleanest way to not need to have some narsty "garbage collection" process for those structs).

The issue becomes self-evident at this point :)

I ended up fixing it in a way that doesn't leave a bitter taste in my mouth because it has plausible use cases other than this (one-way presence subscriptions and/or an "invisible" buddy)

Finally - we do not think that the simple algorithm we saw in libpurple processing of the <message /> stanza is the best one. If you do see a xmlns="http://jabber/protocol/chatstates" element, you can safely assume that the other end supports this protocol. But if you do not see it, it's quite risky to assume that it does not: it can be service <message /> stanza delliverying any other info. Our suggestion would be to have the flag for that option set to "unknown", "supported", "unsupported" (you already have it there), and set the flag to "unknown" initially. Then, you always set to to "supported" when you see a xmlns="http://jabber/protocol/chatstates" element, but you set it to "unsupported" ONLY if you get a <message /> stanza without xmlns="http://jabber/protocol/chatstates" element AND the flag is currently "unknown" AND the <message /> stanza contains a <body /> or an <html /> element.

This is reasonable (and I'll make the change), though isn't applicable to the current situation AFAICT.

But the problem with linking of IM and presence data when the presence from this particular resource has never been received - this is a serious problem for our customers now.

It's not that there hasn't been any presence (if that were the case, I could just say "libpurple doesn't send typing notifications to entities not on the buddy list" and that would be that), it's that the server is explicitly crippling XMPP in a way that I don't see any use in, plausibly violates a few MUSTs in the RFCs, and, as you've discovered, causes issues in other clients which make what I believe to be reasonable assumptions about presence-from-bare-JID.

Note: See TracTickets for help on using tickets.
All information, including names and email addresses, entered onto this website or sent to mailing lists affiliated with this website will be public. Do not post confidential information, especially passwords!