Exemple #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;
  }
Exemple #2
0
  protected void parse(byte[] buf, int len) throws ParseException {
    int i;
    byte b;
    boolean error = false;

    //		if (len > buf.length) {
    //			throw new ParseException(String.format("Parse length(%d) > actual buffer length(%d)\n",
    // len, buf.length),0);
    //		}
    //		String tmpStr = new String(buf, 0, len);
    //		System.err.printf("#####     Parsing buf=[%s], ps.argBuf=[%s]\n", tmpStr.trim(), ps.argBuf);

    for (i = 0; i < len; i++) {
      b = buf[i];

      //          printStatus(buf, i);

      switch (ps.state) {
        case OP_START:
          switch (b) {
            case 'M':
            case 'm':
              ps.state = NatsOp.OP_M;
              break;
            case 'P':
            case 'p':
              ps.state = NatsOp.OP_P;
              break;
            case '+':
              ps.state = NatsOp.OP_PLUS;
              break;
            case '-':
              ps.state = NatsOp.OP_MINUS;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_M:
          switch (b) {
            case 'S':
            case 's':
              ps.state = NatsOp.OP_MS;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MS:
          switch (b) {
            case 'G':
            case 'g':
              ps.state = NatsOp.OP_MSG;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MSG:
          switch (b) {
            case ' ':
            case '\t':
              ps.state = NatsOp.OP_MSG_SPC;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MSG_SPC:
          switch (b) {
            case ' ':
            case '\t':
              continue;
            default:
              ps.state = NatsOp.MSG_ARG;
              ps.as = i;
              break;
          }
          break;
        case MSG_ARG:
          switch (b) {
            case '\r':
              ps.drop = 1;
              break;
            case '\n':
              ByteBuffer arg = null;
              if (ps.argBuf != null) {
                // End of args
                arg = ps.argBuf;
                arg.flip();
                processMsgArgs(arg.array(), arg.arrayOffset(), arg.limit());
              } else {
                //                        	arg = ByteBuffer.wrap(buf, ps.as,
                // i-ps.drop-ps.as).slice();
                processMsgArgs(buf, ps.as, i - ps.drop - ps.as);
              }
              //                		System.err.printf("arrayOffset=%d, length=%d\n",
              // arg.arrayOffset(), arg.limit());
              //						processMsgArgs(arg.array(), arg.arrayOffset(), arg.limit());

              ps.drop = 0;
              ps.as = i + 1;
              ps.state = NatsOp.MSG_PAYLOAD;

              // jump ahead with the index. If this overruns
              // what is left we fall out and process split
              // buffer.
              i = ps.as + ps.ma.size - 1;
              break;
            default:
              // We have a leftover argBuf we'll continuing filling
              if (ps.argBuf != null) {
                try {
                  ps.argBuf.put(b);
                } catch (Exception e) {
                  System.err.printf("i=%d, b=%c, ps.argBuf=%s\n", i, (char) b, ps.argBuf);
                  e.printStackTrace();
                }
              }
              break;
          }
          break;
        case MSG_PAYLOAD:
          boolean done = false;
          //                	System.err.printf("MSG_PAYLOAD: ps.ma.size = %d\n", ps.ma.size);
          //            		System.err.printf("ps.msgBuf.position=%d, i=%d, ps.as=%d,
          // ps.ma.size=%d\n",
          //            				ps.msgBuf.position(), i, ps.as, ps.ma.size);
          if (ps.msgBuf != null) {
            //                		System.err.printf("ps.msgBuf.position=%d, i=%d, ps.as=%d,
            // ps.ma.size=%d\n",
            //                				ps.msgBuf.position(), i, ps.as, ps.ma.size);
            // Already have bytes in the buffer
            if (ps.msgBuf.position() >= ps.ma.size) {
              ps.msgBuf.flip();
              nc.processMsg(ps.msgBuf.array(), 0, ps.msgBuf.limit());
              done = true;
            } else {
              // copy as much as we can to the buffer and skip ahead.
              int toCopy = ps.ma.size - ps.msgBuf.limit();
              int avail = len - i;

              if (avail < toCopy) {
                toCopy = avail;
              }

              //            				System.err.printf("msgBuf=%s(remaining=%d), i=%d, len=%d,
              // ps.ma.size=%d, avail = %d, toCopy=%d,"
              //            						+ " buf.length=%d\n",
              //            						ps.msgBuf, ps.msgBuf.remaining(), i, len, ps.ma.size, avail,
              // toCopy, buf.length);
              if (toCopy > 0) {
                //                				System.err.printf("msgBuf=%s(remaining=%d), i=%d, len=%d,
                // ps.ma.size=%d, avail = %d, toCopy=%d,"
                //                						+ " buf.length=%d\n",
                //                						ps.msgBuf, ps.msgBuf.remaining(), i, len, ps.ma.size, avail,
                // toCopy, buf.length);
                ps.msgBuf.put(buf, i, toCopy);
                // Update our index
                i += toCopy - 1;
              } else {
                ps.msgBuf.put(b);
              }
            }
          } else if (i - ps.as >= ps.ma.size) {
            //                		System.err.printf("i=%d, ps.as=%d, ps.ma.size=%d\n", i, ps.as,
            // ps.ma.size);
            // If we are at or past the end of the payload, go ahead and process it, no
            // buffering needed.
            nc.processMsg(buf, ps.as, i - ps.as); // pass offset and length
            done = true;
          }

          if (done) {
            ps.argBuf = null;
            //                		ps.argBuf.clear();
            ps.msgBuf = null;
            //                		ps.msgBuf.clear();
            ps.state = NatsOp.MSG_END;
          }

          break;
        case MSG_END:
          switch (b) {
            case '\n':
              ps.drop = 0;
              ps.as = i + 1;
              ps.state = NatsOp.OP_START;
              break;
            default:
              continue;
          }
          break;
        case OP_PLUS:
          switch (b) {
            case 'O':
            case 'o':
              ps.state = NatsOp.OP_PLUS_O;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_PLUS_O:
          switch (b) {
            case 'K':
            case 'k':
              ps.state = NatsOp.OP_PLUS_OK;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_PLUS_OK:
          switch (b) {
            case '\n':
              nc.processOK();
              ps.drop = 0;
              ps.state = NatsOp.OP_START;
              break;
          }
          break;
        case OP_MINUS:
          switch (b) {
            case 'E':
            case 'e':
              ps.state = NatsOp.OP_MINUS_E;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MINUS_E:
          switch (b) {
            case 'R':
            case 'r':
              ps.state = NatsOp.OP_MINUS_ER;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MINUS_ER:
          switch (b) {
            case 'R':
            case 'r':
              ps.state = NatsOp.OP_MINUS_ERR;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MINUS_ERR:
          switch (b) {
            case ' ':
            case '\t':
              ps.state = NatsOp.OP_MINUS_ERR_SPC;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_MINUS_ERR_SPC:
          switch (b) {
            case ' ':
            case '\t':
              continue;
            default:
              ps.state = NatsOp.MINUS_ERR_ARG;
              ps.as = i;
              break;
          }
          break;
        case MINUS_ERR_ARG:
          switch (b) {
            case '\r':
              ps.drop = 1;
              break;
            case '\n':
              ByteBuffer arg = null;
              if (ps.argBuf != null) {
                arg = ps.argBuf;
                ps.argBuf = null;
              } else {
                arg = ByteBuffer.wrap(buf, ps.as, i - ps.as);
              }
              nc.processErr(arg);
              ps.drop = 0;
              ps.as = i + 1;
              ps.state = NatsOp.OP_START;
              break;
            default:
              if (ps.argBuf != null) {
                ps.argBuf.put(b);
              }
              break;
          }
          break;
        case OP_P:
          switch (b) {
            case 'I':
            case 'i':
              ps.state = NatsOp.OP_PI;
              break;
            case 'O':
            case 'o':
              ps.state = NatsOp.OP_PO;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_PO:
          switch (b) {
            case 'N':
            case 'n':
              ps.state = NatsOp.OP_PON;
              break;
            default:
              //                            parseError(buf, i);
              error = true;
              break;
          }
          break;
        case OP_PON:
          switch (b) {
            case 'G':
            case 'g':
              ps.state = NatsOp.OP_PONG;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_PONG:
          switch (b) {
            case '\n':
              nc.processPong();
              ps.drop = 0;
              ps.state = NatsOp.OP_START;
              break;
            default:
              break;
          }
          break;
        case OP_PI:
          switch (b) {
            case 'N':
            case 'n':
              ps.state = NatsOp.OP_PIN;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_PIN:
          switch (b) {
            case 'G':
            case 'g':
              ps.state = NatsOp.OP_PING;
              break;
            default:
              error = true;
              break;
          }
          break;
        case OP_PING:
          switch (b) {
            case '\n':
              nc.processPing();
              ps.drop = 0;
              ps.state = NatsOp.OP_START;
              break;
          }
          break;
        default:
          error = true;
          break;
      } // switch(ps.state)

      if (error) {
        error = false;
        throw new ParseException(
            String.format("nats: parse error [%s]: '%s'", ps.state, new String(buf, i, len - i)),
            i);
      }
      //            System.err.printf("After processing index %d, ps.state=%s\n", i, ps.state );
    } // for

    // We have processed the entire buffer
    // Check for split buffer scenarios
    if ((ps.state == NatsOp.MSG_ARG || ps.state == NatsOp.MINUS_ERR_ARG) && (ps.argBuf == null)) {
      ps.argBuf = ByteBuffer.wrap(ps.argBufStore);
      ps.argBuf.put(buf, ps.as, i - ps.drop - ps.as);
      //    		System.err.printf("split msg, no clone, ps.argBuf=%s\n", ps.argBuf);
      // FIXME, check max len
    }
    // Check for split msg
    if (ps.state == NatsOp.MSG_PAYLOAD && ps.msgBuf == null) {
      // We need to clone the msgArg if it is still referencing the
      // read buffer and we are not able to process the msg.
      if (ps.argBuf == null) {
        cloneMsgArg();
        //        		System.err.printf("split msg, after clone, ps.argBuf=%s\n", ps.argBuf);
      }

      // If we will overflow the scratch buffer, just create a
      // new buffer to hold the split message.
      int lrem = len - ps.as; // portion of msg remaining in buffer
      if (ps.ma.size > ps.msgBufStore.length) {
        ps.msgBufStore = new byte[ps.ma.size];
      }
      ps.msgBuf = ByteBuffer.wrap(ps.msgBufStore);
      // copy what's left in the buffer
      ps.msgBuf.put(buf, ps.as, lrem);
    }
  }
Exemple #3
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;
 }