mirror of
https://github.com/coder/coder.git
synced 2025-03-14 10:09:57 +00:00
chore: support building Coder Desktop .dylib
(#15512)
Relates to #14734.
This commit is contained in:
95
.github/workflows/ci.yaml
vendored
95
.github/workflows/ci.yaml
vendored
@ -806,10 +806,91 @@ jobs:
|
||||
|
||||
echo "Required checks have passed"
|
||||
|
||||
# Builds the dylibs and upload it as an artifact so it can be embedded in the main build
|
||||
build-dylib:
|
||||
needs: changes
|
||||
# We always build the dylibs on Go changes to verify we're not merging unbuildable code,
|
||||
# but they need only be signed and uploaded on coder/coder main.
|
||||
if: needs.changes.outputs.docs-only == 'false' || github.ref == 'refs/heads/main'
|
||||
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup build tools
|
||||
run: |
|
||||
brew install bash gnu-getopt make
|
||||
echo "$(brew --prefix bash)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix gnu-getopt)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix make)/libexec/gnubin" >> $GITHUB_PATH
|
||||
|
||||
- name: Setup Go
|
||||
uses: ./.github/actions/setup-go
|
||||
|
||||
- name: Install rcodesign
|
||||
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
wget -O /tmp/rcodesign.tar.gz https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-macos-universal.tar.gz
|
||||
sudo tar -xzf /tmp/rcodesign.tar.gz \
|
||||
-C /usr/local/bin \
|
||||
--strip-components=1 \
|
||||
apple-codesign-0.22.0-macos-universal/rcodesign
|
||||
rm /tmp/rcodesign.tar.gz
|
||||
|
||||
- name: Setup Apple Developer certificate and API key
|
||||
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
touch /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||
chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||
echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12
|
||||
echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt
|
||||
echo "$AC_APIKEY_P8_BASE64" | base64 -d > /tmp/apple_apikey.p8
|
||||
env:
|
||||
AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }}
|
||||
AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }}
|
||||
AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }}
|
||||
|
||||
- name: Build dylibs
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
go mod download
|
||||
|
||||
make gen/mark-fresh
|
||||
make build/coder-dylib
|
||||
env:
|
||||
CODER_SIGN_DARWIN: ${{ github.ref == 'refs/heads/main' && '1' || '0' }}
|
||||
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
|
||||
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dylibs
|
||||
path: |
|
||||
./build/*.h
|
||||
./build/*.dylib
|
||||
retention-days: 7
|
||||
|
||||
- name: Delete Apple Developer certificate and API key
|
||||
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
|
||||
run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||
|
||||
build:
|
||||
# This builds and publishes ghcr.io/coder/coder-preview:main for each commit
|
||||
# to main branch.
|
||||
needs: changes
|
||||
needs:
|
||||
- changes
|
||||
- build-dylib
|
||||
if: github.ref == 'refs/heads/main' && needs.changes.outputs.docs-only == 'false' && !github.event.pull_request.head.repo.fork
|
||||
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
|
||||
permissions:
|
||||
@ -848,6 +929,18 @@ jobs:
|
||||
- name: Install zstd
|
||||
run: sudo apt-get install -y zstd
|
||||
|
||||
- name: Download dylibs
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: dylibs
|
||||
path: ./build
|
||||
|
||||
- name: Insert dylibs
|
||||
run: |
|
||||
mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib
|
||||
mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib
|
||||
mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
93
.github/workflows/release.yaml
vendored
93
.github/workflows/release.yaml
vendored
@ -32,8 +32,80 @@ env:
|
||||
CODER_RELEASE_NOTES: ${{ inputs.release_notes }}
|
||||
|
||||
jobs:
|
||||
# build-dylib is a separate job to build the dylib on macOS.
|
||||
build-dylib:
|
||||
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup build tools
|
||||
run: |
|
||||
brew install bash gnu-getopt make
|
||||
echo "$(brew --prefix bash)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix gnu-getopt)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix make)/libexec/gnubin" >> $GITHUB_PATH
|
||||
|
||||
- name: Setup Go
|
||||
uses: ./.github/actions/setup-go
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
set -euo pipefail
|
||||
wget -O /tmp/rcodesign.tar.gz https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-macos-universal.tar.gz
|
||||
sudo tar -xzf /tmp/rcodesign.tar.gz \
|
||||
-C /usr/local/bin \
|
||||
--strip-components=1 \
|
||||
apple-codesign-0.22.0-macos-universal/rcodesign
|
||||
rm /tmp/rcodesign.tar.gz
|
||||
|
||||
- name: Setup Apple Developer certificate and API key
|
||||
run: |
|
||||
set -euo pipefail
|
||||
touch /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||
chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||
echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12
|
||||
echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt
|
||||
echo "$AC_APIKEY_P8_BASE64" | base64 -d > /tmp/apple_apikey.p8
|
||||
env:
|
||||
AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }}
|
||||
AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }}
|
||||
AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }}
|
||||
|
||||
- name: Build dylibs
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
go mod download
|
||||
|
||||
make gen/mark-fresh
|
||||
make build/coder-dylib
|
||||
env:
|
||||
CODER_SIGN_DARWIN: 1
|
||||
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
|
||||
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dylibs
|
||||
path: |
|
||||
./build/*.h
|
||||
./build/*.dylib
|
||||
retention-days: 7
|
||||
|
||||
- name: Delete Apple Developer certificate and API key
|
||||
run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||
|
||||
release:
|
||||
name: Build and publish
|
||||
needs: build-dylib
|
||||
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
|
||||
permissions:
|
||||
# Required to publish a release
|
||||
@ -145,6 +217,18 @@ jobs:
|
||||
- name: Install nsis and zstd
|
||||
run: sudo apt-get install -y nsis zstd
|
||||
|
||||
- name: Download dylibs
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: dylibs
|
||||
path: ./build
|
||||
|
||||
- name: Insert dylibs
|
||||
run: |
|
||||
mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib
|
||||
mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib
|
||||
mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@ -271,6 +355,7 @@ jobs:
|
||||
${{ steps.image-base-tag.outputs.tag }}
|
||||
|
||||
- name: Verify that images are pushed properly
|
||||
if: steps.image-base-tag.outputs.tag != ''
|
||||
run: |
|
||||
# retry 10 times with a 5 second delay as the images may not be
|
||||
# available immediately
|
||||
@ -303,10 +388,6 @@ jobs:
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
||||
# build Docker images for each architecture
|
||||
version="$(./scripts/version.sh)"
|
||||
make build/coder_"$version"_linux_{amd64,arm64,armv7}.tag
|
||||
|
||||
# we can't build multi-arch if the images aren't pushed, so quit now
|
||||
# if dry-running
|
||||
if [[ "$CODER_RELEASE" != *t* ]]; then
|
||||
@ -314,6 +395,10 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# build Docker images for each architecture
|
||||
version="$(./scripts/version.sh)"
|
||||
make build/coder_"$version"_linux_{amd64,arm64,armv7}.tag
|
||||
|
||||
# build and push multi-arch manifest, this depends on the other images
|
||||
# being pushed so will automatically push them.
|
||||
make push/build/coder_"$version"_linux.tag
|
||||
|
23
Makefile
23
Makefile
@ -79,8 +79,12 @@ PACKAGE_OS_ARCHES := linux_amd64 linux_armv7 linux_arm64
|
||||
# All architectures we build Docker images for (Linux only).
|
||||
DOCKER_ARCHES := amd64 arm64 armv7
|
||||
|
||||
# All ${OS}_${ARCH} combos we build the desktop dylib for.
|
||||
DYLIB_ARCHES := darwin_amd64 darwin_arm64
|
||||
|
||||
# Computed variables based on the above.
|
||||
CODER_SLIM_BINARIES := $(addprefix build/coder-slim_$(VERSION)_,$(OS_ARCHES))
|
||||
CODER_DYLIBS := $(foreach os_arch, $(DYLIB_ARCHES), build/coder-vpn_$(VERSION)_$(os_arch).dylib)
|
||||
CODER_FAT_BINARIES := $(addprefix build/coder_$(VERSION)_,$(OS_ARCHES))
|
||||
CODER_ALL_BINARIES := $(CODER_SLIM_BINARIES) $(CODER_FAT_BINARIES)
|
||||
CODER_TAR_GZ_ARCHIVES := $(foreach os_arch, $(ARCHIVE_TAR_GZ), build/coder_$(VERSION)_$(os_arch).tar.gz)
|
||||
@ -238,6 +242,25 @@ $(CODER_ALL_BINARIES): go.mod go.sum \
|
||||
cp "$@" "./site/out/bin/coder-$$os-$$arch$$dot_ext"
|
||||
fi
|
||||
|
||||
# This task builds Coder Desktop dylibs
|
||||
$(CODER_DYLIBS): go.mod go.sum $(GO_SRC_FILES)
|
||||
@if [ "$(shell uname)" = "Darwin" ]; then
|
||||
$(get-mode-os-arch-ext)
|
||||
./scripts/build_go.sh \
|
||||
--os "$$os" \
|
||||
--arch "$$arch" \
|
||||
--version "$(VERSION)" \
|
||||
--output "$@" \
|
||||
--dylib
|
||||
|
||||
else
|
||||
echo "ERROR: Can't build dylib on non-Darwin OS" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# This task builds both dylibs
|
||||
build/coder-dylib: $(CODER_DYLIBS)
|
||||
|
||||
# This task builds all archives. It parses the target name to get the metadata
|
||||
# for the build, so it must be specified in this format:
|
||||
# build/coder_${version}_${os}_${arch}.${format}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# This script builds a single Go binary of Coder with the given parameters.
|
||||
#
|
||||
# Usage: ./build_go.sh [--version 1.2.3-devel+abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim] [--agpl] [--boringcrypto]
|
||||
# Usage: ./build_go.sh [--version 1.2.3-devel+abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim] [--agpl] [--boringcrypto] [--dylib]
|
||||
#
|
||||
# Defaults to linux:amd64 with slim disabled, but can be controlled with GOOS,
|
||||
# GOARCH and CODER_SLIM_BUILD=1. If no version is specified, defaults to the
|
||||
@ -25,6 +25,9 @@
|
||||
#
|
||||
# If the --boringcrypto parameter is specified, builds use boringcrypto instead of
|
||||
# the standard go crypto libraries.
|
||||
#
|
||||
# If the --dylib parameter is specified, the Coder Desktop `.dylib` is built
|
||||
# instead of the standard binary. This is only supported on macOS arm64 & amd64.
|
||||
|
||||
set -euo pipefail
|
||||
# shellcheck source=scripts/lib.sh
|
||||
@ -36,12 +39,14 @@ arch="${GOARCH:-amd64}"
|
||||
slim="${CODER_SLIM_BUILD:-0}"
|
||||
sign_darwin="${CODER_SIGN_DARWIN:-0}"
|
||||
sign_windows="${CODER_SIGN_WINDOWS:-0}"
|
||||
bin_ident="com.coder.cli"
|
||||
output_path=""
|
||||
agpl="${CODER_BUILD_AGPL:-0}"
|
||||
boringcrypto=${CODER_BUILD_BORINGCRYPTO:-0}
|
||||
debug=0
|
||||
dylib=0
|
||||
|
||||
args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,boringcrypto,debug -- "$@")"
|
||||
args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,boringcrypto,dylib,debug -- "$@")"
|
||||
eval set -- "$args"
|
||||
while true; do
|
||||
case "$1" in
|
||||
@ -78,6 +83,10 @@ while true; do
|
||||
boringcrypto=1
|
||||
shift
|
||||
;;
|
||||
--dylib)
|
||||
dylib=1
|
||||
shift
|
||||
;;
|
||||
--debug)
|
||||
debug=1
|
||||
shift
|
||||
@ -168,18 +177,31 @@ if [[ "$agpl" == 1 ]]; then
|
||||
fi
|
||||
|
||||
cgo=0
|
||||
if [[ "$dylib" == 1 ]]; then
|
||||
if [[ "$os" != "darwin" ]]; then
|
||||
error "dylib builds are not supported on $os"
|
||||
fi
|
||||
cgo=1
|
||||
cmd_path="./vpn/dylib/lib.go"
|
||||
build_args+=("-buildmode=c-shared")
|
||||
SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"
|
||||
export SDKROOT
|
||||
bin_ident="com.coder.vpn"
|
||||
fi
|
||||
|
||||
goexp=""
|
||||
if [[ "$boringcrypto" == 1 ]]; then
|
||||
cgo=1
|
||||
goexp="boringcrypto"
|
||||
fi
|
||||
|
||||
GOEXPERIMENT="$goexp" CGO_ENABLED="$cgo" GOOS="$os" GOARCH="$arch" GOARM="$arm_version" go build \
|
||||
GOEXPERIMENT="$goexp" CGO_ENABLED="$cgo" GOOS="$os" GOARCH="$arch" GOARM="$arm_version" \
|
||||
go build \
|
||||
"${build_args[@]}" \
|
||||
"$cmd_path" 1>&2
|
||||
|
||||
if [[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]]; then
|
||||
execrelative ./sign_darwin.sh "$output_path" 1>&2
|
||||
execrelative ./sign_darwin.sh "$output_path" "$bin_ident" 1>&2
|
||||
fi
|
||||
|
||||
if [[ "$sign_windows" == 1 ]] && [[ "$os" == "windows" ]]; then
|
||||
|
@ -180,10 +180,13 @@ if [[ "$stable" == 1 ]]; then
|
||||
fi
|
||||
|
||||
target_commitish=main # This is the default.
|
||||
release_branch_refname=$(git branch --remotes --contains "${new_tag}" --format '%(refname)' '*/release/*')
|
||||
if [[ -n "${release_branch_refname}" ]]; then
|
||||
# refs/remotes/origin/release/2.9 -> release/2.9
|
||||
target_commitish="release/${release_branch_refname#*release/}"
|
||||
# Skip during dry-runs
|
||||
if [[ "$dry_run" == 0 ]]; then
|
||||
release_branch_refname=$(git branch --remotes --contains "${new_tag}" --format '%(refname)' '*/release/*')
|
||||
if [[ -n "${release_branch_refname}" ]]; then
|
||||
# refs/remotes/origin/release/2.9 -> release/2.9
|
||||
target_commitish="release/${release_branch_refname#*release/}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# We pipe `true` into `gh` so that it never tries to be interactive.
|
||||
|
@ -3,11 +3,14 @@
|
||||
# This script signs the provided darwin binary with an Apple Developer
|
||||
# certificate.
|
||||
#
|
||||
# Usage: ./sign_darwin.sh path/to/binary
|
||||
# Usage: ./sign_darwin.sh path/to/binary binary_identifier
|
||||
#
|
||||
# On success, the input file will be signed using the Apple Developer
|
||||
# certificate.
|
||||
#
|
||||
# For the Coder CLI, the binary_identifier should be "com.coder.cli".
|
||||
# For the CoderVPN `.dylib`, the binary_identifier should be "com.coder.vpn".
|
||||
#
|
||||
# You can check if a binary is signed by running the following command on a Mac:
|
||||
# codesign -dvv path/to/binary
|
||||
#
|
||||
@ -25,15 +28,23 @@ set -euo pipefail
|
||||
# shellcheck source=scripts/lib.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
||||
|
||||
if [[ "$#" -lt 2 ]]; then
|
||||
echo "Usage: $0 path/to/binary binary_identifier"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BINARY_PATH="$1"
|
||||
BINARY_IDENTIFIER="$2"
|
||||
|
||||
# Check dependencies
|
||||
dependencies rcodesign
|
||||
requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE
|
||||
|
||||
# -v is quite verbose, the default output is pretty good on it's own.
|
||||
rcodesign sign \
|
||||
--binary-identifier "com.coder.cli" \
|
||||
--binary-identifier "$BINARY_IDENTIFIER" \
|
||||
--p12-file "$AC_CERTIFICATE_FILE" \
|
||||
--p12-password-file "$AC_CERTIFICATE_PASSWORD_FILE" \
|
||||
--code-signature-flags runtime \
|
||||
"$@" \
|
||||
"$BINARY_PATH" \
|
||||
1>&2
|
||||
|
60
vpn/dylib/lib.go
Normal file
60
vpn/dylib/lib.go
Normal file
@ -0,0 +1,60 @@
|
||||
//go:build darwin
|
||||
|
||||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"cdr.dev/slog"
|
||||
|
||||
"github.com/coder/coder/v2/vpn"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrDupReadFD = -2
|
||||
ErrDupWriteFD = -3
|
||||
ErrOpenPipe = -4
|
||||
ErrNewTunnel = -5
|
||||
)
|
||||
|
||||
// OpenTunnel creates a new VPN tunnel by `dup`ing the provided 'PIPE'
|
||||
// file descriptors for reading, writing, and logging.
|
||||
//
|
||||
//export OpenTunnel
|
||||
func OpenTunnel(cReadFD, cWriteFD int32) int32 {
|
||||
ctx := context.Background()
|
||||
|
||||
readFD, err := unix.Dup(int(cReadFD))
|
||||
if err != nil {
|
||||
return ErrDupReadFD
|
||||
}
|
||||
|
||||
writeFD, err := unix.Dup(int(cWriteFD))
|
||||
if err != nil {
|
||||
unix.Close(readFD)
|
||||
return ErrDupWriteFD
|
||||
}
|
||||
|
||||
conn, err := vpn.NewBidirectionalPipe(uintptr(cReadFD), uintptr(cWriteFD))
|
||||
if err != nil {
|
||||
unix.Close(readFD)
|
||||
unix.Close(writeFD)
|
||||
return ErrOpenPipe
|
||||
}
|
||||
|
||||
// Logs will be sent over the protocol
|
||||
_, err = vpn.NewTunnel(ctx, slog.Make(), conn)
|
||||
if err != nil {
|
||||
unix.Close(readFD)
|
||||
unix.Close(writeFD)
|
||||
return ErrNewTunnel
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {}
|
Reference in New Issue
Block a user