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:
71
cache-client/pom.xml
Normal file
71
cache-client/pom.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>runelite-parent</artifactId>
|
||||
<version>1.2.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>cache-client</artifactId>
|
||||
<name>Cache Client</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>cache</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>protocol</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.runelite</groupId>
|
||||
<artifactId>cache</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
48
cache-client/src/main/java/net/runelite/cache/client/ArchiveResponseHandler.java
vendored
Normal file
48
cache-client/src/main/java/net/runelite/cache/client/ArchiveResponseHandler.java
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.protocol.api.update.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());
|
||||
}
|
||||
|
||||
}
|
||||
454
cache-client/src/main/java/net/runelite/cache/client/CacheClient.java
vendored
Normal file
454
cache-client/src/main/java/net/runelite/cache/client/CacheClient.java
vendored
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* 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.protocol.update.decoders.HandshakeResponseDecoder;
|
||||
import net.runelite.protocol.update.encoders.ArchiveRequestEncoder;
|
||||
import net.runelite.protocol.update.encoders.EncryptionEncoder;
|
||||
import net.runelite.protocol.api.update.ArchiveRequestPacket;
|
||||
import net.runelite.protocol.api.login.HandshakeResponseType;
|
||||
import net.runelite.cache.util.Crc32;
|
||||
import net.runelite.protocol.api.handshake.UpdateHandshakePacket;
|
||||
import net.runelite.protocol.handshake.UpdateHandshakeEncoder;
|
||||
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 UpdateHandshakeEncoder(),
|
||||
new EncryptionEncoder(),
|
||||
new ArchiveRequestEncoder()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Start the client.
|
||||
ChannelFuture f = b.connect(host, PORT).syncUninterruptibly();
|
||||
channel = f.channel();
|
||||
}
|
||||
|
||||
public CompletableFuture<HandshakeResponseType> handshake()
|
||||
{
|
||||
UpdateHandshakePacket handshakePacket = new UpdateHandshakePacket();
|
||||
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);
|
||||
}
|
||||
}
|
||||
49
cache-client/src/main/java/net/runelite/cache/client/CacheClientHandler.java
vendored
Normal file
49
cache-client/src/main/java/net/runelite/cache/client/CacheClientHandler.java
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
31
cache-client/src/main/java/net/runelite/cache/client/ClientState.java
vendored
Normal file
31
cache-client/src/main/java/net/runelite/cache/client/ClientState.java
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
33
cache-client/src/main/java/net/runelite/cache/client/DownloadWatcher.java
vendored
Normal file
33
cache-client/src/main/java/net/runelite/cache/client/DownloadWatcher.java
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
92
cache-client/src/main/java/net/runelite/cache/client/FileResult.java
vendored
Normal file
92
cache-client/src/main/java/net/runelite/cache/client/FileResult.java
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
80
cache-client/src/main/java/net/runelite/cache/client/HandshakeResponseHandler.java
vendored
Normal file
80
cache-client/src/main/java/net/runelite/cache/client/HandshakeResponseHandler.java
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.protocol.update.decoders.ArchiveResponseDecoder;
|
||||
import net.runelite.protocol.api.update.EncryptionPacket;
|
||||
import net.runelite.protocol.api.handshake.HandshakeResponsePacket;
|
||||
import net.runelite.protocol.api.login.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());
|
||||
}
|
||||
|
||||
}
|
||||
101
cache-client/src/main/java/net/runelite/cache/client/IndexInfo.java
vendored
Normal file
101
cache-client/src/main/java/net/runelite/cache/client/IndexInfo.java
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
56
cache-client/src/main/java/net/runelite/cache/client/PendingFileRequest.java
vendored
Normal file
56
cache-client/src/main/java/net/runelite/cache/client/PendingFileRequest.java
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
74
cache-client/src/test/java/net/runelite/cache/client/CacheClientTest.java
vendored
Normal file
74
cache-client/src/test/java/net/runelite/cache/client/CacheClientTest.java
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.protocol.api.login.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user