field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraGeneratedRuntimeStartup.swift (5720B)


      1 import Foundation
      2 import TeraKitBindings
      3 
      4 extension TeraGeneratedRuntimeBackend {
      5   static func start(
      6     configuration: TeraRuntimeLaunchConfiguration, localBackups: Bool = false
      7   ) async throws -> TeraRuntimeBackendStart {
      8     var createdRuntime: TeraRuntime?
      9     do {
     10       let mediaUse = try TeraMediaProcessUse.admit(applicationSupportDirectory: configuration.applicationSupportDirectory)
     11       defer { withExtendedLifetime(mediaUse) {} }
     12       let (runtime, restored) = try await construct(configuration: configuration, localBackups: localBackups)
     13       createdRuntime = runtime
     14       runtime.setAppInfoPlatform(
     15         platform: "iOS",
     16         bundleId: configuration.app.bundleIdentifier,
     17         version: configuration.app.version,
     18         buildNumber: configuration.app.buildNumber,
     19         buildSha: configuration.app.buildSHA
     20       )
     21 
     22       let backend = TeraGeneratedRuntimeBackend(runtime: runtime)
     23       if !restored {
     24         try await bootstrap(runtime: runtime, backend: backend, configuration: configuration)
     25       }
     26       return try await TeraRuntimeBackendStart(
     27         backend: backend,
     28         snapshot: backend.snapshot()
     29       )
     30     } catch {
     31       if let createdRuntime {
     32         _ = try? await createdRuntime.shutdown()
     33       }
     34       throw TeraGeneratedRuntimeFailure.from(error)
     35     }
     36   }
     37 
     38   private static func bootstrap(runtime: TeraRuntime, backend: TeraGeneratedRuntimeBackend,
     39                                 configuration: TeraRuntimeLaunchConfiguration) async throws
     40   {
     41     let currentSettings = try await backend.mobileSettings()
     42     if configuration.adoptBootstrapSettings
     43       || currentSettings.revision == 1 && currentSettings.identity.identities.isEmpty
     44     {
     45       _ = try await backend.replaceMobileSettings(input: configuration.bootstrapSettingsReplacement(current: currentSettings))
     46     }
     47     _ = try await runtime.phase1ApplySettingsToRuntime()
     48   }
     49 
     50   private static func construct(configuration: TeraRuntimeLaunchConfiguration, localBackups: Bool) async throws -> (TeraRuntime, Bool) {
     51     if let guardBytes = try TeraRestoreFiles.readGuard(
     52       applicationSupportDirectory: configuration.applicationSupportDirectory, publicKey: configuration.publicKeyHex
     53     ) {
     54       let runtime = try await TeraRuntime.withHostSignerAndRestoreGuard(
     55         store: FfiRestoreStore(applicationSupportDirectory: configuration.applicationSupportDirectory,
     56                                publicKey: configuration.publicKeyHex, sourceGeneration: configuration.sourceGenerationHex,
     57                                sourceGenerationCreatedAtMs: configuration.sourceGenerationCreatedAtUnixMilliseconds,
     58                                protectedData: configuration.protectedData.generatedValue),
     59         hostSigner: TeraGeneratedHostSigner(signer: configuration.signer), guard: guardBytes, localBackups: localBackups
     60       )
     61       return (runtime, true)
     62     }
     63     let constructor = localBackups ? TeraRuntime.withHostSignerAndLocalBackups : TeraRuntime.withHostSigner
     64     let runtime = try await constructor(
     65       configuration.applicationSupportDirectory, configuration.publicKeyHex,
     66       configuration.sourceGenerationHex, configuration.sourceGenerationCreatedAtUnixMilliseconds,
     67       configuration.protectedData.generatedValue, TeraGeneratedHostSigner(signer: configuration.signer)
     68     )
     69     return (runtime, false)
     70   }
     71 }
     72 
     73 extension TeraRuntimeLaunchConfiguration {
     74   fileprivate func bootstrapSettingsReplacement(
     75     current: TeraMobileSettings
     76   ) -> TeraReplaceSettings {
     77     let environment = networkProfile.settingsValue
     78     var relays = writableRelays.map {
     79       TeraRelayPreference(url: $0, access: .readWrite)
     80     }
     81     if networkProfile != .simulator,
     82        !relays.contains(where: { $0.url == TeraNetworkValidator.canonicalRelay })
     83     {
     84       relays.insert(
     85         TeraRelayPreference(
     86           url: TeraNetworkValidator.canonicalRelay,
     87           access: .readWrite
     88         ),
     89         at: 0
     90       )
     91     }
     92     let authority = blossom?.endpointAuthority.settingsValue
     93       ?? current.blossomAuthority
     94     let primaryOrigin = blossom?.primaryOrigin ?? current.blossomPrimaryOrigin
     95     let fallbackOrigins = blossom?.fallbackOrigins ?? current.blossomFallbackOrigins
     96     return TeraReplaceSettings(
     97       expectedRevision: current.revision,
     98       networkEnvironment: environment,
     99       relays: relays,
    100       blossomAuthority: authority,
    101       blossomPrimaryOrigin: primaryOrigin,
    102       blossomFallbackOrigins: fallbackOrigins,
    103       allowCellularDownloads: current.allowCellularDownloads,
    104       allowCellularUploads: current.allowCellularUploads,
    105       allowBackgroundTransfers: current.allowBackgroundTransfers,
    106       mediaCacheBytes: current.mediaCacheBytes,
    107       mediaCacheArtifacts: current.mediaCacheArtifacts
    108     )
    109   }
    110 }
    111 
    112 extension TeraRuntimeNetworkProfile {
    113   fileprivate var settingsValue: TeraSettingsNetworkEnvironment {
    114     switch self {
    115     case .publicNetwork: .publicNetwork
    116     case .simulator: .simulator
    117     case .device: .physicalDevice
    118     }
    119   }
    120 }
    121 
    122 extension TeraBlossomEndpointAuthority {
    123   fileprivate var settingsValue: TeraBlossomAuthorityPreference {
    124     switch self {
    125     case .publicWebPKI: .publicWebPKI
    126     case .loopbackDevelopment: .loopbackDevelopment
    127     case .privateNetworkDevelopment: .privateNetworkDevelopment
    128     }
    129   }
    130 }
    131 
    132 extension TeraRuntimeClient {
    133   static func production() -> TeraRuntimeClient {
    134     TeraRuntimeClient { configuration in
    135       try await TeraGeneratedRuntimeBackend.start(configuration: configuration)
    136     }
    137   }
    138 }
    139 
    140 extension TeraProtectedDataState {
    141   fileprivate var generatedValue: ProtectedDataAvailability {
    142     switch self {
    143     case .available: .available
    144     case .unavailable: .unavailable
    145     }
    146   }
    147 }