package DBProxy.MySQL.Protocol; import java.util.ArrayList; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.InputStream; public abstract class Packet { public long sequenceId = 0; public abstract ArrayList<byte[]> getPayload(); public byte[] toPacket() { ArrayList<byte[]> payload = this.getPayload(); int size = 0; for (byte[] field : payload) { size += field.length; } byte[] packet = new byte[size + 4]; System.arraycopy(Proto.build_fixed_int(3, size), 0, packet, 0, 3); System.arraycopy(Proto.build_fixed_int(1, this.sequenceId), 0, packet, 3, 1); int offset = 4; for (byte[] field : payload) { System.arraycopy(field, 0, packet, offset, field.length); offset += field.length; } return packet; } public static int getSize(byte[] packet) { int size = (int) new Proto(packet).get_fixed_int(3); return size; } public static byte getType(byte[] packet) { return packet[4]; } public static long getSequenceId(byte[] packet) { return new Proto(packet, 3).get_fixed_int(1); } public static final void dump(byte[] packet) { } public static final void dump_stderr(byte[] packet) { } public static byte[] read_packet(InputStream in) throws IOException { int b = 0; int size = 0; byte[] packet = new byte[3]; // Read size (3) int offset = 0; int target = 3; do { b = in.read(packet, offset, (target - offset)); if (b == -1) { throw new IOException(); } offset += b; } while (offset != target); size = Packet.getSize(packet); byte[] packet_tmp = new byte[size + 4]; System.arraycopy(packet, 0, packet_tmp, 0, 3); packet = packet_tmp; packet_tmp = null; target = packet.length; do { b = in.read(packet, offset, (target - offset)); if (b == -1) { throw new IOException(); } offset += b; } while (offset != target); return packet; } public static ArrayList<byte[]> read_full_result_set(InputStream in, OutputStream out, ArrayList<byte[]> buffer, boolean bufferResultSet) throws IOException { // Assume we have the start of a result set already byte[] packet = buffer.get((buffer.size() - 1)); long colCount = ColCount.loadFromPacket(packet).colCount; // Read the columns and the EOF field for (int i = 0; i < (colCount + 1); i++) { packet = Packet.read_packet(in); if (packet == null) { throw new IOException(); } buffer.add(packet); // Evil optimization if (!bufferResultSet) { Packet.write(out, buffer); out.flush(); buffer.clear(); } } int packedPacketSize = 65535; byte[] packedPacket = new byte[packedPacketSize]; int position = 0; while (true) { packet = Packet.read_packet(in); if (packet == null) { throw new IOException(); } int packetType = Packet.getType(packet); if (packetType == Flags.EOF || packetType == Flags.ERR) { byte[] newPackedPacket = new byte[position]; System.arraycopy(packedPacket, 0, newPackedPacket, 0, position); buffer.add(newPackedPacket); packedPacket = packet; break; } if (position + packet.length > packedPacketSize) { int subsize = packedPacketSize - position; System.arraycopy(packet, 0, packedPacket, position, subsize); buffer.add(packedPacket); // Evil optimization if (!bufferResultSet) { Packet.write(out, buffer); out.flush(); buffer.clear(); } packedPacket = new byte[packedPacketSize]; position = 0; System.arraycopy(packet, subsize, packedPacket, position, packet.length - subsize); position += packet.length - subsize; } else { System.arraycopy(packet, 0, packedPacket, position, packet.length); position += packet.length; } } buffer.add(packedPacket); // Evil optimization if (!bufferResultSet) { Packet.write(out, buffer); buffer.clear(); out.flush(); } if (Packet.getType(packet) == Flags.ERR) { return buffer; } if (EOF.loadFromPacket(packet).hasStatusFlag(Flags.SERVER_MORE_RESULTS_EXISTS)) { buffer.add(Packet.read_packet(in)); buffer = Packet.read_full_result_set(in, out, buffer, bufferResultSet); } return buffer; } public static void write(OutputStream out, ArrayList<byte[]> buffer) throws IOException { for (byte[] packet : buffer) { out.write(packet); } } }