예제 #1
0
  /**
   * Parses a header value. This is called from the generated bytecode.
   *
   * @param buffer The buffer
   * @param remaining The number of bytes remaining
   * @param state The current state
   * @param builder The exchange builder
   * @return The number of bytes remaining
   */
  @SuppressWarnings("unused")
  final int handleHeaderValue(
      ByteBuffer buffer, int remaining, ParseState state, HttpExchangeBuilder builder) {
    StringBuilder stringBuilder = state.stringBuilder;
    if (stringBuilder == null) {
      stringBuilder = new StringBuilder();
    }

    int parseState = state.parseState;
    while (remaining > 0) {
      final byte next = buffer.get();
      --remaining;
      switch (parseState) {
        case NORMAL:
          {
            if (next == '\r') {
              parseState = BEGIN_LINE_END;
            } else if (next == '\n') {
              parseState = LINE_END;
            } else if (next == ' ' || next == '\t') {
              parseState = WHITESPACE;
            } else {
              stringBuilder.append((char) next);
            }
            break;
          }
        case WHITESPACE:
          {
            if (next == '\r') {
              parseState = BEGIN_LINE_END;
            } else if (next == '\n') {
              parseState = LINE_END;
            } else if (next == ' ' || next == '\t') {
            } else {
              if (stringBuilder.length() > 0) {
                stringBuilder.append(' ');
              }
              stringBuilder.append((char) next);
              parseState = NORMAL;
            }
            break;
          }
        case LINE_END:
        case BEGIN_LINE_END:
          {
            if (next == '\n' && parseState == BEGIN_LINE_END) {
              parseState = LINE_END;
            } else if (next == '\t' || next == ' ') {
              // this is a continuation
              parseState = WHITESPACE;
            } else {
              // we have a header
              String nextStandardHeader = state.nextHeader;
              builder.headers.put(nextStandardHeader, stringBuilder.toString());

              state.nextHeader = null;

              state.leftOver = next;
              state.stringBuilder = null;
              if (next == '\r') {
                parseState = AWAIT_DATA_END;
              } else {
                state.state = ParseState.HEADER;
                state.parseState = 0;
                return remaining;
              }
            }
            break;
          }
        case AWAIT_DATA_END:
          {
            state.state = ParseState.PARSE_COMPLETE;
            return remaining;
          }
      }
    }
    // we only write to the state if we did not finish parsing
    state.parseState = parseState;
    state.stringBuilder = stringBuilder;
    return remaining;
  }
예제 #2
0
 /**
  * Parses a path value. This is called from the generated bytecode.
  *
  * @param buffer The buffer
  * @param remaining The number of bytes remaining
  * @param state The current state
  * @param builder The exchange builder
  * @return The number of bytes remaining
  */
 @SuppressWarnings("unused")
 final int handlePath(
     ByteBuffer buffer, int remaining, ParseState state, HttpExchangeBuilder builder) {
   StringBuilder stringBuilder = state.stringBuilder;
   int parseState = state.parseState;
   int canonicalPathStart = state.pos;
   int queryParamPos = state.queryParamPos;
   String nextQueryParam = state.nextHeader;
   if (stringBuilder == null) {
     state.stringBuilder = stringBuilder = new StringBuilder();
   }
   while (remaining > 0) {
     final char next = (char) buffer.get();
     --remaining;
     if (next == ' ' || next == '\t') {
       if (stringBuilder.length() != 0) {
         final String path = stringBuilder.toString();
         builder.fullPath = path;
         if (parseState < HOST_DONE) {
           builder.relativePath = path;
         } else {
           builder.relativePath = path.substring(canonicalPathStart);
         }
         if (parseState == QUERY_PARAM_NAME) {
           builder.addQueryParam(stringBuilder.substring(queryParamPos), "");
         } else if (parseState == QUERY_PARAM_VALUE) {
           builder.addQueryParam(nextQueryParam, stringBuilder.substring(queryParamPos));
         }
         state.state = ParseState.VERSION;
         state.stringBuilder = null;
         state.parseState = 0;
         state.pos = 0;
         state.nextHeader = null;
         state.queryParamPos = 0;
         return remaining;
       }
     } else {
       if (next == ':' && parseState == START) {
         parseState = FIRST_COLON;
       } else if (next == '/' && parseState == FIRST_COLON) {
         parseState = FIRST_SLASH;
       } else if (next == '/' && parseState == FIRST_SLASH) {
         parseState = SECOND_SLASH;
       } else if (next == '/' && parseState == SECOND_SLASH) {
         parseState = HOST_DONE;
         canonicalPathStart = stringBuilder.length();
       } else if (parseState == FIRST_COLON || parseState == FIRST_SLASH) {
         parseState = START;
       } else if (next == '?' && (parseState == START || parseState == HOST_DONE)) {
         parseState = QUERY_PARAM_NAME;
         queryParamPos = stringBuilder.length() + 1;
       } else if (next == '=' && parseState == QUERY_PARAM_NAME) {
         parseState = QUERY_PARAM_VALUE;
         nextQueryParam = stringBuilder.substring(queryParamPos);
         queryParamPos = stringBuilder.length() + 1;
       } else if (next == '&' && parseState == QUERY_PARAM_NAME) {
         parseState = QUERY_PARAM_NAME;
         builder.addQueryParam(stringBuilder.substring(queryParamPos), "");
         nextQueryParam = null;
         queryParamPos = stringBuilder.length() + 1;
       } else if (next == '&' && parseState == QUERY_PARAM_VALUE) {
         parseState = QUERY_PARAM_NAME;
         builder.addQueryParam(nextQueryParam, stringBuilder.substring(queryParamPos));
         nextQueryParam = null;
         queryParamPos = stringBuilder.length() + 1;
       }
       stringBuilder.append(next);
     }
   }
   state.stringBuilder = stringBuilder;
   state.parseState = parseState;
   state.pos = canonicalPathStart;
   state.nextHeader = nextQueryParam;
   state.queryParamPos = queryParamPos;
   return remaining;
 }