docs: function (func, req)
      {
          Strophe.debug("request id " + req.id +
                        "." + req.sends + " state changed to " +
                        req.xhr.readyState);
  
          if (req.abort) {
              req.abort = false;
              return;
          }
  
          // request complete
          var reqStatus;
          if (req.xhr.readyState == 4) {
              reqStatus = 0;
              try {
                  reqStatus = req.xhr.status;
              } catch (e) {
                  // ignore errors from undefined status attribute.  works
                  // around a browser bug
              }
  
              if (typeof(reqStatus) == "undefined") {
                  reqStatus = 0;
              }
  
              if (this.disconnecting) {
                  if (reqStatus >= 400) {
                      this._hitError(reqStatus);
                      return;
                  }
              }
  
              var reqIs0 = (this._requests[0] == req);
              var reqIs1 = (this._requests[1] == req);
  
              if ((reqStatus > 0 && reqStatus < 500) || req.sends > 5) {
                  // remove from internal queue
                  this._removeRequest(req);
                  Strophe.debug("request id " +
                                req.id +
                                " should now be removed");
              }
  
              // request succeeded
              if (reqStatus == 200) {
                  // if request 1 finished, or request 0 finished and request
                  // 1 is over Strophe.SECONDARY_TIMEOUT seconds old, we need to
                  // restart the other - both will be in the first spot, as the
                  // completed request has been removed from the queue already
                  if (reqIs1 ||
                      (reqIs0 && this._requests.length > 0 &&
                       this._requests[0].age() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait))) {
                      this._restartRequest(0);
                  }
                  // call handler
                  Strophe.debug("request id " +
                                req.id + "." +
                                req.sends + " got 200");
                  func(req);
                  this.errors = 0;
              } else {
                  Strophe.error("request id " +
                                req.id + "." +
                                req.sends + " error " + reqStatus +
                                " happened");
                  if (reqStatus === 0 ||
                      (reqStatus >= 400 && reqStatus < 600) ||
                      reqStatus >= 12000) {
                      this._hitError(reqStatus);
                      if (reqStatus >= 400 && reqStatus < 500) {
                          this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING,
                                                    null);
                          this._conn._doDisconnect();
                      }
                  }
              }
  
              if (!((reqStatus > 0 && reqStatus < 500) ||
                    req.sends > 5)) {
                  this._throttledRequestHandler();
              }
          }
      }