mirror of
https://github.com/jellyfin/jellyfin-sdk-kotlin.git
synced 2024-11-23 13:59:42 +00:00
Various tweaks to extended SecureConnectionException exceptions
This commit is contained in:
parent
be2c217bfe
commit
c79081d0cb
@ -27,7 +27,7 @@ import org.jellyfin.sdk.api.client.exception.InvalidStatusException
|
||||
import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
import org.jellyfin.sdk.api.client.exception.TimeoutException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.BadPeerSSLKeyException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.HandShakeCertificateException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.HandshakeCertificateException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.InvalidSSLProtocolImplementationException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.PeerNotAuthenticatedException
|
||||
import org.jellyfin.sdk.api.client.util.ApiSerializer
|
||||
@ -142,25 +142,21 @@ public actual open class KtorClient actual constructor(
|
||||
} catch (err: SerializationException) {
|
||||
logger.error(err) { "Serialization failed" }
|
||||
throw InvalidContentException("Serialization failed", err)
|
||||
} catch (err: SSLKeyException) {
|
||||
logger.error(err) { "Invalid SSL peer key format" }
|
||||
throw BadPeerSSLKeyException("Invalid SSL peer key format", err)
|
||||
} catch (err: SSLPeerUnverifiedException) {
|
||||
logger.error(err) { "Couldn't authenticate peer" }
|
||||
throw PeerNotAuthenticatedException("Couldn't authenticate peer", err)
|
||||
} catch (err: SSLHandshakeException) {
|
||||
logger.error(err) { "SSL Invalid handshake" }
|
||||
throw HandshakeCertificateException("Invalid handshake", err)
|
||||
} catch (err: SSLProtocolException) {
|
||||
logger.error(err) { "Invalid SSL protocol implementation" }
|
||||
throw InvalidSSLProtocolImplementationException("Invalid SSL protocol implementation", err)
|
||||
} catch (err: SSLException) {
|
||||
logger.error(err) { "SSL error occurred" }
|
||||
when (err) {
|
||||
is SSLKeyException -> {
|
||||
throw BadPeerSSLKeyException("Invalid SSL peer key format", err)
|
||||
}
|
||||
is SSLPeerUnverifiedException -> {
|
||||
throw PeerNotAuthenticatedException("Couldn't authenticate peer", err)
|
||||
}
|
||||
is SSLHandshakeException -> {
|
||||
throw HandShakeCertificateException("Invalid hand shake certificate", err)
|
||||
}
|
||||
is SSLProtocolException -> {
|
||||
throw InvalidSSLProtocolImplementationException("Invalid SSL protocol implementation", err)
|
||||
}
|
||||
else -> {
|
||||
throw SecureConnectionException("Unknown SSL error occurred", err)
|
||||
}
|
||||
}
|
||||
logger.error(err) { "Unknown SSL error occurred" }
|
||||
throw SecureConnectionException("Unknown SSL error occurred", err)
|
||||
} catch (err: IOException) {
|
||||
logger.error(err) { "Unknown IO error occurred!" }
|
||||
throw ApiClientException("Unknown IO error occurred!", err)
|
||||
|
@ -129,7 +129,7 @@ public final class org/jellyfin/sdk/api/client/exception/ssl/BadPeerSSLKeyExcept
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
}
|
||||
|
||||
public final class org/jellyfin/sdk/api/client/exception/ssl/HandShakeCertificateException : org/jellyfin/sdk/api/client/exception/SecureConnectionException {
|
||||
public final class org/jellyfin/sdk/api/client/exception/ssl/HandshakeCertificateException : org/jellyfin/sdk/api/client/exception/SecureConnectionException {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
}
|
||||
|
||||
|
@ -7,5 +7,6 @@ import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
* This can happen when a bad key format is given.
|
||||
*/
|
||||
public class BadPeerSSLKeyException(
|
||||
message: String, exception: Throwable
|
||||
): SecureConnectionException(message, exception)
|
||||
message: String,
|
||||
exception: Throwable,
|
||||
) : SecureConnectionException(message, exception)
|
||||
|
@ -7,6 +7,6 @@ import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
* Indicates that the client and server could not negotiate the desired level of security or the certificate was
|
||||
* revoked.
|
||||
*/
|
||||
public class HandShakeCertificateException(
|
||||
public class HandshakeCertificateException(
|
||||
message: String, exception: Throwable
|
||||
): SecureConnectionException(message, exception)
|
@ -7,5 +7,6 @@ import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
* Normally this indicates a flaw in one of the protocol implementations.
|
||||
*/
|
||||
public class InvalidSSLProtocolImplementationException(
|
||||
message: String, exception: Throwable
|
||||
): SecureConnectionException(message, exception)
|
||||
message: String,
|
||||
exception: Throwable,
|
||||
) : SecureConnectionException(message, exception)
|
||||
|
@ -10,5 +10,6 @@ import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
* this exception is thrown.
|
||||
*/
|
||||
public class PeerNotAuthenticatedException(
|
||||
message: String, exception: Throwable
|
||||
): SecureConnectionException(message, exception)
|
||||
message: String,
|
||||
exception: Throwable,
|
||||
) : SecureConnectionException(message, exception)
|
||||
|
@ -245,12 +245,12 @@ public final class org/jellyfin/sdk/discovery/RecommendedServerIssue$SecureConne
|
||||
}
|
||||
|
||||
public final class org/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable : org/jellyfin/sdk/discovery/RecommendedServerIssue {
|
||||
public fun <init> (Ljava/lang/Throwable;)V
|
||||
public final fun component1 ()Ljava/lang/Throwable;
|
||||
public final fun copy (Ljava/lang/Throwable;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public static synthetic fun copy$default (Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;Ljava/lang/Throwable;ILjava/lang/Object;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public fun <init> (Lorg/jellyfin/sdk/api/client/exception/TimeoutException;)V
|
||||
public final fun component1 ()Lorg/jellyfin/sdk/api/client/exception/TimeoutException;
|
||||
public final fun copy (Lorg/jellyfin/sdk/api/client/exception/TimeoutException;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public static synthetic fun copy$default (Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;Lorg/jellyfin/sdk/api/client/exception/TimeoutException;ILjava/lang/Object;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getThrowable ()Ljava/lang/Throwable;
|
||||
public final fun getThrowable ()Lorg/jellyfin/sdk/api/client/exception/TimeoutException;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
@ -230,12 +230,12 @@ public final class org/jellyfin/sdk/discovery/RecommendedServerIssue$SecureConne
|
||||
}
|
||||
|
||||
public final class org/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable : org/jellyfin/sdk/discovery/RecommendedServerIssue {
|
||||
public fun <init> (Ljava/lang/Throwable;)V
|
||||
public final fun component1 ()Ljava/lang/Throwable;
|
||||
public final fun copy (Ljava/lang/Throwable;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public static synthetic fun copy$default (Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;Ljava/lang/Throwable;ILjava/lang/Object;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public fun <init> (Lorg/jellyfin/sdk/api/client/exception/TimeoutException;)V
|
||||
public final fun component1 ()Lorg/jellyfin/sdk/api/client/exception/TimeoutException;
|
||||
public final fun copy (Lorg/jellyfin/sdk/api/client/exception/TimeoutException;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public static synthetic fun copy$default (Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;Lorg/jellyfin/sdk/api/client/exception/TimeoutException;ILjava/lang/Object;)Lorg/jellyfin/sdk/discovery/RecommendedServerIssue$ServerUnreachable;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getThrowable ()Ljava/lang/Throwable;
|
||||
public final fun getThrowable ()Lorg/jellyfin/sdk/api/client/exception/TimeoutException;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
@ -50,25 +50,20 @@ public class RecommendedServerDiscovery constructor(
|
||||
// Failure checks
|
||||
result.systemInfo.exceptionOrNull()?.let { exception ->
|
||||
when (exception) {
|
||||
is SecureConnectionException -> {
|
||||
issues.add(RecommendedServerIssue.SecureConnectionFailed(exception))
|
||||
}
|
||||
is TimeoutException -> {
|
||||
issues.add(RecommendedServerIssue.ServerUnreachable(exception))
|
||||
}
|
||||
else -> {
|
||||
// Did not reply with a system information
|
||||
issues.add(RecommendedServerIssue.MissingSystemInfo(result.systemInfo.exceptionOrNull()))
|
||||
}
|
||||
is SecureConnectionException -> issues.add(RecommendedServerIssue.SecureConnectionFailed(exception))
|
||||
is TimeoutException -> issues.add(RecommendedServerIssue.ServerUnreachable(exception))
|
||||
// Did not reply with a system information
|
||||
else -> issues.add(RecommendedServerIssue.MissingSystemInfo(result.systemInfo.exceptionOrNull()))
|
||||
}
|
||||
|
||||
scores.add(RecommendedServerInfoScore.BAD)
|
||||
}
|
||||
|
||||
// System Info data validation
|
||||
when {
|
||||
// Wrong product name - might be a different service on this connection
|
||||
!systemInfo?.productName.equals(PRODUCT_NAME) -> {
|
||||
issues.add(RecommendedServerIssue.InvalidProductName(systemInfo?.productName))
|
||||
systemInfo != null && !systemInfo.productName.equals(PRODUCT_NAME) -> {
|
||||
issues.add(RecommendedServerIssue.InvalidProductName(systemInfo.productName))
|
||||
scores.add(RecommendedServerInfoScore.BAD)
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,23 @@
|
||||
package org.jellyfin.sdk.discovery
|
||||
|
||||
import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
import org.jellyfin.sdk.api.client.exception.TimeoutException
|
||||
import org.jellyfin.sdk.model.ServerVersion
|
||||
|
||||
public sealed interface RecommendedServerIssue {
|
||||
|
||||
/**
|
||||
* Failed to acquire a secure connection. This happens due to incorrect SSL configurations.
|
||||
*/
|
||||
public data class SecureConnectionFailed(public val sslException: SecureConnectionException) : RecommendedServerIssue
|
||||
public data class SecureConnectionFailed(
|
||||
public val sslException: SecureConnectionException,
|
||||
) : RecommendedServerIssue
|
||||
|
||||
/**
|
||||
* Server is unreachable. This happens when the server is overloaded, unstable or the client is unable to establish a connection.
|
||||
* Server is unreachable. This happens when the server is overloaded, unstable or the client is unable to establish
|
||||
* a connection.
|
||||
*/
|
||||
public data class ServerUnreachable(public val throwable: Throwable) : RecommendedServerIssue
|
||||
public data class ServerUnreachable(public val throwable: TimeoutException) : RecommendedServerIssue
|
||||
|
||||
/**
|
||||
* No system information found from server. Server is returning invalid system info.
|
||||
*/
|
||||
|
@ -1,48 +1,55 @@
|
||||
package org.jellyfin.sdk.api;
|
||||
|
||||
import io.kotest.assertions.retry
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import org.jellyfin.sdk.api.client.exception.SecureConnectionException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.HandShakeCertificateException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.HandshakeCertificateException
|
||||
import org.jellyfin.sdk.api.client.exception.ssl.PeerNotAuthenticatedException
|
||||
import org.jellyfin.sdk.createJellyfin
|
||||
import org.jellyfin.sdk.model.ClientInfo
|
||||
import org.jellyfin.sdk.model.DeviceInfo
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
class SSLResolverTests : FunSpec({
|
||||
|
||||
val jellyfin = createJellyfin {
|
||||
fun getInstance() = createJellyfin {
|
||||
clientInfo = ClientInfo("Jellyfin Testing SSL Errors", "TEST")
|
||||
deviceInfo = DeviceInfo("test", "test")
|
||||
}
|
||||
|
||||
test("should throw HandShakeCertificateException when calling an https endpoint with revoked certificate") {
|
||||
val api = jellyfin.createApi(
|
||||
val api = getInstance().createApi(
|
||||
baseUrl = "https://revoked.badssl.com"
|
||||
)
|
||||
|
||||
shouldThrow<HandShakeCertificateException> {
|
||||
api.request(pathTemplate = "/")
|
||||
retry(3, 1.minutes) {
|
||||
shouldThrow<HandshakeCertificateException> {
|
||||
api.request(pathTemplate = "/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("should throw PeerNotAuthenticatedException when wrong host is returned from https endpoint") {
|
||||
val api = jellyfin.createApi(
|
||||
val api = getInstance().createApi(
|
||||
baseUrl = "https://wrong.host.badssl.com"
|
||||
)
|
||||
|
||||
shouldThrow<PeerNotAuthenticatedException> {
|
||||
api.request(pathTemplate = "/")
|
||||
retry(3, 1.minutes) {
|
||||
shouldThrow<PeerNotAuthenticatedException> {
|
||||
api.request(pathTemplate = "/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("should throw SecureConnectionException when using wrong https port") {
|
||||
val api = jellyfin.createApi(
|
||||
val api = getInstance().createApi(
|
||||
baseUrl = "https://badssl.com:80"
|
||||
)
|
||||
|
||||
shouldThrow<SecureConnectionException> {
|
||||
api.request(pathTemplate = "/")
|
||||
retry(3, 1.minutes) {
|
||||
shouldThrow<SecureConnectionException> {
|
||||
api.request(pathTemplate = "/")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user