Http-bind polling interval check violates spec

Yes, and this is incredibly annoying for any developer working on a client.

Combined with these problems of 100% CPU usage in the HTTP Bind component, deadlocks, and incomplete spec implementation has us possibly looking elsewhere. Can anyone recommend an alternate HTTP binding (proxy, hopefully, so it can at least be used with Openfire) component?

AWenckus wrote:

Openfire implements an older version of the XEP. XEP-0124: HTTP Binding

The conditions you mention are not in this version, Openfire will behave accordingly when it is upgraded to utilized the latest version of the XEP.

That spec version also states that the client “SHOULD make a new request as soon as possible.” That draft and the accepted spec work in the same way. It’s how binding was designed from the start. The client submits an empty stanza, and waits for data. Upon receiving data it immediately connects again in the same way. The problem is when 2 messages are received a couple seconds apart (for example) - the client HAS to disconnect and reconnect to see the second message. The “checkPollingInterval()” in HttpSession.java is not smart enough to handle this case.

Hey Jason,

We ran into the same problem while investigating some work for a potential client. As a potential work around instead of sending an empty stanza you can send a stanza with an empty presence packet. Such as the following:

<body rid='1249243563'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
   <presence></presence>
</body>

It’s not an ideal solution, and we didn’t investigate what (if any) side effects this may cause but it will keep Openfire from sending a 403 when it mistakenly thinks it is being polled too frequently.

Hope that helps,

Ryan

ryang wrote:

Hey Jason,

We ran into the same problem while investigating some work for a potential client. As a potential work around instead of sending an empty stanza you can send a stanza with an empty presence packet. Such as the following:

> 
> <body rid='1249243563'
>       sid='SomeSID'
>       xmlns='http://jabber.org/protocol/httpbind'>
>    <presence></presence>
> </body>

It’s not an ideal solution, and we didn’t investigate what (if any) side effects this may cause but it will keep Openfire from sending a 403 when it mistakenly thinks it is being polled too frequently.

Hope that helps,

Ryan

Ryan,

Although a potential, temporary solution, the problem with this is that anyone with subscription to this user will receive a presence packet. This will cause these users to have to constantly poll the BOSH server, sending more presence packets and perpetuating the problem.

Although a potential, temporary solution, the problem with this is that anyone with subscription to this user will receive a presence packet. This will cause these users to have to constantly poll the BOSH server, sending more presence packets and perpetuating the problem.

Like we’ve both said, it is just a potential, short-term solution and sending empty presence packets was the quickest way to implement it. If we had gone forward with an Openfire/BOSH solution we might have had the client send a custom iq packet to an Openfire plugin that would basically discard the packet upon receiving it.

Ideally, of course, it would nice if the spec was fully implemented within Openfire. Have you studied the Openfire code to see how close it is to being 1.5 or 1.6 compliant? Are you aware of any BOSH testing tools that could be used to speed along development of making it standards compliant?

Cheers,

Ryan

No, unfortunately (fortunately? =D) I am not a Java developer. Right now I’m actually dealing with a polling issue that is basically causing our client to appear slow because we can’t ask for data fast enough (upon login). I’m considering reverting to an older version of Openfire where I might be able to look at the way Sparkweb went about grabbing the roster so quickly.

Hmmm… I have checked the code and Openfire should only be checking the poll interval on polling connections:

From HttpSession:

if (isPoll) {
            checkPollingInterval();
        }

This is checkPollingInterval:

private void checkPollingInterval() throws HttpBindException {
        long time = System.currentTimeMillis();
        if (((time - lastPoll) / 1000) < maxPollingInterval) {
            throw new HttpBindException("Too frequent polling minimum interval is "
                    + maxPollingInterval + ", current interval " + ((time - lastPoll) / 1000),
                    BoshBindingError.policyViolation);
        }
        lastPoll = time;
    }

isPoll is determined at line 514 in HttpSession:

packetsToBeSent.size() <= 0

Alex,

The code you showed indicates that it checks only for “polling packets”, which is used by both “polling connection” and non-polling connection. My first posting has details on what exactly the spec says. If you have questions, please continue the discussion here. This is definitely a problem.

Hey Alex,

Thanks for taking the time to look into this. Looking at the spec and the code I believe that isPoll should be determined by:

getHold() == 0 || getWait() == 0

Cheers,

Ryan

Oh, sure, play the “I’m not a Java developer” card.

Yeah… not like it’d be something difficult to learn (Java) but I don’t have time to with my current project(s) =)

Ryan,

Thanks for the clarification. That makes sense.

Cheers,

Alex

I have created the following issues:

JM-1245

JM-1246

Cheers,

Alex

I’m using a javascript client with openfire http-bind and xmpp.httpbind.client.requests.polling property set to 0!file:///C:/DOCUME%7E1/Ofir/LOCALS%7E1/Temp/moz-screenshot.jpg!

I have issues with and I’m not sure if it is a client bug or related to this discussion.

Can you please explain in what circumstances the current implementation of BOSH should end a client connection and what will be written in the error log?

Is there a temporary workaround?

In my case clients are being disconnected once per few hours with no evident reason.

Thanks.

With these changes in place, I feel like I am getting very close to having a functional AS 2.0 XIFF HttpBinding class working. This is excellent as it will allow our users who are behind restrictive firewalls to connect and chat on our site!

I am currently using an HTTP proxy debugger to watch the traffic that goes back and forth between my client and Openfire and everything looks healthy. One connection is always being held open until either a packet is received or the ‘wait’ time expires, at which point my client opens another connection. I am not getting kicked for polling too fast due to the changes above.

I’ll post any other problems I run into in this thread.

One thing I forgot to mention, a change is required in HttpSession.java (line 767) to prevent some null pointer exceptions:

public Deliverable(String text) {
  this.text = text;
  this.packets = new ArrayList<String>(); // <-- This used to be set to null, which caused NullPointerExceptions during enumeration in some cases
}

And another NullPointerException in HttpSession.java (line 701). This needed a if(packets != null) surrounding it due to the collection sometimes being null.

private void failDelivery(Collection<Packet> packets) {
        if( packets != null ) {
            for (Packet packet : packets) {
                try {
                    backupDeliverer.deliver(packet);
                }
                catch (UnauthorizedException e) {
                    Log.error("Unable to deliver message to backup deliverer", e);
                }
            }
        }
    }

Hi BenV:

Thanks for your changes. I read your post the other day, but didn’t understand that you changes were what was required to fix my problem, until last night when I convinced myself that I wasn’t actually going past the requests element in the response to my session being initiated. Then this afternoon I had a little trace in eclipse that convinced me that this was the right thing to do. I put in your null pointer fixes too, although I haven’t yet experienced any null pointer exceptions.

I found that I could test my javascript code using rhino and John Resig’s env.js. I have attached the fixes that I made to env.js as well as crypt.js from jsjac and my own javascript code for my HttpClientConnection.js and a test script BOSH.js that does the Romeo and Juliet scene from the specifications. Hopefully this is as helpful to someone else as your fixes were to me.

thanks

Rich
env.js (17397 Bytes)
crypt.js (22358 Bytes)
HttpClientConnection.js (8419 Bytes)
BOSH.js (1511 Bytes)

I’m glad these changes helped you out. Any word on if they ever made it into the official tree?

bump