/** * Parses custom packet serialized by hessian marshaller. * * @param ses Session. * @param buf Buffer containing not parsed bytes. * @param state Parser state. * @return Parsed message. * @throws IOException If packet parsing or deserialization failed. */ @Nullable private GridClientMessage parseCustomPacket(GridNioSession ses, ByteBuffer buf, ParserState state) throws IOException { assert state.packetType() == PacketType.GRIDGAIN; assert state.packet() == null; ByteArrayOutputStream tmp = state.buffer(); int len = state.index(); while (buf.remaining() > 0) { byte b = buf.get(); if (len == 0) { tmp.write(b); if (tmp.size() == 4) { len = U.bytesToInt(tmp.toByteArray(), 0); tmp.reset(); if (len == 0) return PING_MESSAGE; else if (len < 0) throw new IOException( "Failed to parse incoming packet (invalid packet length) [ses=" + ses + ", len=" + len + ']'); state.index(len); } } else { tmp.write(b); if (tmp.size() == len) return marshaller.unmarshal(tmp.toByteArray()); } } return null; }
/** * 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; }