faye/faye — pull request #303 by suprememoocow (2014-06-01 14:37:50+00:00)
Title: Client DOS under very certain conditions

This is a very specific problem, but it's one that's caused us a fair amount of trouble.

The conditions required are as follows:
* Long running client connections (hours, days, possibly longer)
* Bad or intermittent network quality
* A server extensions for Faye which rejects an unknown (probably expired) client on /meta/connect.

Imagine a user on a train using a mobile network. The train passed through a tunnel and the connection is lost for a period of two minutes. During this time, the server discards the Faye socket as it hasn't heard from the client for a period greater than the timeout period. The client comes back online and sends a `/meta/connect` message, to which the server responds with a `{ successful: false, advice: { reconnect: "handshake" } }`.

In the implementation as it stands at present, this will lead to `_cycleConnection` being called twice. Each invocation will lead to `connect()` being called twice, which doubles the number of connections occurring over the `advice.interval` period. Each time the above scenario of losing and restoring connectivity is repeated, the number of times `/meta/connect` is called per period is doubled. This quickly leads to a bad situation.

This PR replaces some of `Faye.ENV.setTimeouts` with `addTimeout` calls from the `Faye.Timeouts` mixin, so that multiple calls to `_cycleConnection` don't lead to multiple connects.

It also includes a test which fails for the unpatched client and now passes.

Obviously there may be a better way of handling this situation and if there is I would love to hear how.

Thanks as always for such a fantastic library!