Add cross-domain policy support

Required by the most recent versions of the Java plugin (before it was
killed).

Signed-off-by: Graham <gpe@openrs2.org>
Graham 4 years ago
parent 2a6b97480c
commit 92a01b6262
  1. 46
      game/src/main/kotlin/org/openrs2/game/net/crossdomain/CrossDomainChannelHandler.kt
  2. 20
      game/src/main/kotlin/org/openrs2/game/net/http/Http.kt
  3. 16
      game/src/main/kotlin/org/openrs2/game/net/http/HttpChannelHandler.kt
  4. 6
      game/src/main/kotlin/org/openrs2/game/net/http/HttpChannelInitializer.kt
  5. 22
      game/src/main/kotlin/org/openrs2/game/net/login/LoginChannelHandler.kt
  6. 4
      protocol/src/main/kotlin/org/openrs2/protocol/Protocol.kt
  7. 8
      protocol/src/main/kotlin/org/openrs2/protocol/login/InitCrossDomainConnectionCodec.kt
  8. 1
      protocol/src/main/kotlin/org/openrs2/protocol/login/LoginRequest.kt

@ -0,0 +1,46 @@
package org.openrs2.game.net.crossdomain
import io.netty.buffer.Unpooled
import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelHandler
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.codec.http.HttpHeaderNames
import io.netty.handler.codec.http.HttpMethod
import io.netty.handler.codec.http.HttpRequest
import io.netty.handler.codec.http.HttpResponseStatus
import org.openrs2.game.net.http.Http
@ChannelHandler.Sharable
public object CrossDomainChannelHandler : SimpleChannelInboundHandler<HttpRequest>() {
private const val ENDPOINT = "/crossdomain.xml"
private val POLICY = """
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only" />
<allow-access-from domain="*" />
</cross-domain-policy>
""".trimIndent().plus("\n").toByteArray(Charsets.UTF_8)
override fun handlerAdded(ctx: ChannelHandlerContext) {
ctx.read()
}
override fun channelRead0(ctx: ChannelHandlerContext, msg: HttpRequest) {
if (msg.method() != HttpMethod.GET || msg.uri() != ENDPOINT) {
ctx.write(Http.createResponse(HttpResponseStatus.BAD_REQUEST)).addListener(ChannelFutureListener.CLOSE)
return
}
val response = Http.createResponse(HttpResponseStatus.OK)
response.headers().add(HttpHeaderNames.CONTENT_TYPE, Http.TEXT_X_CROSS_DOMAIN_POLICY)
response.headers().add(HttpHeaderNames.CONTENT_LENGTH, POLICY.size)
ctx.write(response, ctx.voidPromise())
ctx.write(Unpooled.wrappedBuffer(POLICY)).addListener(ChannelFutureListener.CLOSE)
}
override fun channelReadComplete(ctx: ChannelHandlerContext) {
ctx.flush()
}
}

@ -0,0 +1,20 @@
package org.openrs2.game.net.http
import io.netty.handler.codec.http.DefaultHttpResponse
import io.netty.handler.codec.http.HttpHeaderNames
import io.netty.handler.codec.http.HttpHeaderValues
import io.netty.handler.codec.http.HttpResponse
import io.netty.handler.codec.http.HttpResponseStatus
import io.netty.handler.codec.http.HttpVersion
public object Http {
public const val MAX_CONTENT_LENGTH: Int = 65536
public const val TEXT_X_CROSS_DOMAIN_POLICY: String = "text/x-cross-domain-policy"
public fun createResponse(status: HttpResponseStatus): HttpResponse {
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, status)
response.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE)
response.headers().add(HttpHeaderNames.SERVER, "OpenRS2")
return response
}
}

@ -4,13 +4,10 @@ import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelHandler
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.codec.http.DefaultHttpResponse
import io.netty.handler.codec.http.HttpHeaderNames
import io.netty.handler.codec.http.HttpHeaderValues
import io.netty.handler.codec.http.HttpRequest
import io.netty.handler.codec.http.HttpResponse
import io.netty.handler.codec.http.HttpResponseStatus
import io.netty.handler.codec.http.HttpVersion
import org.openrs2.game.net.FileProvider
import javax.inject.Inject
import javax.inject.Singleton
@ -27,17 +24,17 @@ public class HttpChannelHandler @Inject constructor(
override fun channelRead0(ctx: ChannelHandlerContext, msg: HttpRequest) {
val uri = msg.uri()
if (!uri.startsWith("/")) {
ctx.write(createResponse(HttpResponseStatus.BAD_REQUEST)).addListener(ChannelFutureListener.CLOSE)
ctx.write(Http.createResponse(HttpResponseStatus.BAD_REQUEST)).addListener(ChannelFutureListener.CLOSE)
return
}
val file = fileProvider.get(uri.substring(1))
if (file == null) {
ctx.write(createResponse(HttpResponseStatus.NOT_FOUND)).addListener(ChannelFutureListener.CLOSE)
ctx.write(Http.createResponse(HttpResponseStatus.NOT_FOUND)).addListener(ChannelFutureListener.CLOSE)
return
}
val response = createResponse(HttpResponseStatus.OK)
val response = Http.createResponse(HttpResponseStatus.OK)
response.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_OCTET_STREAM)
response.headers().add(HttpHeaderNames.CONTENT_LENGTH, file.count())
@ -48,11 +45,4 @@ public class HttpChannelHandler @Inject constructor(
override fun channelReadComplete(ctx: ChannelHandlerContext) {
ctx.flush()
}
private fun createResponse(status: HttpResponseStatus): HttpResponse {
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, status)
response.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE)
response.headers().add(HttpHeaderNames.SERVER, "OpenRS2")
return response
}
}

@ -16,12 +16,8 @@ public class HttpChannelInitializer @Inject constructor(
ch.pipeline().addLast(
HttpRequestDecoder(),
HttpResponseEncoder(),
HttpObjectAggregator(MAX_CONTENT_LENGTH),
HttpObjectAggregator(Http.MAX_CONTENT_LENGTH),
handler
)
}
private companion object {
private const val MAX_CONTENT_LENGTH = 65536
}
}

@ -5,8 +5,13 @@ import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.codec.DelimiterBasedFrameDecoder
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 org.openrs2.buffer.copiedBuffer
import org.openrs2.game.net.crossdomain.CrossDomainChannelHandler
import org.openrs2.game.net.http.Http
import org.openrs2.game.net.jaggrab.JaggrabChannelHandler
import org.openrs2.game.net.js5.Js5ChannelHandler
import org.openrs2.protocol.Rs2Decoder
@ -32,6 +37,7 @@ public class LoginChannelHandler @Inject constructor(
when (msg) {
is LoginRequest.InitJs5RemoteConnection -> handleInitJs5RemoteConnection(ctx, msg)
is LoginRequest.InitJaggrabConnection -> handleInitJaggrabConnection(ctx)
is LoginRequest.InitCrossDomainConnection -> handleInitCrossDomainConnection(ctx)
}
}
@ -67,6 +73,21 @@ public class LoginChannelHandler @Inject constructor(
ctx.pipeline().remove(this)
}
private fun handleInitCrossDomainConnection(ctx: ChannelHandlerContext) {
ctx.pipeline().addLast(
HttpRequestDecoder(),
HttpResponseEncoder(),
HttpObjectAggregator(Http.MAX_CONTENT_LENGTH),
CrossDomainChannelHandler
)
ctx.fireChannelRead(Unpooled.wrappedBuffer(G))
ctx.pipeline().remove(Rs2Decoder::class.java)
ctx.pipeline().remove(Rs2Encoder::class.java)
ctx.pipeline().remove(this)
}
override fun channelReadComplete(ctx: ChannelHandlerContext) {
ctx.flush()
}
@ -75,5 +96,6 @@ public class LoginChannelHandler @Inject constructor(
private const val BUILD = 550
private const val JAGGRAB_MAX_FRAME_LENGTH = 4096
private val JAGGRAB_DELIMITER = Unpooled.unreleasableBuffer(copiedBuffer("\n\n"))
private val G = byteArrayOf('G'.code.toByte())
}
}

@ -1,6 +1,7 @@
package org.openrs2.protocol
import org.openrs2.protocol.login.ClientOutOfDateCodec
import org.openrs2.protocol.login.InitCrossDomainConnectionCodec
import org.openrs2.protocol.login.InitJaggrabConnectionCodec
import org.openrs2.protocol.login.InitJs5RemoteConnectionCodec
import org.openrs2.protocol.login.IpLimitCodec
@ -32,7 +33,8 @@ public class Protocol(vararg codecs: PacketCodec<*>) {
public val LOGIN_UPSTREAM: Protocol = Protocol(
InitJs5RemoteConnectionCodec,
InitJaggrabConnectionCodec,
RequestWorldListCodec
RequestWorldListCodec,
InitCrossDomainConnectionCodec
)
public val LOGIN_DOWNSTREAM: Protocol = Protocol(
Js5OkCodec,

@ -0,0 +1,8 @@
package org.openrs2.protocol.login
import org.openrs2.protocol.EmptyPacketCodec
public object InitCrossDomainConnectionCodec : EmptyPacketCodec<LoginRequest.InitCrossDomainConnection>(
opcode = 'G'.code,
packet = LoginRequest.InitCrossDomainConnection
)

@ -6,4 +6,5 @@ public sealed class LoginRequest : Packet {
public data class InitJs5RemoteConnection(public val build: Int) : LoginRequest()
public object InitJaggrabConnection : LoginRequest()
public data class RequestWorldList(public val checksum: Int) : LoginRequest()
public object InitCrossDomainConnection : LoginRequest()
}

Loading…
Cancel
Save