Introduce retry limits on automatic reconnects

This change introduces an internal limit on automatic retries to prevent infinite retry loops in certain situations.

In addition, this change allows us to change the behaviour of connection failures (where we were previously connected) from no retry to auto-retry. This makes things easier for clients as this can happen whenever the device is locked or the app goes into the background.

Changing this behaviour was not as bad as anticipated because we only retry if we were previously connected. That means if reachability is lost, we only end up retrying once anyway. The following happens:

* Client is connected
* Internet connection is lost
* Client connection fails - were we previously connected = YES, so auto-retry
* Auto-retry fails immediately - were we previously connected = NO, so no auto-retry
* Delegate is notified that the client will no longer auto-reconnect (at which point you can start reachability checks etc.)

Finally, the internal limit protects us from infinite retry -> fail -> retry loops. 

@mloughran would you mind reviewing this prior to merge?