use of net.runelite.protocol.api.update.ArchiveResponsePacket in project runelite by runelite.
the class ArchiveRequestHandler method handleRequest.
private void handleRequest(ChannelHandlerContext ctx, int index, int archiveId) throws IOException {
logger.info("Client {} requests index {} archive {}", ctx.channel().remoteAddress(), index, archiveId);
Index i = store.findIndex(index);
assert i != null;
Archive archive = i.getArchive(archiveId);
assert archive != null;
Storage storage = store.getStorage();
// is compressed, includes length and type
byte[] packed = storage.loadArchive(archive);
if (packed == null) {
logger.warn("Missing archive {}/{}", index, archiveId);
// is it possible to notify the client of an error with this?
return;
}
byte compression = packed[0];
int compressedSize = Ints.fromBytes(packed[1], packed[2], packed[3], packed[4]);
// size the client expects the data to be
int expectedSize = // compression type
1 + // compressed size
4 + compressedSize + (compression != CompressionType.NONE ? 4 : 0);
if (packed.length != expectedSize) {
// the update server will never have it
assert packed.length - expectedSize == 2 : "packed length != expected size";
packed = Arrays.copyOf(packed, packed.length - 2);
}
ArchiveResponsePacket response = new ArchiveResponsePacket();
response.setIndex(index);
response.setArchive(archiveId);
response.setData(packed);
ctx.writeAndFlush(response);
}
use of net.runelite.protocol.api.update.ArchiveResponsePacket in project runelite by runelite.
the class ArchiveRequestHandler method handleRequest255.
private void handleRequest255(ChannelHandlerContext ctx, int index, int archiveId) throws IOException {
logger.info("Client {} requests 255: index {}, archive {}", ctx.channel().remoteAddress(), index, archiveId);
byte[] compressed;
if (archiveId == 255) {
// index 255 data, for each index:
// 4 byte crc
// 4 byte revision
ByteBuf buffer = ctx.alloc().heapBuffer(store.getIndexes().size() * 8);
for (Index i : store.getIndexes()) {
buffer.writeInt(i.getCrc());
buffer.writeInt(i.getRevision());
}
compressed = compress(CompressionType.NONE, Arrays.copyOf(buffer.array(), buffer.readableBytes()));
buffer.release();
} else {
// Requires disk storage. Use packed index data from
// store as its crc matches
DiskStorage storage = (DiskStorage) store.getStorage();
compressed = storage.readIndex(archiveId);
}
ArchiveResponsePacket response = new ArchiveResponsePacket();
response.setIndex(index);
response.setArchive(archiveId);
response.setData(compressed);
ctx.writeAndFlush(response);
}
use of net.runelite.protocol.api.update.ArchiveResponsePacket in project runelite by runelite.
the class ArchiveResponseEncoderTest method testEncode.
@Test
public void testEncode() throws Exception {
byte[] data = new byte[1000];
Random random = new Random(42L);
random.nextBytes(data);
Container container = new Container(CompressionType.NONE, -1);
container.compress(data, null);
byte[] compressedData = container.data;
ArchiveResponsePacket archiveResponse = new ArchiveResponsePacket();
archiveResponse.setIndex(0);
archiveResponse.setArchive(1);
archiveResponse.setData(compressedData);
ByteBuf buf = Unpooled.buffer(1024);
ArchiveResponseEncoder encoder = new ArchiveResponseEncoder();
encoder.encode(null, archiveResponse, buf);
ArchiveResponseDecoder decoder = new ArchiveResponseDecoder();
List<Object> out = new ArrayList<>();
decoder.decode(null, buf, out);
Assert.assertEquals(1, out.size());
ArchiveResponsePacket response = (ArchiveResponsePacket) out.get(0);
Assert.assertEquals(archiveResponse.getIndex(), response.getIndex());
Assert.assertEquals(archiveResponse.getArchive(), response.getArchive());
Assert.assertArrayEquals(archiveResponse.getData(), response.getData());
byte[] decompressedData = Container.decompress(response.getData(), null).data;
Assert.assertArrayEquals(data, decompressedData);
}
use of net.runelite.protocol.api.update.ArchiveResponsePacket in project runelite by runelite.
the class ArchiveResponseDecoder method decode.
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() < 8) {
return;
}
ByteBuf copy = in.slice();
int index = copy.readUnsignedByte();
int file = copy.readUnsignedShort();
// decompress() starts reading here
int compression = copy.readUnsignedByte();
int compressedFileSize = copy.readInt();
assert compression == CompressionType.NONE || compression == CompressionType.BZ2 || compression == CompressionType.GZ;
int size = compressedFileSize + // 1 byte compresion type, 4 byte compressed size
5 + // compression has leading 4 byte decompressed length
(compression != CompressionType.NONE ? 4 : 0);
assert size > 0;
int breaks = calculateBreaks(size);
// 3 for index/file
if (size + 3 + breaks > in.readableBytes()) {
logger.trace("Index {} archive {}: Not enough data yet {} > {}", index, file, size + 3 + breaks, in.readableBytes());
return;
}
ByteBuf compressedData = Unpooled.buffer(size);
int totalRead = 3;
// skip index/file
in.skipBytes(3);
for (int i = 0; i < breaks + 1; ++i) {
int bytesInBlock = CHUNK_SIZE - (totalRead % CHUNK_SIZE);
int bytesToRead = Math.min(bytesInBlock, size - compressedData.writerIndex());
logger.trace("{}/{}: reading block {}/{}, read so far this block: {}, file status: {}/{}", index, file, (totalRead % CHUNK_SIZE), CHUNK_SIZE, bytesInBlock, compressedData.writerIndex(), size);
ByteBuf chunk = in.readBytes(bytesToRead);
compressedData.writeBytes(chunk);
chunk.release();
totalRead += bytesToRead;
if (i < breaks) {
assert compressedData.writerIndex() < size;
int b = in.readUnsignedByte();
++totalRead;
assert b == 0xff;
}
}
assert compressedData.writerIndex() == size;
logger.trace("{}/{}: done downloading file, remaining buffer {}", index, file, in.readableBytes());
ArchiveResponsePacket archiveResponse = new ArchiveResponsePacket();
archiveResponse.setIndex(index);
archiveResponse.setArchive(file);
archiveResponse.setData(compressedData.array());
out.add(archiveResponse);
compressedData.release();
}
Aggregations