diff --git a/cache/src/main/java/net/runelite/cache/downloader/CacheClient.java b/cache/src/main/java/net/runelite/cache/downloader/CacheClient.java index eea35d418a..e77fdfb851 100644 --- a/cache/src/main/java/net/runelite/cache/downloader/CacheClient.java +++ b/cache/src/main/java/net/runelite/cache/downloader/CacheClient.java @@ -22,7 +22,6 @@ * (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.downloader; import com.google.common.base.Stopwatch; @@ -44,7 +43,9 @@ import java.util.ArrayDeque; import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import net.runelite.cache.downloader.requests.ConnectionInfo; import net.runelite.cache.downloader.requests.FileRequest; +import net.runelite.cache.downloader.requests.HelloHandshake; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Store; @@ -58,14 +59,17 @@ public class CacheClient private static final String HOST = "oldschool1.runescape.com"; private static final int PORT = 43594; - private static final int CLIENT_REVISION = 135; + private static final int CLIENT_REVISION = 138; - private Store store; // store cache will be written to - private int clientRevision; + private final Store store; // store cache will be written to + private final int clientRevision; + + private ClientState state; private EventLoopGroup group = new NioEventLoopGroup(1); private Channel channel; + private CompletableFuture handshakeFuture; private Queue requests = new ArrayDeque<>(); public CacheClient(Store store) @@ -101,7 +105,52 @@ public class CacheClient channel = f.channel(); } - public void stop() + public CompletableFuture handshake() + { + HelloHandshake msg = new HelloHandshake(); + msg.setRevision(getClientRevision()); + + ByteBuf message = Unpooled.buffer(5); + message.writeByte(msg.getType()); // handshake type + message.writeInt(msg.getRevision()); // client revision + + state = ClientState.HANDSHAKING; + channel.writeAndFlush(message); + + logger.info("Sent handshake with revision {}", msg.getRevision()); + + assert handshakeFuture == null; + handshakeFuture = new CompletableFuture<>(); + + return handshakeFuture; + } + + public void onHandshake(int response) + { + assert handshakeFuture != null; + + handshakeFuture.complete(response); + + if (response != HelloHandshake.RESPONSE_OK) + { + close(); + return; + } + + // Send connection info + ConnectionInfo cinfo = new ConnectionInfo(); + ByteBuf outbuf = Unpooled.buffer(4); + outbuf.writeByte(cinfo.getType()); + outbuf.writeMedium(cinfo.getPadding()); + + channel.writeAndFlush(outbuf); + + state = ClientState.CONNECTED; + + logger.info("Client is now connected!"); + } + + public void close() { channel.close().syncUninterruptibly(); group.shutdownGracefully(); @@ -112,13 +161,18 @@ public class CacheClient return clientRevision; } + public ClientState getState() + { + return state; + } + public void download() throws InterruptedException, ExecutionException, FileNotFoundException, IOException { Stopwatch stopwatch = Stopwatch.createStarted(); FileResult result = requestFile(255, 255).get(); result.decompress(null); - + ByteBuf buffer = Unpooled.wrappedBuffer(result.getContents()); int indexCount = result.getContents().length / 8; @@ -211,6 +265,11 @@ public class CacheClient public synchronized CompletableFuture requestFile(int index, int fileId) { + if (state != ClientState.CONNECTED) + { + throw new IllegalStateException("Can't request files until connected!"); + } + ByteBuf buf = Unpooled.buffer(4); FileRequest request = new FileRequest(index, fileId); CompletableFuture future = new CompletableFuture<>(); diff --git a/cache/src/main/java/net/runelite/cache/downloader/CacheClientHandler.java b/cache/src/main/java/net/runelite/cache/downloader/CacheClientHandler.java index 6dc55b9627..252fe8a4df 100644 --- a/cache/src/main/java/net/runelite/cache/downloader/CacheClientHandler.java +++ b/cache/src/main/java/net/runelite/cache/downloader/CacheClientHandler.java @@ -30,7 +30,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; -import net.runelite.cache.downloader.requests.ConnectionInfo; import net.runelite.cache.downloader.requests.HelloHandshake; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,38 +38,22 @@ public class CacheClientHandler extends ChannelInboundHandlerAdapter { private static final Logger logger = LoggerFactory.getLogger(CacheClientHandler.class); - private CacheClient client; - private ClientState state; - private ByteBuf buffer = Unpooled.buffer(512); + private final CacheClient client; + private final ByteBuf buffer = Unpooled.buffer(512); public CacheClientHandler(CacheClient client) { this.client = client; } - @Override - public void channelActive(ChannelHandlerContext ctx) - { - HelloHandshake msg = new HelloHandshake(); - msg.setRevision(client.getClientRevision()); - - ByteBuf message = Unpooled.buffer(5); - message.writeByte(msg.getType()); // handshake type - message.writeInt(msg.getRevision()); // client revision - - ctx.writeAndFlush(message); - - logger.info("Sent handshake with revision {}", msg.getRevision()); - - state = ClientState.HANDSHAKING; - } - @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf inbuf = (ByteBuf) msg; buffer.writeBytes(inbuf); + ClientState state = client.getState(); + if (state == ClientState.HANDSHAKING) { int response = buffer.readByte(); @@ -83,18 +66,9 @@ public class CacheClientHandler extends ChannelInboundHandlerAdapter logger.warn("Client version is outdated"); else logger.warn("Handshake response error {}", response); - - ctx.close(); - return; } - ConnectionInfo cinfo = new ConnectionInfo(); - ByteBuf outbuf = Unpooled.buffer(4); - outbuf.writeByte(cinfo.getType()); - outbuf.writeMedium(cinfo.getPadding()); - - ctx.writeAndFlush(outbuf); - state = ClientState.CONNECTED; + client.onHandshake(response); } else if (state == ClientState.CONNECTED) { @@ -210,7 +184,7 @@ public class CacheClientHandler extends ChannelInboundHandlerAdapter public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. - cause.printStackTrace(); + logger.warn(null, cause); ctx.close(); } } diff --git a/cache/src/test/java/net/runelite/cache/downloader/CacheClientTest.java b/cache/src/test/java/net/runelite/cache/downloader/CacheClientTest.java index f5dc8665a6..ab38a20fce 100644 --- a/cache/src/test/java/net/runelite/cache/downloader/CacheClientTest.java +++ b/cache/src/test/java/net/runelite/cache/downloader/CacheClientTest.java @@ -22,18 +22,23 @@ * (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.downloader; import java.io.File; +import java.util.concurrent.CompletableFuture; import net.runelite.cache.fs.Store; +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() { @@ -49,24 +54,16 @@ public class CacheClientTest CacheClient c = new CacheClient(store); c.connect(); + CompletableFuture handshake = c.handshake(); -// c.requestFile(0, 205).get(); -// c.requestFile(3, 278).get(); -// c.requestFile(3, 127).get(); -// c.requestFile(0, 1210).get(); + Integer result = handshake.get(); + logger.info("Handshake result: {}", result); -// c.requestFile(255, 255).get(); -// c.requestFile(255, 2).get(); - -// c.requestFile(4, 2047); - -// c.requestFile(6, 546); - -// c.requestFile(255, 6).get(); + Assert.assertEquals(0, (int) result); c.download(); - c.stop(); + c.close(); store.save(); }