private static int decodeAttributes(
      final Buffer requestContent,
      int offset,
      final AjpHttpRequest req,
      final boolean tomcatAuthentication) {

    final DataChunk tmpDataChunk = req.tmpDataChunk;

    boolean moreAttr = true;

    while (moreAttr) {
      final byte attributeCode = requestContent.get(offset++);
      if (attributeCode == AjpConstants.SC_A_ARE_DONE) {
        return offset;
      }

      /* Special case ( XXX in future API make it separate type !)
       */
      if (attributeCode == AjpConstants.SC_A_SSL_KEY_SIZE) {
        // Bug 1326: it's an Integer.
        req.setAttribute(SSLSupport.KEY_SIZE_KEY, readShort(requestContent, offset));
        offset += 2;
      }

      if (attributeCode == AjpConstants.SC_A_REQ_ATTRIBUTE) {
        // 2 strings ???...
        offset = setStringAttribute(req, requestContent, offset);
      }

      // 1 string attributes
      switch (attributeCode) {
        case AjpConstants.SC_A_CONTEXT:
          // nothing
          offset = skipBytes(requestContent, offset);
          break;

        case AjpConstants.SC_A_REMOTE_USER:
          if (tomcatAuthentication) {
            // ignore server
            offset = skipBytes(requestContent, offset);
          } else {
            offset = getBytesToDataChunk(requestContent, offset, req.remoteUser());
          }
          break;

        case AjpConstants.SC_A_AUTH_TYPE:
          if (tomcatAuthentication) {
            // ignore server
            offset = skipBytes(requestContent, offset);
          } else {
            offset = getBytesToDataChunk(requestContent, offset, req.authType());
          }
          break;

        case AjpConstants.SC_A_QUERY_STRING:
          offset = getBytesToDataChunk(requestContent, offset, req.getQueryStringDC());
          break;

        case AjpConstants.SC_A_JVM_ROUTE:
          offset = getBytesToDataChunk(requestContent, offset, req.instanceId());
          break;

        case AjpConstants.SC_A_SSL_CERT:
          req.setSecure(true);
          // SSL certificate extraction is costy, initialize on demand
          offset = getBytesToDataChunk(requestContent, offset, req.sslCert());
          break;

        case AjpConstants.SC_A_SSL_CIPHER:
          req.setSecure(true);
          offset =
              setStringAttributeValue(req, SSLSupport.CIPHER_SUITE_KEY, requestContent, offset);
          break;

        case AjpConstants.SC_A_SSL_SESSION:
          req.setSecure(true);
          offset = setStringAttributeValue(req, SSLSupport.SESSION_ID_KEY, requestContent, offset);
          break;

        case AjpConstants.SC_A_SECRET:
          offset = getBytesToDataChunk(requestContent, offset, tmpDataChunk);

          req.setSecret(tmpDataChunk.toString());
          tmpDataChunk.recycle();

          break;

        case AjpConstants.SC_A_STORED_METHOD:
          offset = getBytesToDataChunk(requestContent, offset, req.getMethodDC());
          break;

        default:
          break; // ignore, we don't know about it - backward compat
      }
    }

    return offset;
  }