POC of gomobile

oxtoacart/gomobilepoc
Percy Wegmann 4 months ago
parent 813ca8adea
commit 860a487ac8
No known key found for this signature in database
GPG Key ID: 29D8CDEB4C13D48B

5
.gitignore vendored

@ -26,4 +26,7 @@ tailscale.jks
*.hprof
#IDE
.vscode
.vscode
libtailscale-sources.jar
libtailscale.aar

@ -0,0 +1,4 @@
# Replace JAVA_HOME with the right path for your environment
libtailscale.aar: *.go go.mod go.sum
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home gomobile bind -target android -androidapi 21 libtailscale

@ -0,0 +1,5 @@
module libtailscale
go 1.21.5
require golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b // indirect

@ -0,0 +1,2 @@
golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b h1:kfWLZgb8iUBHdE9WydD5V5dHIS/F6HjlBZNyJfn2bs4=
golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b/go.mod h1:4efzQnuA1nICq6h4kmZRMGzbPiP06lZvgADUu1VpJCE=

@ -0,0 +1,130 @@
package libtailscale
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"tailscale.com/ipn/ipnlocal"
"tailscale.com/ipn/localapi"
"tailscale.com/net/dns"
"tailscale.com/net/netmon"
"tailscale.com/net/tsdial"
"tailscale.com/tsd"
"tailscale.com/types/logid"
"tailscale.com/wgengine"
"tailscale.com/wgengine/router"
)
type Request struct {
Method string
Path string
Headers map[string][]string
Body []byte
}
type Response struct {
StatusCode int
Headers map[string][]string
bodyWriter *bytes.Buffer
}
func (resp *Response) Body() []byte {
return resp.bodyWriter.Bytes()
}
type Tailscale interface {
ProcessRequest(req *Request) *Response
}
type tailscale struct {
backend *ipnlocal.LocalBackend
localapi *localapi.Handler
}
func NewTailscale() (Tailscale, error) {
logf := log.Printf
var sys tsd.System
var logID logid.PrivateID
logID.UnmarshalText([]byte("dead0000dead0000dead0000dead0000dead0000dead0000dead0000dead0000"))
netMon, err := netmon.New(logf)
if err != nil {
log.Printf("netmon.New: %w", err)
}
dialer := new(tsdial.Dialer)
cb := &router.CallbackRouter{
SetBoth: func(rcfg *router.Config, dcfg *dns.OSConfig) error { return nil },
SplitDNS: false,
GetBaseConfigFunc: nil,
}
engine, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{
Tun: nil,
Router: cb,
DNS: cb,
Dialer: dialer,
SetSubsystem: sys.Set,
NetMon: netMon,
})
if err != nil {
return nil, fmt.Errorf("runBackend: NewUserspaceEngine: %v", err)
}
sys.Set(engine)
backend, err := ipnlocal.NewLocalBackend(logf, logID.Public(), &sys, 0)
if err != nil {
return nil, err
}
api := localapi.NewHandler(backend, logf, netMon, logID.Public())
return &tailscale{
backend: backend,
localapi: api,
}, nil
}
func (t *tailscale) ProcessRequest(req *Request) (resp *Response) {
defer func() {
if p := recover(); p != nil {
resp = &Response{
StatusCode: http.StatusInternalServerError,
}
fmt.Fprintf(resp, "%s", p)
}
}()
resp = &Response{
StatusCode: http.StatusOK,
Headers: make(map[string][]string),
bodyWriter: &bytes.Buffer{},
}
t.localapi.ServeHTTP(resp, req.AsHTTPRequest())
return
}
func (req *Request) AsHTTPRequest() *http.Request {
result, _ := http.NewRequest(req.Method, fmt.Sprintf("http://server/%v", req.Path), nil)
if req.Body != nil {
result.Body = io.NopCloser(bytes.NewReader(req.Body))
}
if req.Headers != nil {
for name, values := range req.Headers {
for _, value := range values {
result.Header.Add(name, value)
}
}
}
return result
}
func (resp *Response) Header() http.Header {
return http.Header(resp.Headers)
}
func (resp *Response) WriteHeader(statusCode int) {
resp.StatusCode = statusCode
}
func (resp *Response) Write(p []byte) (int, error) {
return resp.bodyWriter.Write(p)
}
Loading…
Cancel
Save