Add Android client support and unify cross-platform builds
This commit is contained in:
144
mobile/gotunnelmobile/gotunnelmobile.go
Normal file
144
mobile/gotunnelmobile/gotunnelmobile.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package gotunnelmobile
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gotunnel/internal/client/tunnel"
|
||||
"github.com/gotunnel/pkg/crypto"
|
||||
)
|
||||
|
||||
// Service exposes a gomobile-friendly wrapper around the Go tunnel client.
|
||||
type Service struct {
|
||||
mu sync.Mutex
|
||||
|
||||
server string
|
||||
token string
|
||||
dataDir string
|
||||
clientName string
|
||||
clientID string
|
||||
disableTLS bool
|
||||
|
||||
client *tunnel.Client
|
||||
cancel context.CancelFunc
|
||||
running bool
|
||||
status string
|
||||
lastError string
|
||||
}
|
||||
|
||||
// NewService creates a mobile client service wrapper.
|
||||
func NewService() *Service {
|
||||
return &Service{status: "stopped"}
|
||||
}
|
||||
|
||||
// Configure stores the parameters used by Start.
|
||||
func (s *Service) Configure(server, token, dataDir, clientName, clientID string, disableTLS bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.server = strings.TrimSpace(server)
|
||||
s.token = strings.TrimSpace(token)
|
||||
s.dataDir = strings.TrimSpace(dataDir)
|
||||
s.clientName = strings.TrimSpace(clientName)
|
||||
s.clientID = strings.TrimSpace(clientID)
|
||||
s.disableTLS = disableTLS
|
||||
}
|
||||
|
||||
// Start launches the tunnel loop in the background.
|
||||
func (s *Service) Start() string {
|
||||
s.mu.Lock()
|
||||
if s.running {
|
||||
s.mu.Unlock()
|
||||
return ""
|
||||
}
|
||||
if s.server == "" || s.token == "" {
|
||||
s.mu.Unlock()
|
||||
return "server and token are required"
|
||||
}
|
||||
|
||||
features := tunnel.MobilePlatformFeatures()
|
||||
client := tunnel.NewClientWithOptions(s.server, s.token, tunnel.ClientOptions{
|
||||
DataDir: s.dataDir,
|
||||
ClientID: s.clientID,
|
||||
ClientName: s.clientName,
|
||||
Features: &features,
|
||||
})
|
||||
if !s.disableTLS {
|
||||
client.TLSEnabled = true
|
||||
client.TLSConfig = crypto.ClientTLSConfig()
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
s.client = client
|
||||
s.cancel = cancel
|
||||
s.running = true
|
||||
s.status = "running"
|
||||
s.lastError = ""
|
||||
s.mu.Unlock()
|
||||
|
||||
go func() {
|
||||
err := client.RunContext(ctx)
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.running = false
|
||||
s.cancel = nil
|
||||
s.client = nil
|
||||
|
||||
if err != nil {
|
||||
s.status = "error"
|
||||
s.lastError = err.Error()
|
||||
return
|
||||
}
|
||||
|
||||
if s.status != "stopped" {
|
||||
s.status = "stopped"
|
||||
}
|
||||
}()
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Stop cancels the running tunnel loop.
|
||||
func (s *Service) Stop() string {
|
||||
s.mu.Lock()
|
||||
cancel := s.cancel
|
||||
s.cancel = nil
|
||||
s.running = false
|
||||
s.status = "stopped"
|
||||
s.mu.Unlock()
|
||||
|
||||
if cancel != nil {
|
||||
cancel()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Restart restarts the service with the stored configuration.
|
||||
func (s *Service) Restart() string {
|
||||
s.Stop()
|
||||
return s.Start()
|
||||
}
|
||||
|
||||
// IsRunning reports whether the tunnel loop is active.
|
||||
func (s *Service) IsRunning() bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.running
|
||||
}
|
||||
|
||||
// Status returns a coarse-grained runtime status.
|
||||
func (s *Service) Status() string {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.status
|
||||
}
|
||||
|
||||
// LastError returns the last background error string, if any.
|
||||
func (s *Service) LastError() string {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.lastError
|
||||
}
|
||||
Reference in New Issue
Block a user