private void parse(QpidByteBuffer buffer) {
    buffer.mark();
    switch (_state) {
      case PROTO_HDR:
        if (buffer.remaining() < 8) {
          break;
        }
        if (buffer.get() != 'A'
            || buffer.get() != 'M'
            || buffer.get() != 'Q'
            || buffer.get() != 'P') {
          buffer.reset();
          error("bad protocol header: %s", str(buffer));
          _state = ERROR;
        } else {
          byte protoClass = buffer.get();
          byte instance = buffer.get();
          byte major = buffer.get();
          byte minor = buffer.get();

          _serverAssembler.init(new ProtocolHeader(protoClass, instance, major, minor));
          _state = FRAME_HDR;
        }
        break;
      case FRAME_HDR:
        if (buffer.remaining() < ServerFrame.HEADER_SIZE) {
          buffer.reset();
        } else {
          flags = buffer.get();
          type = SegmentType.get(buffer.get());
          int size = (0xFFFF & buffer.getShort());

          size -= ServerFrame.HEADER_SIZE;
          if (size < 0 || size > (_maxFrameSize - ServerFrame.HEADER_SIZE)) {
            error("bad frame size: %d", size);
            _state = ERROR;
          } else {
            buffer.get(); // skip unused byte
            byte b = buffer.get();
            if ((b & 0xF0) != 0) {
              error("non-zero reserved bits in upper nibble of " + "frame header byte 5: '%x'", b);
              _state = ERROR;
            } else {
              track = (byte) (b & 0xF);

              channel = (0xFFFF & buffer.getShort());
              buffer.position(buffer.position() + 4);
              if (size == 0) {
                ServerFrame frame =
                    new ServerFrame(flags, type, track, channel, EMPTY_BYTE_BUFFER.duplicate());
                _serverAssembler.received(frame);

              } else if (buffer.remaining() < size) {
                buffer.reset();
              } else {
                final QpidByteBuffer body = buffer.slice();
                body.limit(size);
                ServerFrame frame = new ServerFrame(flags, type, track, channel, body);
                buffer.position(buffer.position() + size);

                _serverAssembler.received(frame);
              }
            }
          }
        }
        break;
      default:
        throw new IllegalStateException();
    }
  }
 public void closed() {
   _serverAssembler.closed();
 }
 private void error(String fmt, Object... args) {
   _serverAssembler.error(new ProtocolError(ServerFrame.L1, fmt, args));
 }
 public void exception(Throwable t) {
   _serverAssembler.exception(t);
 }