Skip to main content
SCION SDKv0.8.6

The mobile clients

The chat has an Android client and an iOS client. Each client uses the SDK library for its platform. The platform pages explain each library: Android HTTP/3 client and iOS. This page shows how the chat uses the libraries, and how the mobile clients match the Rust client.

One transport in three languages​

The Rust transport has three parts: it builds the client, sends a request, and maps the errors. The Android transport and the iOS transport have the same three parts:

PartRustKotlinSwift
Build the clientScionTransport::newScionTransport.openScionTransport.init
Send a requestrequestsendsend
Map the errorsfailurefailurefailure

In each app, the transport is the only file that imports the SDK. These sections show how each mobile transport adds the library, trusts the server, maps the errors and holds its client:

In all three languages, the SDK renews the token.

The Android client​

The Android client keeps all of its SCION code in one class, ScionTransport.kt. Android HTTP/3 client explains the library that the class uses.

Add the library​

The chat does the steps of Add the SDK to your app in its settings.gradle.kts. The build downloads the Maven archive of a release, checks the archive against the checksums of the release, and unpacks it into libs/maven.

Trust the server​

The chat offers the three trust choices on its connect screen, and turns the choice into a TrustAnchors value. Certificates explains each choice:

ScionTransport.kt
.trust(
when (val trust = config.trust) {
is Trust.SystemRoots -> TrustAnchors.systemDefault()
is Trust.Pinned -> TrustAnchors.pinned(trust.pem.toByteArray())
is Trust.Insecure -> TrustAnchors.insecureNoVerify()
},
)

Map the errors​

The chat sorts each arm of ScionHttp3Exception into the errors of the app. Handling errors explains each arm:

ScionTransport.kt
/** Sorts an SDK failure into the one taxonomy the app knows. */
internal fun failure(error: ScionHttp3Exception): ChatError.Transport {
val kind = when (error) {
is ScionHttp3Exception.Connectivity -> TransportFailure.Connectivity
is ScionHttp3Exception.Resolution -> TransportFailure.Resolution
is ScionHttp3Exception.Connect -> TransportFailure.Connect
is ScionHttp3Exception.Tls -> TransportFailure.Tls
is ScionHttp3Exception.StreamReset, is ScionHttp3Exception.ConnectionLimit ->
TransportFailure.StreamReset
is ScionHttp3Exception.BodyTooLarge -> TransportFailure.BodyTooLarge
is ScionHttp3Exception.Timeout -> TransportFailure.Timeout
is ScionHttp3Exception.Closed -> TransportFailure.Closed
else -> TransportFailure.Protocol
}

return ChatError.Transport(kind, error.message ?: error.toString(), error)
}

The lifetime of the client​

The chat holds one transport at a time. Each Connect on its connect screen builds a new transport and closes the old one. The client's lifetime explains when to close a client. The SDK renews the token.

The iOS client​

The iOS client keeps all of its SCION code in one class, ScionTransport.swift. iOS explains the library that the class uses.

Add the library​

The chat does the steps of Add the SDK to your app in fetch-sdk.sh. The script downloads the package of the release that sdk.version names, checks the package against the checksums of the release, and unpacks it into ios/libs.

Trust the server​

The chat offers the three trust choices on its connect screen, and sets trust from the choice. Certificates explains each choice:

ScionTransport.swift
switch config.trust {
case .systemRoots:
break
case .pinned(let pem):
do {
settings.trust = try .pinned(Data(pem.utf8))
} catch {
throw ChatError.config("the certificate is not readable PEM")
}
case .insecure:
settings.trust = .insecureNoVerify
}

Map the errors​

The chat sorts each case of ScionHttp3Error into the errors of the app. Handling errors explains each case:

ScionTransport.swift
/// Sorts an SDK failure into the one taxonomy the app knows.
func failure(_ error: ScionHttp3Error) -> ChatError {
let kind: TransportFailure
switch error {
case .connectivity: kind = .connectivity
case .resolution: kind = .resolution
case .connect: kind = .connect
case .tls: kind = .tls
case .streamReset: kind = .streamReset
case .timeout: kind = .timeout
case .bodyTooLarge: kind = .bodyTooLarge
default: kind = .protocolError
}

return .transport(kind, error.detail)
}

The lifetime of the client​

The chat holds one transport at a time. Each Connect on its connect screen builds a new transport and shuts down the old one. The client's lifetime explains when to shut down a client. The SDK renews the token.

Reach a server without a TSAR record​

A server in a local SCION network has no TSAR record. The Rust client answers for the host of the server with with_override, as The client shows. The mobile clients do the same:

  • The Android client calls dnsOverride on the client builder.
  • The iOS client sets dnsOverrides in the client settings.

Each maps the host of the server URL to the target address.

Where to go next​