Exemplo n.º 1
0
 // cloneMsgArg is used when the split buffer scenario has the pubArg in the existing read buffer,
 // but
 // we need to hold onto it into the next read.
 private void cloneMsgArg() {
   ps.argBuf = ByteBuffer.wrap(ps.argBufStore);
   //		System.err.printf("ps.argBuf 1= %s\n",  ps.argBuf);
   ps.argBuf.put(ps.ma.subject, 0, ps.ma.subjectLength);
   //		System.err.printf("ps.argBuf 2= %s\n",  ps.argBuf);
   if (ps.ma.replyLength != 0) {
     ps.argBuf.put(ps.ma.reply, 0, ps.ma.replyLength);
   }
   //		System.err.printf("ps.argBuf 3= %s\n",  ps.argBuf);
   ps.argBuf.rewind();
   ps.argBuf.get(ps.ma.subject, 0, ps.ma.subjectLength);
   if (ps.ma.replyLength != 0) {
     ps.argBuf.get(ps.ma.reply, 0, ps.ma.replyLength);
   }
   //		ps.argBuf.flip();
   //		System.err.printf("ps.argBuf 4= %s\n",  ps.argBuf);
 }
Exemplo n.º 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);
    }
  }