Initial commit
This commit is contained in:
commit
c1e7415871
56 changed files with 3225 additions and 0 deletions
8
.devcontainer.json
Normal file
8
.devcontainer.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/rust",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": ["rust-lang.rust-analyzer"]
|
||||
}
|
||||
}
|
||||
}
|
||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
* @conradev
|
||||
43
.github/actions/archive/action.yml
vendored
Normal file
43
.github/actions/archive/action.yml
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
name: Archive
|
||||
inputs:
|
||||
scheme:
|
||||
description: Scheme
|
||||
required: true
|
||||
destination:
|
||||
description: Destination
|
||||
required: true
|
||||
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
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
xcodebuild archive \
|
||||
-allowProvisioningUpdates \
|
||||
-allowProvisioningDeviceRegistration \
|
||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-scheme '${{ inputs.scheme }}' \
|
||||
-destination '${{ inputs.destination }}' \
|
||||
-archivePath '${{ inputs.archive-path }}' \
|
||||
-resultBundlePath BuildResults.xcresult
|
||||
|
||||
./Tools/xcresulttool-github BuildResults.xcresult
|
||||
|
||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
37
.github/actions/build-for-testing/action.yml
vendored
Normal file
37
.github/actions/build-for-testing/action.yml
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
name: Build For Testing
|
||||
inputs:
|
||||
scheme:
|
||||
description: Scheme
|
||||
required: true
|
||||
destination:
|
||||
description: Destination
|
||||
required: true
|
||||
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
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
xcodebuild clean build-for-testing \
|
||||
-allowProvisioningUpdates \
|
||||
-allowProvisioningDeviceRegistration \
|
||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||
-onlyUsePackageVersionsFromResolvedFile \
|
||||
-scheme '${{ inputs.scheme }}' \
|
||||
-destination '${{ inputs.destination }}' \
|
||||
-resultBundlePath BuildResults.xcresult
|
||||
|
||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
47
.github/actions/export/action.yml
vendored
Normal file
47
.github/actions/export/action.yml
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
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
|
||||
destination:
|
||||
description: The Xcode export destination. This can either be "export" or "upload"
|
||||
required: true
|
||||
method:
|
||||
description: The Xcode export method. This can be one of app-store, validation, ad-hoc, package, enterprise, development, developer-id, or mac-application.
|
||||
required: true
|
||||
export-path:
|
||||
description: The path to export the archive to
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- id: notarize
|
||||
shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||
|
||||
echo '{"destination":"${{ inputs.destination }}","method":"${{ inputs.method }}"}' \
|
||||
| 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 }}' \
|
||||
-exportPath '${{ inputs.export-path }}' \
|
||||
-exportOptionsPlist ExportOptions.plist
|
||||
|
||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8 ExportOptions.plist
|
||||
26
.github/actions/import-cert/action.yml
vendored
Normal file
26
.github/actions/import-cert/action.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
name: Import Certificate
|
||||
inputs:
|
||||
certificate:
|
||||
description: 'The certificate in p12 format, encoded as base64'
|
||||
required: true
|
||||
password:
|
||||
description: 'The certificate password'
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
run: |
|
||||
echo -n "${{ inputs.certificate }}" | base64 -d > Developer.p12
|
||||
security create-keychain -p password Developer.keychain
|
||||
security set-keychain-settings -lut 21600 Developer.keychain
|
||||
security unlock-keychain -p password Developer.keychain
|
||||
security import Developer.p12 \
|
||||
-k Developer.keychain \
|
||||
-f pkcs12 \
|
||||
-A \
|
||||
-T /usr/bin/codesign \
|
||||
-T /usr/bin/security \
|
||||
-P ${{ inputs.password }}
|
||||
security set-key-partition-list -S apple-tool:,apple: -k password Developer.keychain
|
||||
security list-keychains -d user -s login.keychain Developer.keychain
|
||||
37
.github/actions/test-without-building/action.yml
vendored
Normal file
37
.github/actions/test-without-building/action.yml
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
name: Test Without Building
|
||||
inputs:
|
||||
scheme:
|
||||
description: Scheme
|
||||
required: true
|
||||
destination:
|
||||
description: Destination
|
||||
required: true
|
||||
test-plan:
|
||||
description: Test Plan
|
||||
required: false
|
||||
artifact-prefix:
|
||||
description: The prefix for the filename of the uploaded xcresults file
|
||||
required: true
|
||||
check-name:
|
||||
description: The check name
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
- shell: bash
|
||||
working-directory: Apple
|
||||
run: |
|
||||
xcodebuild test-without-building \
|
||||
-scheme '${{ inputs.scheme }}' \
|
||||
-destination '${{ inputs.destination }}' \
|
||||
${{ inputs.test-plan && '-testPlan ' }}${{ inputs.test-plan }} \
|
||||
-resultBundlePath "${{ inputs.artifact-prefix }}-${{ steps.vars.outputs.sha_short }}.xcresult"
|
||||
- uses: kishikawakatsumi/xcresulttool@v1
|
||||
if: always()
|
||||
with:
|
||||
path: Apple/${{ inputs.artifact-prefix }}-${{ steps.vars.outputs.sha_short }}.xcresult
|
||||
title: ${{ inputs.check-name }}
|
||||
show-passed-tests: false
|
||||
70
.github/workflows/build-apple.yml
vendored
Normal file
70
.github/workflows/build-apple.yml
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
name: Apple Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
jobs:
|
||||
build:
|
||||
name: Build App (${{ matrix.platform }})
|
||||
runs-on: macos-12
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- scheme: App (iOS)
|
||||
destination: generic/platform=iOS
|
||||
platform: iOS
|
||||
sdk-name: iphoneos
|
||||
- scheme: App (iOS)
|
||||
destination: platform=iOS Simulator,OS=16.2,name=iPhone 14 Pro
|
||||
platform: iOS Simulator
|
||||
sdk-name: iphonesimulator
|
||||
- scheme: App (macOS)
|
||||
destination: platform=macOS
|
||||
platform: macOS
|
||||
sdk-name: macos
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||
submodules: recursive
|
||||
- name: Import Certificate
|
||||
uses: ./.github/actions/import-cert
|
||||
with:
|
||||
certificate: ${{ secrets.DEVELOPER_CERT }}
|
||||
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
||||
- name: Build
|
||||
id: build
|
||||
uses: ./.github/actions/build-for-testing
|
||||
with:
|
||||
scheme: ${{ matrix.scheme }}
|
||||
destination: ${{ matrix.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 }}
|
||||
- name: Xcode Unit Test
|
||||
if: ${{ matrix.xcode-unit-test != '' }}
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/test-without-building
|
||||
with:
|
||||
scheme: ${{ matrix.scheme }}
|
||||
destination: ${{ matrix.destination }}
|
||||
test-plan: ${{ matrix.xcode-unit-test }}
|
||||
artifact-prefix: unit-tests-${{ matrix.sdk-name }}
|
||||
check-name: Xcode Unit Tests (${{ matrix.platform }})
|
||||
- name: Xcode UI Test
|
||||
if: ${{ matrix.xcode-ui-test != '' }}
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/test-without-building
|
||||
with:
|
||||
scheme: ${{ matrix.scheme }}
|
||||
destination: ${{ matrix.destination }}
|
||||
test-plan: ${{ matrix.xcode-ui-test }}
|
||||
artifact-prefix: ui-tests-${{ matrix.sdk-name }}
|
||||
check-name: Xcode UI Tests (${{ matrix.platform }})
|
||||
55
.github/workflows/build-rust.yml
vendored
Normal file
55
.github/workflows/build-rust.yml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
name: Rust Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
jobs:
|
||||
build:
|
||||
name: Build Crate (${{ matrix.platform }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
platform: Linux
|
||||
targets:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- aarch64-unknown-linux-gnu
|
||||
- os: macos-12
|
||||
platform: macOS
|
||||
targets:
|
||||
- x86_64-apple-darwin
|
||||
- aarch64-apple-darwin
|
||||
- aarch64-apple-ios
|
||||
- aarch64-apple-ios-sim
|
||||
- x86_64-apple-ios
|
||||
- os: windows-2022
|
||||
platform: Windows
|
||||
targets:
|
||||
- x86_64-pc-windows-msvc
|
||||
- aarch64-pc-windows-msvc
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||
submodules: recursive
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: stable
|
||||
components: rustfmt
|
||||
targets: ${{ join(matrix.targets, ', ') }}
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: cargo build --verbose --workspace --all-features
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --all-features --target ${{ join(matrix.targets, ' --target ') }}
|
||||
20
.github/workflows/lint-git.yml
vendored
Normal file
20
.github/workflows/lint-git.yml
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
name: Git Lint
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
jobs:
|
||||
lint:
|
||||
name: Git Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Install Gitlint
|
||||
shell: bash
|
||||
run: python -m pip install gitlint
|
||||
- name: Run Gitlint
|
||||
shell: bash
|
||||
run: gitlint --commits "${{ github.event.pull_request.base.sha }}..HEAD"
|
||||
21
.github/workflows/lint-swift.yml
vendored
Normal file
21
.github/workflows/lint-swift.yml
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
name: Swift Lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
jobs:
|
||||
lint:
|
||||
name: Swift Lint
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/realm/swiftlint:latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||
- name: Lint
|
||||
run: swiftlint lint --reporter github-actions-logging
|
||||
65
.github/workflows/release-apple.yml
vendored
Normal file
65
.github/workflows/release-apple.yml
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
name: Build Apple Release
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.configuration['platform'] }} Release
|
||||
runs-on: macos-12
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
configuration:
|
||||
- scheme: App (iOS)
|
||||
destination: generic/platform=iOS
|
||||
platform: iOS
|
||||
method: ad-hoc
|
||||
artifact-file: Apple/Release/Burrow.ipa
|
||||
- scheme: App (macOS)
|
||||
destination: generic/platform=macOS
|
||||
platform: macOS
|
||||
method: mac-application
|
||||
artifact-file: Burrow.app.txz
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||
submodules: recursive
|
||||
- name: Import Certificate
|
||||
uses: ./.github/actions/import-cert
|
||||
with:
|
||||
certificate: ${{ secrets.DEVELOPER_CERT }}
|
||||
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
||||
- name: Archive
|
||||
uses: ./.github/actions/archive
|
||||
with:
|
||||
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: Export Locally
|
||||
uses: ./.github/actions/export
|
||||
with:
|
||||
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: Compress
|
||||
if: ${{ matrix.configuration['platform'] == 'macOS' }}
|
||||
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:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
overwrite: 'false'
|
||||
files: ${{ matrix.configuration['artifact-file'] }}
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Xcode
|
||||
xcuserdata
|
||||
|
||||
# Rust
|
||||
target/
|
||||
19
.gitlint
Normal file
19
.gitlint
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[general]
|
||||
ignore=body-changed-file-mention
|
||||
ignore-merge-commits=false
|
||||
ignore-fixup-commits=false
|
||||
ignore-squash-commits=false
|
||||
ignore-stdin=true
|
||||
fail-without-commits=true
|
||||
|
||||
[title-max-length]
|
||||
line-length=50
|
||||
|
||||
[body-max-line-length]
|
||||
line-length=72
|
||||
|
||||
[title-match-regex]
|
||||
regex=^(?!.*(#\d+))
|
||||
|
||||
[body-match-regex]
|
||||
regex=^(?!.*(#\d+))
|
||||
99
.swiftlint.yml
Normal file
99
.swiftlint.yml
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
opt_in_rules:
|
||||
- anonymous_argument_in_multiline_closure
|
||||
- array_init
|
||||
- attributes
|
||||
- closure_end_indentation
|
||||
- closure_spacing
|
||||
- collection_alignment
|
||||
- contains_over_filter_count
|
||||
- contains_over_filter_is_empty
|
||||
- contains_over_first_not_nil
|
||||
- contains_over_range_nil_comparison
|
||||
- convenience_type
|
||||
- discarded_notification_center_observer
|
||||
- discouraged_assert
|
||||
- discouraged_none_name
|
||||
- discouraged_object_literal
|
||||
- empty_collection_literal
|
||||
- empty_count
|
||||
- empty_string
|
||||
- empty_xctest_method
|
||||
- enum_case_associated_values_count
|
||||
- expiring_todo
|
||||
- explicit_init
|
||||
- fallthrough
|
||||
- fatal_error_message
|
||||
- file_header
|
||||
- file_name_no_space
|
||||
- first_where
|
||||
- flatmap_over_map_reduce
|
||||
- function_default_parameter_at_end
|
||||
- ibinspectable_in_extension
|
||||
- identical_operands
|
||||
- implicitly_unwrapped_optional
|
||||
- indentation_width
|
||||
- joined_default_parameter
|
||||
- last_where
|
||||
- legacy_multiple
|
||||
- legacy_random
|
||||
- literal_expression_end_indentation
|
||||
- lower_acl_than_parent
|
||||
- modifier_order
|
||||
- multiline_arguments
|
||||
- multiline_arguments_brackets
|
||||
- multiline_function_chains
|
||||
- multiline_literal_brackets
|
||||
- multiline_parameters
|
||||
- multiline_parameters_brackets
|
||||
- no_extension_access_modifier
|
||||
- no_grouping_extension
|
||||
- nslocalizedstring_key
|
||||
- nslocalizedstring_require_bundle
|
||||
- number_separator
|
||||
- object_literal
|
||||
- operator_usage_whitespace
|
||||
- optional_enum_case_matching
|
||||
- overridden_super_call
|
||||
- override_in_extension
|
||||
- pattern_matching_keywords
|
||||
- prefer_self_in_static_references
|
||||
- prefer_self_type_over_type_of_self
|
||||
- prefer_zero_over_explicit_init
|
||||
- private_action
|
||||
- private_outlet
|
||||
- private_subject
|
||||
- prohibited_interface_builder
|
||||
- prohibited_super_call
|
||||
- quick_discouraged_call
|
||||
- quick_discouraged_focused_test
|
||||
- quick_discouraged_pending_test
|
||||
- raw_value_for_camel_cased_codable_enum
|
||||
- reduce_into
|
||||
- redundant_nil_coalescing
|
||||
- redundant_type_annotation
|
||||
- required_enum_case
|
||||
- single_test_class
|
||||
- sorted_first_last
|
||||
- sorted_imports
|
||||
- static_operator
|
||||
- strict_fileprivate
|
||||
- strong_iboutlet
|
||||
- switch_case_on_newline
|
||||
- test_case_accessibility
|
||||
- toggle_bool
|
||||
- trailing_closure
|
||||
- type_contents_order
|
||||
- unavailable_function
|
||||
- unneeded_parentheses_in_closure_argument
|
||||
- unowned_variable_capture
|
||||
- untyped_error_in_catch
|
||||
- vertical_parameter_alignment_on_call
|
||||
- vertical_whitespace_closing_braces
|
||||
- vertical_whitespace_opening_braces
|
||||
- weak_delegate
|
||||
- xct_specific_matcher
|
||||
- yoda_condition
|
||||
disabled_rules:
|
||||
- force_try
|
||||
- nesting
|
||||
- todo
|
||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"rust-lang.rust-analyzer",
|
||||
]
|
||||
}
|
||||
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"files.autoSave": "onFocusChange",
|
||||
"files.defaultLanguage": "rust",
|
||||
"explorer.excludeGitIgnore": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"editor.suggest.preview": true,
|
||||
"editor.acceptSuggestionOnEnter": "on",
|
||||
"rust-analyzer.checkOnSave.command": "clippy",
|
||||
"rust-analyzer.restartServerOnConfigChange": true,
|
||||
"rust-analyzer.cargo.features": "all",
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||
},
|
||||
}
|
||||
17
.vscode/tasks.json
vendored
Normal file
17
.vscode/tasks.json
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cargo",
|
||||
"command": "check",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"label": "Check"
|
||||
}
|
||||
]
|
||||
}
|
||||
10
Apple/App/App-iOS.entitlements
Normal file
10
Apple/App/App-iOS.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
10
Apple/App/App-macOS.entitlements
Normal file
10
Apple/App/App-macOS.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
11
Apple/App/Assets.xcassets/AccentColor.colorset/Contents.json
Normal file
11
Apple/App/Assets.xcassets/AccentColor.colorset/Contents.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
63
Apple/App/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
63
Apple/App/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
6
Apple/App/Assets.xcassets/Contents.json
Normal file
6
Apple/App/Assets.xcassets/Contents.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
17
Apple/App/Burrow.xcconfig
Normal file
17
Apple/App/Burrow.xcconfig
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include "../Configuration/App.xcconfig"
|
||||
|
||||
PRODUCT_NAME = Burrow
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER)
|
||||
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphone*] = YES
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphone*] = YES
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphone*] = YES
|
||||
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
|
||||
|
||||
INFOPLIST_KEY_LSApplicationCategoryType[sdk=macos*] = public.app-category.utilities
|
||||
|
||||
CODE_SIGN_ENTITLEMENTS = App/App-iOS.entitlements
|
||||
CODE_SIGN_ENTITLEMENTS[sdk=macos*] = App/App-macOS.entitlements
|
||||
10
Apple/App/BurrowApp.swift
Normal file
10
Apple/App/BurrowApp.swift
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct BurrowApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Apple/App/ContentView.swift
Normal file
19
Apple/App/ContentView.swift
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
Image(systemName: "globe")
|
||||
.imageScale(.large)
|
||||
.foregroundColor(.accentColor)
|
||||
Text("Hello, world!")
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
334
Apple/Burrow.xcodeproj/project.pbxproj
Normal file
334
Apple/Burrow.xcodeproj/project.pbxproj
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 56;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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, ); }; };
|
||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */; };
|
||||
D05B9F7829E39EEC008CB1F9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7729E39EEC008CB1F9 /* ContentView.swift */; };
|
||||
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D05B9F7929E39EED008CB1F9 /* Assets.xcassets */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
D020F65B29E4A697002790F6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D020F65229E4A697002790F6;
|
||||
remoteInfo = BurrowNetworkExtension;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
D020F66129E4A697002790F6 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
D020F65D29E4A697002790F6 /* BurrowNetworkExtension.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = "<group>"; };
|
||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = "<group>"; };
|
||||
D020F64229E4A1FF002790F6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D020F64929E4A34B002790F6 /* Burrow.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Burrow.xcconfig; sourceTree = "<group>"; };
|
||||
D020F64A29E4A452002790F6 /* App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = App.xcconfig; sourceTree = "<group>"; };
|
||||
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BurrowNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
|
||||
D020F65929E4A697002790F6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetworkExtension.xcconfig; sourceTree = "<group>"; };
|
||||
D020F66329E4A703002790F6 /* Extension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Extension.xcconfig; sourceTree = "<group>"; };
|
||||
D020F66629E4A95D002790F6 /* NetworkExtension-macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetworkExtension-macOS.entitlements"; sourceTree = "<group>"; };
|
||||
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetworkExtension-iOS.entitlements"; sourceTree = "<group>"; };
|
||||
D020F66829E4AA74002790F6 /* App-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-iOS.entitlements"; sourceTree = "<group>"; };
|
||||
D020F66929E4AA74002790F6 /* App-macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-macOS.entitlements"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
D05B9F7729E39EEC008CB1F9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D020F65029E4A697002790F6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D05B9F6F29E39EEC008CB1F9 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D020F63C29E4A1FF002790F6 /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */,
|
||||
D020F64A29E4A452002790F6 /* App.xcconfig */,
|
||||
D020F66329E4A703002790F6 /* Extension.xcconfig */,
|
||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */,
|
||||
D020F64229E4A1FF002790F6 /* Info.plist */,
|
||||
);
|
||||
path = Configuration;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D020F65629E4A697002790F6 /* NetworkExtension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */,
|
||||
D020F65929E4A697002790F6 /* Info.plist */,
|
||||
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */,
|
||||
D020F66629E4A95D002790F6 /* NetworkExtension-macOS.entitlements */,
|
||||
D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */,
|
||||
);
|
||||
path = NetworkExtension;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D05B9F6929E39EEC008CB1F9 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D05B9F7429E39EEC008CB1F9 /* App */,
|
||||
D020F65629E4A697002790F6 /* NetworkExtension */,
|
||||
D020F63C29E4A1FF002790F6 /* Configuration */,
|
||||
D05B9F7329E39EEC008CB1F9 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D05B9F7329E39EEC008CB1F9 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D05B9F7229E39EEC008CB1F9 /* Burrow.app */,
|
||||
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D05B9F7429E39EEC008CB1F9 /* App */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */,
|
||||
D05B9F7729E39EEC008CB1F9 /* ContentView.swift */,
|
||||
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */,
|
||||
D020F66829E4AA74002790F6 /* App-iOS.entitlements */,
|
||||
D020F66929E4AA74002790F6 /* App-macOS.entitlements */,
|
||||
D020F64929E4A34B002790F6 /* Burrow.xcconfig */,
|
||||
);
|
||||
path = App;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D020F65229E4A697002790F6 /* NetworkExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */;
|
||||
buildPhases = (
|
||||
D020F64F29E4A697002790F6 /* Sources */,
|
||||
D020F65029E4A697002790F6 /* Frameworks */,
|
||||
D020F65129E4A697002790F6 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = NetworkExtension;
|
||||
productName = BurrowNetworkExtension;
|
||||
productReference = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
D05B9F7129E39EEC008CB1F9 /* Burrow */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D05B9F8129E39EED008CB1F9 /* Build configuration list for PBXNativeTarget "Burrow" */;
|
||||
buildPhases = (
|
||||
D05B9F6E29E39EEC008CB1F9 /* Sources */,
|
||||
D05B9F6F29E39EEC008CB1F9 /* Frameworks */,
|
||||
D05B9F7029E39EEC008CB1F9 /* Resources */,
|
||||
D020F66129E4A697002790F6 /* Embed Foundation Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Burrow;
|
||||
productName = Burrow;
|
||||
productReference = D05B9F7229E39EEC008CB1F9 /* Burrow.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
D05B9F6A29E39EEC008CB1F9 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1430;
|
||||
LastUpgradeCheck = 1430;
|
||||
TargetAttributes = {
|
||||
D020F65229E4A697002790F6 = {
|
||||
CreatedOnToolsVersion = 14.3;
|
||||
};
|
||||
D05B9F7129E39EEC008CB1F9 = {
|
||||
CreatedOnToolsVersion = 14.3;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D05B9F6D29E39EEC008CB1F9 /* Build configuration list for PBXProject "Burrow" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = D05B9F6929E39EEC008CB1F9;
|
||||
productRefGroup = D05B9F7329E39EEC008CB1F9 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D05B9F7129E39EEC008CB1F9 /* Burrow */,
|
||||
D020F65229E4A697002790F6 /* NetworkExtension */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
D020F65129E4A697002790F6 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D05B9F7029E39EEC008CB1F9 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D020F64F29E4A697002790F6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D05B9F6E29E39EEC008CB1F9 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D05B9F7829E39EEC008CB1F9 /* ContentView.swift in Sources */,
|
||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D020F65229E4A697002790F6 /* NetworkExtension */;
|
||||
targetProxy = D020F65B29E4A697002790F6 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D020F65F29E4A697002790F6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D020F66029E4A697002790F6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D05B9F7F29E39EED008CB1F9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F64029E4A1FF002790F6 /* Compiler.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D05B9F8029E39EED008CB1F9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F64029E4A1FF002790F6 /* Compiler.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D05B9F8229E39EED008CB1F9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F64929E4A34B002790F6 /* Burrow.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D05B9F8329E39EED008CB1F9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F64929E4A34B002790F6 /* Burrow.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D020F65F29E4A697002790F6 /* Debug */,
|
||||
D020F66029E4A697002790F6 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D05B9F6D29E39EEC008CB1F9 /* Build configuration list for PBXProject "Burrow" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D05B9F7F29E39EED008CB1F9 /* Debug */,
|
||||
D05B9F8029E39EED008CB1F9 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D05B9F8129E39EED008CB1F9 /* Build configuration list for PBXNativeTarget "Burrow" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D05B9F8229E39EED008CB1F9 /* Debug */,
|
||||
D05B9F8329E39EED008CB1F9 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
}
|
||||
7
Apple/Burrow.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
Apple/Burrow.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
10
Apple/Configuration/App.xcconfig
Normal file
10
Apple/Configuration/App.xcconfig
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
SKIP_INSTALL = NO
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=iphone*] = $(inherited) @executable_path/Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks
|
||||
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor
|
||||
|
||||
ENABLE_PREVIEWS = YES
|
||||
61
Apple/Configuration/Compiler.xcconfig
Normal file
61
Apple/Configuration/Compiler.xcconfig
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#include "Identity.xcconfig"
|
||||
|
||||
SDKROOT = auto
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES
|
||||
|
||||
SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO
|
||||
SUPPORTS_MACCATALYST = NO
|
||||
|
||||
ALWAYS_SEARCH_USER_PATHS = NO
|
||||
PRODUCT_NAME = $(TARGET_NAME:c99extidentifier)
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).$(PRODUCT_NAME)
|
||||
CURRENT_PROJECT_VERSION = 1
|
||||
MARKETING_VERSION = 0.1
|
||||
|
||||
SKIP_INSTALL = YES
|
||||
|
||||
CODE_SIGN_IDENTITY = Apple Development
|
||||
|
||||
INFOPLIST_FILE = Configuration/Info.plist
|
||||
GENERATE_INFOPLIST_FILE = YES
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023 Hack Club
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow
|
||||
|
||||
ENABLE_BITCODE = NO
|
||||
|
||||
ENABLE_APP_SANDBOX[sdk=macosx*] = YES
|
||||
ENABLE_HARDENED_RUNTIME[sdk=macosx*] = YES
|
||||
COMBINE_HIDPI_IMAGES = YES
|
||||
COPY_PHASE_STRIP = NO
|
||||
|
||||
FUSE_BUILD_SCRIPT_PHASES = YES
|
||||
|
||||
APP_GROUP_IDENTIFIER = group.$(APP_BUNDLE_IDENTIFIER)
|
||||
APP_GROUP_IDENTIFIER[sdk=macosx*] = $(DEVELOPMENT_TEAM).$(APP_BUNDLE_IDENTIFIER)
|
||||
|
||||
// Swift
|
||||
SWIFT_VERSION = 5.0
|
||||
SWIFT_EMIT_LOC_STRINGS = YES
|
||||
|
||||
// Release
|
||||
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
|
||||
SWIFT_REFLECTION_METADATA_LEVEL = none
|
||||
SWIFT_COMPILATION_MODE = wholemodule
|
||||
SWIFT_OPTIMIZATION_LEVEL = -Osize
|
||||
LLVM_LTO = YES
|
||||
DEAD_CODE_STRIPPING = YES
|
||||
VALIDATE_PRODUCT = YES
|
||||
|
||||
// Debug
|
||||
ONLY_ACTIVE_ARCH[config=Debug] = YES
|
||||
DEBUG_INFORMATION_FORMAT[config=Debug] = dwarf
|
||||
ENABLE_TESTABILITY[config=Debug] = YES
|
||||
SWIFT_OPTIMIZATION_LEVEL[config=Debug] = -Onone
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = DEBUG
|
||||
SWIFT_COMPILATION_MODE[config=Debug] = singlefile
|
||||
LLVM_LTO[config=Debug] = NO
|
||||
DEAD_CODE_STRIPPING[config=Debug] = NO
|
||||
VALIDATE_PRODUCT[config=Debug] = NO
|
||||
2
Apple/Configuration/Extension.xcconfig
Normal file
2
Apple/Configuration/Extension.xcconfig
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macos*] = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks
|
||||
2
Apple/Configuration/Identity.xcconfig
Normal file
2
Apple/Configuration/Identity.xcconfig
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
DEVELOPMENT_TEAM = 87PW93R2ZR
|
||||
APP_BUNDLE_IDENTIFIER = com.hackclub.burrow
|
||||
8
Apple/Configuration/Info.plist
Normal file
8
Apple/Configuration/Info.plist
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
|
||||
</dict>
|
||||
</plist>
|
||||
13
Apple/NetworkExtension/Info.plist
Normal file
13
Apple/NetworkExtension/Info.plist
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.networkextension.packet-tunnel</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
10
Apple/NetworkExtension/NetworkExtension-iOS.entitlements
Normal file
10
Apple/NetworkExtension/NetworkExtension-iOS.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
10
Apple/NetworkExtension/NetworkExtension-macOS.entitlements
Normal file
10
Apple/NetworkExtension/NetworkExtension-macOS.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
8
Apple/NetworkExtension/NetworkExtension.xcconfig
Normal file
8
Apple/NetworkExtension/NetworkExtension.xcconfig
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include "../Configuration/Extension.xcconfig"
|
||||
|
||||
PRODUCT_NAME = BurrowNetworkExtension
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).network
|
||||
INFOPLIST_FILE = NetworkExtension/Info.plist
|
||||
|
||||
CODE_SIGN_ENTITLEMENTS = NetworkExtension/NetworkExtension-iOS.entitlements
|
||||
CODE_SIGN_ENTITLEMENTS[sdk=macos*] = NetworkExtension/NetworkExtension-macOS.entitlements
|
||||
29
Apple/NetworkExtension/PacketTunnelProvider.swift
Normal file
29
Apple/NetworkExtension/PacketTunnelProvider.swift
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import NetworkExtension
|
||||
|
||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
|
||||
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
||||
// Add code here to start the process of connecting the tunnel.
|
||||
}
|
||||
|
||||
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
// Add code here to start the process of stopping the tunnel.
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
|
||||
// Add code here to handle the message.
|
||||
if let handler = completionHandler {
|
||||
handler(messageData)
|
||||
}
|
||||
}
|
||||
|
||||
override func sleep(completionHandler: @escaping () -> Void) {
|
||||
// Add code here to get ready to sleep.
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func wake() {
|
||||
// Add code here to wake up.
|
||||
}
|
||||
}
|
||||
1523
Cargo.lock
generated
Normal file
1523
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"burrow",
|
||||
"tun-async",
|
||||
"tun"
|
||||
]
|
||||
10
burrow/Cargo.toml
Normal file
10
burrow/Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "burrow"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.21", features = ["rt", "macros"] }
|
||||
tun = { version = "0.1", path = "../tun" }
|
||||
14
burrow/src/main.rs
Normal file
14
burrow/src/main.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use tokio::io::Result;
|
||||
use tun::TunInterface;
|
||||
|
||||
async fn lol() -> Result<()> {
|
||||
let iface = TunInterface::new()?;
|
||||
println!("{:?}", iface.name());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
lol().await.unwrap();
|
||||
}
|
||||
9
tun-async/Cargo.toml
Normal file
9
tun-async/Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "tun-async"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tun = { version = "0.1", path = "../tun" }
|
||||
14
tun-async/src/lib.rs
Normal file
14
tun-async/src/lib.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
24
tun/Cargo.toml
Normal file
24
tun/Cargo.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "tun"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
nix = { version = "0.25", features = ["ioctl"] }
|
||||
socket2 = "0.4"
|
||||
tokio = { version = "1.21", features = [] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
libloading = "0.7"
|
||||
widestring = "1.0"
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
anyhow = "1.0"
|
||||
bindgen = "0.61"
|
||||
hex-literal = "0.3"
|
||||
platforms = "3.0"
|
||||
reqwest = { version = "0.11", features = ["native-tls"] }
|
||||
sha2 = "0.10"
|
||||
tokio = { version = "1.21", features = ["rt"] }
|
||||
zip = { version = "0.6", features = ["deflate"] }
|
||||
79
tun/build.rs
Normal file
79
tun/build.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#[cfg(windows)]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
let buf = reqwest::get("https://www.wintun.net/builds/wintun-0.14.1.zip")
|
||||
.await?
|
||||
.bytes()
|
||||
.await?;
|
||||
assert_content_hash(
|
||||
&buf,
|
||||
hex_literal::hex!("07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51"),
|
||||
);
|
||||
let mut archive = zip::ZipArchive::new(Cursor::new(buf))?;
|
||||
|
||||
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?);
|
||||
|
||||
let mut header = String::new();
|
||||
archive
|
||||
.by_name("wintun/include/wintun.h")?
|
||||
.read_to_string(&mut header)?;
|
||||
header.push_str(
|
||||
"WINTUN_CLOSE_ADAPTER_FUNC WintunCloseAdapter;
|
||||
WINTUN_OPEN_ADAPTER_FUNC WintunOpenAdapter;
|
||||
WINTUN_GET_ADAPTER_LUID_FUNC WintunGetAdapterLUID;
|
||||
WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC WintunGetRunningDriverVersion;
|
||||
WINTUN_DELETE_DRIVER_FUNC WintunDeleteDriver;
|
||||
WINTUN_SET_LOGGER_FUNC WintunSetLogger;
|
||||
WINTUN_START_SESSION_FUNC WintunStartSession;
|
||||
WINTUN_END_SESSION_FUNC WintunEndSession;
|
||||
WINTUN_CREATE_ADAPTER_FUNC WintunCreateAdapter;
|
||||
WINTUN_GET_READ_WAIT_EVENT_FUNC WintunGetReadWaitEvent;
|
||||
WINTUN_RECEIVE_PACKET_FUNC WintunReceivePacket;
|
||||
WINTUN_RELEASE_RECEIVE_PACKET_FUNC WintunReleaseReceivePacket;
|
||||
WINTUN_ALLOCATE_SEND_PACKET_FUNC WintunAllocateSendPacket;
|
||||
WINTUN_SEND_PACKET_FUNC WintunSendPacket;",
|
||||
);
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header_contents("wintun.h", &header)
|
||||
.allowlist_function("Wintun.*")
|
||||
.allowlist_type("WINTUN_.*")
|
||||
.dynamic_library_name("wintun")
|
||||
.dynamic_link_require_all(true)
|
||||
.generate()
|
||||
.unwrap();
|
||||
bindings.write_to_file(out_dir.join("wintun.rs"))?;
|
||||
|
||||
let mut library = Vec::new();
|
||||
let platform = platforms::Platform::find(&env::var("TARGET")?).unwrap();
|
||||
let arch = match platform.target_arch {
|
||||
platforms::target::Arch::Arm => "arm",
|
||||
platforms::Arch::AArch64 => "arm64",
|
||||
platforms::Arch::X86 => "x86",
|
||||
platforms::Arch::X86_64 => "amd64",
|
||||
arch => panic!("{} is not a supported architecture", arch),
|
||||
};
|
||||
archive
|
||||
.by_name(&format!("wintun/bin/{}/wintun.dll", arch))?
|
||||
.read_to_end(&mut library)?;
|
||||
std::fs::write(out_dir.join("wintun.dll"), library)?;
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn assert_content_hash(content: &[u8], hash: [u8; 32]) {
|
||||
use sha2::digest::Update;
|
||||
use sha2::Digest;
|
||||
|
||||
let computed = sha2::Sha256::new().chain(content).finalize();
|
||||
assert_eq!(computed.as_slice(), &hash[..]);
|
||||
}
|
||||
53
tun/src/apple/kern_control.rs
Normal file
53
tun/src/apple/kern_control.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use libc::{sockaddr_ctl, AF_SYSTEM, AF_SYS_CONTROL};
|
||||
use std::io::Result;
|
||||
use std::mem::size_of;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
/// Trait to connect to kernel extensions on Apple platforms
|
||||
///
|
||||
/// Pulled from XNU source: https://github.com/apple/darwin-xnu/blob/main/bsd/sys/kern_control.h
|
||||
pub trait SysControlSocket {
|
||||
fn resolve(&self, name: &str, index: u32) -> Result<socket2::SockAddr>;
|
||||
}
|
||||
|
||||
impl SysControlSocket for socket2::Socket {
|
||||
fn resolve(&self, name: &str, index: u32) -> Result<socket2::SockAddr> {
|
||||
let mut info = sys::ctl_info {
|
||||
ctl_id: 0,
|
||||
ctl_name: [0; 96],
|
||||
};
|
||||
info.ctl_name[..name.len()].copy_from_slice(name.as_bytes());
|
||||
|
||||
unsafe { sys::resolve_ctl_info(self.as_raw_fd(), &mut info as *mut sys::ctl_info)? };
|
||||
|
||||
let (_, addr) = unsafe {
|
||||
socket2::SockAddr::init(|addr_storage, len| {
|
||||
*len = size_of::<sockaddr_ctl>() as u32;
|
||||
|
||||
let mut addr: &mut sockaddr_ctl = &mut *addr_storage.cast();
|
||||
addr.sc_len = *len as u8;
|
||||
addr.sc_family = AF_SYSTEM as u8;
|
||||
addr.ss_sysaddr = AF_SYS_CONTROL as u16;
|
||||
addr.sc_id = info.ctl_id;
|
||||
addr.sc_unit = index;
|
||||
Ok(())
|
||||
})
|
||||
}?;
|
||||
|
||||
Ok(addr)
|
||||
}
|
||||
}
|
||||
|
||||
mod sys {
|
||||
use nix::ioctl_readwrite;
|
||||
|
||||
const MAX_KCTL_NAME: usize = 96;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ctl_info {
|
||||
pub ctl_id: u32,
|
||||
pub ctl_name: [u8; MAX_KCTL_NAME],
|
||||
}
|
||||
|
||||
ioctl_readwrite!(resolve_ctl_info, b'N', 3, ctl_info);
|
||||
}
|
||||
90
tun/src/apple/mod.rs
Normal file
90
tun/src/apple/mod.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
use socket2::SockAddr;
|
||||
use std::io::Result;
|
||||
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
||||
|
||||
mod kern_control;
|
||||
mod queue;
|
||||
|
||||
pub use queue::TunQueue;
|
||||
|
||||
use crate::syscall;
|
||||
use crate::unix::copy_if_name;
|
||||
use kern_control::SysControlSocket;
|
||||
|
||||
pub struct TunInterface {
|
||||
socket: socket2::Socket,
|
||||
}
|
||||
|
||||
impl TunInterface {
|
||||
pub fn new() -> Result<TunInterface> {
|
||||
TunInterface::connect(None)
|
||||
}
|
||||
|
||||
fn connect(addr: Option<SockAddr>) -> Result<TunInterface> {
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
|
||||
let socket = Socket::new(
|
||||
Domain::from(libc::AF_SYSTEM),
|
||||
Type::DGRAM,
|
||||
Some(Protocol::from(libc::SYSPROTO_CONTROL)),
|
||||
)?;
|
||||
let addr = match addr {
|
||||
Some(addr) => addr,
|
||||
None => socket.resolve(sys::UTUN_CONTROL_NAME, 0)?,
|
||||
};
|
||||
socket.connect(&addr)?;
|
||||
|
||||
Ok(TunInterface { socket })
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Result<String> {
|
||||
let mut buf = [0u8; libc::IFNAMSIZ];
|
||||
let mut len = buf.len() as libc::socklen_t;
|
||||
syscall!(getsockopt(
|
||||
self.as_raw_fd(),
|
||||
libc::SYSPROTO_CONTROL,
|
||||
sys::UTUN_OPT_IFNAME,
|
||||
buf.as_mut_ptr() as *mut libc::c_void,
|
||||
&mut len,
|
||||
))?;
|
||||
let name = copy_if_name(buf);
|
||||
Ok(name)
|
||||
}
|
||||
|
||||
pub fn queue(&self) -> Result<TunQueue> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for TunInterface {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.socket.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for TunInterface {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.socket.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
mod sys {
|
||||
pub const UTUN_CONTROL_NAME: &str = "com.apple.net.utun_control";
|
||||
|
||||
pub const UTUN_OPT_IFNAME: libc::c_int = 2;
|
||||
|
||||
/// Copied from https://github.com/rust-lang/socket2/blob/61314a231f73964b3db969ef72c0e9479df320f3/src/sys/unix.rs#L168-L178
|
||||
/// getsockopt is not exposed by socket2
|
||||
#[macro_export]
|
||||
macro_rules! syscall {
|
||||
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
|
||||
#[allow(unused_unsafe)]
|
||||
let res = unsafe { libc::$fn($($arg, )*) };
|
||||
if res == -1 {
|
||||
Err(std::io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}};
|
||||
}
|
||||
}
|
||||
17
tun/src/apple/queue.rs
Normal file
17
tun/src/apple/queue.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
||||
|
||||
pub struct TunQueue {
|
||||
socket: socket2::Socket,
|
||||
}
|
||||
|
||||
impl AsRawFd for TunQueue {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.socket.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for TunQueue {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.socket.into_raw_fd()
|
||||
}
|
||||
}
|
||||
16
tun/src/lib.rs
Normal file
16
tun/src/lib.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#[cfg(target_vendor = "apple")]
|
||||
#[path = "apple/mod.rs"]
|
||||
mod imp;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[path = "linux.rs"]
|
||||
mod imp;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[path = "windows/mod.rs"]
|
||||
mod imp;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||
pub(crate) mod unix;
|
||||
|
||||
pub use imp::{TunInterface, TunQueue};
|
||||
56
tun/src/linux.rs
Normal file
56
tun/src/linux.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use std::fs::OpenOptions;
|
||||
use std::io::Result;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
||||
|
||||
use crate::unix::copy_if_name;
|
||||
|
||||
pub struct TunInterface {
|
||||
inner: socket2::Socket,
|
||||
}
|
||||
|
||||
impl TunInterface {
|
||||
pub fn new() -> Result<TunInterface> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open("/dev/net/tun")?;
|
||||
|
||||
let mut iff = libc::ifreq {
|
||||
ifr_name: [0; libc::IFNAMSIZ],
|
||||
ifr_ifru: libc::__c_anonymous_ifr_ifru {
|
||||
ifru_flags: (libc::IFF_TUN | libc::IFF_TUN_EXCL | libc::IFF_NO_PI) as i16,
|
||||
},
|
||||
};
|
||||
unsafe { sys::tun_set_iff(file.as_raw_fd(), &mut iff)? };
|
||||
|
||||
let inner = unsafe { socket2::Socket::from_raw_fd(file.into_raw_fd()) };
|
||||
Ok(TunInterface { inner })
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Result<String> {
|
||||
let mut iff = libc::ifreq {
|
||||
ifr_name: [0; libc::IFNAMSIZ],
|
||||
ifr_ifru: libc::__c_anonymous_ifr_ifru { ifru_flags: 0 },
|
||||
};
|
||||
unsafe { sys::tun_get_iff(self.inner.as_raw_fd(), &mut iff)? };
|
||||
|
||||
let name = copy_if_name(iff.ifr_name);
|
||||
Ok(name)
|
||||
}
|
||||
}
|
||||
|
||||
mod sys {
|
||||
use nix::{ioctl_read_bad, ioctl_write_ptr_bad, request_code_read, request_code_write};
|
||||
use std::mem::size_of;
|
||||
|
||||
ioctl_write_ptr_bad!(
|
||||
tun_set_iff,
|
||||
request_code_write!(b'T', 202, size_of::<libc::c_int>()),
|
||||
libc::ifreq
|
||||
);
|
||||
ioctl_read_bad!(
|
||||
tun_get_iff,
|
||||
request_code_read!(b'T', 210, size_of::<libc::c_int>()),
|
||||
libc::ifreq
|
||||
);
|
||||
}
|
||||
1
tun/src/queue.rs
Normal file
1
tun/src/queue.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
11
tun/src/unix.rs
Normal file
11
tun/src/unix.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
use std::ffi::CStr;
|
||||
|
||||
pub fn copy_if_name(buf: [u8; libc::IFNAMSIZ]) -> String {
|
||||
// TODO: Switch to `CStr::from_bytes_until_nul` when stabilized
|
||||
unsafe {
|
||||
CStr::from_ptr(buf.as_ptr() as *const _)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
44
tun/src/windows/mod.rs
Normal file
44
tun/src/windows/mod.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use std::io::Result;
|
||||
use std::ptr;
|
||||
use widestring::{u16cstr, U16CString};
|
||||
|
||||
pub struct TunInterface {
|
||||
wintun: sys::wintun,
|
||||
handle: sys::WINTUN_ADAPTER_HANDLE,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl TunInterface {
|
||||
pub fn new() -> Result<TunInterface> {
|
||||
let name = U16CString::from(u16cstr!("ConradNet"));
|
||||
let wintun = sys::wintun::default();
|
||||
let handle =
|
||||
unsafe { wintun.WintunCreateAdapter(name.as_ptr(), name.as_ptr(), ptr::null()) };
|
||||
Ok(TunInterface {
|
||||
wintun,
|
||||
handle,
|
||||
name: String::from("ConradNet"),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TunInterface {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.wintun.WintunCloseAdapter(self.handle) }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sys {
|
||||
#![allow(dead_code, non_camel_case_types, non_snake_case)]
|
||||
include!(concat!(env!("OUT_DIR"), "/wintun.rs"));
|
||||
|
||||
impl Default for wintun {
|
||||
fn default() -> Self {
|
||||
unsafe { wintun::new(format!("{}/wintun.dll", env!("OUT_DIR"))).unwrap() }
|
||||
}
|
||||
}
|
||||
}
|
||||
19
tun/src/windows/queue.rs
Normal file
19
tun/src/windows/queue.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use crate::TunInterface;
|
||||
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
||||
|
||||
pub struct TunQueue {
|
||||
inner: crate::windows::sys::
|
||||
inner: socket2::Socket,
|
||||
}
|
||||
|
||||
impl AsRawFd for TunQueue {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.socket.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for TunQueue {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.socket.into_raw_fd()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue