From 2a51f3cac56f2ee400a0b7d33195de31b443bd88 Mon Sep 17 00:00:00 2001 From: Lika Vorobeva Date: Wed, 5 Oct 2022 16:02:44 +0300 Subject: [PATCH] #11: Send proper json responses --- .../project.pbxproj | 12 +++ .../Extensions/Foundation/Serializer.swift | 6 ++ .../Common/Models/InfoEvent.swift | 13 +++ .../Root/DVPNServer.swift | 11 +-- .../Tunnel/TunnelRouteCollection.swift | 84 +++++++++++-------- 5 files changed, 87 insertions(+), 39 deletions(-) create mode 100644 SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Models/InfoEvent.swift diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj index 6cfe3e0..3aecedf 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 225A83A228EB06BF00F66619 /* NodesProviderType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225A83A128EB06BF00F66619 /* NodesProviderType.swift */; }; 225A83A328EB14B200F66619 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22C3EF0028E6FD95007DB01B /* PacketTunnelProvider.swift */; }; 225A83A628EC81E500F66619 /* WebSocketDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225A83A528EC81E500F66619 /* WebSocketDelegate.swift */; }; + 225A83AC28EDB3C100F66619 /* InfoEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225A83AB28EDB3C100F66619 /* InfoEvent.swift */; }; 22C3EE9028E4638E007DB01B /* WireGuardNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 22C3EE8728E4638E007DB01B /* WireGuardNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 22C3EE9728E463D6007DB01B /* WireGuardKit in Frameworks */ = {isa = PBXBuildFile; productRef = 22C3EE9628E463D6007DB01B /* WireGuardKit */; }; 22C3EE9A28E464A1007DB01B /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 22C3EE9928E464A1007DB01B /* Alamofire */; }; @@ -200,6 +201,7 @@ 225A839C28EAE54400F66619 /* SecurityService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityService.swift; sourceTree = ""; }; 225A83A128EB06BF00F66619 /* NodesProviderType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NodesProviderType.swift; sourceTree = ""; }; 225A83A528EC81E500F66619 /* WebSocketDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketDelegate.swift; sourceTree = ""; }; + 225A83AB28EDB3C100F66619 /* InfoEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoEvent.swift; sourceTree = ""; }; 22C3EE8728E4638E007DB01B /* WireGuardNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WireGuardNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 22C3EE9B28E467E4007DB01B /* SOLARdVPNCommunityCoreiOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SOLARdVPNCommunityCoreiOS.entitlements; sourceTree = ""; }; 22C3EE9D28E4733C007DB01B /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; @@ -422,6 +424,14 @@ path = Tunnel; sourceTree = ""; }; + 225A83AA28EDB3B200F66619 /* Models */ = { + isa = PBXGroup; + children = ( + 225A83AB28EDB3C100F66619 /* InfoEvent.swift */, + ); + path = Models; + sourceTree = ""; + }; 22C3EE9C28E4733C007DB01B /* Shared */ = { isa = PBXGroup; children = ( @@ -660,6 +670,7 @@ 92D6B41B28E2F62A004CF9DF /* Common */ = { isa = PBXGroup; children = ( + 225A83AA28EDB3B200F66619 /* Models */, 923C371228E5B887003CFC03 /* Context */, 22C3EED528E48D9A007DB01B /* Extensions */, 92D6B41C28E2F63D004CF9DF /* Utilities */, @@ -1038,6 +1049,7 @@ 92D6B47128E47E71004CF9DF /* NodesServiceType.swift in Sources */, 22C3EEA828E4733C007DB01B /* Keychain.swift in Sources */, 923C372228E72C87003CFC03 /* NodesByAddressPostBody.swift in Sources */, + 225A83AC28EDB3C100F66619 /* InfoEvent.swift in Sources */, 22C3EECE28E48B52007DB01B /* PeersModel.swift in Sources */, 92D6B41E28E2F64D004CF9DF /* ClientConstants.swift in Sources */, 923C371628E5B9DE003CFC03 /* ContextBuilder.swift in Sources */, diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Extensions/Foundation/Serializer.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Extensions/Foundation/Serializer.swift index 79faa55..666a051 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Extensions/Foundation/Serializer.swift +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Extensions/Foundation/Serializer.swift @@ -68,3 +68,9 @@ extension Encodable { return Serializer.toData(from: self) } } + +extension Data { + var string: String { + String(decoding: self, as: UTF8.self) + } +} diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Models/InfoEvent.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Models/InfoEvent.swift new file mode 100644 index 0000000..904488c --- /dev/null +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Common/Models/InfoEvent.swift @@ -0,0 +1,13 @@ +// +// InfoEvent.swift +// SOLARdVPNCommunityCoreiOS +// +// Created by Lika Vorobeva on 05.10.2022. +// + +import Foundation + +struct InfoEvent: Codable { + let type: String + let value: String +} diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/DVPNServer.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/DVPNServer.swift index f33cb34..f64b93a 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/DVPNServer.swift +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/DVPNServer.swift @@ -27,11 +27,12 @@ extension DVPNServer { do { let api = app.grouped(.init(stringLiteral: ClientConstants.apiPath)) try api.register(collection: NodesRouteCollection(context: context)) - try api.register(collection: - TunnelRouteCollection( - model: ConnectionModel(context: context), - delegate: self - ) + try api.register( + collection: + TunnelRouteCollection( + model: ConnectionModel(context: context), + delegate: self + ) ) try app.start() } catch { diff --git a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Tunnel/TunnelRouteCollection.swift b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Tunnel/TunnelRouteCollection.swift index 8ff410b..dcaba4f 100644 --- a/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Tunnel/TunnelRouteCollection.swift +++ b/SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/RouteCollections/Tunnel/TunnelRouteCollection.swift @@ -9,16 +9,33 @@ import Vapor import Combine enum TunnelRouteEvent: String { - case alreadyConnected - case subscriptionCanceled + case alreadyConnected = "Already Connected" + case alreadyDisconnected = "Already Disconnected" + + var responseStatus: HTTPResponseStatus { + switch self { + case .alreadyConnected: + return .custom(code: 500, reasonPhrase: self.rawValue) + case .alreadyDisconnected: + return .custom(code: 200, reasonPhrase: self.rawValue) + } + } + + var response: Response { + Response(status: responseStatus) + } } +private struct Constants { + let path: PathComponent = "connection" + let connectionType = "tunnelStatus" +} +private let constants = Constants() + class TunnelRouteCollection: RouteCollection { private let model: ConnectionModel private var cancellables = Set() - // Connection Status - @Published private(set) var isConnected: Bool = false private weak var delegate: WebSocketDelegate? init(model: ConnectionModel, delegate: WebSocketDelegate?) { @@ -26,30 +43,31 @@ class TunnelRouteCollection: RouteCollection { self.delegate = delegate subscribeToEvents() - model.setInitData() } func boot(routes: RoutesBuilder) throws { - routes.post("connection", use: createNewSession) - routes.delete("connection", use: startDeactivationOfActiveTunnel) + routes.post(constants.path, use: createNewSession) + routes.delete(constants.path, use: startDeactivationOfActiveTunnel) } } extension TunnelRouteCollection { -#warning("TODO add result") - func startDeactivationOfActiveTunnel(_ req: Request) async throws -> Bool { - model.disconnect() - - return true + func startDeactivationOfActiveTunnel(_ req: Request) -> Response { + let status = model.disconnect() ? .ok : TunnelRouteEvent.alreadyDisconnected.responseStatus + return Response(status: status) } -#warning("TODO add result & pass node") - func createNewSession(_ req: Request) async throws -> Bool { - if isConnected { - return true // && add status TunnelRouteEvent + func createNewSession(_ req: Request) throws -> Response { + do { + let body = try req.content.decode(PostConnectionRequest.self) + let address = body.nodeAddress + + let status = model.connect(to: address) ? .accepted : TunnelRouteEvent.alreadyConnected.responseStatus + + return Response(status: status) + } catch { + return Response(status: .badRequest) } - model.connect() - return true } } @@ -66,8 +84,6 @@ extension TunnelRouteCollection { self.send(error: error) case let .warning(warning): self.send(warning: warning) - case let .info(text): - self.send(info: text) case let .updateTunnelActivity(isActive): self.updateConnection(isConnected: isActive) } @@ -79,24 +95,24 @@ extension TunnelRouteCollection { // MARK: - Handle events extension TunnelRouteCollection { - private func send(error: Error) { -#warning("TODO: send json with error") - delegate?.send(event: error.localizedDescription) + private func send(error: SingleInnerError) { + let data = error.toData()?.string ?? error.error.message + delegate?.send(event: data) } - private func send(warning: Error) { -#warning("TODO: send json with warning") - delegate?.send(event: warning.localizedDescription) - } - - private func send(info: String) { -#warning("TODO: send json with info") - delegate?.send(event: info) + private func send(warning: SingleInnerError) { + let data = warning.toData()?.string ?? warning.error.message + delegate?.send(event: data) } private func updateConnection(isConnected: Bool) { -#warning("TODO: send json with isConnected") - self.isConnected = isConnected - delegate?.send(event: "isConnected \(isConnected)") + log.debug(isConnected) + let event = InfoEvent( + type: constants.connectionType, + value: isConnected ? "connected" : "disconnected" + ) + if let dataString = event.toData()?.string { + delegate?.send(event: dataString) + } } }