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:
| Part | Rust | Kotlin | Swift |
|---|---|---|---|
| Build the client | ScionTransport::new | ScionTransport.open | ScionTransport.init |
| Send a request | request | send | send |
| Map the errors | failure | failure | failure |
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:
- Android: The Android client on this page.
- iOS: The iOS client on this page.
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:
.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:
/** 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:
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:
/// 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
dnsOverrideon the client builder. - The iOS client sets
dnsOverridesin the client settings.
Each maps the host of the server URL to the target address.
Where to go next
- The client: the same transport in Rust.
- Android HTTP/3 client and iOS: the SDK libraries that the mobile clients use.
- From a local SCION network to a real network: the credential, the address and the trust of a real deployment.