docs: function (i)
      {
          var self = this;
          var req = this._requests[i];
          var reqStatus = -1;
  
          try {
              if (req.xhr.readyState == 4) {
                  reqStatus = req.xhr.status;
              }
          } catch (e) {
              Strophe.error("caught an error in _requests[" + i +
                            "], reqStatus: " + reqStatus);
          }
  
          if (typeof(reqStatus) == "undefined") {
              reqStatus = -1;
          }
  
          // make sure we limit the number of retries
          if (req.sends > this._conn.maxRetries) {
              this._conn._onDisconnectTimeout();
              return;
          }
  
          var time_elapsed = req.age();
          var primaryTimeout = (!isNaN(time_elapsed) &&
                                time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait));
          var secondaryTimeout = (req.dead !== null &&
                                  req.timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait));
          var requestCompletedWithServerError = (req.xhr.readyState == 4 &&
                                                 (reqStatus < 1 ||
                                                  reqStatus >= 500));
          if (primaryTimeout || secondaryTimeout ||
              requestCompletedWithServerError) {
              if (secondaryTimeout) {
                  Strophe.error("Request " +
                                this._requests[i].id +
                                " timed out (secondary), restarting");
              }
              req.abort = true;
              req.xhr.abort();
              // setting to null fails on IE6, so set to empty function
              req.xhr.onreadystatechange = function () {};
              this._requests[i] = new Strophe.Request(req.xmlData,
                                                      req.origFunc,
                                                      req.rid,
                                                      req.sends);
              req = this._requests[i];
          }
  
          if (req.xhr.readyState === 0) {
              Strophe.debug("request id " + req.id +
                            "." + req.sends + " posting");
  
              try {
                  req.xhr.open("POST", this._conn.service, this._conn.options.sync ? false : true);
                  req.xhr.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
              } catch (e2) {
                  Strophe.error("XHR open failed.");
                  if (!this._conn.connected) {
                      this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,
                                                "bad-service");
                  }
                  this._conn.disconnect();
                  return;
              }
  
              // Fires the XHR request -- may be invoked immediately
              // or on a gradually expanding retry window for reconnects
              var sendFunc = function () {
                  req.date = new Date();
                  if (self._conn.options.customHeaders){
                      var headers = self._conn.options.customHeaders;
                      for (var header in headers) {
                          if (headers.hasOwnProperty(header)) {
                              req.xhr.setRequestHeader(header, headers[header]);
                          }
                      }
                  }
                  req.xhr.send(req.data);
              };
  
              // Implement progressive backoff for reconnects --
              // First retry (send == 1) should also be instantaneous
              if (req.sends > 1) {
                  // Using a cube of the retry number creates a nicely
                  // expanding retry window
                  var backoff = Math.min(Math.floor(Strophe.TIMEOUT * this.wait),
                                         Math.pow(req.sends, 3)) * 1000;
                  setTimeout(sendFunc, backoff);
              } else {
                  sendFunc();
              }
  
              req.sends++;
  
              if (this._conn.xmlOutput !== Strophe.Connection.prototype.xmlOutput) {
                  if (req.xmlData.nodeName === this.strip && req.xmlData.childNodes.length) {
                      this._conn.xmlOutput(req.xmlData.childNodes[0]);
                  } else {
                      this._conn.xmlOutput(req.xmlData);
                  }
              }
              if (this._conn.rawOutput !== Strophe.Connection.prototype.rawOutput) {
                  this._conn.rawOutput(req.data);
              }
          } else {
              Strophe.debug("_processRequest: " +
                            (i === 0 ? "first" : "second") +
                            " request has readyState of " +
                            req.xhr.readyState);
          }
      }