/* Mangadex@Home Copyright (c) 2020, MangaDex Network This file is part of MangaDex@Home. MangaDex@Home is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. MangaDex@Home is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this MangaDex@Home. If not, see . */ package mdnet.base import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.KotlinModule import java.net.InetAddress import mdnet.base.ServerHandlerJackson.auto import mdnet.base.settings.DevSettings import mdnet.base.settings.RemoteSettings import mdnet.base.settings.ServerSettings import org.apache.http.client.config.RequestConfig import org.apache.http.impl.client.HttpClients import org.http4k.client.Apache4Client import org.http4k.core.Body import org.http4k.core.Method import org.http4k.core.Request import org.http4k.format.ConfigurableJackson import org.http4k.format.asConfigurable import org.http4k.format.withStandardMappings import org.slf4j.LoggerFactory object ServerHandlerJackson : ConfigurableJackson( KotlinModule() .asConfigurable() .withStandardMappings() .done() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) ) class ServerHandler(private val serverSettings: ServerSettings, private val devSettings: DevSettings, private val maxCacheSizeInMebibytes: Long) { private val client = Apache4Client(client = HttpClients.custom() .setDefaultRequestConfig( RequestConfig.custom() .apply { if (serverSettings.clientHostname != "0.0.0.0") { setLocalAddress(InetAddress.getByName(serverSettings.clientHostname)) } } .build()) .build()) fun logoutFromControl(): Boolean { LOGGER.info { "Disconnecting from the control server" } val params = mapOf( "secret" to serverSettings.clientSecret ) val request = STRING_ANY_MAP_LENS(params, Request(Method.POST, getServerAddress() + "stop")) val response = client(request) return response.status.successful } private fun getPingParams(tlsCreatedAt: String? = null): Map = mapOf( "secret" to serverSettings.clientSecret, "port" to let { if (serverSettings.clientExternalPort != 0) { serverSettings.clientExternalPort } else { serverSettings.clientPort } }, "disk_space" to maxCacheSizeInMebibytes * 1024 * 1024, "network_speed" to serverSettings.maxKilobitsPerSecond * 1000 / 8, "build_version" to Constants.CLIENT_BUILD ).let { if (tlsCreatedAt != null) { it.plus("tls_created_at" to tlsCreatedAt) } else { it } } fun loginToControl(): RemoteSettings? { LOGGER.info { "Connecting to the control server" } val request = STRING_ANY_MAP_LENS(getPingParams(), Request(Method.POST, getServerAddress() + "ping")) val response = client(request) return if (response.status.successful) { SERVER_SETTINGS_LENS(response) } else { null } } fun pingControl(old: RemoteSettings): RemoteSettings? { LOGGER.info { "Pinging the control server" } val request = STRING_ANY_MAP_LENS(getPingParams(old.tls!!.createdAt), Request(Method.POST, getServerAddress() + "ping")) val response = client(request) return if (response.status.successful) { SERVER_SETTINGS_LENS(response) } else { null } } private fun getServerAddress(): String { return if (!devSettings.isDev) SERVER_ADDRESS else SERVER_ADDRESS_DEV } companion object { private val LOGGER = LoggerFactory.getLogger(ServerHandler::class.java) private val STRING_ANY_MAP_LENS = Body.auto>().toLens() private val SERVER_SETTINGS_LENS = Body.auto().toLens() private const val SERVER_ADDRESS = "https://api.mangadex.network/" private const val SERVER_ADDRESS_DEV = "https://mangadex-test.net/" } }