From 29693a39cfeb1ed2a9145ff16ebe929204972579 Mon Sep 17 00:00:00 2001 From: Graham Date: Tue, 25 May 2021 22:40:02 +0100 Subject: [PATCH] Add timeout support for all services on the RS2 port Signed-off-by: Graham --- .../org/openrs2/game/net/Rs2ChannelInitializer.kt | 12 ++++++++++++ .../main/kotlin/org/openrs2/game/net/http/Http.kt | 1 - .../openrs2/game/net/http/HttpChannelInitializer.kt | 6 +++++- .../game/net/jaggrab/JaggrabChannelHandler.kt | 7 +++++++ .../org/openrs2/game/net/js5/Js5ChannelHandler.kt | 7 +++++++ .../openrs2/game/net/login/LoginChannelHandler.kt | 10 +++++++--- 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/game/src/main/kotlin/org/openrs2/game/net/Rs2ChannelInitializer.kt b/game/src/main/kotlin/org/openrs2/game/net/Rs2ChannelInitializer.kt index 759a83de53..f49c4341cc 100644 --- a/game/src/main/kotlin/org/openrs2/game/net/Rs2ChannelInitializer.kt +++ b/game/src/main/kotlin/org/openrs2/game/net/Rs2ChannelInitializer.kt @@ -2,10 +2,12 @@ package org.openrs2.game.net import io.netty.channel.Channel import io.netty.channel.ChannelInitializer +import io.netty.handler.timeout.IdleStateHandler import org.openrs2.game.net.login.LoginChannelHandler import org.openrs2.protocol.Protocol import org.openrs2.protocol.Rs2Decoder import org.openrs2.protocol.Rs2Encoder +import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Provider import javax.inject.Singleton @@ -16,9 +18,19 @@ public class Rs2ChannelInitializer @Inject constructor( ) : ChannelInitializer() { override fun initChannel(ch: Channel) { ch.pipeline().addLast( + IdleStateHandler(true, TIMEOUT_SECS, TIMEOUT_SECS, TIMEOUT_SECS, TimeUnit.SECONDS), Rs2Decoder(Protocol.LOGIN_UPSTREAM), Rs2Encoder(Protocol.LOGIN_DOWNSTREAM), handlerProvider.get() ) } + + private companion object { + /* + * On the OSRS servers, login connections take 60 seconds to time out, + * but a JS5 connection only takes 30 seconds. It'd be awkward for us + * to change the timeouts at runtime to fully emulate that behaviour. + */ + private const val TIMEOUT_SECS: Long = 30 + } } diff --git a/game/src/main/kotlin/org/openrs2/game/net/http/Http.kt b/game/src/main/kotlin/org/openrs2/game/net/http/Http.kt index 95aa822f51..13b9f4af0b 100644 --- a/game/src/main/kotlin/org/openrs2/game/net/http/Http.kt +++ b/game/src/main/kotlin/org/openrs2/game/net/http/Http.kt @@ -17,7 +17,6 @@ import org.openrs2.buffer.copiedBuffer import org.openrs2.buffer.use public object Http { - public const val TIMEOUT_SECS: Long = 30 public const val MAX_CONTENT_LENGTH: Int = 65536 public const val TEXT_X_CROSS_DOMAIN_POLICY: String = "text/x-cross-domain-policy" private const val BANNER = "OpenRS2" diff --git a/game/src/main/kotlin/org/openrs2/game/net/http/HttpChannelInitializer.kt b/game/src/main/kotlin/org/openrs2/game/net/http/HttpChannelInitializer.kt index 507c4cc7bc..3b5dbbeb8e 100644 --- a/game/src/main/kotlin/org/openrs2/game/net/http/HttpChannelInitializer.kt +++ b/game/src/main/kotlin/org/openrs2/game/net/http/HttpChannelInitializer.kt @@ -16,11 +16,15 @@ public class HttpChannelInitializer @Inject constructor( ) : ChannelInitializer() { override fun initChannel(ch: Channel) { ch.pipeline().addLast( - IdleStateHandler(true, Http.TIMEOUT_SECS, Http.TIMEOUT_SECS, Http.TIMEOUT_SECS, TimeUnit.SECONDS), + IdleStateHandler(true, TIMEOUT_SECS, TIMEOUT_SECS, TIMEOUT_SECS, TimeUnit.SECONDS), HttpRequestDecoder(), HttpResponseEncoder(), HttpObjectAggregator(Http.MAX_CONTENT_LENGTH), handler ) } + + private companion object { + private const val TIMEOUT_SECS: Long = 30 + } } diff --git a/game/src/main/kotlin/org/openrs2/game/net/jaggrab/JaggrabChannelHandler.kt b/game/src/main/kotlin/org/openrs2/game/net/jaggrab/JaggrabChannelHandler.kt index 72b71df23e..1f3df46025 100644 --- a/game/src/main/kotlin/org/openrs2/game/net/jaggrab/JaggrabChannelHandler.kt +++ b/game/src/main/kotlin/org/openrs2/game/net/jaggrab/JaggrabChannelHandler.kt @@ -4,6 +4,7 @@ import io.netty.channel.ChannelFutureListener import io.netty.channel.ChannelHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler +import io.netty.handler.timeout.IdleStateEvent import org.openrs2.buffer.use import org.openrs2.game.net.FileProvider import org.openrs2.protocol.jaggrab.JaggrabRequest @@ -33,4 +34,10 @@ public class JaggrabChannelHandler @Inject constructor( override fun channelReadComplete(ctx: ChannelHandlerContext) { ctx.flush() } + + override fun userEventTriggered(ctx: ChannelHandlerContext, evt: Any) { + if (evt is IdleStateEvent) { + ctx.close() + } + } } diff --git a/game/src/main/kotlin/org/openrs2/game/net/js5/Js5ChannelHandler.kt b/game/src/main/kotlin/org/openrs2/game/net/js5/Js5ChannelHandler.kt index 7d154c41e4..d3f676ab67 100644 --- a/game/src/main/kotlin/org/openrs2/game/net/js5/Js5ChannelHandler.kt +++ b/game/src/main/kotlin/org/openrs2/game/net/js5/Js5ChannelHandler.kt @@ -2,6 +2,7 @@ package org.openrs2.game.net.js5 import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler +import io.netty.handler.timeout.IdleStateEvent import org.openrs2.protocol.js5.Js5Request import org.openrs2.protocol.js5.XorEncoder import javax.inject.Inject @@ -37,4 +38,10 @@ public class Js5ChannelHandler @Inject constructor( service.notifyIfNotEmpty(client) } } + + override fun userEventTriggered(ctx: ChannelHandlerContext, evt: Any) { + if (evt is IdleStateEvent) { + ctx.close() + } + } } diff --git a/game/src/main/kotlin/org/openrs2/game/net/login/LoginChannelHandler.kt b/game/src/main/kotlin/org/openrs2/game/net/login/LoginChannelHandler.kt index 02684107b8..d55c029a11 100644 --- a/game/src/main/kotlin/org/openrs2/game/net/login/LoginChannelHandler.kt +++ b/game/src/main/kotlin/org/openrs2/game/net/login/LoginChannelHandler.kt @@ -9,7 +9,7 @@ import io.netty.handler.codec.http.HttpObjectAggregator import io.netty.handler.codec.http.HttpRequestDecoder import io.netty.handler.codec.http.HttpResponseEncoder import io.netty.handler.codec.string.StringDecoder -import io.netty.handler.timeout.IdleStateHandler +import io.netty.handler.timeout.IdleStateEvent import org.openrs2.buffer.copiedBuffer import org.openrs2.game.net.crossdomain.CrossDomainChannelHandler import org.openrs2.game.net.http.Http @@ -23,7 +23,6 @@ import org.openrs2.protocol.js5.Js5ResponseEncoder import org.openrs2.protocol.js5.XorDecoder import org.openrs2.protocol.login.LoginRequest import org.openrs2.protocol.login.LoginResponse -import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Provider @@ -77,7 +76,6 @@ public class LoginChannelHandler @Inject constructor( private fun handleInitCrossDomainConnection(ctx: ChannelHandlerContext) { ctx.pipeline().addLast( - IdleStateHandler(true, Http.TIMEOUT_SECS, Http.TIMEOUT_SECS, Http.TIMEOUT_SECS, TimeUnit.SECONDS), HttpRequestDecoder(), HttpResponseEncoder(), HttpObjectAggregator(Http.MAX_CONTENT_LENGTH), @@ -95,6 +93,12 @@ public class LoginChannelHandler @Inject constructor( ctx.flush() } + override fun userEventTriggered(ctx: ChannelHandlerContext, evt: Any) { + if (evt is IdleStateEvent) { + ctx.close() + } + } + private companion object { private const val BUILD = 550 private const val JAGGRAB_MAX_FRAME_LENGTH = 4096