Skip to content

Commit

Permalink
[IOS] VPN core (#901)
Browse files Browse the repository at this point in the history
* Started working on Privacy flow.

* Adding int parsing  and added acceptTerms method.

* Create VPN model and implemented store version logic for IOS

* Added setSelectedTab method in session model.

* Set Device Id and start working on API calling.

* Added switch VPN method in VPN model.

* Added dns as static value.

* Implemented create user API and  show loading view  on swift.

* Hide some feature on iOS.

* Started working on Tunnel.

* Implemented Tunnel.

* clean up code.

* Code refactoring and added some method in session mode.

* Organise code and removed not used class

* Changes in session model.

* Make changes to support panic session.

* Update go.mod

* Remove panic from session model.

* Improve readability and use go const in swift

* Reduce database crashes

* Added vpn.protoc file.

* Updated pathdb.

* Set up basic unit test

* Fixed language issue.

* Added DB as framework.

* Added DBModule

* Added testList to DBModuleTests

* Formatted Database.swift

* Some DBModuleTests succeeding

* More DB tests passing

* Catch error and return.

* Replaced DatabaseFramework with DBModule

* Updated pathdb and add nil statement

* Removed debug code from ValueUtil, stopped embedding frameworks

* Added Swift-lint, and use NS lock for VPNState, Change in utils method in internal sdk.

* Combined TransactionManager and DatabaseManager

* Upgraded to latest pathdb to run in WAL mode, solving issue with crash on reopening database

* Fixed crash with userId.

* Updated pathdb.

* Updated pathdb.

* Run swift linter to fix linter issue and warnings.

* Removed not used files.

* Make changes to support localisation.

---------

Co-authored-by: Ox Cart <ox.to.a.cart@gmail.com>
  • Loading branch information
jigar-f and oxtoacart authored Oct 3, 2023
1 parent 720c2be commit 30cb3a3
Show file tree
Hide file tree
Showing 79 changed files with 4,903 additions and 1,811 deletions.
9 changes: 9 additions & 0 deletions DBModule/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
4 changes: 4 additions & 0 deletions DBModule/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.PHONY: test

test:
xcodebuild -scheme DBModule -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14,OS=16.4' test
14 changes: 14 additions & 0 deletions DBModule/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "sqlite.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stephencelis/SQLite.swift.git",
"state" : {
"revision" : "7a2e3cd27de56f6d396e84f63beefd0267b55ccb",
"version" : "0.14.1"
}
}
],
"version" : 2
}
33 changes: 33 additions & 0 deletions DBModule/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "DBModule",
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "DBModule",
targets: ["DBModule"]),
],
dependencies: [
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.binaryTarget(
name: "Internalsdk",
path: "../ios/internalsdk/Internalsdk.xcframework"),
.target(
name: "DBModule",
dependencies: [
"Internalsdk",
.product(name: "SQLite", package: "SQLite.swift"),
]),
.testTarget(
name: "DBModuleTests",
dependencies: ["DBModule"]),
]
)
231 changes: 231 additions & 0 deletions DBModule/Sources/DBModule/Database.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
//
// DB.swift
// Runner
//
// Created by jigar fumakiya on 28/07/23.
//

import Foundation
import Internalsdk
import SQLite

public struct DatabaseFactory {
public static func getDbManager(databasePath: String) throws -> MinisqlDBProtocol {
guard !databasePath.isEmpty else {
throw NSError(
domain: "DatabasePathError", code: 1,
userInfo: [NSLocalizedDescriptionKey: "Database path cannot be blank"])
}
let connection = try! Connection(databasePath)
connection.trace { print($0) }
return DatabaseManager(database: connection)
}
}

class DatabaseManager: NSObject, MinisqlDBProtocol, MinisqlTxProtocol {
private let database: Connection
private let transactional: Bool
private var currentTransaction: DatabaseManager?
private var savepointName: String?

init(database: Connection, transactional: Bool = false) {
self.database = database
self.transactional = transactional
}

// Static function to get an instance of DatabaseManager
// Expose to Client
static func getDbManager(databasePath: String) throws -> MinisqlDBProtocol {
guard !databasePath.isEmpty else {
throw NSError(
domain: "DatabasePathError", code: 1,
userInfo: [NSLocalizedDescriptionKey: "Database path cannot be blank"])
}
let connection = try! Connection(databasePath)
return DatabaseManager(database: connection)
}

public func begin() throws -> MinisqlTxProtocol {
currentTransaction = DatabaseManager(database: database, transactional: true)
return currentTransaction!
}

func commit() throws {
if let savepointName = savepointName {
try database.run("RELEASE '\(savepointName)'")
}
savepointName = nil
}

func rollback() throws {
if let savepointName = savepointName {
try database.run("ROLLBACK TO SAVEPOINT '\(savepointName)'")
try database.run("RELEASE '\(savepointName)'")
}
savepointName = nil
}

public func close() throws {
// Automatically manages the database connections
}

private func beginTransaction() throws {
savepointName = "Savepoint\(UUID().uuidString)"
if let savepointName = savepointName {
try database.run("SAVEPOINT '\(savepointName)'")
}
}

func exec(_ query: String?, args: MinisqlValuesProtocol?) throws -> MinisqlResultProtocol {
guard let query = query, let args = args else {
throw NSError(
domain: "ArgumentError", code: 1,
userInfo: [NSLocalizedDescriptionKey: "Query or arguments are nil"])
}

let bindings = ValueUtil.toBindingsArray(args)
let statement = try database.prepare(query)
// Start a transaction if none has been started yet
if transactional && savepointName == nil {
try beginTransaction()
}

try runStatement(statement, bindings)
return QueryResult(changes: database.changes)
}

func query(_ query: String?, args: MinisqlValuesProtocol?) throws -> MinisqlRowsProtocol {
guard let query = query, let args = args else {
throw NSError(
domain: "ArgumentError", code: 1,
userInfo: [NSLocalizedDescriptionKey: "Query or arguments are nil"])
}

let bindings = ValueUtil.toBindingsArray(args)
let statement = try database.prepare(query)
// Start a transaction if none has been started yet
if transactional && savepointName == nil {
try beginTransaction()
}

var rows: [Statement.Element] = []

for row in try runStatement(statement, bindings) {
rows.append(row)
}

return RowData(rows: rows)
}

func runStatement(_ statement: Statement, _ bindings: [Binding?]) throws -> Statement {
do {
return try statement.run(bindings)
} catch let SQLite.Result.error(message, code, _) {
throw NSError(domain: message, code: Int(code), userInfo: nil)
} catch let error {
throw NSError(domain: String(describing: error), code: 0, userInfo: nil)
}
}
}

class QueryResult: NSObject, MinisqlResultProtocol {
let changes: Int

init(changes: Int) {
self.changes = changes
}

func lastInsertId(_ ret0_: UnsafeMutablePointer<Int64>?) throws {
ret0_?.pointee = Int64(changes)
}

func rowsAffected(_ ret0_: UnsafeMutablePointer<Int64>?) throws {
ret0_?.pointee = Int64(changes)
}
}

class RowData: NSObject, MinisqlRowsProtocol {
let rows: [Statement.Element]
var currentIndex: Int = -1
private let syncQueue = DispatchQueue(label: "com.lantern.RowData.syncQueue")

init(rows: [Statement.Element]) {
self.rows = rows
}

func close() throws {
// Not sure what to put here
}

func next() -> Bool {
currentIndex += 1
return currentIndex < rows.count
}

/**
This method scans the current row and converts its values to `MinisqlValue` objects.
This method assumes that `values` is an object that supports setting values by index, and `rows` is an array of arrays where each inner array represents a row from a database and contains values of type `Binding`.
- Parameter values: An object that conforms to `MinisqlValuesProtocol`. This object will be populated with the values from the current row, converted to `MinisqlValue` objects.
- Throws: An `NSError` if `values` is `nil` or if `currentIndex` is outside the bounds of the `rows` array.
- Note: This method updates `currentIndex` to point to the next row. If there are no more rows, `next()` will return `false`.
*/
func scan(_ values: MinisqlValuesProtocol?) throws {
try syncQueue.sync {
if values == nil {
throw NSError(
domain: "Scan method failed", code: 0,
userInfo: [NSLocalizedDescriptionKey: "Values object is nil"])
}
if currentIndex >= rows.count {
throw NSError(
domain: "Scan method failed", code: 0,
userInfo: [NSLocalizedDescriptionKey: "Current index is out of bounds"])
}
let currentRow = rows[currentIndex]
for (index, value) in currentRow.enumerated() {
let miniSqlValue = values!.get(index)!
if value != nil {
ValueUtil.setValueFromBinding(binding: value!, value: miniSqlValue)
}
}
}
}
}

public struct ValueArrayFactory {
public static func createValueArrayHandler(values: [MinisqlValue]) -> MinisqlValuesProtocol {
return ValueArrayHandler(values: values)
}
}

class ValueArrayHandler: NSObject, MinisqlValuesProtocol {

var values: [MinisqlValue]

init(values: [MinisqlValue]) {
self.values = values
}

public func get(_ index: Int) -> MinisqlValue? {
guard index < values.count else {
return nil
}
return values[index]
}

func len() -> Int {
return values.count
}

func set(_ index: Int, value: MinisqlValue?) {
guard index < values.count else {
return
}

guard let value = value else {
return
}

values[index] = value
}
}
Loading

0 comments on commit 30cb3a3

Please sign in to comment.