diff --git a/.github/actions/archive/action.yml b/.github/actions/archive/action.yml index f33717e..c34bd3c 100644 --- a/.github/actions/archive/action.yml +++ b/.github/actions/archive/action.yml @@ -29,9 +29,6 @@ runs: xcodebuild archive \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ - -skipPackagePluginValidation \ - -skipMacroValidation \ - -onlyUsePackageVersionsFromResolvedFile \ -authenticationKeyID ${{ inputs.app-store-key-id }} \ -authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \ -authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \ diff --git a/.github/actions/build-for-testing/action.yml b/.github/actions/build-for-testing/action.yml index 2c66963..ce91b43 100644 --- a/.github/actions/build-for-testing/action.yml +++ b/.github/actions/build-for-testing/action.yml @@ -24,7 +24,6 @@ runs: path: | Apple/PackageCache Apple/SourcePackages - Apple/DerivedData key: ${{ runner.os }}-${{ inputs.scheme }}-${{ hashFiles('**/Package.resolved') }} restore-keys: | ${{ runner.os }}-${{ inputs.scheme }}- @@ -34,18 +33,17 @@ runs: run: | echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8 - xcodebuild build-for-testing \ + xcodebuild clean build-for-testing \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ - -skipPackagePluginValidation \ - -skipMacroValidation \ - -onlyUsePackageVersionsFromResolvedFile \ -authenticationKeyID ${{ inputs.app-store-key-id }} \ -authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \ -authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \ + -onlyUsePackageVersionsFromResolvedFile \ -clonedSourcePackagesDirPath SourcePackages \ -packageCachePath $PWD/PackageCache \ - -derivedDataPath $PWD/DerivedData \ + -skipPackagePluginValidation \ + -skipMacroValidation \ -scheme '${{ inputs.scheme }}' \ -destination '${{ inputs.destination }}' \ -resultBundlePath BuildResults.xcresult diff --git a/.github/actions/export/action.yml b/.github/actions/export/action.yml index 635732c..bf007a7 100644 --- a/.github/actions/export/action.yml +++ b/.github/actions/export/action.yml @@ -37,9 +37,6 @@ runs: -exportArchive \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ - -skipPackagePluginValidation \ - -skipMacroValidation \ - -onlyUsePackageVersionsFromResolvedFile \ -authenticationKeyID ${{ inputs.app-store-key-id }} \ -authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \ -authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \ diff --git a/.github/actions/notarize/action.yml b/.github/actions/notarize/action.yml deleted file mode 100644 index 739e9ea..0000000 --- a/.github/actions/notarize/action.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Notarize -inputs: - app-store-key: - description: App Store key in PEM PKCS#8 format - required: true - app-store-key-id: - description: App Store key ID - required: true - app-store-key-issuer-id: - description: App Store key issuer ID - required: true - archive-path: - description: Xcode archive path - required: true -outputs: - notarized-app: - description: The compressed and notarized app - value: ${{ steps.notarize.outputs.notarized-app }} -runs: - using: composite - steps: - - id: notarize - shell: bash - run: | - echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8 - - echo '{"destination":"upload","method":"developer-id"}' \ - | plutil -convert xml1 -o ExportOptions.plist - - - xcodebuild \ - -exportArchive \ - -allowProvisioningUpdates \ - -allowProvisioningDeviceRegistration \ - -authenticationKeyID ${{ inputs.app-store-key-id }} \ - -authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \ - -authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \ - -archivePath '${{ inputs.archive-path }}' \ - -exportOptionsPlist ExportOptions.plist - - until xcodebuild \ - -exportNotarizedApp \ - -allowProvisioningUpdates \ - -allowProvisioningDeviceRegistration \ - -authenticationKeyID ${{ inputs.app-store-key-id }} \ - -authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \ - -authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \ - -archivePath '${{ inputs.archive-path }}' \ - -exportPath Release - do - echo "Failed to export app, trying again in 10s..." - sleep 10 - done - - tar --options xz:compression-level=9 -C Release -cJvf Wallet.txz ./ - echo "notarized-app=Wallet.txz" >> $GITHUB_OUTPUT - - rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8 Release ExportOptions.plist diff --git a/.github/workflows/build-appimage.yml b/.github/workflows/build-appimage.yml deleted file mode 100644 index ef5c525..0000000 --- a/.github/workflows/build-appimage.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Build AppImage -on: - push: - branches: [main] - pull_request: -jobs: - appimage: - name: Build AppImage - runs-on: ubuntu-latest - container: docker - steps: - - uses: actions/checkout@v4 - - name: Build AppImage - run: | - docker build -t appimage-builder . -f burrow-gtk/build-aux/Dockerfile - docker create --name temp appimage-builder - docker cp temp:/app/burrow-gtk/build-appimage/Burrow-x86_64.AppImage . - docker rm temp - - uses: actions/upload-artifact@v4 - with: - name: AppImage - path: Burrow-x86_64.AppImage - diff --git a/.github/workflows/build-apple.yml b/.github/workflows/build-apple.yml index 19ef417..da0f56a 100644 --- a/.github/workflows/build-apple.yml +++ b/.github/workflows/build-apple.yml @@ -12,7 +12,7 @@ concurrency: jobs: build: name: Build App (${{ matrix.platform }}) - runs-on: macos-14 + runs-on: macos-13 strategy: fail-fast: false matrix: diff --git a/.github/workflows/build-flatpak.yml b/.github/workflows/build-flatpak.yml index d74eec3..e0e804e 100644 --- a/.github/workflows/build-flatpak.yml +++ b/.github/workflows/build-flatpak.yml @@ -1,4 +1,7 @@ -on: workflow_dispatch +on: + push: + branches: [main] + pull_request: name: Build Flatpak jobs: flatpak: diff --git a/.github/workflows/release-apple.yml b/.github/workflows/release-apple.yml index 6164ea6..3ea185d 100644 --- a/.github/workflows/release-apple.yml +++ b/.github/workflows/release-apple.yml @@ -1,27 +1,26 @@ name: Build Apple Release on: - pull_request: - branches: - - "*" + release: + types: + - created jobs: build: name: Build ${{ matrix.configuration['platform'] }} Release - runs-on: macos-14 + runs-on: macos-13 strategy: fail-fast: false matrix: configuration: - - destination: generic/platform=iOS + - scheme: App (iOS) + destination: generic/platform=iOS platform: iOS + method: ad-hoc artifact-file: Apple/Release/Burrow.ipa - rust-targets: - - aarch64-apple-ios - - destination: generic/platform=macOS + - scheme: App (macOS) + destination: generic/platform=macOS platform: macOS + method: mac-application artifact-file: Burrow.app.txz - rust-targets: - - x86_64-apple-darwin - - aarch64-apple-darwin env: DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer steps: @@ -35,36 +34,32 @@ jobs: with: certificate: ${{ secrets.DEVELOPER_CERT }} password: ${{ secrets.DEVELOPER_CERT_PASSWORD }} - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ join(matrix.rust-targets, ', ') }} - name: Archive uses: ./.github/actions/archive with: - scheme: App + scheme: ${{ matrix.configuration['scheme'] }} destination: ${{ matrix.configuration['destination'] }} app-store-key: ${{ secrets.APPSTORE_KEY }} app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }} app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }} archive-path: Burrow.xcarchive - - name: Upload + - name: Export Locally uses: ./.github/actions/export with: - method: app-store-connect - destination: upload + method: ${{ matrix.configuration['method'] }} + destination: export app-store-key: ${{ secrets.APPSTORE_KEY }} app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }} app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }} archive-path: Burrow.xcarchive export-path: Release - - name: Notarize + - name: Compress if: ${{ matrix.configuration['platform'] == 'macOS' }} - uses: ./.github/actions/notarize + shell: bash + run: tar --options xz:compression-level=9 -C Apple/Release -cJf Burrow.app.txz ./ + - name: Attach Artifact + uses: SierraSoftworks/gh-releases@v1.0.6 with: - app-store-key: ${{ secrets.APPSTORE_KEY }} - app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }} - app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }} - archive-path: Burrow.xcarchive - product-name: Burrow.app - + token: ${{ secrets.GITHUB_TOKEN }} + overwrite: 'false' + files: ${{ matrix.configuration['artifact-file'] }} diff --git a/.swiftlint.yml b/.swiftlint.yml index 22ef035..d609718 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -46,6 +46,7 @@ opt_in_rules: - multiline_parameters - multiline_parameters_brackets - no_extension_access_modifier +- no_grouping_extension - nslocalizedstring_key - nslocalizedstring_require_bundle - number_separator @@ -75,7 +76,9 @@ opt_in_rules: - sorted_first_last - sorted_imports - static_operator +- strict_fileprivate - strong_iboutlet +- switch_case_on_newline - test_case_accessibility - toggle_bool - trailing_closure @@ -94,5 +97,3 @@ disabled_rules: - force_try - nesting - todo -- trailing_comma -- switch_case_on_newline diff --git a/Apple/App/App.xcconfig b/Apple/App/App.xcconfig index 4e42ddc..1d63205 100644 --- a/Apple/App/App.xcconfig +++ b/Apple/App/App.xcconfig @@ -11,12 +11,7 @@ INFOPLIST_KEY_UIStatusBarStyle[sdk=iphone*] = UIStatusBarStyleDefault INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2 -EXCLUDED_SOURCE_FILE_NAMES = MainMenu.xib -EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*] = -INFOPLIST_KEY_LSUIElement[sdk=macosx*] = YES -INFOPLIST_KEY_NSMainNibFile[sdk=macosx*] = MainMenu -INFOPLIST_KEY_NSPrincipalClass[sdk=macosx*] = NSApplication INFOPLIST_KEY_LSApplicationCategoryType[sdk=macosx*] = public.app-category.utilities CODE_SIGN_ENTITLEMENTS = App/App-iOS.entitlements diff --git a/Apple/App/AppDelegate.swift b/Apple/App/AppDelegate.swift index 6085d85..f42b52f 100644 --- a/Apple/App/AppDelegate.swift +++ b/Apple/App/AppDelegate.swift @@ -3,7 +3,6 @@ import AppKit import SwiftUI @MainActor -@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { private let quitItem: NSMenuItem = { let quitItem = NSMenuItem( @@ -17,7 +16,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { }() private let toggleItem: NSMenuItem = { - let toggleView = NSHostingView(rootView: MenuItemToggleView()) + let toggleView = NSHostingView(rootView: MenuItemToggleView(tunnel: BurrowApp.tunnel)) toggleView.frame.size = CGSize(width: 300, height: 32) toggleView.autoresizingMask = [.width] diff --git a/Apple/App/Assets.xcassets/HackClub.colorset/Contents.json b/Apple/App/Assets.xcassets/HackClub.colorset/Contents.json deleted file mode 100644 index 911b4b1..0000000 --- a/Apple/App/Assets.xcassets/HackClub.colorset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "colors" : [ - { - "color" : { - "color-space" : "srgb", - "components" : { - "alpha" : "1.000", - "blue" : "0x50", - "green" : "0x37", - "red" : "0xEC" - } - }, - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Apple/App/Assets.xcassets/HackClub.imageset/Contents.json b/Apple/App/Assets.xcassets/HackClub.imageset/Contents.json deleted file mode 100644 index ddd0664..0000000 --- a/Apple/App/Assets.xcassets/HackClub.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "flag-standalone-wtransparent.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Apple/App/Assets.xcassets/HackClub.imageset/flag-standalone-wtransparent.pdf b/Apple/App/Assets.xcassets/HackClub.imageset/flag-standalone-wtransparent.pdf deleted file mode 100644 index 1506fe9..0000000 Binary files a/Apple/App/Assets.xcassets/HackClub.imageset/flag-standalone-wtransparent.pdf and /dev/null differ diff --git a/Apple/App/Assets.xcassets/WireGuard.colorset/Contents.json b/Apple/App/Assets.xcassets/WireGuard.colorset/Contents.json deleted file mode 100644 index 092ec69..0000000 --- a/Apple/App/Assets.xcassets/WireGuard.colorset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "colors" : [ - { - "color" : { - "color-space" : "srgb", - "components" : { - "alpha" : "1.000", - "blue" : "0x1A", - "green" : "0x17", - "red" : "0x88" - } - }, - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Apple/App/Assets.xcassets/WireGuard.imageset/Contents.json b/Apple/App/Assets.xcassets/WireGuard.imageset/Contents.json deleted file mode 100644 index e7fe15a..0000000 --- a/Apple/App/Assets.xcassets/WireGuard.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "filename" : "WireGuard.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/Apple/App/Assets.xcassets/WireGuard.imageset/WireGuard.svg b/Apple/App/Assets.xcassets/WireGuard.imageset/WireGuard.svg deleted file mode 100644 index 9520f89..0000000 --- a/Apple/App/Assets.xcassets/WireGuard.imageset/WireGuard.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Apple/App/Assets.xcassets/WireGuardTitle.imageset/Contents.json b/Apple/App/Assets.xcassets/WireGuardTitle.imageset/Contents.json deleted file mode 100644 index 782dd12..0000000 --- a/Apple/App/Assets.xcassets/WireGuardTitle.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "filename" : "WireGuardTitle.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Apple/App/Assets.xcassets/WireGuardTitle.imageset/WireGuardTitle.svg b/Apple/App/Assets.xcassets/WireGuardTitle.imageset/WireGuardTitle.svg deleted file mode 100644 index 64946da..0000000 --- a/Apple/App/Assets.xcassets/WireGuardTitle.imageset/WireGuardTitle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/Apple/App/BurrowApp.swift b/Apple/App/BurrowApp.swift index 21ebf84..e8aed86 100644 --- a/Apple/App/BurrowApp.swift +++ b/Apple/App/BurrowApp.swift @@ -1,13 +1,21 @@ import SwiftUI -#if !os(macOS) -@MainActor @main +@MainActor struct BurrowApp: App { + static let tunnel = Tunnel { manager, proto in + proto.serverAddress = "hackclub.com" + manager.localizedDescription = "Burrow" + } + + #if os(macOS) + @NSApplicationDelegateAdaptor(AppDelegate.self) + var delegate + #endif + var body: some Scene { WindowGroup { - BurrowView() + TunnelView(tunnel: Self.tunnel) } } } -#endif diff --git a/Apple/App/BurrowView.swift b/Apple/App/BurrowView.swift deleted file mode 100644 index b78b1e1..0000000 --- a/Apple/App/BurrowView.swift +++ /dev/null @@ -1,26 +0,0 @@ -import SwiftUI - -struct BurrowView: View { - var body: some View { - NavigationStack { - VStack { - NetworkCarouselView() - Spacer() - TunnelStatusView() - TunnelButton() - .padding(.bottom) - } - .padding() - .navigationTitle("Networks") - } - } -} - -#if DEBUG -struct NetworkView_Previews: PreviewProvider { - static var previews: some View { - BurrowView() - .environment(\.tunnel, PreviewTunnel()) - } -} -#endif diff --git a/Apple/App/FloatingButtonStyle.swift b/Apple/App/FloatingButtonStyle.swift deleted file mode 100644 index 53ab5ed..0000000 --- a/Apple/App/FloatingButtonStyle.swift +++ /dev/null @@ -1,50 +0,0 @@ -import SwiftUI - -struct FloatingButtonStyle: ButtonStyle { - static let duration = 0.08 - - var color: Color - var cornerRadius: CGFloat - - func makeBody(configuration: Configuration) -> some View { - configuration.label - .font(.headline) - .foregroundColor(.white) - .frame(minHeight: 48) - .padding(.horizontal) - .background( - RoundedRectangle(cornerRadius: cornerRadius) - .fill( - LinearGradient( - colors: [ - configuration.isPressed ? color.opacity(0.9) : color.opacity(0.9), - configuration.isPressed ? color.opacity(0.9) : color - ], - startPoint: .init(x: 0.2, y: 0), - endPoint: .init(x: 0.8, y: 1) - ) - ) - .background( - RoundedRectangle(cornerRadius: cornerRadius) - .fill(configuration.isPressed ? .black : .white) - ) - ) - .shadow(color: .black.opacity(configuration.isPressed ? 0.0 : 0.1), radius: 2.5, x: 0, y: 2) - .scaleEffect(configuration.isPressed ? 0.975 : 1.0) - .padding(.bottom, 2) - .animation( - configuration.isPressed ? .easeOut(duration: Self.duration) : .easeIn(duration: Self.duration), - value: configuration.isPressed - ) - } -} - -extension ButtonStyle where Self == FloatingButtonStyle { - static var floating: FloatingButtonStyle { - floating() - } - - static func floating(color: Color = .accentColor, cornerRadius: CGFloat = 10) -> FloatingButtonStyle { - FloatingButtonStyle(color: color, cornerRadius: cornerRadius) - } -} diff --git a/Apple/App/MainMenu.xib b/Apple/App/MainMenu.xib deleted file mode 100644 index 8933f30..0000000 --- a/Apple/App/MainMenu.xib +++ /dev/null @@ -1,679 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Apple/App/Menu/MenuView.swift b/Apple/App/Menu/MenuView.swift new file mode 100644 index 0000000..eab8da2 --- /dev/null +++ b/Apple/App/Menu/MenuView.swift @@ -0,0 +1,60 @@ +// +// MenuView.swift +// App +// +// Created by Thomas Stubblefield on 5/13/23. +// + +import SwiftUI + +struct MenuItemToggleView: View { + var tunnel: Tunnel + + var body: some View { + HStack { + Text("Burrow") + .font(.headline) + Spacer() + Toggle("Burrow", isOn: tunnel.isOn) + .labelsHidden() + .disabled(tunnel.isDisabled) + .toggleStyle(.switch) + } + .padding(.horizontal, 4) + .padding(10) + .frame(minWidth: 300, minHeight: 32, maxHeight: 32) + } +} + +extension Tunnel { + var isDisabled: Bool { + switch self.status { + case .disconnected, .permissionRequired, .connected: + return false + case .unknown, .disabled, .connecting, .reasserting, .disconnecting, .invalid, .configurationReadWriteFailed: + return true + } + } + + var isOn: Binding { + Binding { + switch self.status { + case .connecting, .reasserting, .connected: + true + default: + false + } + } set: { newValue in + switch (self.status, newValue) { + case (.permissionRequired, true): + Task { try await self.configure() } + case (.disconnected, true): + try? self.start() + case (.connected, false): + self.stop() + default: + return + } + } + } +} diff --git a/Apple/App/MenuItemToggleView.swift b/Apple/App/MenuItemToggleView.swift deleted file mode 100644 index 07db51d..0000000 --- a/Apple/App/MenuItemToggleView.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// MenuItemToggleView.swift -// App -// -// Created by Thomas Stubblefield on 5/13/23. -// - -import SwiftUI - -struct MenuItemToggleView: View { - @Environment(\.tunnel) - var tunnel: Tunnel - - var body: some View { - HStack { - VStack(alignment: .leading) { - Text("Burrow") - .font(.headline) - Text(tunnel.status.description) - .font(.subheadline) - } - Spacer() - Toggle(isOn: tunnel.toggleIsOn) { - } - .disabled(tunnel.toggleDisabled) - .toggleStyle(.switch) - } - .accessibilityElement(children: .combine) - .padding(.horizontal, 4) - .padding(10) - .frame(minWidth: 300, minHeight: 32, maxHeight: 32) - } -} - -extension Tunnel { - fileprivate var toggleDisabled: Bool { - switch status { - case .disconnected, .permissionRequired, .connected, .disconnecting: - false - case .unknown, .disabled, .connecting, .reasserting, .invalid, .configurationReadWriteFailed: - true - } - } - - var toggleIsOn: Binding { - Binding { - switch status { - case .connecting, .reasserting, .connected: - true - default: - false - } - } set: { newValue in - switch (status, newValue) { - case (.permissionRequired, true): - enable() - case (_, true): - start() - case (_, false): - stop() - } - } - } -} diff --git a/Apple/App/NetworkExtensionTunnel.swift b/Apple/App/NetworkExtensionTunnel.swift deleted file mode 100644 index 08002de..0000000 --- a/Apple/App/NetworkExtensionTunnel.swift +++ /dev/null @@ -1,167 +0,0 @@ -import BurrowShared -import NetworkExtension - -@Observable -class NetworkExtensionTunnel: Tunnel { - @MainActor private(set) var status: TunnelStatus = .unknown - private var error: NEVPNError? - - private let logger = Logger.logger(for: Tunnel.self) - private let bundleIdentifier: String - private var tasks: [Task] = [] - - // Each manager corresponds to one entry in the Settings app. - // Our goal is to maintain a single manager, so we create one if none exist and delete any extra. - private var managers: [NEVPNManager]? { - didSet { Task { await updateStatus() } } - } - - private var currentStatus: TunnelStatus { - guard let managers = managers else { - guard let error = error else { - return .unknown - } - - switch error.code { - case .configurationReadWriteFailed: - return .configurationReadWriteFailed - default: - return .unknown - } - } - - guard let manager = managers.first else { - return .permissionRequired - } - - guard manager.isEnabled else { - return .disabled - } - - return manager.connection.tunnelStatus - } - - convenience init() { - self.init(Constants.networkExtensionBundleIdentifier) - } - - init(_ bundleIdentifier: String) { - self.bundleIdentifier = bundleIdentifier - - let center = NotificationCenter.default - let configurationChanged = Task { [weak self] in - for try await _ in center.notifications(named: .NEVPNConfigurationChange).map({ _ in () }) { - await self?.update() - } - } - let statusChanged = Task { [weak self] in - for try await _ in center.notifications(named: .NEVPNStatusDidChange).map({ _ in () }) { - await self?.updateStatus() - } - } - tasks = [configurationChanged, statusChanged] - - Task { await update() } - } - - private func update() async { - do { - managers = try await NETunnelProviderManager.managers - await self.updateStatus() - } catch let vpnError as NEVPNError { - error = vpnError - } catch { - logger.error("Failed to update VPN configurations: \(error)") - } - } - - private func updateStatus() async { - await MainActor.run { - status = currentStatus - } - } - - func configure() async throws { - if managers == nil { - await update() - } - - guard let managers = managers else { return } - - if managers.count > 1 { - try await withThrowingTaskGroup(of: Void.self, returning: Void.self) { group in - for manager in managers.suffix(from: 1) { - group.addTask { try await manager.remove() } - } - try await group.waitForAll() - } - } - - guard managers.isEmpty else { return } - - let manager = NETunnelProviderManager() - manager.localizedDescription = "Burrow" - - let proto = NETunnelProviderProtocol() - proto.providerBundleIdentifier = bundleIdentifier - proto.serverAddress = "hackclub.com" - - manager.protocolConfiguration = proto - try await manager.save() - } - - func start() { - guard let manager = managers?.first else { return } - Task { - do { - if !manager.isEnabled { - manager.isEnabled = true - try await manager.save() - } - try manager.connection.startVPNTunnel() - } catch { - logger.error("Failed to start: \(error)") - } - } - } - - func stop() { - guard let manager = managers?.first else { return } - manager.connection.stopVPNTunnel() - } - - func enable() { - Task { - do { - try await configure() - } catch { - logger.error("Failed to enable: \(error)") - } - } - } - - deinit { - tasks.forEach { $0.cancel() } - } -} - -extension NEVPNConnection { - fileprivate var tunnelStatus: TunnelStatus { - switch status { - case .connected: - .connected(connectedDate!) - case .connecting: - .connecting - case .disconnecting: - .disconnecting - case .disconnected: - .disconnected - case .reasserting: - .reasserting - case .invalid: - .invalid - @unknown default: - .unknown - } - } -} diff --git a/Apple/App/NetworkView.swift b/Apple/App/NetworkView.swift deleted file mode 100644 index 290254c..0000000 --- a/Apple/App/NetworkView.swift +++ /dev/null @@ -1,88 +0,0 @@ -import SwiftUI - -struct NetworkView: View { - var color: Color - var content: () -> Content - - private var gradient: LinearGradient { - LinearGradient( - colors: [ - color.opacity(0.8), - color - ], - startPoint: .init(x: 0.2, y: 0), - endPoint: .init(x: 0.8, y: 1) - ) - } - - var body: some View { - content() - .frame(maxWidth: .infinity, minHeight: 175, maxHeight: 175) - .background( - RoundedRectangle(cornerRadius: 10) - .fill(gradient) - .background( - RoundedRectangle(cornerRadius: 10) - .fill(.white) - ) - ) - .shadow(color: .black.opacity(0.1), radius: 3.0, x: 0, y: 2) - } -} - -struct AddNetworkView: View { - var body: some View { - Text("Add Network") - .frame(maxWidth: .infinity, minHeight: 175, maxHeight: 175) - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(style: .init(lineWidth: 2, dash: [6])) - ) - } -} - -extension NetworkView where Content == AnyView { - init(network: any Network) { - color = network.backgroundColor - content = { AnyView(network.label) } - } -} - -struct NetworkCarouselView: View { - var networks: [any Network] = [ - HackClub(id: "1"), - HackClub(id: "2"), - WireGuard(id: "4"), - HackClub(id: "5"), - ] - - var body: some View { - ScrollView(.horizontal) { - LazyHStack { - ForEach(networks, id: \.id) { network in - NetworkView(network: network) - .containerRelativeFrame(.horizontal, count: 10, span: 7, spacing: 0, alignment: .center) - .scrollTransition(.interactive, axis: .horizontal) { content, phase in - content - .scaleEffect(1.0 - abs(phase.value) * 0.1) - } - } - AddNetworkView() - } - .scrollTargetLayout() - } - .scrollClipDisabled() - .scrollIndicators(.hidden) - .defaultScrollAnchor(.center) - .scrollTargetBehavior(.viewAligned) - .containerRelativeFrame(.horizontal) - } -} - -#if DEBUG -struct NetworkCarouselView_Previews: PreviewProvider { - static var previews: some View { - NetworkCarouselView() - } -} -#endif diff --git a/Apple/App/Networks/HackClub.swift b/Apple/App/Networks/HackClub.swift deleted file mode 100644 index f7df674..0000000 --- a/Apple/App/Networks/HackClub.swift +++ /dev/null @@ -1,23 +0,0 @@ -import SwiftUI - -struct HackClub: Network { - var id: String - var backgroundColor: Color { .init("HackClub") } - - var label: some View { - GeometryReader { reader in - VStack(alignment: .leading) { - Image("HackClub") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: reader.size.height / 4) - Spacer() - Text("@conradev") - .foregroundStyle(.white) - .font(.body.monospaced()) - } - .padding() - .frame(maxWidth: .infinity) - } - } -} diff --git a/Apple/App/Networks/Network.swift b/Apple/App/Networks/Network.swift deleted file mode 100644 index d441d24..0000000 --- a/Apple/App/Networks/Network.swift +++ /dev/null @@ -1,10 +0,0 @@ -import SwiftUI - -protocol Network { - associatedtype Label: View - - var id: String { get } - var backgroundColor: Color { get } - - var label: Label { get } -} diff --git a/Apple/App/Networks/WireGuard.swift b/Apple/App/Networks/WireGuard.swift deleted file mode 100644 index 499288a..0000000 --- a/Apple/App/Networks/WireGuard.swift +++ /dev/null @@ -1,30 +0,0 @@ -import SwiftUI - -struct WireGuard: Network { - var id: String - var backgroundColor: Color { .init("WireGuard") } - - var label: some View { - GeometryReader { reader in - VStack(alignment: .leading) { - HStack { - Image("WireGuard") - .resizable() - .aspectRatio(contentMode: .fit) - Image("WireGuardTitle") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: reader.size.width / 2) - Spacer() - } - .frame(maxWidth: .infinity, maxHeight: reader.size.height / 4) - Spacer() - Text("@conradev") - .foregroundStyle(.white) - .font(.body.monospaced()) - } - .padding() - .frame(maxWidth: .infinity) - } - } -} diff --git a/Apple/App/Status.swift b/Apple/App/Status.swift new file mode 100644 index 0000000..c08cdd1 --- /dev/null +++ b/Apple/App/Status.swift @@ -0,0 +1,42 @@ +import Foundation +import NetworkExtension + +extension Tunnel { + enum Status: CustomStringConvertible, Equatable, Hashable { + case unknown + case permissionRequired + case disabled + case connecting + case connected(Date) + case disconnecting + case disconnected + case reasserting + case invalid + case configurationReadWriteFailed + + var description: String { + switch self { + case .unknown: + return "Unknown" + case .permissionRequired: + return "Permission Required" + case .disconnected: + return "Disconnected" + case .disabled: + return "Disabled" + case .connecting: + return "Connecting" + case .connected: + return "Connected" + case .disconnecting: + return "Disconnecting" + case .reasserting: + return "Reasserting" + case .invalid: + return "Invalid" + case .configurationReadWriteFailed: + return "System Error" + } + } + } +} diff --git a/Apple/App/Tunnel.swift b/Apple/App/Tunnel.swift index 8db366f..5542170 100644 --- a/Apple/App/Tunnel.swift +++ b/Apple/App/Tunnel.swift @@ -1,50 +1,146 @@ +import BurrowShared +import NetworkExtension import SwiftUI -protocol Tunnel { - var status: TunnelStatus { get } - - func start() - func stop() - func enable() -} - -enum TunnelStatus: Equatable, Hashable { - case unknown - case permissionRequired - case disabled - case connecting - case connected(Date) - case disconnecting - case disconnected - case reasserting - case invalid - case configurationReadWriteFailed -} - -struct TunnelKey: EnvironmentKey { - static let defaultValue: any Tunnel = NetworkExtensionTunnel() -} - -extension EnvironmentValues { - var tunnel: any Tunnel { - get { self[TunnelKey.self] } - set { self[TunnelKey.self] = newValue } - } -} - -#if DEBUG @Observable -class PreviewTunnel: Tunnel { - var status: TunnelStatus = .permissionRequired +class Tunnel { + private(set) var status: Status = .unknown + private var error: NEVPNError? - func start() { - status = .connected(.now) + private let logger = Logger.logger(for: Tunnel.self) + private let bundleIdentifier: String + private let configure: (NETunnelProviderManager, NETunnelProviderProtocol) -> Void + private var tasks: [Task] = [] + + // Each manager corresponds to one entry in the Settings app. + // Our goal is to maintain a single manager, so we create one if none exist and delete extra if there are any. + private var managers: [NEVPNManager]? { + didSet { status = currentStatus } } + + private var currentStatus: Status { + guard let managers = managers else { + guard let error = error else { + return .unknown + } + + switch error.code { + case .configurationReadWriteFailed: + return .configurationReadWriteFailed + default: + return .unknown + } + } + + guard let manager = managers.first else { + return .permissionRequired + } + + guard manager.isEnabled else { + return .disabled + } + + return manager.connection.tunnelStatus + } + + convenience init(configure: @escaping (NETunnelProviderManager, NETunnelProviderProtocol) -> Void) { + self.init("com.hackclub.burrow.network", configure: configure) + } + + init(_ bundleIdentifier: String, configure: @escaping (NETunnelProviderManager, NETunnelProviderProtocol) -> Void) { + self.bundleIdentifier = bundleIdentifier + self.configure = configure + + let center = NotificationCenter.default + let configurationChanged = Task { + for try await _ in center.notifications(named: .NEVPNConfigurationChange).map({ _ in () }) { + await update() + } + } + let statusChanged = Task { + for try await _ in center.notifications(named: .NEVPNStatusDidChange).map({ _ in () }) { + await MainActor.run { + status = currentStatus + } + } + } + tasks = [configurationChanged, statusChanged] + + Task { await update() } + } + + private func update() async { + do { + let updated = try await NETunnelProviderManager.managers + await MainActor.run { + managers = updated + } + } catch let vpnError as NEVPNError { + error = vpnError + } catch { + logger.error("Failed to update VPN configurations: \(error)") + } + } + + func configure() async throws { + if managers == nil { + await update() + } + + guard let managers = managers else { return } + + if managers.count > 1 { + try await withThrowingTaskGroup(of: Void.self, returning: Void.self) { group in + for manager in managers.suffix(from: 1) { + group.addTask { try await manager.remove() } + } + try await group.waitForAll() + } + } + + if managers.isEmpty { + let manager = NETunnelProviderManager() + let proto = NETunnelProviderProtocol() + proto.providerBundleIdentifier = bundleIdentifier + configure(manager, proto) + + manager.protocolConfiguration = proto + try await manager.save() + } + } + + func start() throws { + guard let manager = managers?.first else { return } + try manager.connection.startVPNTunnel() + } + func stop() { - status = .disconnected + guard let manager = managers?.first else { return } + manager.connection.stopVPNTunnel() } - func enable() { - status = .disconnected + + deinit { + tasks.forEach { $0.cancel() } + } +} + +extension NEVPNConnection { + var tunnelStatus: Tunnel.Status { + switch status { + case .connected: + .connected(connectedDate!) + case .connecting: + .connecting + case .disconnecting: + .disconnecting + case .disconnected: + .disconnected + case .reasserting: + .reasserting + case .invalid: + .invalid + @unknown default: + .unknown + } } } -#endif diff --git a/Apple/App/TunnelButton.swift b/Apple/App/TunnelButton.swift deleted file mode 100644 index df8d7e6..0000000 --- a/Apple/App/TunnelButton.swift +++ /dev/null @@ -1,61 +0,0 @@ -import SwiftUI - -struct TunnelButton: View { - @Environment(\.tunnel) - var tunnel: any Tunnel - - var body: some View { - if let action = tunnel.action { - Button { - tunnel.perform(action) - } label: { - Text(action.description) - } - .padding(.horizontal) - .buttonStyle(.floating) - } - } -} - -extension Tunnel { - fileprivate var action: TunnelButton.Action? { - switch status { - case .permissionRequired, .invalid: - .enable - case .disabled, .disconnecting, .disconnected: - .start - case .connecting, .connected, .reasserting: - .stop - case .unknown, .configurationReadWriteFailed: - nil - } - } -} - -extension TunnelButton { - fileprivate enum Action { - case enable - case start - case stop - } -} - -extension TunnelButton.Action { - var description: LocalizedStringKey { - switch self { - case .enable: "Enable" - case .start: "Start" - case .stop: "Stop" - } - } -} - -extension Tunnel { - fileprivate func perform(_ action: TunnelButton.Action) { - switch action { - case .enable: enable() - case .start: start() - case .stop: stop() - } - } -} diff --git a/Apple/App/TunnelStatusView.swift b/Apple/App/TunnelStatusView.swift deleted file mode 100644 index 3593516..0000000 --- a/Apple/App/TunnelStatusView.swift +++ /dev/null @@ -1,37 +0,0 @@ -import SwiftUI - -struct TunnelStatusView: View { - @Environment(\.tunnel) - var tunnel: any Tunnel - - var body: some View { - Text(tunnel.status.description) - } -} - -extension TunnelStatus: CustomStringConvertible { - var description: String { - switch self { - case .unknown: - "Unknown" - case .permissionRequired: - "Permission Required" - case .disconnected: - "Disconnected" - case .disabled: - "Disabled" - case .connecting: - "Connecting…" - case .connected: - "Connected" - case .disconnecting: - "Disconnecting…" - case .reasserting: - "Reasserting…" - case .invalid: - "Invalid" - case .configurationReadWriteFailed: - "System Error" - } - } -} diff --git a/Apple/App/TunnelView.swift b/Apple/App/TunnelView.swift new file mode 100644 index 0000000..dd91603 --- /dev/null +++ b/Apple/App/TunnelView.swift @@ -0,0 +1,34 @@ +import SwiftUI + +struct TunnelView: View { + var tunnel: Tunnel + + var body: some View { + VStack { + Text(verbatim: tunnel.status.description) + switch tunnel.status { + case .connected: + Button("Disconnect", action: stop) + case .permissionRequired: + Button("Allow", action: configure) + case .disconnected: + Button("Start", action: start) + default: + EmptyView() + } + } + .padding() + } + + private func start() { + try? tunnel.start() + } + + private func stop() { + tunnel.stop() + } + + private func configure() { + Task { try await tunnel.configure() } + } +} diff --git a/Apple/Burrow.xcodeproj/project.pbxproj b/Apple/Burrow.xcodeproj/project.pbxproj index 8717a30..428d9ab 100644 --- a/Apple/Burrow.xcodeproj/project.pbxproj +++ b/Apple/Burrow.xcodeproj/project.pbxproj @@ -9,32 +9,24 @@ /* Begin PBXBuildFile section */ 0B28F1562ABF463A000D44B0 /* DataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B28F1552ABF463A000D44B0 /* DataTypes.swift */; }; 0B46E8E02AC918CA00BA2A3C /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B46E8DF2AC918CA00BA2A3C /* Client.swift */; }; - 43AA26D82A10004900F14CE6 /* MenuItemToggleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA26D72A10004900F14CE6 /* MenuItemToggleView.swift */; }; + 43AA26D82A10004900F14CE6 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA26D72A10004900F14CE6 /* MenuView.swift */; }; D00117312B2FFFC900D87C25 /* NWConnection+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00117302B2FFFC900D87C25 /* NWConnection+Async.swift */; }; D00117332B3001A400D87C25 /* NewlineProtocolFramer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00117322B3001A400D87C25 /* NewlineProtocolFramer.swift */; }; D001173B2B30341C00D87C25 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = D001173A2B30341C00D87C25 /* Logging.swift */; }; D00117442B30372900D87C25 /* libBurrowShared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D00117382B30341C00D87C25 /* libBurrowShared.a */; }; D00117452B30372C00D87C25 /* libBurrowShared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D00117382B30341C00D87C25 /* libBurrowShared.a */; }; D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00AA8962A4669BC005C8102 /* AppDelegate.swift */; }; - D01A79312B81630D0024EC91 /* NetworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01A79302B81630D0024EC91 /* NetworkView.swift */; }; D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */; }; D020F65D29E4A697002790F6 /* BurrowNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - D032E6522B8A79C20006B8AD /* HackClub.swift in Sources */ = {isa = PBXBuildFile; fileRef = D032E6512B8A79C20006B8AD /* HackClub.swift */; }; - D032E6542B8A79DA0006B8AD /* WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D032E6532B8A79DA0006B8AD /* WireGuard.swift */; }; D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */; }; - D05B9F7829E39EEC008CB1F9 /* BurrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7729E39EEC008CB1F9 /* BurrowView.swift */; }; + D05B9F7829E39EEC008CB1F9 /* TunnelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7729E39EEC008CB1F9 /* TunnelView.swift */; }; D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D05B9F7929E39EED008CB1F9 /* Assets.xcassets */; }; - D05EF8C82B81818D0017AB4F /* FloatingButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05EF8C72B81818D0017AB4F /* FloatingButtonStyle.swift */; }; D08252762B5C9FC4005DA378 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08252752B5C9FC4005DA378 /* Constants.swift */; }; - D09150422B9D2AF700BE3CB0 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D09150412B9D2AF700BE3CB0 /* MainMenu.xib */; }; D0BCC5FD2A086D4700AD070D /* NetworkExtension+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */; }; + D0BCC5FF2A086E1C00AD070D /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BCC5FE2A086E1C00AD070D /* Status.swift */; }; D0BCC6082A0981FE00AD070D /* Tunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B98FC629FDC5B5004E7149 /* Tunnel.swift */; }; D0BCC6092A09A03E00AD070D /* libburrow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCC6032A09535900AD070D /* libburrow.a */; }; D0BCC60A2A09A0B800AD070D /* build-rust.sh in Resources */ = {isa = PBXBuildFile; fileRef = D0B98FBF29FD8072004E7149 /* build-rust.sh */; }; - D0FAB5922B818A5900F6A84B /* NetworkExtensionTunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FAB5912B818A5900F6A84B /* NetworkExtensionTunnel.swift */; }; - D0FAB5962B818B2900F6A84B /* TunnelButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FAB5952B818B2900F6A84B /* TunnelButton.swift */; }; - D0FAB5982B818B8200F6A84B /* TunnelStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FAB5972B818B8200F6A84B /* TunnelStatusView.swift */; }; - D0FAB59A2B818B9600F6A84B /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FAB5992B818B9600F6A84B /* Network.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -78,7 +70,7 @@ /* Begin PBXFileReference section */ 0B28F1552ABF463A000D44B0 /* DataTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTypes.swift; sourceTree = ""; }; 0B46E8DF2AC918CA00BA2A3C /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; - 43AA26D72A10004900F14CE6 /* MenuItemToggleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuItemToggleView.swift; sourceTree = ""; }; + 43AA26D72A10004900F14CE6 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = ""; }; D00117302B2FFFC900D87C25 /* NWConnection+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NWConnection+Async.swift"; sourceTree = ""; }; D00117322B3001A400D87C25 /* NewlineProtocolFramer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewlineProtocolFramer.swift; sourceTree = ""; }; D00117382B30341C00D87C25 /* libBurrowShared.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBurrowShared.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -86,7 +78,6 @@ D00117412B30347800D87C25 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; D00117422B30348D00D87C25 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = ""; }; D00AA8962A4669BC005C8102 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - D01A79302B81630D0024EC91 /* NetworkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkView.swift; sourceTree = ""; }; D020F63D29E4A1FF002790F6 /* Identity.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = ""; }; D020F64029E4A1FF002790F6 /* Compiler.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = ""; }; D020F64229E4A1FF002790F6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -101,26 +92,19 @@ D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetworkExtension-iOS.entitlements"; sourceTree = ""; }; D020F66829E4AA74002790F6 /* App-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-iOS.entitlements"; sourceTree = ""; }; D020F66929E4AA74002790F6 /* App-macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-macOS.entitlements"; sourceTree = ""; }; - D032E6512B8A79C20006B8AD /* HackClub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HackClub.swift; sourceTree = ""; }; - D032E6532B8A79DA0006B8AD /* WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuard.swift; sourceTree = ""; }; D05B9F7229E39EEC008CB1F9 /* Burrow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Burrow.app; sourceTree = BUILT_PRODUCTS_DIR; }; D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowApp.swift; sourceTree = ""; }; - D05B9F7729E39EEC008CB1F9 /* BurrowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowView.swift; sourceTree = ""; }; + D05B9F7729E39EEC008CB1F9 /* TunnelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelView.swift; sourceTree = ""; }; D05B9F7929E39EED008CB1F9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - D05EF8C72B81818D0017AB4F /* FloatingButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingButtonStyle.swift; sourceTree = ""; }; D08252742B5C9DEB005DA378 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; }; D08252752B5C9FC4005DA378 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; - D09150412B9D2AF700BE3CB0 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; D0B98FBF29FD8072004E7149 /* build-rust.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-rust.sh"; sourceTree = ""; }; D0B98FC629FDC5B5004E7149 /* Tunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tunnel.swift; sourceTree = ""; }; D0B98FD829FDDB6F004E7149 /* libburrow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libburrow.h; sourceTree = ""; }; D0B98FDC29FDDDCF004E7149 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NetworkExtension+Async.swift"; sourceTree = ""; }; + D0BCC5FE2A086E1C00AD070D /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; D0BCC6032A09535900AD070D /* libburrow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libburrow.a; sourceTree = BUILT_PRODUCTS_DIR; }; - D0FAB5912B818A5900F6A84B /* NetworkExtensionTunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkExtensionTunnel.swift; sourceTree = ""; }; - D0FAB5952B818B2900F6A84B /* TunnelButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelButton.swift; sourceTree = ""; }; - D0FAB5972B818B8200F6A84B /* TunnelStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelStatusView.swift; sourceTree = ""; }; - D0FAB5992B818B9600F6A84B /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -151,6 +135,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 43AA26D62A0FFFD000F14CE6 /* Menu */ = { + isa = PBXGroup; + children = ( + 43AA26D72A10004900F14CE6 /* MenuView.swift */, + ); + path = Menu; + sourceTree = ""; + }; D00117392B30341C00D87C25 /* Shared */ = { isa = PBXGroup; children = ( @@ -207,16 +199,6 @@ path = NetworkExtension; sourceTree = ""; }; - D032E64D2B8A69C90006B8AD /* Networks */ = { - isa = PBXGroup; - children = ( - D0FAB5992B818B9600F6A84B /* Network.swift */, - D032E6512B8A79C20006B8AD /* HackClub.swift */, - D032E6532B8A79DA0006B8AD /* WireGuard.swift */, - ); - path = Networks; - sourceTree = ""; - }; D05B9F6929E39EEC008CB1F9 = { isa = PBXGroup; children = ( @@ -242,20 +224,14 @@ D05B9F7429E39EEC008CB1F9 /* App */ = { isa = PBXGroup; children = ( + 43AA26D62A0FFFD000F14CE6 /* Menu */, D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */, D00AA8962A4669BC005C8102 /* AppDelegate.swift */, - 43AA26D72A10004900F14CE6 /* MenuItemToggleView.swift */, - D05B9F7729E39EEC008CB1F9 /* BurrowView.swift */, - D01A79302B81630D0024EC91 /* NetworkView.swift */, - D032E64D2B8A69C90006B8AD /* Networks */, - D0FAB5972B818B8200F6A84B /* TunnelStatusView.swift */, - D0FAB5952B818B2900F6A84B /* TunnelButton.swift */, + D05B9F7729E39EEC008CB1F9 /* TunnelView.swift */, D0B98FC629FDC5B5004E7149 /* Tunnel.swift */, - D0FAB5912B818A5900F6A84B /* NetworkExtensionTunnel.swift */, + D0BCC5FE2A086E1C00AD070D /* Status.swift */, D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */, - D05EF8C72B81818D0017AB4F /* FloatingButtonStyle.swift */, D05B9F7929E39EED008CB1F9 /* Assets.xcassets */, - D09150412B9D2AF700BE3CB0 /* MainMenu.xib */, D020F66829E4AA74002790F6 /* App-iOS.entitlements */, D020F66929E4AA74002790F6 /* App-macOS.entitlements */, D020F64929E4A34B002790F6 /* App.xcconfig */, @@ -343,7 +319,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1510; - LastUpgradeCheck = 1520; + LastUpgradeCheck = 1430; TargetAttributes = { D00117372B30341C00D87C25 = { CreatedOnToolsVersion = 15.1; @@ -393,7 +369,6 @@ buildActionMask = 2147483647; files = ( D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */, - D09150422B9D2AF700BE3CB0 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -448,19 +423,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D0FAB59A2B818B9600F6A84B /* Network.swift in Sources */, D0BCC6082A0981FE00AD070D /* Tunnel.swift in Sources */, - D0FAB5982B818B8200F6A84B /* TunnelStatusView.swift in Sources */, - 43AA26D82A10004900F14CE6 /* MenuItemToggleView.swift in Sources */, - D05B9F7829E39EEC008CB1F9 /* BurrowView.swift in Sources */, - D0FAB5922B818A5900F6A84B /* NetworkExtensionTunnel.swift in Sources */, - D0FAB5962B818B2900F6A84B /* TunnelButton.swift in Sources */, + 43AA26D82A10004900F14CE6 /* MenuView.swift in Sources */, + D05B9F7829E39EEC008CB1F9 /* TunnelView.swift in Sources */, + D0BCC5FF2A086E1C00AD070D /* Status.swift in Sources */, D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */, - D05EF8C82B81818D0017AB4F /* FloatingButtonStyle.swift in Sources */, - D032E6522B8A79C20006B8AD /* HackClub.swift in Sources */, D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */, - D01A79312B81630D0024EC91 /* NetworkView.swift in Sources */, - D032E6542B8A79DA0006B8AD /* WireGuard.swift in Sources */, D0BCC5FD2A086D4700AD070D /* NetworkExtension+Async.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -600,8 +568,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/realm/SwiftLint.git"; requirement = { - branch = main; - kind = branch; + kind = upToNextMajorVersion; + minimumVersion = 0.54.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9378372..7522840 100644 --- a/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { - "revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531", - "version" : "1.2.3" + "revision" : "fee6933f37fde9a5e12a1e4aeaa93fe60116ff2a", + "version" : "1.2.2" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", - "version" : "509.1.1" + "revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036", + "version" : "509.0.2" } }, { @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/realm/SwiftLint.git", "state" : { - "branch" : "main", - "revision" : "7595ad3fafc1a31086dc40ba01fd898bf6b42d5f" + "revision" : "f17a4f9dfb6a6afb0408426354e4180daaf49cee", + "version" : "0.54.0" } }, { @@ -68,8 +68,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/drmohundro/SWXMLHash.git", "state" : { - "revision" : "a853604c9e9a83ad9954c7e3d2a565273982471f", - "version" : "7.0.2" + "revision" : "4d0f62f561458cbe1f732171e625f03195151b60", + "version" : "7.0.1" } }, { diff --git a/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme b/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme index 670823d..c63f8e6 100644 --- a/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme +++ b/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme @@ -1,6 +1,6 @@ : Codable where T: Codable { struct ServerConfigData: Codable { struct InternalConfig: Codable { - let address: [String] + let address: String? let name: String? let mtu: Int32? } diff --git a/Apple/NetworkExtension/PacketTunnelProvider.swift b/Apple/NetworkExtension/PacketTunnelProvider.swift index a07daa3..9231676 100644 --- a/Apple/NetworkExtension/PacketTunnelProvider.swift +++ b/Apple/NetworkExtension/PacketTunnelProvider.swift @@ -6,16 +6,10 @@ import os class PacketTunnelProvider: NEPacketTunnelProvider { private let logger = Logger.logger(for: PacketTunnelProvider.self) - override init() { - do { - libburrow.spawnInProcess(socketPath: try Constants.socketURL.path) - } catch { - logger.error("Failed to spawn: \(error)") - } - } - override func startTunnel(options: [String: NSObject]? = nil) async throws { do { + libburrow.spawnInProcess(socketPath: try Constants.socketURL.path) + let client = try Client() let command = BurrowRequest(id: 0, command: "ServerConfig") @@ -37,7 +31,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { command: BurrowStartRequest( Start: BurrowStartRequest.StartOptions( tun: BurrowStartRequest.TunOptions( - name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: [] + name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil ) ) ) @@ -50,34 +44,14 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } - override func stopTunnel(with reason: NEProviderStopReason) async { - do { - let client = try Client() - let command = BurrowRequest(id: 0, command: "Stop") - let data = try await client.request(command, type: Response>.self) - self.logger.log("Stopped client.") - } catch { - self.logger.error("Failed to stop tunnel: \(error)") - } - } - private func generateTunSettings(from: ServerConfigData) -> NETunnelNetworkSettings? { let cfig = from.ServerConfig - let nst = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "1.1.1.1") - var v4Addresses = [String]() - var v6Addresses = [String]() - for addr in cfig.address { - if IPv4Address(addr) != nil { - v6Addresses.append(addr) - } - if IPv6Address(addr) != nil { - v4Addresses.append(addr) - } + guard let addr = cfig.address else { + return nil } - nst.ipv4Settings = NEIPv4Settings(addresses: v4Addresses, subnetMasks: v4Addresses.map { _ in - "255.255.255.0" - }) - nst.ipv6Settings = NEIPv6Settings(addresses: v6Addresses, networkPrefixLengths: v6Addresses.map { _ in 64 }) + // Using a makeshift remote tunnel address + let nst = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "1.1.1.1") + nst.ipv4Settings = NEIPv4Settings(addresses: [addr], subnetMasks: ["255.255.255.0"]) logger.log("Initialized ipv4 settings: \(nst.ipv4Settings)") return nst } diff --git a/Apple/NetworkExtension/libburrow/build-rust.sh b/Apple/NetworkExtension/libburrow/build-rust.sh index fffa0d0..1ac73fb 100755 --- a/Apple/NetworkExtension/libburrow/build-rust.sh +++ b/Apple/NetworkExtension/libburrow/build-rust.sh @@ -56,10 +56,10 @@ CARGO_ARGS+=("--lib") # Pass the configuration (Debug or Release) through to cargo if [[ $SWIFT_ACTIVE_COMPILATION_CONDITIONS == *DEBUG* ]]; then - CARGO_TARGET_SUBDIR="debug" + CARGO_DIR="debug" else CARGO_ARGS+=("--release") - CARGO_TARGET_SUBDIR="release" + CARGO_DIR="release" fi if [[ -x "$(command -v rustup)" ]]; then @@ -70,11 +70,11 @@ fi # Run cargo without the various environment variables set by Xcode. # Those variables can confuse cargo and the build scripts it runs. -env -i PATH="$CARGO_PATH" CARGO_TARGET_DIR="${CONFIGURATION_TEMP_DIR}/target" cargo build "${CARGO_ARGS[@]}" +env -i PATH="$CARGO_PATH" cargo build "${CARGO_ARGS[@]}" mkdir -p "${BUILT_PRODUCTS_DIR}" # Use `lipo` to merge the architectures together into BUILT_PRODUCTS_DIR /usr/bin/xcrun --sdk $PLATFORM_NAME lipo \ - -create $(printf "${CONFIGURATION_TEMP_DIR}/target/%q/${CARGO_TARGET_SUBDIR}/libburrow.a " "${RUST_TARGETS[@]}") \ + -create $(printf "${PROJECT_DIR}/../target/%q/${CARGO_DIR}/libburrow.a " "${RUST_TARGETS[@]}") \ -output "${BUILT_PRODUCTS_DIR}/libburrow.a" diff --git a/Apple/Shared/Constants.swift b/Apple/Shared/Constants.swift index 634c500..cb56cb3 100644 --- a/Apple/Shared/Constants.swift +++ b/Apple/Shared/Constants.swift @@ -7,7 +7,6 @@ public enum Constants { public static let bundleIdentifier = AppBundleIdentifier public static let appGroupIdentifier = AppGroupIdentifier - public static let networkExtensionBundleIdentifier = NetworkExtensionBundleIdentifier public static var groupContainerURL: URL { get throws { try _groupContainerURL.get() } diff --git a/Apple/Shared/Constants/Constants.h b/Apple/Shared/Constants/Constants.h index 5278b61..09806c5 100644 --- a/Apple/Shared/Constants/Constants.h +++ b/Apple/Shared/Constants/Constants.h @@ -7,6 +7,5 @@ NS_ASSUME_NONNULL_BEGIN static NSString * const AppBundleIdentifier = MACRO_STRING(APP_BUNDLE_IDENTIFIER); static NSString * const AppGroupIdentifier = MACRO_STRING(APP_GROUP_IDENTIFIER); -static NSString * const NetworkExtensionBundleIdentifier = MACRO_STRING(NETWORK_EXTENSION_BUNDLE_IDENTIFIER); NS_ASSUME_NONNULL_END diff --git a/Apple/Shared/Shared.xcconfig b/Apple/Shared/Shared.xcconfig index f344e8b..50718bd 100644 --- a/Apple/Shared/Shared.xcconfig +++ b/Apple/Shared/Shared.xcconfig @@ -2,4 +2,4 @@ PRODUCT_NAME = BurrowShared MERGEABLE_LIBRARY = YES SWIFT_INCLUDE_PATHS = $(PROJECT_DIR)/Shared/Constants -GCC_PREPROCESSOR_DEFINITIONS = APP_BUNDLE_IDENTIFIER=$(APP_BUNDLE_IDENTIFIER) APP_GROUP_IDENTIFIER=$(APP_GROUP_IDENTIFIER) NETWORK_EXTENSION_BUNDLE_IDENTIFIER=$(NETWORK_EXTENSION_BUNDLE_IDENTIFIER) +GCC_PREPROCESSOR_DEFINITIONS = APP_BUNDLE_IDENTIFIER=$(APP_BUNDLE_IDENTIFIER) APP_GROUP_IDENTIFIER=$(APP_GROUP_IDENTIFIER) diff --git a/Cargo.lock b/Cargo.lock index a75bd28..85f11e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1074,7 +1074,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -2114,6 +2114,16 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.5" @@ -2295,7 +2305,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio-macros", "tracing", "windows-sys 0.48.0", @@ -2537,7 +2547,7 @@ dependencies = [ "reqwest", "schemars", "serde", - "socket2", + "socket2 0.4.10", "ssri", "tempfile", "tokio", diff --git a/Dockerfile b/Dockerfile index 9f54478..b1500bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/rust:1.76.0-slim-bookworm AS builder +FROM docker.io/library/rust:1.70.0-slim-bookworm AS builder ARG TARGETPLATFORM ARG LLVM_VERSION=16 diff --git a/Makefile b/Makefile index d0c9bd9..18b4b27 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -tun := $(shell ifconfig -l | sed 's/ /\n/g' | grep utun | tail -n 1) +tun_num := $(shell ifconfig | awk -F 'utun|[: ]' '/utun[0-9]/ {print $$2}' | tail -n 1) cargo_console := RUST_BACKTRACE=1 RUST_LOG=debug RUSTFLAGS='--cfg tokio_unstable' cargo run --all-features cargo_norm := RUST_BACKTRACE=1 RUST_LOG=debug cargo run @@ -17,33 +17,17 @@ daemon: start: @$(cargo_norm) start -stop: - @$(cargo_norm) stop - test-dns: @sudo route delete 8.8.8.8 - @sudo route add 8.8.8.8 -interface $(tun) + @sudo route add 8.8.8.8 -interface utun$(tun_num) @dig @8.8.8.8 hackclub.com test-https: @sudo route delete 193.183.0.162 - @sudo route add 193.183.0.162 -interface $(tun) + @sudo route add 193.183.0.162 -interface utun$(tun_num) @curl -vv https://search.marginalia.nu -v4_target := 146.190.62.39 test-http: - @sudo route delete ${v4_target} - @sudo route add ${v4_target} -interface $(tun) - @curl -vv ${v4_target}:80 - -test-ipv4: - @sudo route delete ${v4_target} - @sudo route add ${v4_target} -interface $(tun) - @ping ${v4_target} - -v6_target := 2001:4860:4860::8888 -test-ipv6: - @sudo route delete ${v6_target} - @sudo route -n add -inet6 ${v6_target} -interface $(tun) - @echo preparing - @sudo ping6 -v ${v6_target} + @sudo route delete 146.190.62.39 + @sudo route add 146.190.62.39 -interface utun$(tun_num) + @curl -vv 146.190.62.39:80 diff --git a/README.md b/README.md index 89914d0..7492039 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,13 @@ Burrow is an open source tool for burrowing through firewalls, built by teenager ## Contributing -Burrow is fully open source, you can fork the repo and start contributing easily. For more information and in-depth discussions, visit the `#burrow` channel on the [Hack Club Slack](https://hackclub.com/slack/), here you can ask for help and talk with other people interested in burrow! Checkout [GETTING_STARTED.md](./docs/GETTING_STARTED.md) for build instructions and [GTK_APP.md](./docs/GTK_APP.md) for the Linux app. +Burrow is fully open source, you can fork the repo and start contributing easily. For more information and in-depth discussions, visit the `#burrow` channel on the [Hack Club Slack](https://hackclub.com/slack/), here you can ask for help and talk with other people interested in burrow! For more information on how to contribute, please see [CONTRIBUTING.md] The project structure is divided in the following folders: ``` Apple/ # Xcode project for burrow on macOS and iOS burrow/ # Higher-level API library for tun and tun-async -burrow-gtk/ # GTK project for burrow on Linux tun/ # Low-level interface to OS networking src/ tokio/ # Async/Tokio code diff --git a/burrow-gtk/Cargo.lock b/burrow-gtk/Cargo.lock index 6721318..d0b7009 100644 --- a/burrow-gtk/Cargo.lock +++ b/burrow-gtk/Cargo.lock @@ -257,16 +257,16 @@ dependencies = [ "caps", "chacha20poly1305", "clap", - "console", + "env_logger", "fehler", "futures", "hmac", "ip_network", "ip_network_table", + "ipnet", "libsystemd", "log", - "nix 0.27.1", - "once_cell", + "nix", "parking_lot", "rand", "rand_core", @@ -281,6 +281,7 @@ dependencies = [ "tracing-oslog", "tracing-subscriber", "tun", + "uuid", "x25519-dalek", ] @@ -331,11 +332,11 @@ dependencies = [ [[package]] name = "cairo-rs" -version = "0.17.10" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "cairo-sys-rs", "glib", "libc", @@ -345,9 +346,9 @@ dependencies = [ [[package]] name = "cairo-sys-rs" -version = "0.17.10" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691d0c66b1fb4881be80a760cb8fe76ea97218312f9dfe2c9cc0f496ca279cb1" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ "glib-sys", "libc", @@ -500,19 +501,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "console" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.52.0", -] - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -629,12 +617,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "encoding_rs" version = "0.8.33" @@ -644,6 +626,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -735,14 +730,13 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", "nanorand", - "pin-project", "spin", ] @@ -873,11 +867,10 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.17.10" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" dependencies = [ - "bitflags 1.3.2", "gdk-pixbuf-sys", "gio", "glib", @@ -887,9 +880,9 @@ dependencies = [ [[package]] name = "gdk-pixbuf-sys" -version = "0.17.10" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9285ec3c113c66d7d0ab5676599176f1f42f4944ca1b581852215bf5694870cb" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" dependencies = [ "gio-sys", "glib-sys", @@ -900,11 +893,10 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.6.3" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3abf96408a26e3eddf881a7f893a1e111767137136e347745e8ea6ed12731ff" +checksum = "7edb019ad581f8ecf8ea8e4baa6df7c483a95b5a59be3140be6a9c3b0c632af6" dependencies = [ - "bitflags 1.3.2", "cairo-rs", "gdk-pixbuf", "gdk4-sys", @@ -916,9 +908,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.6.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc92aa1608c089c49393d014c38ac0390d01e4841e1fedaa75dbcef77aaed64" +checksum = "dbab43f332a3cf1df9974da690b5bb0e26720ed09a228178ce52175372dcfef0" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -982,11 +974,10 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gio" -version = "0.17.10" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" dependencies = [ - "bitflags 1.3.2", "futures-channel", "futures-core", "futures-io", @@ -1002,9 +993,9 @@ dependencies = [ [[package]] name = "gio-sys" -version = "0.17.10" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ccf87c30a12c469b6d958950f6a9c09f2be20b7773f7e70d20b867fdf2628c3" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" dependencies = [ "glib-sys", "gobject-sys", @@ -1015,11 +1006,11 @@ dependencies = [ [[package]] name = "glib" -version = "0.17.10" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "futures-channel", "futures-core", "futures-executor", @@ -1044,24 +1035,23 @@ checksum = "3431c56f463443cba9bc3600248bc6d680cb614c2ee1cdd39dab5415bd12ac5c" [[package]] name = "glib-macros" -version = "0.17.10" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" dependencies = [ - "anyhow", "heck", - "proc-macro-crate", + "proc-macro-crate 2.0.1", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] name = "glib-sys" -version = "0.17.10" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d80aa6ea7bba0baac79222204aa786a6293078c210abe69ef1336911d4bdc4f0" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" dependencies = [ "libc", "system-deps", @@ -1075,9 +1065,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gobject-sys" -version = "0.17.10" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd34c3317740a6358ec04572c1bcfd3ac0b5b6529275fae255b237b314bb8062" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" dependencies = [ "glib-sys", "libc", @@ -1086,9 +1076,9 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.17.10" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def4bb01265b59ed548b05455040d272d989b3012c42d4c1bbd39083cb9b40d9" +checksum = "3b2228cda1505613a7a956cca69076892cfbda84fc2b7a62b94a41a272c0c401" dependencies = [ "glib", "graphene-sys", @@ -1097,9 +1087,9 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.17.10" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1856fc817e6a6675e36cea0bd9a3afe296f5d9709d1e2d3182803ac77f0ab21d" +checksum = "cc4144cee8fc8788f2a9b73dc5f1d4e1189d1f95305c4cb7bd9c1af1cfa31f59" dependencies = [ "glib-sys", "libc", @@ -1109,11 +1099,10 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.6.3" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f01ef44fa7cac15e2da9978529383e6bee03e570ba5bf7036b4c10a15cc3a3c" +checksum = "0d958e351d2f210309b32d081c832d7de0aca0b077aa10d88336c6379bd01f7e" dependencies = [ - "bitflags 1.3.2", "cairo-rs", "gdk4", "glib", @@ -1125,9 +1114,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.6.3" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07a84fb4dcf1323d29435aa85e2f5f58bef564342bef06775ec7bd0da1f01b0" +checksum = "12bd9e3effea989f020e8f1ff3fa3b8c63ba93d43b899c11a118868853a56d55" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -1141,11 +1130,10 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.6.6" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28a32a04cd75cef14a0983f8b0c669e0fe152a0a7725accdeb594e2c764c88b" +checksum = "5aeb51aa3e9728575a053e1f43543cd9992ac2477e1b186ad824fd4adfb70842" dependencies = [ - "bitflags 1.3.2", "cairo-rs", "field-offset", "futures-channel", @@ -1158,18 +1146,17 @@ dependencies = [ "gtk4-macros", "gtk4-sys", "libc", - "once_cell", "pango", ] [[package]] name = "gtk4-macros" -version = "0.6.6" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a4d6b61570f76d3ee542d984da443b1cd69b6105264c61afec3abed08c2500f" +checksum = "d57ec49cf9b657f69a05bca8027cff0a8dfd0c49e812be026fc7311f2163832f" dependencies = [ "anyhow", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", @@ -1178,9 +1165,9 @@ dependencies = [ [[package]] name = "gtk4-sys" -version = "0.6.3" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8283f707b07e019e76c7f2934bdd4180c277e08aa93f4c0d8dd07b7a34e22f" +checksum = "54d8c4aa23638ce9faa2caf7e2a27d4a1295af2155c8e8d28c4d4eeca7a65eb8" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1290,6 +1277,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.28" @@ -1383,6 +1376,20 @@ name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +dependencies = [ + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.52.0", +] [[package]] name = "itoa" @@ -1422,11 +1429,10 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libadwaita" -version = "0.4.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab9c0843f9f23ff25634df2743690c3a1faffe0a190e60c490878517eb81abf" +checksum = "2fe7e70c06507ed10a16cda707f358fbe60fe0dc237498f78c686ade92fd979c" dependencies = [ - "bitflags 1.3.2", "gdk-pixbuf", "gdk4", "gio", @@ -1439,9 +1445,9 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.4.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4231cb2499a9f0c4cdfa4885414b33e39901ddcac61150bc0bb4ff8a57ede404" +checksum = "5e10aaa38de1d53374f90deeb4535209adc40cc5dba37f9704724169bceec69a" dependencies = [ "gdk4-sys", "gio-sys", @@ -1481,14 +1487,14 @@ dependencies = [ [[package]] name = "libsystemd" -version = "0.7.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c592dc396b464005f78a5853555b9f240bc5378bf5221acc4e129910b2678869" +checksum = "88b9597a67aa1c81a6624603e6bd0bcefb9e0f94c9c54970ec53771082104b4e" dependencies = [ "hmac", "libc", "log", - "nix 0.27.1", + "nix", "nom", "once_cell", "serde", @@ -1669,18 +1675,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "libc", - "memoffset 0.9.0", -] - [[package]] name = "nom" version = "7.1.3" @@ -1813,11 +1807,10 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pango" -version = "0.17.10" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" dependencies = [ - "bitflags 1.3.2", "gio", "glib", "libc", @@ -1827,9 +1820,9 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.17.10" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da69f9f3850b0d8990d462f8c709561975e95f689c1cdf0fecdebde78b35195" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" dependencies = [ "glib-sys", "gobject-sys", @@ -1901,26 +1894,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pin-project" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1988,6 +1961,16 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-crate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2115,9 +2098,8 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "relm4" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c16f3fad883034773b7f5af4d7e865532b8f3641e5a8bab2a34561a8d960d81" +version = "0.7.0-beta.2" +source = "git+https://github.com/Relm4/Relm4#e189eee06b887470e0fd65cbaf6d7c0161bed5ea" dependencies = [ "async-trait", "flume", @@ -2133,9 +2115,8 @@ dependencies = [ [[package]] name = "relm4-macros" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9340e2553c0a184a80a0bfa1dcf73c47f3d48933aa6be90724b202f9fbd24735" +version = "0.7.0-beta.2" +source = "git+https://github.com/Relm4/Relm4#e189eee06b887470e0fd65cbaf6d7c0161bed5ea" dependencies = [ "proc-macro2", "quote", @@ -2566,6 +2547,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.56" @@ -2643,7 +2633,6 @@ dependencies = [ "pin-project-lite", "socket2 0.5.5", "tokio-macros", - "tracing", "windows-sys 0.48.0", ] @@ -2850,7 +2839,7 @@ dependencies = [ "libc", "libloading 0.7.4", "log", - "nix 0.26.4", + "nix", "reqwest", "schemars", "serde", @@ -2936,6 +2925,7 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ + "getrandom", "serde", ] @@ -3088,6 +3078,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/burrow-gtk/Cargo.toml b/burrow-gtk/Cargo.toml index 21cb52e..244c161 100644 --- a/burrow-gtk/Cargo.toml +++ b/burrow-gtk/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0" -relm4 = { version = "0.6", features = ["libadwaita", "gnome_44"]} +relm4 = { features = ["libadwaita", "gnome_45"], git = "https://github.com/Relm4/Relm4" } burrow = { version = "*", path = "../burrow/" } tokio = { version = "1.35.0", features = ["time", "sync"] } gettext-rs = { version = "0.7.0", features = ["gettext-system"] } diff --git a/burrow-gtk/build-aux/Dockerfile b/burrow-gtk/build-aux/Dockerfile deleted file mode 100644 index df07c4a..0000000 --- a/burrow-gtk/build-aux/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM fedora:39 - -ENV DEBIAN_FRONTEND=noninteractive - -RUN set -eux && \ - dnf update -y && \ - dnf install -y clang ninja-build cmake meson gtk4-devel glib2-devel libadwaita-devel desktop-file-utils libappstream-glib util-linux wget fuse fuse-libs file - -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal -ENV PATH="/root/.cargo/bin:${PATH}" - -WORKDIR /app -COPY . /app - -RUN cd /app/burrow-gtk/ && \ - ./build-aux/build_appimage.sh - - diff --git a/burrow-gtk/build-aux/build_appimage.sh b/burrow-gtk/build-aux/build_appimage.sh deleted file mode 100755 index cd58c17..0000000 --- a/burrow-gtk/build-aux/build_appimage.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -set -ex - -BURROW_GTK_ROOT="$(readlink -f $(dirname -- "$(readlink -f -- "$BASH_SOURCE")")/..)" -BURROW_GTK_BUILD="$BURROW_GTK_ROOT/build-appimage" -LINUXDEPLOY_VERSION="${LINUXDEPLOY_VERSION:-"1-alpha-20240109-1"}" -BURROW_BUILD_TYPE="${BURROW_BUILD_TYPE:-"release"}" - -if [ "$BURROW_GTK_ROOT" != $(pwd) ]; then - echo "Make sure to cd into burrow-gtk" - exit 1 -fi - -ARCHITECTURE=$(lscpu | grep Architecture | awk '{print $2}') - -if [ "$ARCHITECTURE" == "x86_64" ]; then - wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/$LINUXDEPLOY_VERSION/linuxdeploy-x86_64.AppImage" -o /dev/null -O /tmp/linuxdeploy - chmod a+x /tmp/linuxdeploy -elif [ "$ARCHITECTURE" == "aarch64" ]; then - wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/$LINUXDEPLOY_VERSION/linuxdeploy-aarch64.AppImage" -o /dev/null -O /tmp/linuxdeploy - chmod a+x /tmp/linuxdeploy -fi - -meson setup $BURROW_GTK_BUILD --bindir bin --prefix /usr --buildtype $BURROW_BUILD_TYPE -meson compile -C $BURROW_GTK_BUILD -DESTDIR=AppDir meson install -C $BURROW_GTK_BUILD -cargo b --$BURROW_BUILD_TYPE --manifest-path=../Cargo.toml -/tmp/linuxdeploy --appimage-extract-and-run --appdir $BURROW_GTK_BUILD/AppDir -e $BURROW_GTK_BUILD/../../target/$BURROW_BUILD_TYPE/burrow --output appimage -mv *.AppImage $BURROW_GTK_BUILD diff --git a/burrow-gtk/meson.build b/burrow-gtk/meson.build index 8c2d5c1..70d8403 100644 --- a/burrow-gtk/meson.build +++ b/burrow-gtk/meson.build @@ -34,8 +34,8 @@ i18n = import('i18n') gnome = import('gnome') # External Dependencies -dependency('gtk4', version: '>= 4.0') -dependency('libadwaita-1', version: '>= 1.2') +dependency('gtk4', version: '>= 4.12') +dependency('libadwaita-1', version: '>= 1.4') glib_compile_resources = find_program('glib-compile-resources', required: true) glib_compile_schemas = find_program('glib-compile-schemas', required: true) diff --git a/burrow-gtk/src/components/app.rs b/burrow-gtk/src/components/app.rs index 62c98c0..b42b718 100644 --- a/burrow-gtk/src/components/app.rs +++ b/burrow-gtk/src/components/app.rs @@ -6,7 +6,7 @@ const RECONNECT_POLL_TIME: Duration = Duration::from_secs(5); pub struct App { daemon_client: Arc>>, - settings_screen: Controller, + _settings_screen: Controller, switch_screen: AsyncController, } @@ -81,35 +81,23 @@ impl AsyncComponent for App { let view_switcher_bar = adw::ViewSwitcherBar::builder().stack(&view_stack).build(); view_switcher_bar.set_reveal(true); - // When libadwaita 1.4 support becomes more avaliable, this approach is more appropriate - // - // let toolbar = adw::ToolbarView::new(); - // toolbar.add_top_bar( - // &adw::HeaderBar::builder() - // .title_widget(>k::Label::new(Some("Burrow"))) - // .build(), - // ); - // toolbar.add_bottom_bar(&view_switcher_bar); - // toolbar.set_content(Some(&view_stack)); - // root.set_content(Some(&toolbar)); - - let content = gtk::Box::new(gtk::Orientation::Vertical, 0); - content.append( + let toolbar = adw::ToolbarView::new(); + toolbar.add_top_bar( &adw::HeaderBar::builder() .title_widget(>k::Label::new(Some("Burrow"))) .build(), ); - content.append(&view_stack); - content.append(&view_switcher_bar); + toolbar.add_bottom_bar(&view_switcher_bar); + toolbar.set_content(Some(&view_stack)); - root.set_content(Some(&content)); + root.set_content(Some(&toolbar)); sender.input(AppMsg::PostInit); let model = App { daemon_client, switch_screen, - settings_screen, + _settings_screen: settings_screen, }; AsyncComponentParts { model, widgets } @@ -132,23 +120,14 @@ impl AsyncComponent for App { disconnected_daemon_client = true; self.switch_screen .emit(switch_screen::SwitchScreenMsg::DaemonDisconnect); - self.settings_screen - .emit(settings_screen::SettingsScreenMsg::DaemonStateChange) } } if disconnected_daemon_client || daemon_client.is_none() { - match DaemonClient::new().await { - Ok(new_daemon_client) => { - *daemon_client = Some(new_daemon_client); - self.switch_screen - .emit(switch_screen::SwitchScreenMsg::DaemonReconnect); - self.settings_screen - .emit(settings_screen::SettingsScreenMsg::DaemonStateChange) - } - Err(_e) => { - // TODO: Handle Error - } + *daemon_client = DaemonClient::new().await.ok(); + if daemon_client.is_some() { + self.switch_screen + .emit(switch_screen::SwitchScreenMsg::DaemonReconnect); } } } diff --git a/burrow-gtk/src/components/mod.rs b/burrow-gtk/src/components/mod.rs index b134809..b1cc938 100644 --- a/burrow-gtk/src/components/mod.rs +++ b/burrow-gtk/src/components/mod.rs @@ -18,4 +18,3 @@ mod settings_screen; mod switch_screen; pub use app::*; -pub use settings::{DaemonGroupMsg, DiagGroupMsg}; diff --git a/burrow-gtk/src/components/settings/daemon_group.rs b/burrow-gtk/src/components/settings/daemon_group.rs deleted file mode 100644 index 3817ca6..0000000 --- a/burrow-gtk/src/components/settings/daemon_group.rs +++ /dev/null @@ -1,111 +0,0 @@ -use super::*; -use std::process::Command; - -#[derive(Debug)] -pub struct DaemonGroup { - system_setup: SystemSetup, - daemon_client: Arc>>, - already_running: bool, -} - -pub struct DaemonGroupInit { - pub daemon_client: Arc>>, - pub system_setup: SystemSetup, -} - -#[derive(Debug)] -pub enum DaemonGroupMsg { - LaunchLocal, - DaemonStateChange, -} - -#[relm4::component(pub, async)] -impl AsyncComponent for DaemonGroup { - type Init = DaemonGroupInit; - type Input = DaemonGroupMsg; - type Output = (); - type CommandOutput = (); - - view! { - #[name(group)] - adw::PreferencesGroup { - #[watch] - set_sensitive: - (model.system_setup == SystemSetup::AppImage || model.system_setup == SystemSetup::Other) && - !model.already_running, - set_title: "Local Daemon", - set_description: Some("Run Local Daemon"), - - gtk::Button { - set_label: "Launch", - connect_clicked => DaemonGroupMsg::LaunchLocal - } - } - } - - async fn init( - init: Self::Init, - root: Self::Root, - sender: AsyncComponentSender, - ) -> AsyncComponentParts { - // Should be impossible to panic here - let model = DaemonGroup { - system_setup: init.system_setup, - daemon_client: init.daemon_client.clone(), - already_running: init.daemon_client.lock().await.is_some(), - }; - - let widgets = view_output!(); - - AsyncComponentParts { model, widgets } - } - - async fn update( - &mut self, - msg: Self::Input, - _sender: AsyncComponentSender, - _root: &Self::Root, - ) { - match msg { - DaemonGroupMsg::LaunchLocal => { - let burrow_original_bin = std::env::vars() - .find(|(k, _)| k == "APPDIR") - .map(|(_, v)| v + "/usr/bin/burrow") - .unwrap_or("/usr/bin/burrow".to_owned()); - - let mut burrow_bin = - String::from_utf8(Command::new("mktemp").output().unwrap().stdout).unwrap(); - burrow_bin.pop(); - - let privileged_spawn_script = format!( - r#"TEMP=$(mktemp -p /root) -cp {} $TEMP -chmod +x $TEMP -setcap CAP_NET_BIND_SERVICE,CAP_NET_ADMIN+eip $TEMP -mv $TEMP /tmp/burrow-detached-daemon"#, - burrow_original_bin - ) - .replace('\n', "&&"); - - // TODO: Handle error condition - - Command::new("pkexec") - .arg("sh") - .arg("-c") - .arg(privileged_spawn_script) - .arg(&burrow_bin) - .output() - .unwrap(); - - Command::new("/tmp/burrow-detached-daemon") - .env("RUST_LOG", "debug") - .arg("daemon") - .spawn() - .unwrap(); - } - DaemonGroupMsg::DaemonStateChange => { - self.already_running = self.daemon_client.lock().await.is_some(); - } - } - } -} diff --git a/burrow-gtk/src/components/settings/diag_group.rs b/burrow-gtk/src/components/settings/diag_group.rs index a15e0ea..be542cd 100644 --- a/burrow-gtk/src/components/settings/diag_group.rs +++ b/burrow-gtk/src/components/settings/diag_group.rs @@ -1,10 +1,11 @@ use super::*; +use diag::{StatusTernary, SystemSetup}; #[derive(Debug)] pub struct DiagGroup { daemon_client: Arc>>, - system_setup: SystemSetup, + init_system: SystemSetup, service_installed: StatusTernary, socket_installed: StatusTernary, socket_enabled: StatusTernary, @@ -13,20 +14,19 @@ pub struct DiagGroup { pub struct DiagGroupInit { pub daemon_client: Arc>>, - pub system_setup: SystemSetup, } impl DiagGroup { async fn new(daemon_client: Arc>>) -> Result { - let system_setup = SystemSetup::new(); + let setup = SystemSetup::new(); let daemon_running = daemon_client.lock().await.is_some(); Ok(Self { - service_installed: system_setup.is_service_installed()?, - socket_installed: system_setup.is_socket_installed()?, - socket_enabled: system_setup.is_socket_enabled()?, + service_installed: setup.is_service_installed()?, + socket_installed: setup.is_socket_installed()?, + socket_enabled: setup.is_socket_enabled()?, daemon_running, - system_setup, + init_system: setup, daemon_client, }) } @@ -52,7 +52,7 @@ impl AsyncComponent for DiagGroup { adw::ActionRow { #[watch] - set_title: &format!("System Type: {}", model.system_setup) + set_title: &format!("Init System: {}", model.init_system) }, adw::ActionRow { #[watch] diff --git a/burrow-gtk/src/components/settings/mod.rs b/burrow-gtk/src/components/settings/mod.rs index aa87db2..53f46d4 100644 --- a/burrow-gtk/src/components/settings/mod.rs +++ b/burrow-gtk/src/components/settings/mod.rs @@ -1,8 +1,5 @@ use super::*; -use diag::{StatusTernary, SystemSetup}; -mod daemon_group; mod diag_group; -pub use daemon_group::{DaemonGroup, DaemonGroupInit, DaemonGroupMsg}; -pub use diag_group::{DiagGroup, DiagGroupInit, DiagGroupMsg}; +pub use diag_group::{DiagGroup, DiagGroupInit}; diff --git a/burrow-gtk/src/components/settings_screen.rs b/burrow-gtk/src/components/settings_screen.rs index 971f262..778eb84 100644 --- a/burrow-gtk/src/components/settings_screen.rs +++ b/burrow-gtk/src/components/settings_screen.rs @@ -1,24 +1,17 @@ use super::*; -use diag::SystemSetup; pub struct SettingsScreen { - diag_group: AsyncController, - daemon_group: AsyncController, + _diag_group: AsyncController, } pub struct SettingsScreenInit { pub daemon_client: Arc>>, } -#[derive(Debug, PartialEq, Eq)] -pub enum SettingsScreenMsg { - DaemonStateChange, -} - #[relm4::component(pub)] impl SimpleComponent for SettingsScreen { type Init = SettingsScreenInit; - type Input = SettingsScreenMsg; + type Input = (); type Output = (); view! { @@ -28,44 +21,24 @@ impl SimpleComponent for SettingsScreen { fn init( init: Self::Init, - root: &Self::Root, + root: Self::Root, sender: ComponentSender, ) -> ComponentParts { - let system_setup = SystemSetup::new(); - let diag_group = settings::DiagGroup::builder() .launch(settings::DiagGroupInit { - system_setup, daemon_client: Arc::clone(&init.daemon_client), }) - .forward(sender.input_sender(), |_| { - SettingsScreenMsg::DaemonStateChange - }); - - let daemon_group = settings::DaemonGroup::builder() - .launch(settings::DaemonGroupInit { - system_setup, - daemon_client: Arc::clone(&init.daemon_client), - }) - .forward(sender.input_sender(), |_| { - SettingsScreenMsg::DaemonStateChange - }); + .forward(sender.input_sender(), |_| ()); let widgets = view_output!(); widgets.preferences.add(diag_group.widget()); - widgets.preferences.add(daemon_group.widget()); - let model = SettingsScreen { diag_group, daemon_group }; + let model = SettingsScreen { + _diag_group: diag_group, + }; ComponentParts { model, widgets } } - fn update(&mut self, _: Self::Input, _sender: ComponentSender) { - // Currently, `SettingsScreenMsg` only has one variant, so the if is ambiguous. - // - // if let SettingsScreenMsg::DaemonStateChange = msg { - self.diag_group.emit(DiagGroupMsg::Refresh); - self.daemon_group.emit(DaemonGroupMsg::DaemonStateChange); - // } - } + fn update(&mut self, _: Self::Input, _sender: ComponentSender) {} } diff --git a/burrow-gtk/src/components/switch_screen.rs b/burrow-gtk/src/components/switch_screen.rs index f660536..a296c09 100644 --- a/burrow-gtk/src/components/switch_screen.rs +++ b/burrow-gtk/src/components/switch_screen.rs @@ -29,7 +29,7 @@ impl AsyncComponent for SwitchScreen { view! { gtk::Box { set_orientation: gtk::Orientation::Vertical, - set_valign: Align::Fill, + set_valign: Align::BaselineFill, gtk::Box { set_orientation: gtk::Orientation::Vertical, diff --git a/burrow-gtk/src/diag.rs b/burrow-gtk/src/diag.rs index ab4757e..348293e 100644 --- a/burrow-gtk/src/diag.rs +++ b/burrow-gtk/src/diag.rs @@ -15,18 +15,15 @@ pub enum StatusTernary { // Realistically, we may not explicitly "support" non-systemd platforms which would simply this // code greatly. // Along with replacing [`StatusTernary`] with good old [`bool`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy)] pub enum SystemSetup { Systemd, - AppImage, Other, } impl SystemSetup { pub fn new() -> Self { - if is_appimage() { - SystemSetup::AppImage - } else if Command::new("systemctl").arg("--version").output().is_ok() { + if Command::new("systemctl").arg("--version").output().is_ok() { SystemSetup::Systemd } else { SystemSetup::Other @@ -36,7 +33,6 @@ impl SystemSetup { pub fn is_service_installed(&self) -> Result { match self { SystemSetup::Systemd => Ok(fs::metadata(SYSTEMD_SERVICE_LOC).is_ok().into()), - SystemSetup::AppImage => Ok(StatusTernary::NA), SystemSetup::Other => Ok(StatusTernary::NA), } } @@ -44,7 +40,6 @@ impl SystemSetup { pub fn is_socket_installed(&self) -> Result { match self { SystemSetup::Systemd => Ok(fs::metadata(SYSTEMD_SOCKET_LOC).is_ok().into()), - SystemSetup::AppImage => Ok(StatusTernary::NA), SystemSetup::Other => Ok(StatusTernary::NA), } } @@ -60,7 +55,6 @@ impl SystemSetup { let output = String::from_utf8(output)?; Ok((output == "enabled\n").into()) } - SystemSetup::AppImage => Ok(StatusTernary::NA), SystemSetup::Other => Ok(StatusTernary::NA), } } @@ -80,12 +74,7 @@ impl Display for SystemSetup { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { SystemSetup::Systemd => "Systemd", - SystemSetup::AppImage => "AppImage", SystemSetup::Other => "Other", }) } } - -pub fn is_appimage() -> bool { - std::env::vars().any(|(k, _)| k == "APPDIR") -} diff --git a/burrow-server-compose.yml b/burrow-server-compose.yml deleted file mode 100644 index 4ba31ee..0000000 --- a/burrow-server-compose.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: "2.1" -networks: - wg6: - enable_ipv6: true - ipam: - driver: default - config: - - subnet: "aa:bb:cc:de::/64" -services: - burrow: - image: lscr.io/linuxserver/wireguard:latest - privileged: true - container_name: burrow_server - cap_add: - - NET_ADMIN - - SYS_MODULE - environment: - - PUID=1000 - - PGID=1000 - - TZ=Asia/Calcutta - - SERVERURL=wg.burrow.rs - - SERVERPORT=51820 - - PEERS=10 - - PEERDNS=1.1.1.1 - - INTERNAL_SUBNET=10.13.13.0 - - ALLOWEDIPS=0.0.0.0/0, ::/0 - - PERSISTENTKEEPALIVE_PEERS=all - - LOG_CONFS=true #optional - volumes: - - ./config:/config - - /lib/modules:/lib/modules - ports: - - 51820:51820/udp - sysctls: - - net.ipv4.conf.all.src_valid_mark=1 - - net.ipv6.conf.all.disable_ipv6=0 - - net.ipv6.conf.eth0.proxy_ndp=1 - restart: unless-stopped \ No newline at end of file diff --git a/burrow/src/daemon/instance.rs b/burrow/src/daemon/instance.rs index 0d3e726..34e9878 100644 --- a/burrow/src/daemon/instance.rs +++ b/burrow/src/daemon/instance.rs @@ -21,7 +21,7 @@ enum RunState { pub struct DaemonInstance { rx: async_channel::Receiver, sx: async_channel::Sender, - tun_interface: Arc>>, + tun_interface: Option>>, wg_interface: Arc>, wg_state: RunState, } @@ -36,7 +36,7 @@ impl DaemonInstance { rx, sx, wg_interface, - tun_interface: Arc::new(RwLock::new(None)), + tun_interface: None, wg_state: RunState::Idle, } } @@ -50,15 +50,15 @@ impl DaemonInstance { warn!("Got start, but tun interface already up."); } RunState::Idle => { - let tun_if = st.tun.open()?; - debug!("Setting tun on wg_interface"); - self.wg_interface.read().await.set_tun(tun_if).await; - debug!("tun set on wg_interface"); + let tun_if = Arc::new(RwLock::new(st.tun.open()?)); debug!("Setting tun_interface"); - self.tun_interface = self.wg_interface.read().await.get_tun(); + self.tun_interface = Some(tun_if.clone()); debug!("tun_interface set: {:?}", self.tun_interface); + debug!("Setting tun on wg_interface"); + self.wg_interface.write().await.set_tun(tun_if); + debug!("tun set on wg_interface"); debug!("Cloning wg_interface"); let tmp_wg = self.wg_interface.clone(); @@ -82,18 +82,22 @@ impl DaemonInstance { } Ok(DaemonResponseData::None) } - DaemonCommand::ServerInfo => match &self.tun_interface.read().await.as_ref() { + DaemonCommand::ServerInfo => match &self.tun_interface { None => Ok(DaemonResponseData::None), Some(ti) => { info!("{:?}", ti); Ok(DaemonResponseData::ServerInfo(ServerInfo::try_from( - ti.inner.get_ref(), + ti.read().await.inner.get_ref(), )?)) } }, DaemonCommand::Stop => { - self.wg_interface.read().await.remove_tun().await; - self.wg_state = RunState::Idle; + if self.tun_interface.is_some() { + self.tun_interface = None; + info!("Daemon stopping tun interface."); + } else { + warn!("Got stop, but tun interface is not up.") + } Ok(DaemonResponseData::None) } DaemonCommand::ServerConfig => { diff --git a/burrow/src/daemon/response.rs b/burrow/src/daemon/response.rs index 37ee5d9..172d4c7 100644 --- a/burrow/src/daemon/response.rs +++ b/burrow/src/daemon/response.rs @@ -57,7 +57,7 @@ impl TryFrom<&TunInterface> for ServerInfo { #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct ServerConfig { - pub address: Vec, + pub address: Option, pub name: Option, pub mtu: Option, } @@ -65,7 +65,7 @@ pub struct ServerConfig { impl Default for ServerConfig { fn default() -> Self { Self { - address: vec!["10.13.13.2".to_string()], // Dummy remote address + address: Some("10.13.13.2".to_string()), // Dummy remote address name: None, mtu: None, } diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap index f78eeaa..0eb9096 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap @@ -2,4 +2,4 @@ source: burrow/src/daemon/command.rs expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions {\n tun: TunOptions { ..TunOptions::default() },\n })).unwrap()" --- -{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":[]}}} +{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}} diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap index eee563d..bfd5117 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap @@ -2,4 +2,4 @@ source: burrow/src/daemon/command.rs expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions::default())).unwrap()" --- -{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":[]}}} +{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}} diff --git a/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap b/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap index 0b9385c..9752ebc 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap @@ -2,4 +2,4 @@ source: burrow/src/daemon/response.rs expression: "serde_json::to_string(&DaemonResponse::new(Ok::(DaemonResponseData::ServerConfig(ServerConfig::default()))))?" --- -{"result":{"Ok":{"ServerConfig":{"address":["10.13.13.2"],"name":null,"mtu":null}}},"id":0} +{"result":{"Ok":{"ServerConfig":{"address":"10.13.13.2","name":null,"mtu":null}}},"id":0} diff --git a/burrow/src/main.rs b/burrow/src/main.rs index 71d1c02..79bb70b 100644 --- a/burrow/src/main.rs +++ b/burrow/src/main.rs @@ -55,7 +55,7 @@ async fn try_start() -> Result<()> { let mut client = DaemonClient::new().await?; client .send_command(DaemonCommand::Start(DaemonStartOptions { - tun: TunOptions::new().address(vec!["10.13.13.2", "::2"]), + tun: TunOptions::new().address("10.13.13.2"), })) .await .map(|_| ()) diff --git a/burrow/src/tracing.rs b/burrow/src/tracing.rs index 861b41f..279f45d 100644 --- a/burrow/src/tracing.rs +++ b/burrow/src/tracing.rs @@ -39,7 +39,6 @@ pub fn initialize() { tracing_subscriber::fmt::layer() .with_level(true) .with_writer(std::io::stderr) - .with_line_number(true) .compact() .with_filter(EnvFilter::from_default_env()) }); diff --git a/burrow/src/wireguard/config.rs b/burrow/src/wireguard/config.rs index ed7b3cd..afe7499 100644 --- a/burrow/src/wireguard/config.rs +++ b/burrow/src/wireguard/config.rs @@ -42,7 +42,7 @@ pub struct Peer { pub struct Interface { pub private_key: String, - pub address: Vec, + pub address: String, pub listen_port: u32, pub dns: Vec, pub mtu: Option, @@ -93,8 +93,8 @@ impl Default for Config { fn default() -> Self { Self { interface: Interface { - private_key: "OEPVdomeLTxTIBvv3TYsJRge0Hp9NMiY0sIrhT8OWG8=".into(), - address: vec!["10.13.13.2/24".into()], + private_key: "GNqIAOCRxjl/cicZyvkvpTklgQuUmGUIEkH7IXF/sEE=".into(), + address: "10.13.13.2/24".into(), listen_port: 51820, dns: Default::default(), mtu: Default::default(), @@ -102,8 +102,8 @@ impl Default for Config { peers: vec![Peer { endpoint: "wg.burrow.rs:51820".into(), allowed_ips: vec!["8.8.8.8/32".into(), "0.0.0.0/0".into()], - public_key: "8GaFjVO6c4luCHG4ONO+1bFG8tO+Zz5/Gy+Geht1USM=".into(), - preshared_key: Some("ha7j4BjD49sIzyF9SNlbueK0AMHghlj6+u0G3bzC698=".into()), + public_key: "uy75leriJay0+oHLhRMpV+A5xAQ0hCJ+q7Ww81AOvT4=".into(), + preshared_key: Some("s7lx/mg+reVEMnGnqeyYOQkzD86n2+gYnx1M9ygi08k=".into()), persistent_keepalive: Default::default(), name: Default::default(), }], diff --git a/burrow/src/wireguard/iface.rs b/burrow/src/wireguard/iface.rs index 6097082..620c96c 100755 --- a/burrow/src/wireguard/iface.rs +++ b/burrow/src/wireguard/iface.rs @@ -1,11 +1,10 @@ use std::{net::IpAddr, sync::Arc}; -use std::ops::Deref; use anyhow::Error; use fehler::throws; use futures::future::join_all; use ip_network_table::IpNetworkTable; -use tokio::sync::{RwLock, Notify}; +use tokio::sync::RwLock; use tracing::{debug, error}; use tun::tokio::TunInterface; @@ -47,21 +46,9 @@ impl FromIterator for IndexedPcbs { } } -enum IfaceStatus { - Running, - Idle -} - pub struct Interface { - tun: Arc>>, + tun: Option>>, pcbs: Arc, - status: Arc>, - stop_notifier: Arc, -} - -async fn is_running(status: Arc>) -> bool { - let st = status.read().await; - matches!(st.deref(), IfaceStatus::Running) } impl Interface { @@ -73,54 +60,35 @@ impl Interface { .collect::>()?; let pcbs = Arc::new(pcbs); - Self { pcbs, tun: Arc::new(RwLock::new(None)), status: Arc::new(RwLock::new(IfaceStatus::Idle)), stop_notifier: Arc::new(Notify::new()) } + Self { pcbs, tun: None } } - pub async fn set_tun(&self, tun: TunInterface) { - debug!("Setting tun interface"); - self.tun.write().await.replace(tun); - let mut st = self.status.write().await; - *st = IfaceStatus::Running; - } - - pub fn get_tun(&self) -> Arc>> { - self.tun.clone() - } - - pub async fn remove_tun(&self){ - let mut st = self.status.write().await; - self.stop_notifier.notify_waiters(); - *st = IfaceStatus::Idle; + pub fn set_tun(&mut self, tun: Arc>) { + self.tun = Some(tun); } pub async fn run(&self) -> anyhow::Result<()> { let pcbs = self.pcbs.clone(); let tun = self .tun - .clone(); - let status = self.status.clone(); - let stop_notifier = self.stop_notifier.clone(); + .clone() + .ok_or(anyhow::anyhow!("tun interface does not exist"))?; log::info!("Starting interface"); let outgoing = async move { - while is_running(status.clone()).await { + loop { let mut buf = [0u8; 3000]; let src = { - let t = tun.read().await; - let Some(_tun) = t.as_ref() else { - continue; + let src = match tun.read().await.recv(&mut buf[..]).await { + Ok(len) => &buf[..len], + Err(e) => { + error!("Failed to read from interface: {}", e); + continue + } }; - tokio::select! { - _ = stop_notifier.notified() => continue, - pkg = _tun.recv(&mut buf[..]) => match pkg { - Ok(len) => &buf[..len], - Err(e) => { - error!("Failed to read from interface: {}", e); - continue - } - }, - } + debug!("Read {} bytes from interface", src.len()); + src }; let dst_addr = match Tunnel::dst_address(src) { @@ -155,7 +123,8 @@ impl Interface { let mut tsks = vec![]; let tun = self .tun - .clone(); + .clone() + .ok_or(anyhow::anyhow!("tun interface does not exist"))?; let outgoing = tokio::task::spawn(outgoing); tsks.push(outgoing); debug!("preparing to spawn read tasks"); @@ -180,10 +149,9 @@ impl Interface { }; let pcb = pcbs.pcbs[i].clone(); - let status = self.status.clone(); let update_timers_tsk = async move { let mut buf = [0u8; 65535]; - while is_running(status.clone()).await { + loop { tokio::time::sleep(tokio::time::Duration::from_millis(250)).await; match pcb.update_timers(&mut buf).await { Ok(..) => (), @@ -196,9 +164,8 @@ impl Interface { }; let pcb = pcbs.pcbs[i].clone(); - let status = self.status.clone(); let reset_rate_limiter_tsk = async move { - while is_running(status.clone()).await { + loop { tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; pcb.reset_rate_limiter().await; } diff --git a/burrow/src/wireguard/pcb.rs b/burrow/src/wireguard/pcb.rs index 974d84e..db57968 100755 --- a/burrow/src/wireguard/pcb.rs +++ b/burrow/src/wireguard/pcb.rs @@ -54,7 +54,7 @@ impl PeerPcb { Ok(()) } - pub async fn run(&self, tun_interface: Arc>>) -> Result<(), Error> { + pub async fn run(&self, tun_interface: Arc>) -> Result<(), Error> { tracing::debug!("starting read loop for pcb... for {:?}", &self); let rid: i32 = random(); let mut buf: [u8; 3000] = [0u8; 3000]; @@ -106,12 +106,12 @@ impl PeerPcb { } TunnResult::WriteToTunnelV4(packet, addr) => { tracing::debug!("WriteToTunnelV4: {:?}, {:?}", packet, addr); - tun_interface.read().await.as_ref().ok_or(anyhow::anyhow!("tun interface does not exist"))?.send(packet).await?; + tun_interface.read().await.send(packet).await?; break } TunnResult::WriteToTunnelV6(packet, addr) => { tracing::debug!("WriteToTunnelV6: {:?}, {:?}", packet, addr); - tun_interface.read().await.as_ref().ok_or(anyhow::anyhow!("tun interface does not exist"))?.send(packet).await?; + tun_interface.read().await.send(packet).await?; break } } diff --git a/docs/GTK_APP.md b/docs/GTK_APP.md index ef73d2b..9b103a3 100644 --- a/docs/GTK_APP.md +++ b/docs/GTK_APP.md @@ -1,79 +1,22 @@ # Linux GTK App Getting Started -Currently, the GTK App can be built as a binary or as an AppImage. -Note that the flatpak version can compile but will not run properly! - ## Dependencies ### Install Build Dependencies -
- Debian - - > Note: Burrow currently cannot compile on Debian Stable (Bookworm) due to its outdated dependencies - - 1. Install build dependencies - - ``` - sudo apt install -y clang meson cmake pkg-config libgtk-4-dev libadwaita-1-dev gettext desktop-file-utils - ``` - - 2. Install flatpak builder (Optional) - - ``` - sudo apt install -y flatpak-builder - ``` - - 3. Install AppImage build tools (Optional) - - ``` - sudo apt install -y wget fuse file - ``` - -
-
Fedora - 1. Install build dependencies + 1. Install build dependencies ``` - sudo dnf install -y clang ninja-build cmake meson gtk4-devel glib2-devel libadwaita-devel desktop-file-utils libappstream-glib + sudo dnf install clang ninja cmake meson gtk4-devel glib2-devel libadwaita-devel desktop-file-utils libappstream-glib ``` 2. Install flatpak builder (Optional) ``` - sudo dnf install -y flatpak-builder - ``` - - 3. Install AppImage build tools (Optional) - - ``` - sudo dnf install -y util-linux wget fuse fuse-libs file - ``` - -
- -
- Void Linux (glibc) - - 1. Install build dependencies - - ``` - sudo xbps-install -Sy gcc clang meson cmake pkg-config gtk4-devel gettext desktop-file-utils gtk4-update-icon-cache appstream-glib - ``` - - 2. Install flatpak builder (Optional) - - ``` - sudo xbps-install -Sy flatpak-builder - ``` - - 3. Install AppImage build tools (Optional) - - ``` - sudo xbps-install -Sy wget fuse file + sudo dnf install flatpak-builder ```
@@ -108,10 +51,10 @@ flatpak install --user \
Flatpak - 1. Compile and install the flatpak + 1. Compile and install the flatpak ``` - flatpak-builder + flatpak-builder --user --install --force-clean --disable-rofiles-fuse \ flatpak_debug/ \ burrow-gtk/build-aux/com.hackclub.burrow.devel.json @@ -119,23 +62,6 @@ flatpak install --user \
-
- AppImage - - 1. Enter the `burrow-gtk` - - ```bash - cd burrow-gtk - ``` - - 2. Compile the AppImage - - ``` - ./build-aux/build_appimage.sh - ``` - -
- ## Running @@ -157,14 +83,3 @@ flatpak install --user \ ``` - -
- AppImage - - The compiled binary can be found in `build-appimage/Burrow-*.AppImage`. - - ``` - ./build-appimage/Burrow-*.AppImage - ``` - -
diff --git a/server_patch.txt b/server_patch.txt deleted file mode 100644 index de8e14c..0000000 --- a/server_patch.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Add this to ~/server/wg0.conf upon regeneration - -PostUp = iptables -A FORWARD -i %i -j ACCEPT - -PostUp = iptables -A FORWARD -o %i -j ACCEPT - -PostUp = iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE - -PostUp = ip6tables -A FORWARD -i %i -j ACCEPT - -PostUp = ip6tables -A FORWARD -o %i -j ACCEPT - -PostDown = iptables -D FORWARD -i %i -j ACCEPT - -PostDown = iptables -D FORWARD -o %i -j ACCEPT - -PostDown = iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE - -PostDown = ip6tables -D FORWARD -i %i -j ACCEPT - -PostDown = ip6tables -D FORWARD -o %i -j ACCEPT \ No newline at end of file diff --git a/tun/Cargo.toml b/tun/Cargo.toml index 7413f65..e67e45f 100644 --- a/tun/Cargo.toml +++ b/tun/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" libc = "0.2" fehler = "1.0" nix = { version = "0.26", features = ["ioctl"] } -socket2 = "0.5" +socket2 = "0.4" tokio = { version = "1.28", features = [] } byteorder = "1.4" tracing = "0.1" diff --git a/tun/src/options.rs b/tun/src/options.rs index e21bf5f..339f71a 100644 --- a/tun/src/options.rs +++ b/tun/src/options.rs @@ -21,7 +21,7 @@ pub struct TunOptions { /// (Apple) Retrieve the tun interface pub tun_retrieve: bool, /// (Linux) The IP address of the tun interface. - pub address: Vec, + pub address: Option, } impl TunOptions { @@ -44,8 +44,8 @@ impl TunOptions { self } - pub fn address(mut self, address: Vec) -> Self { - self.address = address.iter().map(|x| x.to_string()).collect(); + pub fn address(mut self, address: impl ToString) -> Self { + self.address = Some(address.to_string()); self } diff --git a/tun/src/unix/apple/kern_control.rs b/tun/src/unix/apple/kern_control.rs index 6075233..76e576f 100644 --- a/tun/src/unix/apple/kern_control.rs +++ b/tun/src/unix/apple/kern_control.rs @@ -21,7 +21,7 @@ impl SysControlSocket for socket2::Socket { unsafe { sys::resolve_ctl_info(self.as_raw_fd(), &mut info as *mut sys::ctl_info)? }; let (_, addr) = unsafe { - socket2::SockAddr::try_init(|addr_storage, len| { + socket2::SockAddr::init(|addr_storage, len| { *len = size_of::() as u32; let addr: &mut sys::sockaddr_ctl = &mut *addr_storage.cast(); diff --git a/tun/src/unix/apple/mod.rs b/tun/src/unix/apple/mod.rs index 6e859ca..2787cde 100644 --- a/tun/src/unix/apple/mod.rs +++ b/tun/src/unix/apple/mod.rs @@ -1,11 +1,13 @@ -use std::{io::{Error, IoSlice}, mem, net::{Ipv4Addr, SocketAddrV4}, os::fd::{AsRawFd, FromRawFd, RawFd}, ptr}; -use std::net::{IpAddr, Ipv6Addr, SocketAddrV6}; -use std::ptr::addr_of; +use std::{ + io::{Error, IoSlice}, + mem, + net::{Ipv4Addr, SocketAddrV4}, + os::fd::{AsRawFd, FromRawFd, RawFd}, +}; use byteorder::{ByteOrder, NetworkEndian}; use fehler::throws; -use libc::{c_char, iovec, writev, AF_INET, AF_INET6, sockaddr_in6}; -use nix::sys::socket::SockaddrIn6; +use libc::{c_char, iovec, writev, AF_INET, AF_INET6}; use socket2::{Domain, SockAddr, Socket, Type}; use tracing::{self, instrument}; @@ -47,7 +49,7 @@ impl TunInterface { pub fn retrieve() -> Option { (3..100) .filter_map(|fd| unsafe { - let peer_addr = socket2::SockAddr::try_init(|storage, len| { + let peer_addr = socket2::SockAddr::init(|storage, len| { *len = mem::size_of::() as u32; libc::getpeername(fd, storage as *mut _, len); Ok(()) @@ -69,12 +71,9 @@ impl TunInterface { #[throws] fn configure(&self, options: TunOptions) { - for addr in options.address{ - if let Ok(addr) = addr.parse::() { - match addr { - IpAddr::V4(addr) => {self.set_ipv4_addr(addr)?} - IpAddr::V6(addr) => {self.set_ipv6_addr(addr)?} - } + if let Some(addr) = options.address { + if let Ok(addr) = addr.parse() { + self.set_ipv4_addr(addr)?; } } } @@ -118,14 +117,6 @@ impl TunInterface { iff } - #[throws] - #[instrument] - fn in6_ifreq(&self) -> sys::in6_ifreq { - let mut iff: sys::in6_ifreq = unsafe { mem::zeroed() }; - iff.ifr_name = string_to_ifname(&self.name()?); - iff - } - #[throws] #[instrument] pub fn set_ipv4_addr(&self, addr: Ipv4Addr) { @@ -145,21 +136,6 @@ impl TunInterface { Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr)) } - #[throws] - pub fn set_ipv6_addr(&self, addr: Ipv6Addr) { - // let addr = SockAddr::from(SocketAddrV6::new(addr, 0, 0, 0)); - // println!("addr: {:?}", addr); - // let mut iff = self.in6_ifreq()?; - // let sto = addr.as_storage(); - // let ifadddr_ptr: *const sockaddr_in6 = addr_of!(sto).cast(); - // iff.ifr_ifru.ifru_addr = unsafe { *ifadddr_ptr }; - // println!("ifru addr set"); - // println!("{:?}", sys::SIOCSIFADDR_IN6); - // self.perform6(|fd| unsafe { sys::if_set_addr6(fd, &iff) })?; - // tracing::info!("ipv6_addr_set"); - tracing::warn!("Setting IPV6 address on MacOS CLI mode is not supported yet."); - } - #[throws] fn perform(&self, perform: impl FnOnce(RawFd) -> Result) -> R { let span = tracing::info_span!("perform", fd = self.as_raw_fd()); @@ -169,15 +145,6 @@ impl TunInterface { perform(socket.as_raw_fd())? } - #[throws] - fn perform6(&self, perform: impl FnOnce(RawFd) -> Result) -> R { - let span = tracing::info_span!("perform6", fd = self.as_raw_fd()); - let _enter = span.enter(); - - let socket = Socket::new(Domain::IPV6, Type::DGRAM, None)?; - perform(socket.as_raw_fd())? - } - #[throws] #[instrument] pub fn mtu(&self) -> i32 { diff --git a/tun/src/unix/apple/sys.rs b/tun/src/unix/apple/sys.rs index d48d6ee..b4d4a6a 100644 --- a/tun/src/unix/apple/sys.rs +++ b/tun/src/unix/apple/sys.rs @@ -1,6 +1,6 @@ use std::mem; -use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr, sockaddr_in6, time_t}; +use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr}; pub use libc::{ c_void, sockaddr_ctl, @@ -23,7 +23,6 @@ pub const UTUN_CONTROL_NAME: &str = "com.apple.net.utun_control"; pub const UTUN_OPT_IFNAME: libc::c_int = 2; pub const MAX_KCTL_NAME: usize = 96; -pub const SCOPE6_ID_MAX: usize = 16; #[repr(C)] #[derive(Copy, Clone, Debug)] @@ -75,107 +74,7 @@ pub struct ifreq { pub ifr_ifru: ifr_ifru, } -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct in6_addrlifetime{ - pub ia6t_expire: time_t, - pub ia6t_preferred: time_t, - pub ia6t_vltime: u32, - pub ia6t_pltime: u32, -} - -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct in6_ifstat { - pub ifs6_in_receive: u64, - pub ifs6_in_hdrerr: u64, - pub ifs6_in_toobig: u64, - pub ifs6_in_noroute: u64, - pub ifs6_in_addrerr: u64, - pub ifs6_in_protounknown: u64, - pub ifs6_in_truncated: u64, - pub ifs6_in_discard: u64, - pub ifs6_in_deliver: u64, - pub ifs6_out_forward: u64, - pub ifs6_out_request: u64, - pub ifs6_out_discard: u64, - pub ifs6_out_fragok: u64, - pub ifs6_out_fragfail: u64, - pub ifs6_out_fragcreat: u64, - pub ifs6_reass_reqd: u64, - pub ifs6_reass_ok: u64, - pub ifs6_atmfrag_rcvd: u64, - pub ifs6_reass_fail: u64, - pub ifs6_in_mcast: u64, - pub ifs6_out_mcast: u64, - pub ifs6_cantfoward_icmp6: u64, - pub ifs6_addr_expiry_cnt: u64, - pub ifs6_pfx_expiry_cnt: u64, - pub ifs6_defrtr_expiry_cnt: u64, -} - -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct icmp6_ifstat { - pub ifs6_in_msg: u64, - pub ifs6_in_error: u64, - pub ifs6_in_dstunreach: u64, - pub ifs6_in_adminprohib: u64, - pub ifs6_in_timeexceed: u64, - pub ifs6_in_paramprob: u64, - pub ifs6_in_pkttoobig: u64, - pub ifs6_in_echo: u64, - pub ifs6_in_echoreply: u64, - pub ifs6_in_routersolicit: u64, - pub ifs6_in_routeradvert: u64, - pub ifs6_in_neighborsolicit: u64, - pub ifs6_in_neighboradvert: u64, - pub ifs6_in_redirect: u64, - pub ifs6_in_mldquery: u64, - pub ifs6_in_mldreport: u64, - pub ifs6_in_mlddone: u64, - pub ifs6_out_msg: u64, - pub ifs6_out_error: u64, - pub ifs6_out_dstunreach: u64, - pub ifs6_out_adminprohib: u64, - pub ifs6_out_timeexceed: u64, - pub ifs6_out_paramprob: u64, - pub ifs6_out_pkttoobig: u64, - pub ifs6_out_echo: u64, - pub ifs6_out_echoreply: u64, - pub ifs6_out_routersolicit: u64, - pub ifs6_out_routeradvert: u64, - pub ifs6_out_neighborsolicit: u64, - pub ifs6_out_neighboradvert: u64, - pub ifs6_out_redirect: u64, - pub ifs6_out_mldquery: u64, - pub ifs6_out_mldreport: u64, - pub ifs6_out_mlddone: u64, -} - -#[repr(C)] -pub union ifr_ifru6 { - pub ifru_addr: sockaddr_in6, - pub ifru_dstaddr: sockaddr_in6, - pub ifru_flags: c_int, - pub ifru_flags6: c_int, - pub ifru_metric: c_int, - pub ifru_intval: c_int, - pub ifru_data: *mut c_char, - pub ifru_lifetime: in6_addrlifetime, // ifru_lifetime - pub ifru_stat: in6_ifstat, - pub ifru_icmp6stat: icmp6_ifstat, - pub ifru_scope_id: [u32; SCOPE6_ID_MAX] -} - -#[repr(C)] -pub struct in6_ifreq { - pub ifr_name: [c_char; IFNAMSIZ], - pub ifr_ifru: ifr_ifru6, -} - pub const SIOCSIFADDR: c_ulong = request_code_write!(b'i', 12, mem::size_of::()); -pub const SIOCSIFADDR_IN6: c_ulong = request_code_write!(b'i', 12, mem::size_of::()); pub const SIOCGIFMTU: c_ulong = request_code_readwrite!(b'i', 51, mem::size_of::()); pub const SIOCSIFMTU: c_ulong = request_code_write!(b'i', 52, mem::size_of::()); pub const SIOCGIFNETMASK: c_ulong = request_code_readwrite!(b'i', 37, mem::size_of::()); @@ -198,6 +97,5 @@ ioctl_read_bad!(if_get_addr, libc::SIOCGIFADDR, ifreq); ioctl_read_bad!(if_get_mtu, SIOCGIFMTU, ifreq); ioctl_read_bad!(if_get_netmask, SIOCGIFNETMASK, ifreq); ioctl_write_ptr_bad!(if_set_addr, SIOCSIFADDR, ifreq); -ioctl_write_ptr_bad!(if_set_addr6, SIOCSIFADDR_IN6, in6_ifreq); ioctl_write_ptr_bad!(if_set_mtu, SIOCSIFMTU, ifreq); ioctl_write_ptr_bad!(if_set_netmask, SIOCSIFNETMASK, ifreq); diff --git a/tun/tests/packets.rs b/tun/tests/packets.rs index 80c078b..28090a2 100644 --- a/tun/tests/packets.rs +++ b/tun/tests/packets.rs @@ -1,5 +1,4 @@ use std::{io::Error, net::Ipv4Addr}; -use std::net::Ipv6Addr; use fehler::throws; use tun::TunInterface; @@ -34,15 +33,3 @@ fn write_packets() { let bytes_written = tun.send(&buf)?; assert_eq!(bytes_written, 1504); } - -#[test] -#[throws] -#[ignore = "requires interactivity"] -#[cfg(not(target_os = "windows"))] -fn set_ipv6() { - let tun = TunInterface::new()?; - println!("tun name: {:?}", tun.name()?); - let targ_addr: Ipv6Addr = "::1".parse().unwrap(); - println!("v6 addr: {:?}", targ_addr); - tun.set_ipv6_addr(targ_addr)?; -} \ No newline at end of file