Пример #1
0
 private IntegerHolder parse16BitInteger(ByteBuffer buf, AjpParseState state) {
   if (!buf.hasRemaining()) {
     return new IntegerHolder(-1, false);
   }
   int number = state.currentIntegerPart;
   if (number == -1) {
     number = (buf.get() & 0xFF);
   }
   if (buf.hasRemaining()) {
     final byte b = buf.get();
     int result = ((0xFF & number) << 8) + (b & 0xFF);
     state.currentIntegerPart = -1;
     return new IntegerHolder(result, true);
   } else {
     state.currentIntegerPart = number;
     return new IntegerHolder(-1, false);
   }
 }
Пример #2
0
  private StringHolder parseString(ByteBuffer buf, AjpParseState state, boolean header) {
    if (!buf.hasRemaining()) {
      return new StringHolder(null, false);
    }
    int stringLength = state.stringLength;
    if (stringLength == -1) {
      int number = buf.get() & 0xFF;
      if (buf.hasRemaining()) {
        final byte b = buf.get();
        stringLength = ((0xFF & number) << 8) + (b & 0xFF);
      } else {
        state.stringLength = number | STRING_LENGTH_MASK;
        return new StringHolder(null, false);
      }
    } else if ((stringLength & STRING_LENGTH_MASK) != 0) {
      int number = stringLength & ~STRING_LENGTH_MASK;
      stringLength = ((0xFF & number) << 8) + (buf.get() & 0xFF);
    }
    if (header && (stringLength & 0xFF00) != 0) {
      state.stringLength = -1;
      return new StringHolder(HTTP_HEADERS[stringLength & 0xFF]);
    }
    if (stringLength == 0xFFFF) {
      // OxFFFF means null
      state.stringLength = -1;
      return new StringHolder(null, true);
    }
    StringBuilder builder = state.currentString;

    if (builder == null) {
      builder = new StringBuilder();
      state.currentString = builder;
    }
    int length = builder.length();
    while (length < stringLength) {
      if (!buf.hasRemaining()) {
        state.stringLength = stringLength;
        return new StringHolder(null, false);
      }
      builder.append((char) buf.get());
      ++length;
    }

    if (buf.hasRemaining()) {
      buf.get(); // null terminator
      state.currentString = null;
      state.stringLength = -1;
      return new StringHolder(builder.toString(), true);
    } else {
      return new StringHolder(null, false);
    }
  }
Пример #3
0
 public void parse(
     final ByteBuffer buf, final AjpParseState state, final HttpServerExchange exchange) {
   if (!buf.hasRemaining()) {
     return;
   }
   switch (state.state) {
     case AjpParseState.BEGIN:
       {
         IntegerHolder result = parse16BitInteger(buf, state);
         if (!result.readComplete) {
           return;
         } else {
           if (result.value != 0x1234) {
             throw new IllegalStateException("Wrong magic number");
           }
         }
       }
     case AjpParseState.READING_DATA_SIZE:
       {
         IntegerHolder result = parse16BitInteger(buf, state);
         if (!result.readComplete) {
           state.state = AjpParseState.READING_DATA_SIZE;
           return;
         } else {
           state.dataSize = result.value;
         }
       }
     case AjpParseState.READING_PREFIX_CODE:
       {
         if (!buf.hasRemaining()) {
           state.state = AjpParseState.READING_PREFIX_CODE;
           return;
         } else {
           final byte prefix = buf.get();
           if (prefix != 2) {
             throw new IllegalArgumentException(
                 "We do not support prefix codes other than 2 yet. Received: " + prefix);
           }
         }
       }
     case AjpParseState.READING_METHOD:
       {
         if (!buf.hasRemaining()) {
           state.state = AjpParseState.READING_METHOD;
           return;
         } else {
           int method = buf.get();
           if (method > 0 && method < 28) {
             exchange.setRequestMethod(HTTP_METHODS[method]);
           } else {
             throw new IllegalArgumentException("Unknown method type " + method);
           }
         }
       }
     case AjpParseState.READING_PROTOCOL:
       {
         StringHolder result = parseString(buf, state, false);
         if (result.readComplete) {
           // TODO: more efficient way of doing this
           exchange.setProtocol(HttpString.tryFromString(result.value));
         } else {
           state.state = AjpParseState.READING_PROTOCOL;
           return;
         }
       }
     case AjpParseState.READING_REQUEST_URI:
       {
         StringHolder result = parseString(buf, state, false);
         if (result.readComplete) {
           String res = result.value;
           exchange.setRequestPath(res);
           exchange.setRelativePath(res);
         } else {
           state.state = AjpParseState.READING_REQUEST_URI;
           return;
         }
       }
     case AjpParseState.READING_REMOTE_ADDR:
       {
         StringHolder result = parseString(buf, state, false);
         if (result.readComplete) {
           // exchange.setRequestURI(result.value);
         } else {
           state.state = AjpParseState.READING_REMOTE_ADDR;
           return;
         }
       }
     case AjpParseState.READING_REMOTE_HOST:
       {
         StringHolder result = parseString(buf, state, false);
         if (result.readComplete) {
           // exchange.setRequestURI(result.value);
         } else {
           state.state = AjpParseState.READING_REMOTE_HOST;
           return;
         }
       }
     case AjpParseState.READING_SERVER_NAME:
       {
         StringHolder result = parseString(buf, state, false);
         if (result.readComplete) {
           // exchange.setRequestURI(result.value);
         } else {
           state.state = AjpParseState.READING_SERVER_NAME;
           return;
         }
       }
     case AjpParseState.READING_SERVER_PORT:
       {
         IntegerHolder result = parse16BitInteger(buf, state);
         if (result.readComplete) {
           // exchange.setRequestURI(result.value);
         } else {
           state.state = AjpParseState.READING_SERVER_PORT;
           return;
         }
       }
     case AjpParseState.READING_IS_SSL:
       {
         if (!buf.hasRemaining()) {
           state.state = AjpParseState.READING_IS_SSL;
           return;
         } else {
           final byte isSsl = buf.get();
         }
       }
     case AjpParseState.READING_NUM_HEADERS:
       {
         IntegerHolder result = parse16BitInteger(buf, state);
         if (!result.readComplete) {
           state.state = AjpParseState.READING_NUM_HEADERS;
           return;
         } else {
           state.numHeaders = result.value;
         }
       }
     case AjpParseState.READING_HEADERS:
       {
         int readHeaders = exchange.getRequestHeaders().getHeaderNames().size();
         while (readHeaders < state.numHeaders) {
           if (state.currentHeader == null) {
             StringHolder result = parseString(buf, state, true);
             if (!result.readComplete) {
               state.state = AjpParseState.READING_HEADERS;
               return;
             }
             if (result.header != null) {
               state.currentHeader = result.header;
             } else {
               state.currentHeader = HttpString.tryFromString(result.value);
             }
           }
           StringHolder result = parseString(buf, state, false);
           if (!result.readComplete) {
             state.state = AjpParseState.READING_HEADERS;
             return;
           }
           exchange.getRequestHeaders().add(state.currentHeader, result.value);
           state.currentHeader = null;
           ++readHeaders;
         }
       }
     case AjpParseState.READING_ATTRIBUTES:
       {
         for (; ; ) {
           if (state.currentAttribute == null && state.currentIntegerPart == -1) {
             if (!buf.hasRemaining()) {
               state.state = AjpParseState.READING_ATTRIBUTES;
               return;
             }
             int val = (0xFF & buf.get());
             if (val == 0xFF) {
               state.state = AjpParseState.DONE;
               return;
             } else if (val == 0x0A) {
               // we need to read the name. We overload currentIntegerPart to avoid adding another
               // state field
               state.currentIntegerPart = 1;
             } else {
               state.currentAttribute = ATTRIBUTES[val];
             }
           }
           if (state.currentIntegerPart == 1) {
             StringHolder result = parseString(buf, state, false);
             if (!result.readComplete) {
               state.state = AjpParseState.READING_ATTRIBUTES;
               return;
             }
             state.currentAttribute = result.value;
             state.currentIntegerPart = -1;
           }
           StringHolder result = parseString(buf, state, false);
           if (!result.readComplete) {
             state.state = AjpParseState.READING_ATTRIBUTES;
             return;
           }
           // query string.
           if (state.currentAttribute.equals(ATTRIBUTES[5])) {
             String res = result.value;
             exchange.setQueryString(res);
             int stringStart = 0;
             String attrName = null;
             for (int i = 0; i < res.length(); ++i) {
               char c = res.charAt(i);
               if (c == '=' && attrName == null) {
                 attrName = res.substring(stringStart, i);
                 stringStart = i + 1;
               } else if (c == '&') {
                 if (attrName != null) {
                   exchange.addQueryParam(attrName, res.substring(stringStart, i));
                 } else {
                   exchange.addQueryParam(res.substring(stringStart, i), "");
                 }
                 stringStart = i + 1;
                 attrName = null;
               }
             }
             if (attrName != null) {
               exchange.addQueryParam(attrName, res.substring(stringStart, res.length()));
             } else if (res.length() != stringStart) {
               exchange.addQueryParam(res.substring(stringStart, res.length()), "");
             }
           }
           // TODO: do something with the attributes
           state.currentAttribute = null;
         }
       }
   }
   state.state = AjpParseState.DONE;
 }