Optional App Experiment

This commit is contained in:
Sarah Jamie Lewis 2023-03-01 09:48:34 -08:00
parent cb314528c3
commit a48b217d2c
6 changed files with 100 additions and 119 deletions

View File

@ -51,7 +51,7 @@ var appServers server.Servers
var killStatsUpdate chan bool = make(chan bool, 1)
var enabled bool = false
func InitServers(acn connectivity.ACN, appdir string, ) *ServersFunctionality {
func Init(acn connectivity.ACN, appdir string, ) *ServersFunctionality {
lock.Lock()
defer lock.Unlock()
if appServers == nil {
@ -62,7 +62,10 @@ func InitServers(acn connectivity.ACN, appdir string, ) *ServersFunctionality {
}
appServers = server.NewServers(acn, serversDir)
}
return new(ServersFunctionality)
serversFunctionality := new(ServersFunctionality)
return serversFunctionality
}
// track acnStatus across events
@ -115,7 +118,7 @@ func (sh *ServersFunctionality) UpdateSettings(appl app.Application, acn connect
} else {
sh.LoadServers(appl, acn, app.DefactoPasswordForUnencryptedProfiles)
if !sh.Enabled() {
sh.Enable(appl)
sh.Enable(appl, acn)
serversList := sh.ListServers()
for _, server := range serversList {
serverInfo := sh.GetServerInfo(server)
@ -161,11 +164,15 @@ func (sh *ServersFunctionality) LaunchServers(appl app.Application, acn connecti
}
}
func (sf *ServersFunctionality) Enable(application app.Application) {
func (sf *ServersFunctionality) Enable(application app.Application, acn connectivity.ACN, ) {
lock.Lock()
defer lock.Unlock()
if appServers != nil && !enabled {
enabled = true
// load unencrypted profiles
sf.LoadServers(application, acn, app.DefactoPasswordForUnencryptedProfiles)
go cacheForwardServerMetricUpdates(application)
}
}

View File

@ -12,8 +12,14 @@ import (
func main() {
loadedExperiments := make(map[string]bool)
for _, exp := range os.Args[1:] {
loadedExperiments[exp] = true
}
generatedBindingsPrefix := ``
generatedBindings := ``
experimentRegistry := ``
file, err := os.Open("spec")
if err != nil {
log.Fatal(err)
@ -37,31 +43,58 @@ func main() {
fType := parts[0]
fName := parts[1]
args := parts[2:]
if strings.HasPrefix(line, "import") {
experiment := ""
if strings.HasPrefix(fType, "!") {
experiment = strings.ReplaceAll(fType, "!", "")
if _, gen := loadedExperiments[experiment]; gen {
fType = parts[1]
fName = parts[2]
args = parts[3:]
} else {
continue // skip experiment
}
}
if strings.HasPrefix(fType, "import") {
generatedBindingsPrefix += fName + "\n"
continue
}
if strings.HasPrefix(fType, "global") {
generatedBindings += fmt.Sprintf("var %s %s\n", parts[2], parts[3])
experimentRegistry += fmt.Sprintf(`
%s = %s.Init(&globalACN, appDir)
eventHandler.AddModule(%s)
%s.Enable(application, &globalACN)
`, parts[2], parts[4], parts[2], parts[2])
continue
}
fmt.Printf("generating %v function for %v\n", fType, fName)
switch fType {
case "app":
generatedBindings = generateAppFunction(generatedBindings, fName, parts[2:])
generatedBindings = generateAppFunction(generatedBindings, fName, args)
case "exp":
generatedBindings = generateExpFunction(generatedBindings, fName, experiment, args)
case "(json)app":
generatedBindings = generateJsonAppFunction(generatedBindings, fName, parts[2:])
generatedBindings = generateJsonAppFunction(generatedBindings, fName, args)
case "profile":
generatedBindings = generateProfileFunction(generatedBindings, fName, parts[2:])
generatedBindings = generateProfileFunction(generatedBindings, fName, args)
case "(json)profile":
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, parts[2:])
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args)
case "@profile-experiment":
experiment := parts[2]
generatedBindings = generateExperimentalProfileFunction(generatedBindings, experiment, fName, parts[3:])
experiment := args[0]
generatedBindings = generateExperimentalProfileFunction(generatedBindings, experiment, fName, args[1:])
case "@(json)profile-experiment":
experiment := parts[2]
generatedBindings = generateExperimentalJsonProfileFunction(generatedBindings, experiment, fName, parts[3:])
experiment := args[0]
generatedBindings = generateExperimentalJsonProfileFunction(generatedBindings, experiment, fName, args[1:])
default:
fmt.Printf("unknown function type %v\n", parts)
os.Exit(1)
}
@ -78,6 +111,7 @@ func main() {
template, _ := os.ReadFile("templates/lib_template.go")
templateString := string(template)
templateString = strings.ReplaceAll(templateString, "{{BINDINGS}}", generatedBindings)
templateString = strings.ReplaceAll(templateString, "{{EXPERIMENT_REGISTER}}", experimentRegistry)
templateString = strings.ReplaceAll(templateString, "{{IMPORTS}}", generatedBindingsPrefix)
os.WriteFile("lib.go", []byte(templateString), 0644)
}
@ -133,6 +167,10 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
argTypeParts := strings.Split(argSpec, ":")
argType := argTypeParts[0]
switch argType {
case "application":
gUse = append(gUse, "application")
case "acn":
gUse = append(gUse, "&globalACN")
case "profile":
c1, c2, c3, c4 := profileHandleArgPrototype()
cArgs = append(cArgs, c1)
@ -235,6 +273,31 @@ func {{FNAME}}({{GO_ARGS_SPEC}}) {
return bindings
}
func generateExpFunction(bindings string, name string, exp string, argsTypes []string) string {
appPrototype := `
//export c_{{FNAME}}
func c_{{FNAME}}({{C_ARGS}}) {
{{FNAME}}({{C2GO_ARGS}})
}
func {{FNAME}}({{GO_ARGS_SPEC}}) {
{{EXPERIMENT}}.{{LIBNAME}}({{GO_ARG}})
}
`
cArgs, c2GoArgs, goSpec, gUse := mapArgs(argsTypes)
appPrototype = strings.ReplaceAll(appPrototype, "{{FNAME}}", strings.TrimPrefix(name, "Enhanced"))
appPrototype = strings.ReplaceAll(appPrototype, "{{EXPERIMENT}}", exp)
appPrototype = strings.ReplaceAll(appPrototype, "{{LIBNAME}}", name)
appPrototype = strings.ReplaceAll(appPrototype, "{{C_ARGS}}", cArgs)
appPrototype = strings.ReplaceAll(appPrototype, "{{C2GO_ARGS}}", c2GoArgs)
appPrototype = strings.ReplaceAll(appPrototype, "{{GO_ARGS_SPEC}}", goSpec)
appPrototype = strings.ReplaceAll(appPrototype, "{{GO_ARG}}", gUse)
bindings += appPrototype
return bindings
}
func generateJsonAppFunction(bindings string, name string, argsTypes []string) string {
appPrototype := `
//export c_{{FNAME}}

4
go.mod
View File

@ -3,15 +3,13 @@ module git.openprivacy.ca/cwtch.im/cwtch-autobindings
go 1.19
require (
cwtch.im/cwtch v0.18.10-0.20230227213132-dfaed356c491
cwtch.im/cwtch v0.19.0
git.openprivacy.ca/cwtch.im/server v1.4.5
git.openprivacy.ca/openprivacy/connectivity v1.8.6
git.openprivacy.ca/openprivacy/log v1.0.3
github.com/mutecomm/go-sqlcipher/v4 v4.4.2
)
replace cwtch.im/cwtch => /home/sarah/workspace/src/cwtch.im/cwtch
require (
filippo.io/edwards25519 v1.0.0 // indirect
git.openprivacy.ca/cwtch.im/tapir v0.6.0 // indirect

12
go.sum
View File

@ -1,8 +1,6 @@
cwtch.im/cwtch v0.18.0/go.mod h1:StheazFFY7PKqBbEyDVLhzWW6WOat41zV0ckC240c5Y=
cwtch.im/cwtch v0.18.10-0.20230227213132-dfaed356c491 h1:pzzWnyXQHsnKDNHhG+JRTlDg3Eit62grfkM6KeUiv8g=
cwtch.im/cwtch v0.18.10-0.20230227213132-dfaed356c491/go.mod h1:h8S7EgEM+8pE1k+XLB5jAFdIPlOzwoXEY0GH5mQye5A=
cwtch.im/cwtch v0.18.10-0.20230227220552-0f83fb79f0c7 h1:hHKB6bPgYPwjOBGg3JR/3ovmSys1rKs6nsnpkrXslbU=
cwtch.im/cwtch v0.18.10-0.20230227220552-0f83fb79f0c7/go.mod h1:h8S7EgEM+8pE1k+XLB5jAFdIPlOzwoXEY0GH5mQye5A=
cwtch.im/cwtch v0.19.0 h1:s5YkU3od1ZJB+8OXoJAy8vjgi6lkIVhbdkXIE8V+iZY=
cwtch.im/cwtch v0.19.0/go.mod h1:h8S7EgEM+8pE1k+XLB5jAFdIPlOzwoXEY0GH5mQye5A=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
@ -92,12 +90,8 @@ golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d h1:3qF+Z8Hkrw9sOhrFHti9TlB1Hkac1x+DNRkv0XQiFjo=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mobile v0.0.0-20221110043201-43a038452099 h1:aIu0lKmfdgtn2uTj7JI2oN4TUrQvgB+wzTPO23bCKt8=
golang.org/x/mobile v0.0.0-20221110043201-43a038452099/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -148,8 +142,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

12
spec
View File

@ -43,4 +43,14 @@ import "cwtch.im/cwtch/functionality/filesharing"
# Server Hosting Experiment
# app-experiment ServerFunctionality
!serverExperiment import "git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
!serverExperiment global serverExperiment *servers.ServersFunctionality servers
!serverExperiment exp CreateServer application password string:description bool:autostart
!serverExperiment exp SetServerAttribute application string:handle string:key string:val
!serverExperiment exp LoadServers application acn password
!serverExperiment exp LaunchServers application acn
!serverExperiment exp LaunchServer application string:handle
!serverExperiment exp StopServer application string:handle
!serverExperiment exp StopServers application
!serverExperiment exp DestroyServers
!serverExperiment exp DeleteServer application string:handle password

View File

@ -12,9 +12,7 @@ import (
"cwtch.im/cwtch/model/constants"
"encoding/json"
"fmt"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/utils"
_ "git.openprivacy.ca/cwtch.im/server"
"git.openprivacy.ca/openprivacy/connectivity/tor"
"git.openprivacy.ca/openprivacy/log"
"os"
@ -165,7 +163,7 @@ func _startCwtch(appDir string, torPath string) {
// Allow the user of a custom torrc
globalAppDir = appDir
globalTorPath = torPath
settingsFile := app.InitApp(appDir)
settingsFile := app.LoadAppSettings(appDir)
newACN, settings := buildACN(settingsFile.ReadGlobalSettings(), globalTorPath, globalAppDir)
globalACN = connectivity.NewProxyACN(newACN)
settingsFile.WriteGlobalSettings(settings)
@ -193,10 +191,8 @@ func _startCwtch(appDir string, torPath string) {
application.QueryACNVersion()
application.LoadProfiles(app.DefactoPasswordForUnencryptedProfiles)
serverExperiment = servers.InitServers(&globalACN, appDir)
eventHandler.AddModule(serverExperiment)
serverExperiment.Enable(application)
serverExperiment.LoadServers(application, &globalACN, app.DefactoPasswordForUnencryptedProfiles)
{{EXPERIMENT_REGISTER}}
}
// the pointer returned from this function **must** be freed using c_Free
@ -494,91 +490,6 @@ func UpdateSettings(settingsJson string) {
application.UpdateSettings(newSettings)
}
//***** Server APIs *****
var serverExperiment *servers.ServersFunctionality
//export c_LoadServers
func c_LoadServers(passwordPtr *C.char, passwordLen C.int) {
LoadServers(C.GoStringN(passwordPtr, passwordLen))
}
func LoadServers(password string) {
serverExperiment.LoadServers(application, &globalACN, password)
}
//export c_CreateServer
func c_CreateServer(passwordPtr *C.char, passwordLen C.int, descPtr *C.char, descLen C.int, autostart C.char) {
CreateServer(C.GoStringN(passwordPtr, passwordLen), C.GoStringN(descPtr, descLen), autostart == 1)
}
func CreateServer(password string, description string, autostart bool) {
serverExperiment.CreateServer(application, password, description, autostart)
}
//export c_DeleteServer
func c_DeleteServer(onionPtr *C.char, onionLen C.int, currentPasswordPtr *C.char, currentPasswordLen C.int) {
DeleteServer(C.GoStringN(onionPtr, onionLen), C.GoStringN(currentPasswordPtr, currentPasswordLen))
}
func DeleteServer(onion string, currentPassword string) {
serverExperiment.DeleteServer(application, onion, currentPassword)
}
//export c_LaunchServers
func c_LaunchServers() {
LaunchServers()
}
func LaunchServers() {
serverExperiment.LaunchServers(application, &globalACN)
}
//export c_LaunchServer
func c_LaunchServer(onionPtr *C.char, onionLen C.int) {
LaunchServer(C.GoStringN(onionPtr, onionLen))
}
func LaunchServer(onion string) {
serverExperiment.LaunchServer(application, onion)
}
//export c_StopServer
func c_StopServer(onionPtr *C.char, onionLen C.int) {
StopServer(C.GoStringN(onionPtr, onionLen))
}
func StopServer(onion string) {
serverExperiment.StopServer(application, onion)
}
//export c_StopServers
func c_StopServers() {
StopServers()
}
func StopServers() {
serverExperiment.StopServers(application)
}
//export c_DestroyServers
func c_DestroyServers() {
DestroyServers()
}
func DestroyServers() {
serverExperiment.DestroyServers()
}
//export c_SetServerAttribute
func c_SetServerAttribute(onionPtr *C.char, onionLen C.int, keyPtr *C.char, keyLen C.int, valPtr *C.char, valLen C.int) {
SetServerAttribute(C.GoStringN(onionPtr, onionLen), C.GoStringN(keyPtr, keyLen), C.GoStringN(valPtr, valLen))
}
func SetServerAttribute(onion string, key string, val string) {
serverExperiment.SetServerAttribute(application, onion, key, val)
}
{{BINDINGS}}