cache: split cache client and server into their own projects
Split handshake and update protocol also into their own projects
This commit is contained in:
@@ -22,71 +22,63 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
package net.runelite.cache;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.definitions.InventoryDefinition;
|
||||
import net.runelite.cache.definitions.loaders.InventoryLoader;
|
||||
import net.runelite.cache.fs.Archive;
|
||||
import net.runelite.cache.fs.ArchiveFiles;
|
||||
import net.runelite.cache.fs.FSFile;
|
||||
import net.runelite.cache.fs.Index;
|
||||
import net.runelite.cache.fs.Storage;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CacheServer implements AutoCloseable
|
||||
public class InventoryManager
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(CacheServer.class);
|
||||
|
||||
private static final int PORT = 43594;
|
||||
|
||||
private final EventLoopGroup group = new NioEventLoopGroup(1);
|
||||
|
||||
private Channel channel;
|
||||
|
||||
private final Store store;
|
||||
private final int revision;
|
||||
private final List<InventoryDefinition> inventories = new ArrayList<>();
|
||||
|
||||
public CacheServer(Store store, int revision)
|
||||
public InventoryManager(Store store)
|
||||
{
|
||||
this.store = store;
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
public void start()
|
||||
public void load() throws IOException
|
||||
{
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.group(group)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.childHandler(new CacheServerInitializer(this));
|
||||
InventoryLoader loader = new InventoryLoader();
|
||||
|
||||
ChannelFuture f = b.bind(PORT).syncUninterruptibly();
|
||||
channel = f.channel();
|
||||
Storage storage = store.getStorage();
|
||||
Index index = store.getIndex(IndexType.CONFIGS);
|
||||
Archive archive = index.getArchive(ConfigType.INV.getId());
|
||||
|
||||
logger.info("Server is now listening on {}", PORT);
|
||||
byte[] archiveData = storage.loadArchive(archive);
|
||||
ArchiveFiles files = archive.getFiles(archiveData);
|
||||
|
||||
for (FSFile file : files.getFiles())
|
||||
{
|
||||
InventoryDefinition inv = loader.load(file.getFileId(), file.getContents());
|
||||
inventories.add(inv);
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForClose()
|
||||
public List<InventoryDefinition> getInventories()
|
||||
{
|
||||
channel.closeFuture().awaitUninterruptibly();
|
||||
return Collections.unmodifiableList(inventories);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
public InventoryDefinition findInventory(int id)
|
||||
{
|
||||
channel.close().syncUninterruptibly();
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
|
||||
public int getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
public Store getStore()
|
||||
{
|
||||
return store;
|
||||
for (InventoryDefinition def : inventories)
|
||||
{
|
||||
if (def.id == id)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import net.runelite.cache.protocol.packets.ArchiveResponsePacket;
|
||||
|
||||
public class ArchiveResponseHandler extends SimpleChannelInboundHandler<ArchiveResponsePacket>
|
||||
{
|
||||
private final CacheClient client;
|
||||
|
||||
public ArchiveResponseHandler(CacheClient client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, ArchiveResponsePacket archiveResponse) throws Exception
|
||||
{
|
||||
client.onFileFinish(archiveResponse.getIndex(),
|
||||
archiveResponse.getArchive(),
|
||||
archiveResponse.getData());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,456 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.runelite.cache.fs.Archive;
|
||||
import net.runelite.cache.fs.Index;
|
||||
import net.runelite.cache.fs.Storage;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import net.runelite.cache.index.ArchiveData;
|
||||
import net.runelite.cache.index.IndexData;
|
||||
import net.runelite.cache.protocol.decoders.HandshakeResponseDecoder;
|
||||
import net.runelite.cache.protocol.encoders.ArchiveRequestEncoder;
|
||||
import net.runelite.cache.protocol.encoders.EncryptionEncoder;
|
||||
import net.runelite.cache.protocol.encoders.HandshakeEncoder;
|
||||
import net.runelite.cache.protocol.packets.ArchiveRequestPacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponseType;
|
||||
import net.runelite.cache.protocol.packets.HandshakeType;
|
||||
import net.runelite.cache.util.Crc32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CacheClient implements AutoCloseable
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(CacheClient.class);
|
||||
|
||||
private static final String HOST = "oldschool1.runescape.com";
|
||||
private static final int PORT = 43594;
|
||||
|
||||
private static final int MAX_REQUESTS = 19; // too many and the server closes the conncetion
|
||||
|
||||
private final Store store; // store cache will be written to
|
||||
private final String host;
|
||||
private final int clientRevision;
|
||||
private DownloadWatcher watcher;
|
||||
|
||||
private ClientState state;
|
||||
|
||||
private final EventLoopGroup group = new NioEventLoopGroup(1);
|
||||
private Channel channel;
|
||||
|
||||
private CompletableFuture<HandshakeResponseType> handshakeFuture;
|
||||
private final Queue<PendingFileRequest> requests = new ArrayDeque<>();
|
||||
|
||||
public CacheClient(Store store, int clientRevision)
|
||||
{
|
||||
this(store, HOST, clientRevision);
|
||||
}
|
||||
|
||||
public CacheClient(Store store, String host, int clientRevision)
|
||||
{
|
||||
this.store = store;
|
||||
this.host = host;
|
||||
this.clientRevision = clientRevision;
|
||||
}
|
||||
|
||||
public CacheClient(Store store, int clientRevision, DownloadWatcher watcher)
|
||||
{
|
||||
this(store, clientRevision);
|
||||
this.watcher = watcher;
|
||||
}
|
||||
|
||||
public void connect()
|
||||
{
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.handler(new ChannelInitializer<SocketChannel>()
|
||||
{
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception
|
||||
{
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
|
||||
//p.addFirst(new HttpProxyHandler(new InetSocketAddress("runelite.net", 3128)));
|
||||
p.addLast("decoder", new HandshakeResponseDecoder());
|
||||
|
||||
p.addLast(
|
||||
new CacheClientHandler(),
|
||||
new HandshakeResponseHandler(CacheClient.this),
|
||||
new ArchiveResponseHandler(CacheClient.this)
|
||||
);
|
||||
|
||||
p.addLast(
|
||||
new HandshakeEncoder(),
|
||||
new EncryptionEncoder(),
|
||||
new ArchiveRequestEncoder()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Start the client.
|
||||
ChannelFuture f = b.connect(host, PORT).syncUninterruptibly();
|
||||
channel = f.channel();
|
||||
}
|
||||
|
||||
public CompletableFuture<HandshakeResponseType> handshake()
|
||||
{
|
||||
HandshakePacket handshakePacket = new HandshakePacket();
|
||||
handshakePacket.setType(HandshakeType.ON_DEMAND);
|
||||
handshakePacket.setRevision(getClientRevision());
|
||||
|
||||
state = ClientState.HANDSHAKING;
|
||||
|
||||
assert handshakeFuture == null;
|
||||
handshakeFuture = new CompletableFuture<>();
|
||||
|
||||
channel.writeAndFlush(handshakePacket);
|
||||
|
||||
logger.info("Sent handshake with revision {}", handshakePacket.getRevision());
|
||||
|
||||
return handshakeFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
channel.close().syncUninterruptibly();
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
|
||||
public int getClientRevision()
|
||||
{
|
||||
return clientRevision;
|
||||
}
|
||||
|
||||
public ClientState getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
void setState(ClientState state)
|
||||
{
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
CompletableFuture<HandshakeResponseType> getHandshakeFuture()
|
||||
{
|
||||
return handshakeFuture;
|
||||
}
|
||||
|
||||
public List<IndexInfo> requestIndexes() throws IOException
|
||||
{
|
||||
logger.info("Requesting indexes");
|
||||
|
||||
FileResult result = requestFile(255, 255, true).join();
|
||||
result.decompress(null);
|
||||
|
||||
ByteBuf buffer = Unpooled.wrappedBuffer(result.getContents());
|
||||
int indexCount = result.getContents().length / 8;
|
||||
List<IndexInfo> indexInfo = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < indexCount; ++i)
|
||||
{
|
||||
int crc = buffer.readInt();
|
||||
int revision = buffer.readInt();
|
||||
indexInfo.add(new IndexInfo(i, crc, revision));
|
||||
}
|
||||
|
||||
return indexInfo;
|
||||
}
|
||||
|
||||
public void download() throws IOException
|
||||
{
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
List<IndexInfo> indexes = requestIndexes();
|
||||
for (IndexInfo indexInfo : indexes)
|
||||
{
|
||||
int i = indexInfo.getId();
|
||||
int crc = indexInfo.getCrc();
|
||||
int revision = indexInfo.getRevision();
|
||||
|
||||
Index index = store.findIndex(i);
|
||||
|
||||
if (index == null)
|
||||
{
|
||||
logger.info("Index {} does not exist, creating", i);
|
||||
}
|
||||
else if (index.getRevision() != revision)
|
||||
{
|
||||
if (revision < index.getRevision())
|
||||
{
|
||||
logger.warn("Index {} revision is going BACKWARDS! (our revision {}, their revision {})", index.getId(), index.getRevision(), revision);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.info("Index {} has the wrong revision (our revision {}, their revision {})", index.getId(), index.getRevision(), revision);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// despite the index being up to date, not everything
|
||||
// can be downloaded, eg. for tracks.
|
||||
logger.info("Index {} is up to date", index.getId());
|
||||
}
|
||||
|
||||
logger.info("Downloading index {}", i);
|
||||
|
||||
FileResult indexFileResult = requestFile(255, i, true).join();
|
||||
indexFileResult.decompress(null);
|
||||
|
||||
logger.info("Downloaded index {}", i);
|
||||
|
||||
if (indexFileResult.getCrc() != crc)
|
||||
{
|
||||
logger.warn("Corrupted download for index {}", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexData indexData = new IndexData();
|
||||
indexData.load(indexFileResult.getContents());
|
||||
|
||||
if (index == null)
|
||||
{
|
||||
index = store.addIndex(i);
|
||||
}
|
||||
|
||||
// update index settings
|
||||
index.setProtocol(indexData.getProtocol());
|
||||
index.setNamed(indexData.isNamed());
|
||||
index.setCrc(crc);
|
||||
index.setRevision(revision);
|
||||
|
||||
logger.info("Index {} has {} archives", i, indexData.getArchives().length);
|
||||
|
||||
for (ArchiveData ad : indexData.getArchives())
|
||||
{
|
||||
Archive existing = index.getArchive(ad.getId());
|
||||
|
||||
if (existing != null && existing.getRevision() == ad.getRevision()
|
||||
&& existing.getCrc() == ad.getCrc()
|
||||
&& existing.getNameHash() == ad.getNameHash())
|
||||
{
|
||||
logger.debug("Archive {}/{} in index {} is up to date",
|
||||
ad.getId(), indexData.getArchives().length, index.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
logger.info("Archive {}/{} in index {} is out of date, downloading",
|
||||
ad.getId(), indexData.getArchives().length, index.getId());
|
||||
}
|
||||
else if (ad.getRevision() < existing.getRevision())
|
||||
{
|
||||
logger.warn("Archive {}/{} in index {} revision is going BACKWARDS! (our revision {}, their revision {})",
|
||||
ad.getId(), indexData.getArchives().length, index.getId(),
|
||||
existing.getRevision(), ad.getRevision());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.info("Archive {}/{} in index {} is out of date, downloading. " +
|
||||
"revision: ours: {} theirs: {}, crc: ours: {} theirs {}, name: ours {} theirs {}",
|
||||
ad.getId(), indexData.getArchives().length, index.getId(),
|
||||
existing.getRevision(), ad.getRevision(),
|
||||
existing.getCrc(), ad.getCrc(),
|
||||
existing.getNameHash(), ad.getNameHash());
|
||||
}
|
||||
|
||||
final Archive archive = existing == null
|
||||
? index.addArchive(ad.getId())
|
||||
: existing;
|
||||
|
||||
archive.setRevision(ad.getRevision());
|
||||
archive.setCrc(ad.getCrc());
|
||||
archive.setNameHash(ad.getNameHash());
|
||||
|
||||
// Add files
|
||||
archive.setFileData(ad.getFiles());
|
||||
|
||||
CompletableFuture<FileResult> future = requestFile(index.getId(), ad.getId(), false);
|
||||
future.handle((fr, ex) ->
|
||||
{
|
||||
byte[] data = fr.getCompressedData();
|
||||
|
||||
Crc32 crc32 = new Crc32();
|
||||
crc32.update(data, 0, data.length);
|
||||
int hash = crc32.getHash();
|
||||
|
||||
if (hash != archive.getCrc())
|
||||
{
|
||||
logger.warn("crc mismatch on downloaded archive {}/{}: {} != {}",
|
||||
archive.getIndex().getId(), archive.getArchiveId(),
|
||||
hash, archive.getCrc());
|
||||
throw new RuntimeException("crc mismatch");
|
||||
}
|
||||
|
||||
if (watcher != null)
|
||||
{
|
||||
watcher.downloadComplete(archive, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Storage storage = store.getStorage();
|
||||
storage.saveArchive(archive, data);
|
||||
}
|
||||
catch (IOException ex1)
|
||||
{
|
||||
logger.warn("unable to save archive data", ex1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// flush any pending requests
|
||||
channel.flush();
|
||||
|
||||
while (!requests.isEmpty())
|
||||
{
|
||||
// wait for pending requests
|
||||
synchronized (this)
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
logger.warn(null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stopwatch.stop();
|
||||
logger.info("Download completed in {}", stopwatch);
|
||||
}
|
||||
|
||||
private synchronized CompletableFuture<FileResult> requestFile(int index, int fileId, boolean flush)
|
||||
{
|
||||
if (state != ClientState.CONNECTED)
|
||||
{
|
||||
throw new IllegalStateException("Can't request files until connected!");
|
||||
}
|
||||
|
||||
if (!flush)
|
||||
{
|
||||
while (requests.size() >= MAX_REQUESTS)
|
||||
{
|
||||
channel.flush();
|
||||
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
logger.warn("interrupted while waiting for requests", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveRequestPacket archiveRequest = new ArchiveRequestPacket();
|
||||
archiveRequest.setPriority(false);
|
||||
archiveRequest.setIndex(index);
|
||||
archiveRequest.setArchive(fileId);
|
||||
|
||||
CompletableFuture<FileResult> future = new CompletableFuture<>();
|
||||
PendingFileRequest pf = new PendingFileRequest(index,
|
||||
fileId, future);
|
||||
|
||||
logger.trace("Sending request for {}/{}", index, fileId);
|
||||
|
||||
requests.add(pf);
|
||||
|
||||
if (!flush)
|
||||
{
|
||||
channel.write(archiveRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
channel.writeAndFlush(archiveRequest);
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
private PendingFileRequest findRequest(int index, int file)
|
||||
{
|
||||
for (PendingFileRequest pr : requests)
|
||||
{
|
||||
if (pr.getIndex() == index && pr.getArchive() == file)
|
||||
{
|
||||
return pr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected synchronized void onFileFinish(int index, int file, byte[] compressedData)
|
||||
{
|
||||
PendingFileRequest pr = findRequest(index, file);
|
||||
|
||||
if (pr == null)
|
||||
{
|
||||
logger.warn("File download {}/{} with no pending request", index, file);
|
||||
return;
|
||||
}
|
||||
|
||||
requests.remove(pr);
|
||||
|
||||
notify();
|
||||
|
||||
FileResult result = new FileResult(index, file, compressedData);
|
||||
|
||||
logger.debug("File download finished for index {} file {}, length {}", index, file, compressedData.length);
|
||||
|
||||
pr.getFuture().complete(result);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CacheClientHandler extends ChannelInboundHandlerAdapter
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(CacheClientHandler.class);
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
logger.warn("Channel has gone inactive");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
|
||||
{
|
||||
// Close the connection when an exception is raised.
|
||||
logger.warn(null, cause);
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
public enum ClientState
|
||||
{
|
||||
HANDSHAKING,
|
||||
CONNECTED
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import net.runelite.cache.fs.Archive;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DownloadWatcher
|
||||
{
|
||||
void downloadComplete(Archive archive, byte[] data);
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import net.runelite.cache.fs.Container;
|
||||
|
||||
public class FileResult
|
||||
{
|
||||
private final int index;
|
||||
private final int fileId;
|
||||
private final byte[] compressedData;
|
||||
|
||||
private byte[] contents;
|
||||
private int revision;
|
||||
private int crc;
|
||||
private int compression; // compression method used by archive data
|
||||
|
||||
public FileResult(int index, int fileId, byte[] compressedData)
|
||||
{
|
||||
this.index = index;
|
||||
this.fileId = fileId;
|
||||
this.compressedData = compressedData;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getFileId()
|
||||
{
|
||||
return fileId;
|
||||
}
|
||||
|
||||
public byte[] getCompressedData()
|
||||
{
|
||||
return compressedData;
|
||||
}
|
||||
|
||||
public void decompress(int[] keys) throws IOException
|
||||
{
|
||||
Container res = Container.decompress(compressedData, keys);
|
||||
|
||||
contents = res.data;
|
||||
revision = res.revision;
|
||||
crc = res.crc;
|
||||
compression = res.compression;
|
||||
}
|
||||
|
||||
public byte[] getContents()
|
||||
{
|
||||
return contents;
|
||||
}
|
||||
|
||||
public int getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
public int getCrc()
|
||||
{
|
||||
return crc;
|
||||
}
|
||||
|
||||
public int getCompression()
|
||||
{
|
||||
return compression;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.runelite.cache.protocol.decoders.ArchiveResponseDecoder;
|
||||
import net.runelite.cache.protocol.packets.EncryptionPacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponsePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponseType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HandshakeResponseHandler extends SimpleChannelInboundHandler<HandshakeResponsePacket>
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(HandshakeResponseHandler.class);
|
||||
|
||||
private final CacheClient client;
|
||||
|
||||
public HandshakeResponseHandler(CacheClient client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, HandshakeResponsePacket handshakeResponse) throws Exception
|
||||
{
|
||||
Channel channel = ctx.channel();
|
||||
ChannelPipeline p = ctx.pipeline();
|
||||
CompletableFuture<HandshakeResponseType> handshakeFuture = client.getHandshakeFuture();
|
||||
|
||||
assert handshakeFuture != null;
|
||||
|
||||
if (handshakeResponse.getResponse() != HandshakeResponseType.RESPONSE_OK)
|
||||
{
|
||||
logger.warn("Non-ok response from server {}", handshakeResponse.getResponse());
|
||||
ctx.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Send encryption packet
|
||||
EncryptionPacket encryptionPacket = new EncryptionPacket();
|
||||
encryptionPacket.setKey((byte) 0);
|
||||
channel.writeAndFlush(encryptionPacket);
|
||||
|
||||
client.setState(ClientState.CONNECTED);
|
||||
|
||||
logger.info("Client is now connected!");
|
||||
|
||||
p.replace("decoder", "decoder", new ArchiveResponseDecoder());
|
||||
|
||||
handshakeFuture.complete(handshakeResponse.getResponse());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
public class IndexInfo
|
||||
{
|
||||
private final int id;
|
||||
private final int crc;
|
||||
private final int revision;
|
||||
|
||||
public IndexInfo(int id, int crc, int revision)
|
||||
{
|
||||
this.id = id;
|
||||
this.crc = crc;
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "IndexInfo{" + "id=" + id + ", crc=" + crc + ", revision=" + revision + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 5;
|
||||
hash = 71 * hash + this.id;
|
||||
hash = 71 * hash + this.crc;
|
||||
hash = 71 * hash + this.revision;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final IndexInfo other = (IndexInfo) obj;
|
||||
if (this.id != other.id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.crc != other.crc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.revision != other.revision)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getCrc()
|
||||
{
|
||||
return crc;
|
||||
}
|
||||
|
||||
public int getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class PendingFileRequest
|
||||
{
|
||||
private final int index;
|
||||
private final int archive;
|
||||
private final CompletableFuture<FileResult> future;
|
||||
|
||||
public PendingFileRequest(int index, int archive, CompletableFuture<FileResult> future)
|
||||
{
|
||||
this.index = index;
|
||||
this.archive = archive;
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getArchive()
|
||||
{
|
||||
return archive;
|
||||
}
|
||||
|
||||
public CompletableFuture<FileResult> getFuture()
|
||||
{
|
||||
return future;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.decoders;
|
||||
|
||||
import net.runelite.cache.server.CacheFrameDecoder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.protocol.packets.ArchiveRequestPacket;
|
||||
|
||||
public class ArchiveRequestDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
|
||||
{
|
||||
byte opcode = in.getByte(in.readerIndex());
|
||||
if (opcode != CacheFrameDecoder.ARCHIVE_REQUEST_HIGH
|
||||
&& opcode != CacheFrameDecoder.ARCHIVE_REQUEST_LOW)
|
||||
{
|
||||
ctx.fireChannelRead(in.retain());
|
||||
return;
|
||||
}
|
||||
|
||||
byte priority = in.readByte();
|
||||
int index = in.readByte() & 0xFF;
|
||||
int archiveId = in.readShort() & 0xFFFF;
|
||||
|
||||
ArchiveRequestPacket archiveRequest = new ArchiveRequestPacket();
|
||||
archiveRequest.setPriority(priority == 1);
|
||||
archiveRequest.setIndex(index);
|
||||
archiveRequest.setArchive(archiveId);
|
||||
out.add(archiveRequest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.decoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.fs.jagex.CompressionType;
|
||||
import net.runelite.cache.protocol.packets.ArchiveResponsePacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ArchiveResponseDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ArchiveResponseDecoder.class);
|
||||
|
||||
private static final int CHUNK_SIZE = 512;
|
||||
|
||||
@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
|
||||
+ 5 // 1 byte compresion type, 4 byte compressed size
|
||||
+ (compression != CompressionType.NONE ? 4 : 0); // compression has leading 4 byte decompressed length
|
||||
|
||||
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;
|
||||
in.skipBytes(3); // skip index/file
|
||||
|
||||
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);
|
||||
|
||||
compressedData.writeBytes(in.readBytes(bytesToRead));
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate how many breaks there are in the file stream. There are
|
||||
* calculateBreaks()+1 total chunks in the file stream
|
||||
*
|
||||
* File contents are sent in 512 byte chunks, with the first byte of
|
||||
* each chunk except for the first one being 0xff.
|
||||
*
|
||||
* The first chunk has an 8 byte header (index, file, compression,
|
||||
* compressed size). So, the first chunk can contain 512 - 8 bytes of
|
||||
* the file, and each chunk after 511 bytes.
|
||||
*
|
||||
* The 'size' parameter has the compression type and size included in
|
||||
* it, since they haven't been read yet by the buffer stream, as
|
||||
* decompress() reads it, so we use 512 - 3 (because 8-5) = 3
|
||||
*/
|
||||
private static int calculateBreaks(int size)
|
||||
{
|
||||
int initialSize = CHUNK_SIZE - 3;
|
||||
if (size <= initialSize)
|
||||
{
|
||||
return 0; // First in the initial chunk, no breaks
|
||||
}
|
||||
int left = size - initialSize;
|
||||
|
||||
if (left % (CHUNK_SIZE - 1) == 0)
|
||||
{
|
||||
return (left / (CHUNK_SIZE - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// / 511 because 511 bytes of the file per chunk.
|
||||
// + 1 if there is some left over, it still needs its
|
||||
// own chunk
|
||||
return (left / (CHUNK_SIZE - 1)) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.decoders;
|
||||
|
||||
import net.runelite.cache.server.CacheFrameDecoder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.protocol.packets.EncryptionPacket;
|
||||
|
||||
public class EncryptionDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
|
||||
{
|
||||
if (in.getByte(in.readerIndex()) != CacheFrameDecoder.ENCRYPTION)
|
||||
{
|
||||
ctx.fireChannelRead(in.retain());
|
||||
return;
|
||||
}
|
||||
|
||||
in.readByte();
|
||||
byte xorKey = in.readByte();
|
||||
in.readShort(); // always 0
|
||||
|
||||
EncryptionPacket encryptionPacket = new EncryptionPacket();
|
||||
encryptionPacket.setKey(xorKey);
|
||||
out.add(encryptionPacket);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.decoders;
|
||||
|
||||
import net.runelite.cache.server.CacheFrameDecoder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.protocol.packets.HandshakePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeType;
|
||||
|
||||
public class HandshakeDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
|
||||
{
|
||||
if (in.getByte(in.readerIndex()) != CacheFrameDecoder.HANDSHAKE_ON_DEMAND)
|
||||
{
|
||||
ctx.fireChannelRead(in.retain());
|
||||
return;
|
||||
}
|
||||
|
||||
byte type = in.readByte();
|
||||
int revision = in.readInt();
|
||||
|
||||
HandshakePacket handshakePacket = new HandshakePacket();
|
||||
handshakePacket.setType(HandshakeType.of(type));
|
||||
handshakePacket.setRevision(revision);
|
||||
out.add(handshakePacket);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.decoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponsePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponseType;
|
||||
|
||||
public class HandshakeResponseDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
|
||||
{
|
||||
if (in.readableBytes() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
byte response = in.readByte();
|
||||
|
||||
HandshakeResponsePacket handshakeResponse = new HandshakeResponsePacket();
|
||||
handshakeResponse.setResponse(HandshakeResponseType.of(response));
|
||||
out.add(handshakeResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.runelite.cache.protocol.packets.ArchiveRequestPacket;
|
||||
|
||||
public class ArchiveRequestEncoder extends MessageToByteEncoder<ArchiveRequestPacket>
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ArchiveRequestPacket archiveRequest, ByteBuf out) throws Exception
|
||||
{
|
||||
out.writeByte(archiveRequest.isPriority() ? 1 : 0);
|
||||
out.writeByte(archiveRequest.getIndex());
|
||||
out.writeShort(archiveRequest.getArchive());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.runelite.cache.protocol.packets.ArchiveResponsePacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ArchiveResponseEncoder extends MessageToByteEncoder<ArchiveResponsePacket>
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ArchiveResponseEncoder.class);
|
||||
|
||||
private static final int CHUNK_SIZE = 512;
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ArchiveResponsePacket archiveResponse, ByteBuf out) throws Exception
|
||||
{
|
||||
// archive file header
|
||||
// 1 byte index
|
||||
// 2 byte archive
|
||||
out.writeByte(archiveResponse.getIndex());
|
||||
out.writeShort(archiveResponse.getArchive());
|
||||
|
||||
int pos = out.readableBytes();
|
||||
|
||||
// next is the compressed data which starts with compression
|
||||
// type and length
|
||||
ByteBuf file = Unpooled.wrappedBuffer(archiveResponse.getData());
|
||||
// - 3 for the header
|
||||
int chunkSize = Math.min(file.readableBytes(), CHUNK_SIZE - 3);
|
||||
|
||||
out.writeBytes(file.readBytes(chunkSize));
|
||||
|
||||
while (file.isReadable())
|
||||
{
|
||||
out.writeByte(0xff);
|
||||
|
||||
chunkSize = Math.min(file.readableBytes(), CHUNK_SIZE - 1);
|
||||
out.writeBytes(file.readBytes(chunkSize));
|
||||
}
|
||||
|
||||
int size = out.readableBytes() - pos;
|
||||
logger.debug("Wrote index {} archive {} (size {}) in {} bytes",
|
||||
archiveResponse.getIndex(), archiveResponse.getArchive(),
|
||||
archiveResponse.getData().length, size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.runelite.cache.protocol.packets.EncryptionPacket;
|
||||
|
||||
public class EncryptionEncoder extends MessageToByteEncoder<EncryptionPacket>
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, EncryptionPacket encryptionPacket, ByteBuf out) throws Exception
|
||||
{
|
||||
out.writeByte(EncryptionPacket.OPCODE);
|
||||
out.writeByte(encryptionPacket.getKey());
|
||||
out.writeShort(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.runelite.cache.protocol.packets.HandshakePacket;
|
||||
|
||||
public class HandshakeEncoder extends MessageToByteEncoder<HandshakePacket>
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, HandshakePacket handshakePacket, ByteBuf out) throws Exception
|
||||
{
|
||||
out.writeByte(handshakePacket.getType().getValue());
|
||||
out.writeInt(handshakePacket.getRevision());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponsePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponseType;
|
||||
|
||||
public class HandshakeResponseEncoder extends MessageToByteEncoder<HandshakeResponsePacket>
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, HandshakeResponsePacket handshakeResponse, ByteBuf out) throws Exception
|
||||
{
|
||||
HandshakeResponseType handshakeResponseType = handshakeResponse.getResponse();
|
||||
out.writeByte(handshakeResponseType.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class XorEncoder extends MessageToByteEncoder<ByteBuf>
|
||||
{
|
||||
private byte key;
|
||||
|
||||
public byte getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(byte key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception
|
||||
{
|
||||
if (key == 0)
|
||||
{
|
||||
out.writeBytes(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
while (msg.isReadable())
|
||||
{
|
||||
out.writeByte(msg.readByte() ^ key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public class ArchiveRequestPacket
|
||||
{
|
||||
private boolean priority;
|
||||
private int index;
|
||||
private int archive;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ArchiveRequestPacket{" + "priority=" + priority + ", index=" + index + ", archive=" + archive + '}';
|
||||
}
|
||||
|
||||
public boolean isPriority()
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(boolean priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getArchive()
|
||||
{
|
||||
return archive;
|
||||
}
|
||||
|
||||
public void setArchive(int archive)
|
||||
{
|
||||
this.archive = archive;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public class ArchiveResponsePacket
|
||||
{
|
||||
private int index;
|
||||
private int archive;
|
||||
private byte[] data;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ArchiveResponsePacket{" + "index=" + index + ", archive=" + archive + ", data=" + data + '}';
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getArchive()
|
||||
{
|
||||
return archive;
|
||||
}
|
||||
|
||||
public void setArchive(int archive)
|
||||
{
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
public byte[] getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public class EncryptionPacket
|
||||
{
|
||||
public static final int OPCODE = 4;
|
||||
|
||||
private byte key;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "EncryptionPacket{" + "key=" + key + '}';
|
||||
}
|
||||
|
||||
public byte getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(byte key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public class HandshakePacket
|
||||
{
|
||||
private HandshakeType type;
|
||||
private int revision;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "HandshakePacket{" + "type=" + type + ", revision=" + revision + '}';
|
||||
}
|
||||
|
||||
public HandshakeType getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(HandshakeType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
public void setRevision(int revision)
|
||||
{
|
||||
this.revision = revision;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public class HandshakeResponsePacket
|
||||
{
|
||||
private HandshakeResponseType response;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "HandshakeResponsePacket{" + "response=" + response + '}';
|
||||
}
|
||||
|
||||
public HandshakeResponseType getResponse()
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(HandshakeResponseType response)
|
||||
{
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public enum HandshakeResponseType
|
||||
{
|
||||
RESPONSE_OK(0),
|
||||
ACCOUNT_DISABLED(4),
|
||||
ACCOUNT_ONLINE(5),
|
||||
RESPONSE_OUTDATED(6),
|
||||
WORLD_FULL(7),
|
||||
SERVER_OFFLINE(8),
|
||||
LIMITED_EXCEEDED(9),
|
||||
BAD_SESSION_ID(10),
|
||||
ACCOUNT_HIJACK(11),
|
||||
MEMBERS_WORLD(12),
|
||||
COULD_NOT_COMPLETE_LOGIN(13),
|
||||
SERVER_BEING_UPDATED(14),
|
||||
TOO_MANY_ATTEMPTS(16),
|
||||
MEMBERS_ONLY_AREA(17),
|
||||
ACCOUNT_LOCKED(18),
|
||||
CLOSED_BETA(19),
|
||||
INVALID_LOGINSERVER(20),
|
||||
MALFORMED_PACKET(22),
|
||||
NO_REPLY_FROM_LOGINSERVER(23),
|
||||
ERR_LOADING_PROFILE(24),
|
||||
UNEXPECTED_LOGINSERVER_RESPONSE(25),
|
||||
IP_BANNED(26),
|
||||
SERVICE_UNAVAILABLE(27),
|
||||
NO_DISPLAY_NAME(31),
|
||||
BILLING_ERROR(32),
|
||||
ACCOUNT_INACCESSABLE(37),
|
||||
VOTE_TO_PLAY(38),
|
||||
NOT_ELIGIBLE(55),
|
||||
NEED_AUTHENTICATOR(56),
|
||||
AUTHENTICATOR_CODE_WRONG(57);
|
||||
|
||||
private final byte value;
|
||||
|
||||
private HandshakeResponseType(int value)
|
||||
{
|
||||
this.value = (byte) value;
|
||||
}
|
||||
|
||||
public byte getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public static HandshakeResponseType of(byte value)
|
||||
{
|
||||
for (HandshakeResponseType type : values())
|
||||
{
|
||||
if (type.value == value)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package net.runelite.cache.protocol.packets;
|
||||
|
||||
public enum HandshakeType
|
||||
{
|
||||
ON_DEMAND(15);
|
||||
|
||||
private final byte value;
|
||||
|
||||
private HandshakeType(int value)
|
||||
{
|
||||
this.value = (byte) value;
|
||||
}
|
||||
|
||||
public byte getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public static HandshakeType of(byte value)
|
||||
{
|
||||
for (HandshakeType type : values())
|
||||
{
|
||||
if (type.value == value)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import net.runelite.cache.fs.Archive;
|
||||
import net.runelite.cache.fs.Container;
|
||||
import net.runelite.cache.fs.Index;
|
||||
import net.runelite.cache.fs.Storage;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import net.runelite.cache.fs.jagex.CompressionType;
|
||||
import net.runelite.cache.fs.jagex.DiskStorage;
|
||||
import net.runelite.cache.protocol.packets.ArchiveRequestPacket;
|
||||
import net.runelite.cache.protocol.packets.ArchiveResponsePacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ArchiveRequestHandler extends SimpleChannelInboundHandler<ArchiveRequestPacket>
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ArchiveRequestHandler.class);
|
||||
|
||||
private final Store store;
|
||||
|
||||
public ArchiveRequestHandler(Store store)
|
||||
{
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, ArchiveRequestPacket archiveRequest) throws Exception
|
||||
{
|
||||
if (archiveRequest.getIndex() == 255)
|
||||
{
|
||||
handleRequest255(ctx, archiveRequest.getIndex(),
|
||||
archiveRequest.getArchive());
|
||||
}
|
||||
else
|
||||
{
|
||||
handleRequest(ctx, archiveRequest.getIndex(),
|
||||
archiveRequest.getArchive());
|
||||
}
|
||||
}
|
||||
|
||||
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 = Unpooled.buffer(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()));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
byte[] packed = storage.loadArchive(archive); // is compressed, includes length and type
|
||||
|
||||
if (packed == null)
|
||||
{
|
||||
logger.warn("Missing archive {}/{}", index, archiveId);
|
||||
return; // is it possible to notify the client of an error with this?
|
||||
}
|
||||
|
||||
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 = 1 // compression type
|
||||
+ 4 // compressed size
|
||||
+ compressedSize
|
||||
+ (compression != CompressionType.NONE ? 4 : 0);
|
||||
if (packed.length != expectedSize)
|
||||
{
|
||||
// It may have the archive revision appended at the end.
|
||||
// The data the client writes will have it, but the data fetched from
|
||||
// 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);
|
||||
}
|
||||
|
||||
private byte[] compress(int compression, byte[] data) throws IOException
|
||||
{
|
||||
Container container = new Container(compression, -1);
|
||||
container.compress(data, null);
|
||||
return container.data;
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.protocol.packets.EncryptionPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CacheFrameDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(CacheFrameDecoder.class);
|
||||
|
||||
public static final int ARCHIVE_REQUEST_LOW = 0;
|
||||
public static final int ARCHIVE_REQUEST_HIGH = 1;
|
||||
public static final int ENCRYPTION = EncryptionPacket.OPCODE;
|
||||
public static final int HANDSHAKE_ON_DEMAND = 15;
|
||||
|
||||
private ClientState state = ClientState.HANDSHAKING;
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
|
||||
{
|
||||
in.markReaderIndex();
|
||||
byte opcode = in.readByte();
|
||||
in.resetReaderIndex();
|
||||
|
||||
int length;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case HANDSHAKE_ON_DEMAND:
|
||||
length = 5;
|
||||
|
||||
if (state != ClientState.HANDSHAKING)
|
||||
{
|
||||
ctx.close();
|
||||
return;
|
||||
}
|
||||
state = ClientState.CONNECTED;
|
||||
break;
|
||||
case ARCHIVE_REQUEST_LOW:
|
||||
case ARCHIVE_REQUEST_HIGH:
|
||||
case ENCRYPTION:
|
||||
length = 4;
|
||||
|
||||
if (state != ClientState.CONNECTED)
|
||||
{
|
||||
ctx.close();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.debug("Unknown packet opcode from {}: {}",
|
||||
ctx.channel().remoteAddress(), opcode);
|
||||
ctx.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (in.readableBytes() < length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf packet = in.readRetainedSlice(length);
|
||||
out.add(packet);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
import net.runelite.cache.protocol.decoders.HandshakeDecoder;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.runelite.cache.protocol.decoders.ArchiveRequestDecoder;
|
||||
import net.runelite.cache.protocol.decoders.EncryptionDecoder;
|
||||
import net.runelite.cache.protocol.encoders.ArchiveResponseEncoder;
|
||||
import net.runelite.cache.protocol.encoders.HandshakeResponseEncoder;
|
||||
import net.runelite.cache.protocol.encoders.XorEncoder;
|
||||
|
||||
public class CacheServerInitializer extends ChannelInitializer<SocketChannel>
|
||||
{
|
||||
private final CacheServer server;
|
||||
|
||||
public CacheServerInitializer(CacheServer server)
|
||||
{
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception
|
||||
{
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
|
||||
p.addLast(
|
||||
new CacheFrameDecoder(),
|
||||
new HandshakeDecoder(),
|
||||
new EncryptionDecoder(),
|
||||
new ArchiveRequestDecoder()
|
||||
);
|
||||
|
||||
p.addLast(
|
||||
new HandshakeResponseEncoder(),
|
||||
new XorEncoder(),
|
||||
new ArchiveResponseEncoder()
|
||||
);
|
||||
|
||||
p.addLast(
|
||||
new ArchiveRequestHandler(server.getStore()),
|
||||
new EncryptionHandler(),
|
||||
new HandshakeHandler(server)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
public enum ClientState
|
||||
{
|
||||
HANDSHAKING,
|
||||
CONNECTED
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import net.runelite.cache.protocol.encoders.XorEncoder;
|
||||
import net.runelite.cache.protocol.packets.EncryptionPacket;
|
||||
|
||||
public class EncryptionHandler extends SimpleChannelInboundHandler<EncryptionPacket>
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, EncryptionPacket encryptionPacket) throws Exception
|
||||
{
|
||||
ChannelPipeline p = ctx.pipeline();
|
||||
XorEncoder xorEncoder = p.get(XorEncoder.class);
|
||||
if (xorEncoder != null)
|
||||
{
|
||||
xorEncoder.setKey(encryptionPacket.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import net.runelite.cache.protocol.packets.HandshakePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponsePacket;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponseType;
|
||||
import net.runelite.cache.protocol.packets.HandshakeType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HandshakeHandler extends SimpleChannelInboundHandler<HandshakePacket>
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(HandshakeHandler.class);
|
||||
|
||||
private final CacheServer server;
|
||||
|
||||
public HandshakeHandler(CacheServer server)
|
||||
{
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, HandshakePacket handshakePacket) throws Exception
|
||||
{
|
||||
if (handshakePacket.getType() != HandshakeType.ON_DEMAND)
|
||||
{
|
||||
logger.warn("Expected handshake type ON_DEMAND");
|
||||
ctx.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (handshakePacket.getRevision() != server.getRevision())
|
||||
{
|
||||
logger.warn("Incorrect version for client {}, expected {}",
|
||||
handshakePacket.getRevision(), server.getRevision());
|
||||
ctx.close();
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Handshake complete from client {}, type {}, revision {}",
|
||||
ctx.channel().remoteAddress(), handshakePacket.getType(),
|
||||
handshakePacket.getRevision());
|
||||
|
||||
HandshakeResponsePacket handshakeResponse = new HandshakeResponsePacket();
|
||||
handshakeResponse.setResponse(HandshakeResponseType.RESPONSE_OK);
|
||||
ctx.channel().writeAndFlush(handshakeResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.client;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.runelite.cache.CacheProperties;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import net.runelite.cache.protocol.packets.HandshakeResponseType;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.impl.SimpleLogger;
|
||||
|
||||
public class CacheClientTest
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(CacheClientTest.class);
|
||||
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "TRACE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void test() throws Exception
|
||||
{
|
||||
try (Store store = new Store(new File("D:\\rs\\07\\temp\\cache")))
|
||||
{
|
||||
store.load();
|
||||
|
||||
CacheClient c = new CacheClient(store, CacheProperties.getRsVersion());
|
||||
c.connect();
|
||||
CompletableFuture<HandshakeResponseType> handshake = c.handshake();
|
||||
|
||||
HandshakeResponseType result = handshake.get();
|
||||
logger.info("Handshake result: {}", result);
|
||||
|
||||
Assert.assertEquals(HandshakeResponseType.RESPONSE_OK, result);
|
||||
|
||||
c.download();
|
||||
|
||||
c.close();
|
||||
|
||||
store.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import net.runelite.cache.fs.Container;
|
||||
import net.runelite.cache.fs.jagex.CompressionType;
|
||||
import net.runelite.cache.fs.jagex.DataFile;
|
||||
import net.runelite.cache.protocol.decoders.ArchiveResponseDecoder;
|
||||
import net.runelite.cache.protocol.packets.ArchiveResponsePacket;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ArchiveResponseEncoderTest
|
||||
{
|
||||
@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;//DataFile.compress(data, CompressionType.NONE, -1, null);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.protocol.encoders;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class XorEncoderTest
|
||||
{
|
||||
@Test
|
||||
public void testEncode() throws Exception
|
||||
{
|
||||
ByteBuf buf = Unpooled.buffer(1);
|
||||
buf.markWriterIndex();
|
||||
buf.writeByte(0xff);
|
||||
|
||||
XorEncoder encoder = new XorEncoder();
|
||||
encoder.setKey((byte) 0x1);
|
||||
|
||||
ByteBuf out = Unpooled.buffer(1);
|
||||
encoder.encode(null, buf, out);
|
||||
|
||||
byte encoded = out.readByte();
|
||||
Assert.assertEquals((Byte) (byte) 0xfe, (Byte) encoded);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache.server;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import net.runelite.cache.StoreLocation;
|
||||
import net.runelite.cache.client.CacheClient;
|
||||
import net.runelite.cache.fs.Archive;
|
||||
import net.runelite.cache.fs.Container;
|
||||
import net.runelite.cache.fs.Index;
|
||||
import net.runelite.cache.fs.Storage;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import net.runelite.cache.index.FileData;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
public class CacheServerTest
|
||||
{
|
||||
private static final String HOST = "localhost";
|
||||
private static final int REVISION = 154;
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder folder = StoreLocation.getTemporaryFolder();
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDownload() throws Exception
|
||||
{
|
||||
try (Store store = new Store(StoreLocation.LOCATION);
|
||||
CacheServer server = new CacheServer(store, REVISION))
|
||||
{
|
||||
store.load();
|
||||
|
||||
server.start();
|
||||
|
||||
try (CacheClient client = new CacheClient(new Store(folder.newFolder()), HOST, REVISION))
|
||||
{
|
||||
client.connect();
|
||||
client.handshake().get();
|
||||
client.download();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServer() throws Exception
|
||||
{
|
||||
try (Store store = new Store(folder.newFolder());
|
||||
CacheServer server = new CacheServer(store, REVISION))
|
||||
{
|
||||
addInitialFilesToStore(store);
|
||||
|
||||
store.save();
|
||||
|
||||
server.start();
|
||||
|
||||
try (Store store2 = new Store(folder.newFolder());
|
||||
CacheClient client = new CacheClient(store2, HOST, REVISION))
|
||||
{
|
||||
client.connect();
|
||||
client.handshake().get();
|
||||
client.download();
|
||||
|
||||
Index index = store2.findIndex(0);
|
||||
Archive archive = index.getArchive(0);
|
||||
|
||||
FileData[] files = archive.getFileData();
|
||||
FileData file = files[0];
|
||||
assertEquals(7, file.getNameHash());
|
||||
|
||||
Storage storage = store2.getStorage();
|
||||
byte[] data = storage.loadArchive(archive);
|
||||
data = archive.decompress(data);
|
||||
assertArrayEquals("test".getBytes(), data);
|
||||
assertEquals(store.getIndexes().get(0).getArchive(0).getCrc(), archive.getCrc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addInitialFilesToStore(Store store) throws FileNotFoundException, IOException
|
||||
{
|
||||
Storage storage = store.getStorage();
|
||||
Index index = store.addIndex(0);
|
||||
|
||||
Archive archive = index.addArchive(0);
|
||||
FileData[] files = new FileData[1];
|
||||
archive.setFileData(files);
|
||||
FileData file = files[0] = new FileData();
|
||||
file.setNameHash(7);
|
||||
byte[] data = "test".getBytes();
|
||||
|
||||
Container container = new Container(archive.getCompression(), -1);
|
||||
container.compress(data, null);
|
||||
byte[] compressedData = container.data;
|
||||
storage.saveArchive(archive, compressedData);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user