Explorar el Código

Merge branch 'values'

Rod Hynes hace 6 años
padre
commit
6069824ca3

+ 2 - 0
.travis.yml

@@ -26,6 +26,7 @@ script:
 #    tun_test.go:226: startTestTCPClient failed: syscall.Connect failed: connection timed out
 #
 #- sudo -E env "PATH=$PATH" go test -race -v ./common/tun
+- go test -race -v ./common/values
 - go test -race -v ./common/wildcard
 - go test -race -v ./transferstats
 - go test -race -v ./server
@@ -45,6 +46,7 @@ script:
 - go test -v -covermode=count -coverprofile=tactics.coverprofile ./common/tactics
 # TODO: see comment above
 #- sudo -E env "PATH=$PATH" go test -v -covermode=count -coverprofile=tun.coverprofile ./common/tun
+- go test -v -covermode=count -coverprofile=values.coverprofile ./common/values
 - go test -v -covermode=count -coverprofile=wildcard.coverprofile ./common/wildcard
 - go test -v -covermode=count -coverprofile=transferstats.coverprofile ./transferstats
 - go test -v -covermode=count -coverprofile=server.coverprofile ./server

+ 5 - 5
ClientLibrary/build-darwin.sh

@@ -83,11 +83,11 @@ prepare_build () {
   LDFLAGS="\
   -s \
   -w \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=$BUILDDATE \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=$BUILDREPO \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=$BUILDREV \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=$GOVERSION \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=$DEPENDENCIES \
   "
 
   echo "Variables for ldflags:"

+ 5 - 5
ClientLibrary/make.bash

@@ -36,11 +36,11 @@ prepare_build () {
   LDFLAGS="\
   -s \
   -w \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=$BUILDDATE \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=$BUILDREPO \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=$BUILDREV \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=$GOVERSION \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=$DEPENDENCIES \
   "
 
   echo "Variables for ldflags:"

+ 0 - 27
ClientLibrary/privatePlugins.go

@@ -1,27 +0,0 @@
-// +build PRIVATE_PLUGINS
-
-/*
- * Copyright (c) 2015, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package main
-
-import (
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/client_plugins"
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/common_plugins"
-)

+ 2 - 1
ConsoleClient/main.go

@@ -34,6 +34,7 @@ import (
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tun"
 )
@@ -99,7 +100,7 @@ func main() {
 	flag.Parse()
 
 	if versionDetails {
-		b := common.GetBuildInfo()
+		b := buildinfo.GetBuildInfo()
 
 		var printableDependencies bytes.Buffer
 		var dependencyMap map[string]string

+ 5 - 5
ConsoleClient/make.bash

@@ -31,11 +31,11 @@ prepare_build () {
   LDFLAGS="\
   -s \
   -w \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=$BUILDDATE \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=$BUILDREPO \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=$BUILDREV \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=$GOVERSION \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=$DEPENDENCIES \
   "
   echo -e "${BUILDDATE}\n${BUILDREPO}\n${BUILDREV}\n" > $BUILDINFOFILE
 

+ 0 - 27
ConsoleClient/privatePlugins.go

@@ -1,27 +0,0 @@
-// +build PRIVATE_PLUGINS
-
-/*
- * Copyright (c) 2015, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package main
-
-import (
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/client_plugins"
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/common_plugins"
-)

+ 6 - 6
MobileLibrary/Android/make.bash

@@ -38,12 +38,12 @@ DEPENDENCIES=$(cd ../psi && echo -n "{" && GOOS=android go list -tags "${BUILD_T
 LDFLAGS="\
 -s \
 -w \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.gomobileVersion=$GOMOBILEVERSION \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=$BUILDDATE \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=$BUILDREPO \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=$BUILDREV \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=$GOVERSION \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.gomobileVersion=$GOMOBILEVERSION \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=$DEPENDENCIES \
 "
 
 echo "Variables for ldflags:"

+ 6 - 6
MobileLibrary/iOS/build-psiphon-framework.sh

@@ -139,12 +139,12 @@ DEPENDENCIES=$(echo -n "{" && GOOS=darwin go list -tags "${BUILD_TAGS}" -f '{{ra
 LDFLAGS="\
 -s \
 -w \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=${BUILDDATE} \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=${BUILDREPO} \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=${BUILDREV} \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=${GOVERSION} \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.gomobileVersion=${GOMOBILEVERSION} \
--X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=${DEPENDENCIES} \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=${BUILDDATE} \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=${BUILDREPO} \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=${BUILDREV} \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=${GOVERSION} \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.gomobileVersion=${GOMOBILEVERSION} \
+-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=${DEPENDENCIES} \
 "
 
 echo ""

+ 2 - 1
MobileLibrary/psi/psi.go

@@ -34,6 +34,7 @@ import (
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tun"
 )
@@ -259,7 +260,7 @@ func SendFeedback(configJson, diagnosticsJson, b64EncodedPublicKey, uploadServer
 
 // Get build info from tunnel-core
 func GetBuildInfo() string {
-	buildInfo, err := json.Marshal(common.GetBuildInfo())
+	buildInfo, err := json.Marshal(buildinfo.GetBuildInfo())
 	if err != nil {
 		return ""
 	}

+ 5 - 5
README.md

@@ -34,11 +34,11 @@ Client Setup
     DEPENDENCIES=$(echo -n "{" && go list -f '{{range $dep := .Deps}}{{printf "%s\n" $dep}}{{end}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | xargs -I pkg bash -c 'cd $GOPATH/src/pkg && echo -n "\"pkg\":\"$(git rev-parse --short HEAD)\","' | sed 's/,$/}/')
 
     LDFLAGS="\
-    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
-    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
-    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
-    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
-    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
+    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=$BUILDDATE \
+    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=$BUILDREPO \
+    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=$BUILDREV \
+    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=$GOVERSION \
+    -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=$DEPENDENCIES \
     "
     ```
 

+ 2 - 1
Server/main.go

@@ -33,6 +33,7 @@ import (
 
 	"github.com/Psiphon-Inc/rotate-safe-writer"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server"
 	"github.com/mitchellh/panicwrap"
@@ -284,7 +285,7 @@ func panicHandler(output string) {
 
 		logEvent := make(map[string]string)
 		logEvent["host_id"] = config.HostID
-		logEvent["build_rev"] = common.GetBuildInfo().BuildRev
+		logEvent["build_rev"] = buildinfo.GetBuildInfo().BuildRev
 		logEvent["timestamp"] = time.Now().Format(time.RFC3339)
 		logEvent["event_name"] = "server_panic"
 

+ 5 - 5
Server/make.bash

@@ -31,11 +31,11 @@ prepare_build () {
 
   LDFLAGS="\
   -linkmode external -extldflags \"-static\" \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION \
-  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=$BUILDDATE \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=$BUILDREPO \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=$BUILDREV \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=$GOVERSION \
+  -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.dependencies=$DEPENDENCIES \
   "
   echo -e "${BUILDDATE}\n${BUILDREPO}\n${BUILDREV}\n" > $BUILDINFOFILE
 

+ 0 - 27
Server/privatePlugins.go

@@ -1,27 +0,0 @@
-// +build PRIVATE_PLUGINS
-
-/*
- * Copyright (c) 2015, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package main
-
-import (
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/common_plugins"
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/server_plugins"
-)

+ 12 - 7
psiphon/common/buildinfo.go → psiphon/common/buildinfo/buildinfo.go

@@ -17,11 +17,13 @@
  *
  */
 
-package common
+package buildinfo
 
 import (
 	"encoding/json"
 	"strings"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 )
 
 /*
@@ -32,22 +34,22 @@ Without those build flags, the build info in the notice will simply be empty str
 Suggestions for how to fill in the values will be given for each variable.
 Note that any passed value must contain no whitespace.
 */
-// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=`date --iso-8601=seconds`
+// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildDate=`date --iso-8601=seconds`
 var buildDate string
 
-// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=`git config --get remote.origin.url`
+// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRepo=`git config --get remote.origin.url`
 var buildRepo string
 
-// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=`git rev-parse --short HEAD`
+// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.buildRev=`git rev-parse --short HEAD`
 var buildRev string
 
-// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=`go version | perl -ne '/go version (.*?) / && print $1'`
+// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.goVersion=`go version | perl -ne '/go version (.*?) / && print $1'`
 var goVersion string
 
-// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.gomobileVersion=`gomobile version | perl -ne '/gomobile version (.*?) / && print $1'`
+// -X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo.gomobileVersion=`gomobile version | perl -ne '/gomobile version (.*?) / && print $1'`
 var gomobileVersion string
 
-// -X github.com/Psiphon-Labs/psiphon-tunnel-core/common.dependencies=`echo -n "{" && go list -f '{{range $dep := .Deps}}{{printf "%s\n" $dep}}{{end}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | xargs -I pkg bash -c 'cd $GOPATH/src/pkg && echo -n "\"pkg\":\"$(git rev-parse --short HEAD)\","' | sed 's/,$/}/'`
+// -X github.com/Psiphon-Labs/psiphon-tunnel-core/common/buildinfo.dependencies=`echo -n "{" && go list -f '{{range $dep := .Deps}}{{printf "%s\n" $dep}}{{end}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | xargs -I pkg bash -c 'cd $GOPATH/src/pkg && echo -n "\"pkg\":\"$(git rev-parse --short HEAD)\","' | sed 's/,$/}/'`
 // Dependencies should be listed as a JSON object like the following (no spaces) {"github.com/Psiphon-Labs/psiphon-tunnel-core":"abcdef","...":"..."}
 var dependencies string
 
@@ -59,6 +61,7 @@ type BuildInfo struct {
 	GoVersion       string          `json:"goVersion"`
 	GomobileVersion string          `json:"gomobileVersion,omitempty"`
 	Dependencies    json.RawMessage `json:"dependencies"`
+	ValuesRev       string          `json:"valuesRev"`
 }
 
 // ToMap converts 'BuildInfo' struct to 'map[string]interface{}'
@@ -73,6 +76,7 @@ func (bi *BuildInfo) ToMap() *map[string]interface{} {
 		"buildRev":     bi.BuildRev,
 		"goVersion":    bi.GoVersion,
 		"dependencies": dependenciesMap,
+		"valuesRev":    bi.ValuesRev,
 	}
 
 	return &buildInfoMap
@@ -91,6 +95,7 @@ func GetBuildInfo() *BuildInfo {
 		GoVersion:       strings.TrimSpace(goVersion),
 		GomobileVersion: strings.TrimSpace(gomobileVersion),
 		Dependencies:    json.RawMessage(strings.TrimSpace(dependencies)),
+		ValuesRev:       values.GetRevision(),
 	}
 
 	return &buildInfo

+ 0 - 38
psiphon/common/hostNameGenerator.go

@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2016, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package common
-
-import (
-	"sync/atomic"
-)
-
-var registeredHostNameGenerator atomic.Value
-
-func RegisterHostNameGenerator(generator func() string) {
-	registeredHostNameGenerator.Store(generator)
-}
-
-func GenerateHostName() string {
-	generator := registeredHostNameGenerator.Load()
-	if generator != nil {
-		return generator.(func() string)()
-	}
-	return "www.example.org"
-}

+ 2 - 1
psiphon/common/quic/quic.go

@@ -53,6 +53,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 	quic_go "github.com/lucas-clemente/quic-go"
 	"github.com/lucas-clemente/quic-go/h2quic"
 	"github.com/lucas-clemente/quic-go/qerr"
@@ -80,7 +81,7 @@ func Listen(
 	obfuscationKey string) (*Listener, error) {
 
 	certificate, privateKey, err := common.GenerateWebServerCertificate(
-		common.GenerateHostName())
+		values.GetHostName())
 	if err != nil {
 		return nil, common.ContextError(err)
 	}

+ 7 - 7
MobileLibrary/psi/privatePlugins.go → psiphon/common/values/init.go

@@ -1,7 +1,7 @@
-// +build PRIVATE_PLUGINS
+// +build INIT_PSIPHON_COMMON_VALUES
 
 /*
- * Copyright (c) 2015, Psiphon Inc.
+ * Copyright (c) 2019, Psiphon Inc.
  * All rights reserved.
  *
  * This program is free software: you can redistribute it and/or modify
@@ -19,9 +19,9 @@
  *
  */
 
-package psi
+package values
 
-import (
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/client_plugins"
-	_ "github.com/Psiphon-Inc/psiphon-tunnel-core-private-plugins/common_plugins"
-)
+// This file is a guard against building with INIT_PSIPHON_COMMON_VALUES
+// without replacing init.go.
+
+var buildGuard = intentionally_undefined

+ 218 - 0
psiphon/common/values/values.go

@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2019, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+
+Package values provides a mechanism for specifying and selecting dynamic
+values employed by the Psiphon client and server.
+
+*/
+package values
+
+import (
+	"bytes"
+	"encoding/gob"
+	"errors"
+	"strings"
+	"sync/atomic"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/nacl/secretbox"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
+)
+
+// ValueSpec specifies a value selection space.
+type ValueSpec struct {
+	Parts   []PartSpec
+	Padding []byte
+}
+
+type PartSpec struct {
+	Items              []string
+	MinCount, MaxCount int
+}
+
+// NewPickOneSpec creates a simple spec to select one item from a list as a
+// value.
+func NewPickOneSpec(items []string) *ValueSpec {
+	return &ValueSpec{Parts: []PartSpec{{Items: items, MinCount: 1, MaxCount: 1}}}
+}
+
+// GetValue selects a value according to the spec. An optional seed may
+// be specified to support replay.
+func (spec *ValueSpec) GetValue(seed *prng.Seed) string {
+	rangeFunc := prng.Range
+	intnFunc := prng.Intn
+	if seed != nil {
+		PRNG := prng.NewPRNGWithSeed(seed)
+		rangeFunc = PRNG.Range
+		intnFunc = PRNG.Intn
+	}
+	var value strings.Builder
+	for _, part := range spec.Parts {
+		count := rangeFunc(part.MinCount, part.MaxCount)
+		for i := 0; i < count; i++ {
+			value.WriteString(part.Items[intnFunc(len(part.Items))])
+		}
+	}
+	return value.String()
+}
+
+// Obfuscate creates an obfuscated blob from a spec.
+func (spec *ValueSpec) Obfuscate(
+	obfuscationKey []byte,
+	minPadding, maxPadding int) ([]byte, error) {
+
+	if len(obfuscationKey) != 32 {
+		return nil, common.ContextError(errors.New("invalid key length"))
+	}
+	var key [32]byte
+	copy(key[:], []byte(obfuscationKey))
+
+	spec.Padding = prng.Padding(minPadding, maxPadding)
+
+	var obfuscatedValueSpec bytes.Buffer
+	err := gob.NewEncoder(&obfuscatedValueSpec).Encode(spec)
+	if err != nil {
+		return nil, common.ContextError(err)
+	}
+
+	return secretbox.Seal(
+		nil, []byte(obfuscatedValueSpec.Bytes()), &[24]byte{}, &key), nil
+}
+
+// DeobfuscateValueSpec reconstitutes an obfuscated spec.
+func DeobfuscateValueSpec(obfuscatedValueSpec, obfuscationKey []byte) *ValueSpec {
+
+	if len(obfuscationKey) != 32 {
+		return nil
+	}
+	var key [32]byte
+	copy(key[:], obfuscationKey)
+
+	deobfuscatedValueSpec, ok := secretbox.Open(nil, obfuscatedValueSpec, &[24]byte{}, &key)
+	if !ok {
+		return nil
+	}
+
+	spec := new(ValueSpec)
+	err := gob.NewDecoder(bytes.NewBuffer(deobfuscatedValueSpec)).Decode(spec)
+	if err != nil {
+		return nil
+	}
+	spec.Padding = nil
+
+	return spec
+}
+
+var (
+	revision              atomic.Value
+	sshClientVersionsSpec atomic.Value
+	sshServerVersionsSpec atomic.Value
+	userAgentsSpec        atomic.Value
+	hostNamesSpec         atomic.Value
+)
+
+// SetRevision set the revision value, which may be used to track which value
+// specs are active. The revision is not managed by this package and must be
+// set by the package user.
+func SetRevision(rev string) {
+	revision.Store(rev)
+}
+
+// GetRevision gets the previously set revision.
+func GetRevision() string {
+	rev, ok := revision.Load().(string)
+	if !ok {
+		return "none"
+	}
+	return rev
+}
+
+// SetSSHClientVersionsSpec sets the corresponding value spec.
+func SetSSHClientVersionsSpec(spec *ValueSpec) {
+	if spec == nil {
+		return
+	}
+	sshClientVersionsSpec.Store(spec)
+}
+
+// GetSSHClientVersion selects a value based on the previously set spec, or
+// returns a default when no spec is set.
+func GetSSHClientVersion() string {
+	spec, ok := sshClientVersionsSpec.Load().(*ValueSpec)
+	if !ok {
+		return ""
+	}
+	return spec.GetValue(nil)
+}
+
+// SetSSHServerVersionsSpec sets the corresponding value spec.
+func SetSSHServerVersionsSpec(spec *ValueSpec) {
+	if spec == nil {
+		return
+	}
+	sshServerVersionsSpec.Store(spec)
+}
+
+// GetSSHServerVersion selects a value based on the previously set spec, or
+// returns a default when no spec is set.
+func GetSSHServerVersion(seed *prng.Seed) string {
+	spec, ok := sshServerVersionsSpec.Load().(*ValueSpec)
+	if !ok {
+		return ""
+	}
+	return spec.GetValue(seed)
+}
+
+// SetUserAgentsSpec sets the corresponding value spec.
+func SetUserAgentsSpec(spec *ValueSpec) {
+	if spec == nil {
+		return
+	}
+	userAgentsSpec.Store(spec)
+}
+
+// GetUserAgent selects a value based on the previously set spec, or
+// returns a default when no spec is set.
+func GetUserAgent() string {
+	spec, ok := userAgentsSpec.Load().(*ValueSpec)
+	if !ok {
+		return ""
+	}
+	return spec.GetValue(nil)
+}
+
+// SetHostNamesSpec sets the corresponding value spec.
+func SetHostNamesSpec(spec *ValueSpec) {
+	if spec == nil {
+		return
+	}
+	hostNamesSpec.Store(spec)
+}
+
+// GetHostName selects a value based on the previously set spec, or
+// returns a default when no spec is set.
+func GetHostName() string {
+	spec, ok := hostNamesSpec.Load().(*ValueSpec)
+	if !ok {
+		return "www.example.org"
+	}
+	return spec.GetValue(nil)
+}

+ 67 - 0
psiphon/common/values/values_test.go

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package values
+
+import (
+	"testing"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+)
+
+func TestValues(t *testing.T) {
+
+	testValues := []string{"a", "b", "c"}
+
+	spec := NewPickOneSpec(testValues)
+
+	key, err := common.MakeSecureRandomBytes(32)
+	if err != nil {
+		t.Fatalf("MakeSecureRandomBytes failed: %s", err)
+	}
+
+	obfuscatedSpec, err := spec.Obfuscate(key, 10, 20)
+	if err != nil {
+		t.Fatalf("Obfuscate failed: %s", err)
+	}
+
+	spec = DeobfuscateValueSpec(obfuscatedSpec, key)
+	if spec == nil {
+		t.Fatalf("DeobfuscateValueSpec failed")
+	}
+
+	values := make(map[string]bool)
+
+	SetUserAgentsSpec(spec)
+
+	for i := 0; i < 100; i++ {
+		values[GetUserAgent()] = true
+	}
+
+	if len(values) != len(testValues) {
+		t.Fatalf("unexpected values count")
+	}
+
+	for _, testValue := range testValues {
+		_, ok := values[testValue]
+		if !ok {
+			t.Fatalf("unexpected missing value")
+		}
+	}
+}

+ 23 - 5
psiphon/dialParameters.go

@@ -36,6 +36,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 	utls "github.com/refraction-networking/utls"
 	regen "github.com/zach-klippenstein/goregen"
 )
@@ -286,7 +287,7 @@ func MakeDialParameters(
 
 	if !isReplay || !replaySSH {
 		dialParams.SelectedSSHClientVersion = true
-		dialParams.SSHClientVersion = pickSSHClientVersion()
+		dialParams.SSHClientVersion = values.GetSSHClientVersion()
 		dialParams.SSHKEXSeed, err = prng.NewSeed()
 		if err != nil {
 			return nil, common.ContextError(err)
@@ -376,7 +377,7 @@ func MakeDialParameters(
 
 			dialParams.MeekSNIServerName = ""
 			if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
-				dialParams.MeekSNIServerName = common.GenerateHostName()
+				dialParams.MeekSNIServerName = values.GetHostName()
 				dialParams.MeekTransformedHostName = true
 			}
 
@@ -385,7 +386,7 @@ func MakeDialParameters(
 			dialParams.MeekHostHeader = ""
 			hostname := serverEntry.IpAddress
 			if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
-				hostname = common.GenerateHostName()
+				hostname = values.GetHostName()
 				dialParams.MeekTransformedHostName = true
 			}
 			if serverEntry.MeekServerPort == 80 {
@@ -396,7 +397,7 @@ func MakeDialParameters(
 		} else if protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) {
 
 			dialParams.QUICDialSNIAddress = fmt.Sprintf(
-				"%s:%d", common.GenerateHostName(), serverEntry.SshObfuscatedQUICPort)
+				"%s:%d", values.GetHostName(), serverEntry.SshObfuscatedQUICPort)
 		}
 	}
 
@@ -541,7 +542,7 @@ func MakeDialParameters(
 	if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) || dialParams.UpstreamProxyType == "http" {
 
 		if !isReplay || !replayUserAgent {
-			dialParams.SelectedUserAgent, dialParams.UserAgent = PickUserAgentIfUnset(p, dialCustomHeaders)
+			dialParams.SelectedUserAgent, dialParams.UserAgent = selectUserAgentIfUnset(p, dialCustomHeaders)
 		}
 
 		if dialParams.SelectedUserAgent {
@@ -864,6 +865,23 @@ func selectQUICVersion(allowObfuscatedQUIC bool, p *parameters.ClientParametersS
 	return quicVersions[choice]
 }
 
+// selectUserAgentIfUnset selects a User-Agent header if one is not set.
+func selectUserAgentIfUnset(
+	p *parameters.ClientParametersSnapshot, headers http.Header) (bool, string) {
+
+	if _, ok := headers["User-Agent"]; !ok {
+
+		userAgent := ""
+		if p.WeightedCoinFlip(parameters.PickUserAgentProbability) {
+			userAgent = values.GetUserAgent()
+		}
+
+		return true, userAgent
+	}
+
+	return false, ""
+}
+
 func makeDialCustomHeaders(
 	config *Config,
 	p *parameters.ClientParametersSnapshot) http.Header {

+ 5 - 8
psiphon/dialParameters_test.go

@@ -32,6 +32,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 )
 
 func TestDialParametersAndReplay(t *testing.T) {
@@ -99,15 +100,11 @@ func runDialParametersAndReplay(t *testing.T, tunnelProtocol string) {
 		return tunnelProtocol, true
 	}
 
-	RegisterSSHClientVersionPicker(func() string {
-		versions := []string{"SSH-2.0-A", "SSH-2.0-B", "SSH-2.0-C"}
-		return versions[prng.Intn(len(versions))]
-	})
+	values.SetSSHClientVersionsSpec(
+		values.NewPickOneSpec([]string{"SSH-2.0-A", "SSH-2.0-B", "SSH-2.0-C"}))
 
-	RegisterUserAgentPicker(func() string {
-		versions := []string{"ua1", "ua2", "ua3"}
-		return versions[prng.Intn(len(versions))]
-	})
+	values.SetUserAgentsSpec(
+		values.NewPickOneSpec([]string{"ua1", "ua2", "ua3"}))
 
 	// Test: expected dial parameter fields set
 

+ 2 - 1
psiphon/notice.go

@@ -32,6 +32,7 @@ import (
 	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 )
 
 type noticeLogger struct {
@@ -715,7 +716,7 @@ func NoticeLocalProxyError(proxyType string, err error) {
 func NoticeBuildInfo() {
 	singletonNoticeLogger.outputNotice(
 		"BuildInfo", noticeIsDiagnostic,
-		"buildInfo", common.GetBuildInfo())
+		"buildInfo", buildinfo.GetBuildInfo())
 }
 
 // NoticeExiting indicates that tunnel-core is exiting imminently.

+ 2 - 1
psiphon/server/config.go

@@ -41,6 +41,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/osl"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tactics"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 )
 
 const (
@@ -466,7 +467,7 @@ func LoadConfig(configJSON []byte) (*Config, error) {
 				"DeriveSSHServerVersionPRNGSeed failed: %s", err)
 		}
 
-		serverVersion := pickSSHServerVersion(seed)
+		serverVersion := values.GetSSHServerVersion(seed)
 		if serverVersion != "" {
 			config.SSHServerVersion = serverVersion
 		}

+ 2 - 1
psiphon/server/log.go

@@ -32,6 +32,7 @@ import (
 
 	"github.com/Psiphon-Inc/rotate-safe-writer"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 	"github.com/sirupsen/logrus"
 )
 
@@ -237,7 +238,7 @@ func InitLogging(config *Config) (retErr error) {
 	initLogging.Do(func() {
 
 		logHostID = config.HostID
-		logBuildRev = common.GetBuildInfo().BuildRev
+		logBuildRev = buildinfo.GetBuildInfo().BuildRev
 
 		level, err := logrus.ParseLevel(config.LogLevel)
 		if err != nil {

+ 2 - 1
psiphon/server/meek.go

@@ -44,6 +44,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 	tris "github.com/Psiphon-Labs/tls-tris"
 )
 
@@ -937,7 +938,7 @@ func makeMeekTLSConfig(
 	support *SupportServices,
 	isFronted, useObfuscatedSessionTickets bool) (*tris.Config, error) {
 
-	certificate, privateKey, err := common.GenerateWebServerCertificate(common.GenerateHostName())
+	certificate, privateKey, err := common.GenerateWebServerCertificate(values.GetHostName())
 	if err != nil {
 		return nil, common.ContextError(err)
 	}

+ 3 - 6
psiphon/server/server_test.go

@@ -46,6 +46,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tactics"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 	"golang.org/x/net/proxy"
 )
 
@@ -776,13 +777,9 @@ func runServer(t *testing.T, runConfig *runServerConfig) {
 
 	// configure client
 
-	psiphon.RegisterSSHClientVersionPicker(func() string {
-		return testSSHClientVersions[prng.Intn(len(testSSHClientVersions))]
-	})
+	values.SetSSHClientVersionsSpec(values.NewPickOneSpec(testSSHClientVersions))
 
-	psiphon.RegisterUserAgentPicker(func() string {
-		return testUserAgents[prng.Intn(len(testUserAgents))]
-	})
+	values.SetUserAgentsSpec(values.NewPickOneSpec(testUserAgents))
 
 	// TODO: currently, TargetServerEntry only works with one tunnel
 	numTunnels := 1

+ 2 - 1
psiphon/server/services.go

@@ -34,6 +34,7 @@ import (
 	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/osl"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tactics"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tun"
@@ -65,7 +66,7 @@ func RunServices(configJSON []byte) error {
 		return common.ContextError(err)
 	}
 
-	log.WithContextFields(*common.GetBuildInfo().ToMap()).Info("startup")
+	log.WithContextFields(*buildinfo.GetBuildInfo().ToMap()).Info("startup")
 
 	waitGroup := new(sync.WaitGroup)
 	shutdownBroadcast := make(chan struct{})

+ 0 - 40
psiphon/server/sshServerVersionPicker.go

@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2019, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package server
-
-import (
-	"sync/atomic"
-
-	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
-)
-
-var registeredSSHServerVersionPicker atomic.Value
-
-func RegisterSSHServerVersionPicker(picker func(*prng.Seed) string) {
-	registeredSSHServerVersionPicker.Store(picker)
-}
-
-func pickSSHServerVersion(seed *prng.Seed) string {
-	picker := registeredSSHServerVersionPicker.Load()
-	if picker != nil {
-		return picker.(func(*prng.Seed) string)(seed)
-	}
-	return ""
-}

+ 3 - 2
psiphon/serverApi.go

@@ -36,6 +36,7 @@ import (
 	"strings"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
@@ -615,7 +616,7 @@ func RecordRemoteServerListStat(
 	params["sponsor_id"] = config.GetSponsorID()
 	params["client_version"] = config.ClientVersion
 	params["client_platform"] = config.ClientPlatform
-	params["client_build_rev"] = common.GetBuildInfo().BuildRev
+	params["client_build_rev"] = buildinfo.GetBuildInfo().BuildRev
 
 	params["client_download_timestamp"] = common.TruncateTimestampToHour(common.GetCurrentTimestamp())
 	params["url"] = url
@@ -784,7 +785,7 @@ func getBaseAPIParameters(
 	params["client_version"] = config.ClientVersion
 	params["relay_protocol"] = dialParams.TunnelProtocol
 	params["client_platform"] = config.ClientPlatform
-	params["client_build_rev"] = common.GetBuildInfo().BuildRev
+	params["client_build_rev"] = buildinfo.GetBuildInfo().BuildRev
 	params["tunnel_whole_device"] = strconv.Itoa(config.TunnelWholeDevice)
 
 	// The following parameters may be blank and must

+ 0 - 38
psiphon/sshClientVersionPicker.go

@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package psiphon
-
-import (
-	"sync/atomic"
-)
-
-var registeredSSHClientVersionPicker atomic.Value
-
-func RegisterSSHClientVersionPicker(picker func() string) {
-	registeredSSHClientVersionPicker.Store(picker)
-}
-
-func pickSSHClientVersion() string {
-	picker := registeredSSHClientVersionPicker.Load()
-	if picker != nil {
-		return picker.(func() string)()
-	}
-	return ""
-}

+ 2 - 1
psiphon/tlsDialer_test.go

@@ -32,6 +32,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 	tris "github.com/Psiphon-Labs/tls-tris"
 	utls "github.com/refraction-networking/utls"
 )
@@ -73,7 +74,7 @@ func testTLSDialerCompatibility(t *testing.T, address string) {
 
 		// Same tls-tris config as psiphon/server/meek.go
 
-		certificate, privateKey, err := common.GenerateWebServerCertificate(common.GenerateHostName())
+		certificate, privateKey, err := common.GenerateWebServerCertificate(values.GetHostName())
 		if err != nil {
 			t.Fatalf("%s\n", err)
 		}

+ 0 - 58
psiphon/userAgentPicker.go

@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2017, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package psiphon
-
-import (
-	"net/http"
-	"sync/atomic"
-
-	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
-)
-
-var registeredUserAgentPicker atomic.Value
-
-func RegisterUserAgentPicker(picker func() string) {
-	registeredUserAgentPicker.Store(picker)
-}
-
-func pickUserAgent() string {
-	picker := registeredUserAgentPicker.Load()
-	if picker != nil {
-		return picker.(func() string)()
-	}
-	return ""
-}
-
-// PickUserAgentIfUnset selects a User-Agent header if one is not set.
-func PickUserAgentIfUnset(
-	p *parameters.ClientParametersSnapshot, headers http.Header) (bool, string) {
-
-	if _, ok := headers["User-Agent"]; !ok {
-
-		userAgent := ""
-		if p.WeightedCoinFlip(parameters.PickUserAgentProbability) {
-			userAgent = pickUserAgent()
-		}
-
-		return true, userAgent
-	}
-
-	return false, ""
-}

+ 4 - 9
psiphon/userAgent_test.go

@@ -31,7 +31,7 @@ import (
 	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
-	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server"
 	"github.com/elazarl/goproxy"
 )
@@ -55,13 +55,8 @@ var userAgentCountsMutex sync.Mutex
 var userAgentCounts map[string]int
 var initUserAgentCounter sync.Once
 
-func pickMockUserAgent() string {
-	index := prng.Intn(len(mockUserAgents))
-	return mockUserAgents[index]
-}
-
-func initMockUserAgentPicker() {
-	RegisterUserAgentPicker(pickMockUserAgent)
+func initMockUserAgents() {
+	values.SetUserAgentsSpec(values.NewPickOneSpec(mockUserAgents))
 }
 
 func resetUserAgentCounts() {
@@ -159,7 +154,7 @@ func attemptConnectionsWithUserAgent(
 	}
 	defer os.RemoveAll(testDataDirName)
 
-	initMockUserAgentPicker()
+	initMockUserAgents()
 	initUserAgentCounterUpstreamProxy()
 	resetUserAgentCounts()