diff --git a/build.gradle b/build.gradle index 313c79a..6b4c63f 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { } group = "com.mangadex" -version = "1.0.0-rc4" +version = "1.0.0-rc5" mainClassName = "mdnet.base.MangaDexClient" repositories { diff --git a/src/main/kotlin/mdnet/base/Application.kt b/src/main/kotlin/mdnet/base/Application.kt index 4d002df..2703acf 100644 --- a/src/main/kotlin/mdnet/base/Application.kt +++ b/src/main/kotlin/mdnet/base/Application.kt @@ -44,15 +44,22 @@ fun getServer(cache: DiskLruCache, serverSettings: ServerSettings, clientSetting val client = ApacheClient(responseBodyMode = BodyMode.Stream, client = HttpClients.custom() .setDefaultRequestConfig(RequestConfig.custom() .setCookieSpec(CookieSpecs.IGNORE_COOKIES) + .setConnectTimeout(3000) + .setSocketTimeout(3000) + .setConnectionRequestTimeout(3000) .build()) + .setMaxConnTotal(10) .build()) val app = { dataSaver: Boolean -> { request: Request -> - val chapterHash = Path.of("chapterHash")(request) val fileName = Path.of("fileName")(request) + if (LOGGER.isTraceEnabled) { + LOGGER.trace("Request for $chapterHash/$fileName received") + } + val rc4Bytes = if (dataSaver) { md5Bytes("saver$chapterHash.$fileName") } else { @@ -109,21 +116,21 @@ fun getServer(cache: DiskLruCache, serverSettings: ServerSettings, clientSetting if (mdResponse.status != Status.OK) { if (LOGGER.isTraceEnabled) { - LOGGER.trace("Request for $chapterHash/$fileName errored with status {}", mdResponse.status) + LOGGER.trace("Upstream query for $chapterHash/$fileName errored with status {}", mdResponse.status) } mdResponse.close() Response(mdResponse.status) } else { + if (LOGGER.isTraceEnabled) { + LOGGER.trace("Upstream query for $chapterHash/$fileName succeeded") + } + val contentLength = mdResponse.header("Content-Length")!! val contentType = mdResponse.header("Content-Type")!! - - if (LOGGER.isTraceEnabled) { - LOGGER.trace("Grabbing DiskLruCache editor instance") - } - val editor = cache.edit(cacheId) - val lastModified = mdResponse.header("Last-Modified")!! + val editor = cache.edit(cacheId) + // A null editor means that this file is being written to // concurrently so we skip the cache process if (editor != null) { diff --git a/src/main/kotlin/mdnet/base/Netty.kt b/src/main/kotlin/mdnet/base/Netty.kt index 6e18e13..703d3fd 100644 --- a/src/main/kotlin/mdnet/base/Netty.kt +++ b/src/main/kotlin/mdnet/base/Netty.kt @@ -13,6 +13,7 @@ import io.netty.channel.ServerChannel import io.netty.channel.nio.NioEventLoopGroup import io.netty.channel.socket.SocketChannel import io.netty.channel.socket.nio.NioServerSocketChannel +import io.netty.handler.codec.DecoderException import io.netty.handler.codec.http.DefaultFullHttpResponse import io.netty.handler.codec.http.HttpHeaderNames import io.netty.handler.codec.http.HttpObjectAggregator @@ -30,11 +31,15 @@ import org.http4k.core.HttpHandler import org.http4k.server.Http4kChannelHandler import org.http4k.server.Http4kServer import org.http4k.server.ServerConfig +import org.slf4j.LoggerFactory import java.net.InetSocketAddress import java.nio.charset.StandardCharsets import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicReference +import javax.net.ssl.SSLException + +private val LOGGER = LoggerFactory.getLogger("Application") @Sharable class ConnectionCounter : ChannelInboundHandlerAdapter() { @@ -105,6 +110,18 @@ class Netty(private val tls: ServerSettings.TlsCert, private val clientSettings: ch.pipeline().addLast("burstLimiter", burstLimiter) ch.pipeline().addLast("streamer", ChunkedWriteHandler()) ch.pipeline().addLast("handler", Http4kChannelHandler(httpHandler)) + + ch.pipeline().addLast("handle_ssl", object : ChannelInboundHandlerAdapter() { + override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) { + if (cause is SSLException || (cause is DecoderException && cause.cause is SSLException)) { + if (LOGGER.isTraceEnabled) { + LOGGER.trace("Ignored invalid SSL connection") + } + } else { + ctx.fireExceptionCaught(cause) + } + } + }) } }) .option(ChannelOption.SO_BACKLOG, 1000)