diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionServiceError.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionServiceError.swift new file mode 100644 index 0000000..a4c496a --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionServiceError.swift @@ -0,0 +1,38 @@ +// +// SessionsServiceError.swift +// SOLARdVPNCommunityCoreiOS +// +// Created by Lika Vorobeva on 29.11.2021. +// + +import Foundation + +enum SessionsServiceError: LocalizedError { + case invalidURL + + case connectionParsingFailed + case nodeMisconfigured + case noQuota + + case serverLocalized(String) + case other(Error) +} + +extension SessionsServiceError { + static var allCases: [SessionsServiceError] { + [.connectionParsingFailed, .nodeMisconfigured, .noQuota] + } + + var innerCodes: [Int] { + switch self { + case .nodeMisconfigured: + return [3, 4, 5] + case .noQuota: + return [9, 10] + case .connectionParsingFailed: + return [6, 7, 8] + default: + return [] + } + } +} diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionsService.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionsService.swift new file mode 100644 index 0000000..1d1689d --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionsService.swift @@ -0,0 +1,100 @@ +// +// SessionsService.swift +// SOLARdVPNCommunityCoreiOS +// +// Created by Lika Vorobeva on 20.07.2022. +// + +import Foundation +import SentinelWallet +import SOLARAPI +import WireGuardKit +import Vapor + +final class SessionsService { + private let walletService: WalletService + private let sessionProvider: NodeSessionProviderType + private let subscriptionsProvider: SubscriptionsProviderType + + init( + sessionProvider: NodeSessionProviderType, + subscriptionsProvider: SubscriptionsProviderType, + walletService: WalletService + ) { + self.sessionProvider = sessionProvider + self.subscriptionsProvider = subscriptionsProvider + self.walletService = walletService + } +} + +// MARK: - SubscriptionsServiceType + +extension SessionsService: SessionsServiceType { + func loadActiveSessions(completion: @escaping (Result<[SentinelWallet.Session], Error>) -> Void) { + subscriptionsProvider.queryActiveSessions(for: walletService.currentWalletAddress, completion: completion) + } + + func stopActiveSessions(completion: @escaping (Result) -> Void) { + guard let sender = walletService.createTransactionSender() else { + completion(.failure(SubscriptionsServiceError.missingMnemonic)) + return + } + + subscriptionsProvider.stopActiveSessions(sender: sender, completion: completion) + } + + func startSession(on subscriptionID: UInt64, node: String, completion: @escaping (Result) -> Void) { + guard let sender = walletService.createTransactionSender() else { + completion(.failure(SubscriptionsServiceError.missingMnemonic)) + return + } + + subscriptionsProvider.startNewSession(on: subscriptionID, sender: sender, node: node, completion: completion) + } + + func fetchConnectionData( + remoteURLString: String, + id: UInt64, + accountAddress: String, + signature: String, + completion: @escaping (Result<(Data, PrivateKey), SessionsServiceError>) -> Void + ) { + guard var components = URLComponents(string: remoteURLString) else { + completion(.failure(SessionsServiceError.invalidURL)) + return + } + components.scheme = "http" + + guard let urlString = components.string, let remoteURL = URL(string: urlString) else { + completion(.failure(SessionsServiceError.invalidURL)) + return + } + let wgKey = PrivateKey() + + sessionProvider.createClient( + remoteURL: remoteURL, + address: accountAddress, + id: "\(id)", + request: .init(key: wgKey.publicKey.base64Key, signature: signature)) { result in + switch result { + case .success(let infoResult): + guard infoResult.success, let stringData = infoResult.result else { + completion(.failure(.connectionParsingFailed)) + return + } + guard let data = Data(base64Encoded: stringData), data.bytes.count == 58 else { + completion(.failure(.connectionParsingFailed)) + return + } + + completion(.success((data, wgKey))) + case .failure(let error): + #warning("TODO: map error") +// let mapper = Self.mapNetworkError(handleSpecificGenericErrors: { error -> SessionsServiceError? in +// return SessionsServiceError.allCases.first(where: { $0.innerCodes.contains(error.code) }) +// }) +// completion(.failure(error)) + } + } + } +} diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionsServiceType.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionsServiceType.swift new file mode 100644 index 0000000..d937d31 --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Services/SessionsService/SessionsServiceType.swift @@ -0,0 +1,23 @@ +// +// SessionsServiceType.swift +// SOLARdVPNCommunityCoreiOS +// +// Created by Lika Vorobeva on 20.07.2022. +// + +import Foundation +import SentinelWallet +import WireGuardKit + +protocol SessionsServiceType { + func loadActiveSessions(completion: @escaping (Result<[Session], Error>) -> Void) + func stopActiveSessions(completion: @escaping (Result) -> Void) + func startSession(on subscriptionID: UInt64, node: String, completion: @escaping (Result) -> Void) + func fetchConnectionData( + remoteURLString: String, + id: UInt64, + accountAddress: String, + signature: String, + completion: @escaping (Result<(Data, PrivateKey), SessionsServiceError>) -> Void + ) +}