diff --git a/x/examples/mobileproxy-clib/.gitignore b/x/examples/mobileproxy-clib/.gitignore new file mode 100644 index 00000000..fb7cbdf7 --- /dev/null +++ b/x/examples/mobileproxy-clib/.gitignore @@ -0,0 +1,2 @@ +demo/demo +demo/mobileproxy-clib* \ No newline at end of file diff --git a/x/examples/mobileproxy-clib/README.md b/x/examples/mobileproxy-clib/README.md new file mode 100644 index 00000000..f2ef2146 --- /dev/null +++ b/x/examples/mobileproxy-clib/README.md @@ -0,0 +1,25 @@ +# Mobileproxy CLib Wrapper + +This is a C wrapper for the mobileproxy library. It is intended to be used downstream by native wrappers like Swift or Java. + +## Demo + +To run the demo, you first must build the library for your platform. You can build the library by running: + +```bash +cd x + +CGO_ENABLED=1 go build -buildmode=c-shared -o=examples/mobileproxy-clib/demo/mobileproxy-clib ./examples/mobileproxy-clib +``` + +Then, you can build and run the demo by doing the following: + +```bash +cd examples/mobileproxy-clib/demo + +# build the demo +gcc -o demo demo.c mobileproxy-clib + +# run the demo +./demo +``` diff --git a/x/examples/mobileproxy-clib/demo/demo.c b/x/examples/mobileproxy-clib/demo/demo.c new file mode 100644 index 00000000..e9c0aa47 --- /dev/null +++ b/x/examples/mobileproxy-clib/demo/demo.c @@ -0,0 +1,35 @@ +// Copyright 2024 Jigsaw Operations LLC +// +// 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 +// +// https://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. + +#include +#include "mobileproxy-clib.h" + +int main() +{ + StreamDialer dialer; + Proxy proxy; + + dialer = NewStreamDialerFromConfig("split:3"); + proxy = RunProxy("127.0.0.1:1234", dialer); + + printf("Running proxy on 127.0.0.1:1234\nPress to terminate..."); + getc(stdin); + + // Stop the proxy and clean up + StopProxy(proxy, 1000); + ReleaseProxy(proxy); + ReleaseStreamDialer(dialer); + + return 0; +} diff --git a/x/examples/mobileproxy-clib/main.go b/x/examples/mobileproxy-clib/main.go new file mode 100644 index 00000000..3eb69121 --- /dev/null +++ b/x/examples/mobileproxy-clib/main.go @@ -0,0 +1,102 @@ +// Copyright 2024 Jigsaw Operations LLC +// +// 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 +// +// https://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. + +package main + +/* +#include // uintptr_t + +typedef uintptr_t StreamDialer; +typedef uintptr_t Proxy; +*/ +import "C" + +import ( + "runtime/cgo" + + "github.com/Jigsaw-Code/outline-sdk/x/mobileproxy" +) + +const nullptr = C.uintptr_t(0) + +func marshalStreamDialer(dialer *mobileproxy.StreamDialer) C.StreamDialer { + return C.StreamDialer(cgo.NewHandle(dialer)) +} + +func unmarshalStreamDialer(dialerHandle C.StreamDialer) *mobileproxy.StreamDialer { + return cgo.Handle(dialerHandle).Value().(*mobileproxy.StreamDialer) +} + +//export NewStreamDialerFromConfig +func NewStreamDialerFromConfig(config *C.char) C.StreamDialer { + sd, err := mobileproxy.NewStreamDialerFromConfig(C.GoString(config)) + + if err != nil { + // TODO: return error + return nullptr + } + + return marshalStreamDialer(sd) +} + +//export ReleaseStreamDialer +func ReleaseStreamDialer(dialerHandle C.StreamDialer) { + cgo.Handle(dialerHandle).Delete() +} + +func marshalProxy(proxy *mobileproxy.Proxy) C.Proxy { + return C.Proxy(cgo.NewHandle(proxy)) +} + +func unmarshalProxy(proxyHandle C.Proxy) *mobileproxy.Proxy { + return cgo.Handle(proxyHandle).Value().(*mobileproxy.Proxy) +} + +//export RunProxy +func RunProxy(address *C.char, dialerHandle C.StreamDialer) C.Proxy { + dialer := unmarshalStreamDialer(dialerHandle) + + proxy, err := mobileproxy.RunProxy(C.GoString(address), dialer) + + if err != nil { + // TODO: return error + return nullptr + } + + return marshalProxy(proxy) +} + +//export AddURLProxy +func AddURLProxy(proxyHandle C.Proxy, url *C.char, dialerHandle C.StreamDialer) { + proxy := unmarshalProxy(proxyHandle) + dialer := unmarshalStreamDialer(dialerHandle) + + proxy.AddURLProxy(C.GoString(url), dialer) +} + +//export StopProxy +func StopProxy(proxyHandle C.Proxy, timeoutSeconds C.uint) { + proxy := unmarshalProxy(proxyHandle) + proxy.Stop(int(timeoutSeconds)) +} + +//export ReleaseProxy +func ReleaseProxy(proxyHandle C.Proxy) { + cgo.Handle(proxyHandle).Delete() +} + +func main() { + // We need the main function to make possible + // CGO compiler to compile the package as C shared library +}