diff options
Diffstat (limited to 'exports/exports.go')
| -rw-r--r-- | exports/exports.go | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/exports/exports.go b/exports/exports.go index a20ffb8..3ef6781 100644 --- a/exports/exports.go +++ b/exports/exports.go @@ -27,6 +27,7 @@ import ( "codeberg.org/eduVPN/eduvpn-common/client" "codeberg.org/eduVPN/eduvpn-common/i18n/err" + "codeberg.org/eduVPN/eduvpn-common/proxy" "codeberg.org/eduVPN/eduvpn-common/types/cookie" errtypes "codeberg.org/eduVPN/eduvpn-common/types/error" srvtypes "codeberg.org/eduVPN/eduvpn-common/types/server" @@ -876,6 +877,112 @@ func StartFailover(c C.uintptr_t, gateway *C.char, mtu C.int, readRxBytes C.Read return droppedC, nil } +// NewProxyguard creates the 'proxyguard' procedure in eduvpn-common. +// If the proxy cannot be created it returns an error. +// +// This function proxies WireGuard UDP connections over HTTP: [ProxyGuard on Codeberg](https://codeberg.org/eduvpn/proxyguard). +// +// These input variables can be gotten from the configuration that is retrieved using the `proxy` JSON key +// +// - `c` is the cookie. Note that if you cancel/delete the cookie, ProxyGuard gets cleaned up. Common automatically cleans up ProxyGuard when `Cleanup` is called, but it is good to cleanup yourself too. +// - `lp` is the `port` of the local udp ProxyGuard connection, this is what is set to the WireGuard endpoint +// - `tcpsp` is the TCP source port. Pass 0 if you do not route based on source port, so far only the Linux client has to pass non-zero. +// - `peer` is the `ip:port` of the remote server +// - `proxySetup` is a callback which is called when the socket is setting up, this can be used for configuring routing in the client. It takes two arguments: the file descriptor (integer) and a JSON list of IPs the client connects to +// +// Example Input: ```NewProxyguard(myCookie, 1337, 0, "5.5.5.5:51820", proxySetupCB)``` +// +// Example Output: ```null``` +// +//export NewProxyguard +func NewProxyguard(c C.uintptr_t, lp C.int, tcpsp C.int, peer *C.char, proxySetup C.ProxySetup) (C.uintptr_t, *C.char) { + ck, err := getCookie(c) + if err != nil { + return 0, getCError(err) + } + proxy, proxyErr := proxy.NewProxyguard(ck.Context(), int(lp), int(tcpsp), C.GoString(peer), func(fd int) { + if proxySetup == nil { + return + } + C.call_proxy_setup(proxySetup, C.int(fd)) + }) + if proxyErr != nil { + return 0, getCError(proxyErr) + } + return C.uintptr_t(cgo.NewHandle(proxy)), nil +} + +// ProxyguardRestart restarts ProxyGuard, call this when a network change happens +// +// Example Input: ```ProxyguardRestart(proxyHandle)``` +// +// Example Output: ```"failed restarting ProxyGuard"``` +// +//export ProxyguardRestart +func ProxyguardRestart(proxyH C.uintptr_t) *C.char { + pr, err := getProxy(proxyH) + if err != nil { + return getCError(err) + } + pr.Restart() + return nil +} + +func getProxy(proxyH C.uintptr_t) (*proxy.Proxy, error) { + h := cgo.Handle(proxyH) + v, ok := h.Value().(*proxy.Proxy) + if !ok { + return nil, i18nerr.NewInternal("value is not a proxyguard wrapper") + } + return v, nil +} + +// ProxyguardTunnel starts the tunneling for ProxyGuard +// `c` is the cookie +// `proxyH` is the proxy handle +// `wglisten` is the port WireGuard is listening on +// +//export ProxyguardTunnel +func ProxyguardTunnel(c C.uintptr_t, proxyH C.uintptr_t, wglisten C.int) *C.char { + ck, err := getCookie(c) + if err != nil { + return getCError(err) + } + pr, err := getProxy(proxyH) + if err != nil { + return getCError(err) + } + tunnelErr := pr.Tunnel(ck.Context(), int(wglisten)) + + // after tunneling is done, the handle should be deleted + cgo.Handle(proxyH).Delete() + return getCError(tunnelErr) +} + +// ProxyguardPeerIPs gets the Peer IPs configured by ProxyGuard +// Example Input: ```ProxyguardPeerIPs(handle)``` +// +// Example Output: ```["1.1.1.1"], null``` +// +//export ProxyguardPeerIPs +func ProxyguardPeerIPs(proxyH C.uintptr_t) (*C.char, *C.char) { + pr, err := getProxy(proxyH) + if err != nil { + return nil, getCError(err) + } + pips := pr.PeerIPS + + b, err := json.Marshal(pips) + if err != nil { + return nil, getCError(i18nerr.WrapInternal(err, "failed converting Peer IPs to JSON")) + } + ret, err := getReturnData(string(b)) + if err != nil { + return nil, getCError(err) + } + return C.CString(ret), nil +} + // SetState sets the state of the state machine. // // Note: this transitions the FSM into the new state without passing any data to it. |
