Beispiel #1
0
  /**
   * Validates incoming packet and deserializes all fields that need to be deserialized.
   *
   * @param ses Session on which packet is being parsed.
   * @param req Raw packet.
   * @return Same packet with fields deserialized.
   * @throws IOException If parsing failed.
   * @throws GridException If deserialization failed.
   */
  private GridClientMessage assemble(GridNioSession ses, GridTcpRestPacket req)
      throws IOException, GridException {
    byte[] extras = req.extras();

    // First, decode key and value, if any
    if (req.key() != null || req.value() != null) {
      short keyFlags = 0;
      short valFlags = 0;

      if (req.hasFlags()) {
        if (extras == null || extras.length < FLAGS_LENGTH)
          throw new IOException(
              "Failed to parse incoming packet (flags required for command) [ses="
                  + ses
                  + ", opCode="
                  + Integer.toHexString(req.operationCode() & 0xFF)
                  + ']');

        keyFlags = U.bytesToShort(extras, 0);
        valFlags = U.bytesToShort(extras, 2);
      }

      if (req.key() != null) {
        assert req.key() instanceof byte[];

        byte[] rawKey = (byte[]) req.key();

        // Only values can be hessian-encoded.
        req.key(decodeObj(keyFlags, rawKey));
      }

      if (req.value() != null) {
        assert req.value() instanceof byte[];

        byte[] rawVal = (byte[]) req.value();

        req.value(decodeObj(valFlags, rawVal));
      }
    }

    if (req.hasExpiration()) {
      if (extras == null || extras.length < 8)
        throw new IOException(
            "Failed to parse incoming packet (expiration value required for command) [ses="
                + ses
                + ", opCode="
                + Integer.toHexString(req.operationCode() & 0xFF)
                + ']');

      req.expiration(U.bytesToInt(extras, 4) & 0xFFFFFFFFL);
    }

    if (req.hasInitial()) {
      if (extras == null || extras.length < 16)
        throw new IOException(
            "Failed to parse incoming packet (initial value required for command) [ses="
                + ses
                + ", opCode="
                + Integer.toHexString(req.operationCode() & 0xFF)
                + ']');

      req.initial(U.bytesToLong(extras, 8));
    }

    if (req.hasDelta()) {
      if (extras == null || extras.length < 8)
        throw new IOException(
            "Failed to parse incoming packet (delta value required for command) [ses="
                + ses
                + ", opCode="
                + Integer.toHexString(req.operationCode() & 0xFF)
                + ']');

      req.delta(U.bytesToLong(extras, 0));
    }

    if (extras != null) {
      // Clients that include cache name must always include flags.
      int length = 4;

      if (req.hasExpiration()) length += 4;

      if (req.hasDelta()) length += 8;

      if (req.hasInitial()) length += 8;

      if (extras.length - length > 0) {
        byte[] cacheName = new byte[extras.length - length];

        System.arraycopy(extras, length, cacheName, 0, extras.length - length);

        req.cacheName(new String(cacheName));
      }
    }

    return req;
  }
Beispiel #2
0
  /**
   * Parses memcache protocol message.
   *
   * @param ses Session.
   * @param buf Buffer containing not parsed bytes.
   * @param state Current parser state.
   * @return Parsed packet.s
   * @throws IOException If packet cannot be parsed.
   * @throws GridException If deserialization error occurred.
   */
  @Nullable
  private GridClientMessage parseMemcachePacket(
      GridNioSession ses, ByteBuffer buf, ParserState state) throws IOException, GridException {
    assert state.packetType() == PacketType.MEMCACHE;
    assert state.packet() != null;
    assert state.packet() instanceof GridTcpRestPacket;

    GridTcpRestPacket req = (GridTcpRestPacket) state.packet();
    ByteArrayOutputStream tmp = state.buffer();
    int i = state.index();

    while (buf.remaining() > 0) {
      byte b = buf.get();

      if (i == 0) req.requestFlag(b);
      else if (i == 1) req.operationCode(b);
      else if (i == 2 || i == 3) {
        tmp.write(b);

        if (i == 3) {
          req.keyLength(U.bytesToShort(tmp.toByteArray(), 0));

          tmp.reset();
        }
      } else if (i == 4) req.extrasLength(b);
      else if (i >= 8 && i <= 11) {
        tmp.write(b);

        if (i == 11) {
          req.totalLength(U.bytesToInt(tmp.toByteArray(), 0));

          tmp.reset();
        }
      } else if (i >= 12 && i <= 15) {
        tmp.write(b);

        if (i == 15) {
          req.opaque(tmp.toByteArray());

          tmp.reset();
        }
      } else if (i >= HDR_LEN && i < HDR_LEN + req.extrasLength()) {
        tmp.write(b);

        if (i == HDR_LEN + req.extrasLength() - 1) {
          req.extras(tmp.toByteArray());

          tmp.reset();
        }
      } else if (i >= HDR_LEN + req.extrasLength()
          && i < HDR_LEN + req.extrasLength() + req.keyLength()) {
        tmp.write(b);

        if (i == HDR_LEN + req.extrasLength() + req.keyLength() - 1) {
          req.key(tmp.toByteArray());

          tmp.reset();
        }
      } else if (i >= HDR_LEN + req.extrasLength() + req.keyLength()
          && i < HDR_LEN + req.totalLength()) {
        tmp.write(b);

        if (i == HDR_LEN + req.totalLength() - 1) {
          req.value(tmp.toByteArray());

          tmp.reset();
        }
      }

      if (i == HDR_LEN + req.totalLength() - 1)
        // Assembled the packet.
        return assemble(ses, req);

      i++;
    }

    state.index(i);

    return null;
  }