/* 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 import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.KotlinModule import mdnet.ServerHandlerJackson.auto import mdnet.logging.info import mdnet.settings.DevSettings import mdnet.settings.RemoteSettings import mdnet.settings.ServerSettings import org.apache.hc.client5.http.impl.DefaultSchemePortResolver import org.apache.hc.client5.http.impl.classic.HttpClients import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner import org.apache.hc.core5.http.HttpHost import org.apache.hc.core5.http.protocol.HttpContext import org.http4k.client.ApacheClient 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 import java.net.InetAddress object ServerHandlerJackson : ConfigurableJackson( KotlinModule() .asConfigurable() .withStandardMappings() .done() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) ) class BackendApi( private val serverSettings: ServerSettings, private val devSettings: DevSettings, private val maxCacheSizeInMebibytes: Long ) { private val client = ApacheClient( client = HttpClients.custom() .setRoutePlanner( object : DefaultRoutePlanner(DefaultSchemePortResolver()) { override fun determineLocalAddress(firstHop: HttpHost?, context: HttpContext?): InetAddress { return InetAddress.getByName(serverSettings.hostname) } } ) .build() ) fun logoutFromControl(): Boolean { LOGGER.info { "Disconnecting from the control server" } val params = mapOf( "secret" to serverSettings.secret ) 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.secret, "port" to let { if (serverSettings.externalPort != 0) { serverSettings.externalPort } else { serverSettings.port } }, "disk_space" to maxCacheSizeInMebibytes * 1024 * 1024, "network_speed" to serverSettings.externalMaxKilobitsPerSecond * 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 devSettings.devUrl ?: SERVER_ADDRESS } companion object { private val LOGGER = LoggerFactory.getLogger(BackendApi::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/" } }