diff --git a/.gitignore b/.gitignore index c982fde..4ecb352 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /build /bin +/_obj intra/split/example/example # General diff --git a/Makefile b/Makefile index 8acd8a9..05df311 100644 --- a/Makefile +++ b/Makefile @@ -42,23 +42,33 @@ ELECTRON_PATH=$(IMPORT_PATH)/outline/electron LINUX_BUILDDIR=$(BUILDDIR)/linux -linux: $(LINUX_BUILDDIR)/tun2socks +linux: $(LINUX_BUILDDIR)/tun2socks $(LINUX_BUILDDIR)/libtun2socks.so $(LINUX_BUILDDIR)/tun2socks: $(XGO) mkdir -p "$(LINUX_BUILDDIR)" $(XGO) -ldflags $(XGO_LDFLAGS) --targets=linux/amd64 -dest "$(LINUX_BUILDDIR)" "$(ELECTRON_PATH)" mv "$(LINUX_BUILDDIR)/electron-linux-amd64" "$@" +$(LINUX_BUILDDIR)/libtun2socks.so: $(XGO) + mkdir -p "$(LINUX_BUILDDIR)" + $(XGO) -buildmode c-shared -ldflags $(XGO_LDFLAGS) --targets=linux/amd64 -dest "$(LINUX_BUILDDIR)" "$(ELECTRON_PATH)" + mv "$(LINUX_BUILDDIR)/electron-linux-amd64.so" "$@" + WINDOWS_BUILDDIR=$(BUILDDIR)/windows -windows: $(WINDOWS_BUILDDIR)/tun2socks.exe +windows: $(WINDOWS_BUILDDIR)/tun2socks.exe $(WINDOWS_BUILDDIR)/tun2socks.dll $(WINDOWS_BUILDDIR)/tun2socks.exe: $(XGO) mkdir -p "$(WINDOWS_BUILDDIR)" $(XGO) -ldflags $(XGO_LDFLAGS) --targets=windows/386 -dest "$(WINDOWS_BUILDDIR)" "$(ELECTRON_PATH)" mv "$(WINDOWS_BUILDDIR)/electron-windows-386.exe" "$@" +$(WINDOWS_BUILDDIR)/tun2socks.dll: $(XGO) + mkdir -p "$(WINDOWS_BUILDDIR)" + $(XGO) -buildmode c-shared -ldflags $(XGO_LDFLAGS) --targets=windows/386 -dest "$(WINDOWS_BUILDDIR)" "$(ELECTRON_PATH)" + mv "$(WINDOWS_BUILDDIR)/electron-windows-386.dll" "$@" + $(GOMOBILE): go.mod env GOBIN="$(GOBIN)" go install golang.org/x/mobile/cmd/gomobile diff --git a/outline/electron/libtun2socks.go b/outline/electron/libtun2socks.go new file mode 100644 index 0000000..e2539b2 --- /dev/null +++ b/outline/electron/libtun2socks.go @@ -0,0 +1,63 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Use the following command line to generate a C header file: +// go tool cgo -exportheader ./build/libtun2socks.h ./outline/electron/lib.go + +package main + +/* +#include // for uint32_t +*/ +import "C" + +import ( + "runtime/cgo" + "unsafe" + + oss "github.com/Jigsaw-Code/outline-go-tun2socks/outline/shadowsocks" +) + +// Function returns a tuple [status, pErr]. If pErr is nil (means no errors), +// status is one of the following: +// - 0 (NoError): can connect by TCP and UDP +// - 4 (UDPConnectivity): can only connect by TCP (UDP failed) +// - 3 (AuthenticationFailure): wrong server credentials +// - 5 (Unreachable): server is not reachable at all +// +// Otherwise if pErr is not nil, it means there are unexpected errors (status +// will be 1 (Unexpected)). +// +// The caller must call ReleaseError(pErr) later to make sure Go will garbage +// collect the error object, otherwise memory leak will happen. +// +//export CheckConnectivity +func CheckConnectivity() (status C.uint32_t, pErr unsafe.Pointer) { + status = oss.Unexpected + pErr = nil + return +} + +// If pErr points to an existing error object, this function will return pErr +// object to Go's garbage collector. If pErr is nil, we will do nothing. +// +// In either case, the caller should not use pErr object any more. +// +//export ReleaseError +func ReleaseError(pErr unsafe.Pointer) { + p := (*cgo.Handle)(pErr) + if p != nil { + (*p).Delete() + } +}