Selaa lähdekoodia

Merge pull request #189 from rod-hynes/master

psinet: move to seperate package; support hot reload of database file
Rod Hynes 9 vuotta sitten
vanhempi
sitoutus
d5acc87518

+ 3 - 2
psiphon/server/api.go

@@ -31,6 +31,7 @@ import (
 	"unicode"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server/psinet"
 )
 
 const MAX_API_PARAMS_SIZE = 256 * 1024 // 256KB
@@ -50,7 +51,7 @@ type requestJSONObject map[string]interface{}
 //
 func sshAPIRequestHandler(
 	config *Config,
-	psinetDatabase *PsinetDatabase,
+	psinetDatabase *psinet.Database,
 	geoIPData GeoIPData,
 	name string,
 	requestPayload []byte) ([]byte, error) {
@@ -84,7 +85,7 @@ func sshAPIRequestHandler(
 // stats to record, etc.
 func handshakeAPIRequestHandler(
 	config *Config,
-	psinetDatabase *PsinetDatabase,
+	psinetDatabase *psinet.Database,
 	geoIPData GeoIPData,
 	params requestJSONObject) ([]byte, error) {
 

+ 0 - 72
psiphon/server/psinet.go

@@ -1,72 +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 server
-
-// PsinetDatabase serves Psiphon API data requests. It's safe for
-// concurrent usage.
-type PsinetDatabase struct {
-}
-
-// NewPsinetDatabase initializes a PsinetDatabase. It loads the specified
-// file, which should be in the Psiphon automation jsonpickle format, and
-// prepares to serve data requests.
-// The input "" is valid and returns a functional PsinetDatabase with no
-// data.
-func NewPsinetDatabase(filename string) (*PsinetDatabase, error) {
-
-	// TODO: implement
-
-	return &PsinetDatabase{}, nil
-}
-
-// GetHomepages returns a list of  home pages for the specified sponsor,
-// region, and platform.
-func (psinet *PsinetDatabase) GetHomepages(sponsorID, clientRegion, clientPlatform string) []string {
-
-	// TODO: implement
-
-	return make([]string, 0)
-}
-
-// GetUpgradeClientVersion returns a new client version when an upgrade is
-// indicated for the specified client current version. The result is "" when
-// no upgrade is available.
-func (psinet *PsinetDatabase) GetUpgradeClientVersion(clientVersion, clientPlatform string) string {
-
-	// TODO: implement
-
-	return ""
-}
-
-// GetHttpsRequestRegexes returns bytes transferred stats regexes for the
-// specified sponsor.
-func (psinet *PsinetDatabase) GetHttpsRequestRegexes(sponsorID string) []map[string]string {
-
-	return make([]map[string]string, 0)
-}
-
-// DiscoverServers selects new encoded server entries to be "discovered" by
-// the client, using the discoveryValue as the input into the discovery algorithm.
-func (psinet *PsinetDatabase) DiscoverServers(propagationChannelID string, discoveryValue int) []string {
-
-	// TODO: implement
-
-	return make([]string, 0)
-}

+ 109 - 0
psiphon/server/psinet/psinet.go

@@ -0,0 +1,109 @@
+/*
+ * 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 psiphon/server/psinet implements psinet database services. The psinet
+// database is a JSON-format file containing information about the Psiphon network,
+// including sponsors, home pages, stats regexes, available upgrades, and other
+// servers for discovery. This package also implements the Psiphon discovery algorithm.
+package psinet
+
+import (
+	"sync"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
+)
+
+// Database serves Psiphon API data requests. It's safe for
+// concurrent usage.
+type Database struct {
+	mutex sync.RWMutex
+
+	// TODO: implement
+}
+
+// NewDatabase initializes a Database, calling Load on the specified
+// filename.
+func NewDatabase(filename string) (*Database, error) {
+
+	database := &Database{}
+
+	err := database.Load(filename)
+	if err != nil {
+		return nil, psiphon.ContextError(err)
+	}
+
+	return database, nil
+}
+
+// Load [re]initializes the Database with the Psiphon network data
+// in the specified file. This function obtains a write lock on
+// the database, blocking all readers.
+// The input "" is valid and initializes a functional Database
+// with no data.
+func (db *Database) Load(filename string) error {
+	db.mutex.Lock()
+	defer db.mutex.Unlock()
+
+	// TODO: implement
+
+	return nil
+}
+
+// GetHomepages returns a list of  home pages for the specified sponsor,
+// region, and platform.
+func (db *Database) GetHomepages(sponsorID, clientRegion, clientPlatform string) []string {
+	db.mutex.RLock()
+	defer db.mutex.RUnlock()
+
+	// TODO: implement
+
+	return make([]string, 0)
+}
+
+// GetUpgradeClientVersion returns a new client version when an upgrade is
+// indicated for the specified client current version. The result is "" when
+// no upgrade is available.
+func (db *Database) GetUpgradeClientVersion(clientVersion, clientPlatform string) string {
+	db.mutex.RLock()
+	defer db.mutex.RUnlock()
+
+	// TODO: implement
+
+	return ""
+}
+
+// GetHttpsRequestRegexes returns bytes transferred stats regexes for the
+// specified sponsor.
+func (db *Database) GetHttpsRequestRegexes(sponsorID string) []map[string]string {
+	db.mutex.RLock()
+	defer db.mutex.RUnlock()
+
+	return make([]map[string]string, 0)
+}
+
+// DiscoverServers selects new encoded server entries to be "discovered" by
+// the client, using the discoveryValue as the input into the discovery algorithm.
+func (db *Database) DiscoverServers(propagationChannelID string, discoveryValue int) []string {
+	db.mutex.RLock()
+	defer db.mutex.RUnlock()
+
+	// TODO: implement
+
+	return make([]string, 0)
+}

+ 2 - 1
psiphon/server/services.go

@@ -32,6 +32,7 @@ import (
 	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server/psinet"
 )
 
 // RunServices initializes support functions including logging and GeoIP services;
@@ -57,7 +58,7 @@ func RunServices(encodedConfigs [][]byte) error {
 		return psiphon.ContextError(err)
 	}
 
-	psinetDatabase, err := NewPsinetDatabase(config.PsinetDatabaseFilename)
+	psinetDatabase, err := psinet.NewDatabase(config.PsinetDatabaseFilename)
 	if err != nil {
 		log.WithContextFields(LogFields{"error": err}).Error("init PsinetDatabase failed")
 		return psiphon.ContextError(err)

+ 4 - 3
psiphon/server/tunnelServer.go

@@ -31,6 +31,7 @@ import (
 	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server/psinet"
 	"golang.org/x/crypto/ssh"
 )
 
@@ -53,7 +54,7 @@ type TunnelServer struct {
 // NewTunnelServer initializes a new tunnel server.
 func NewTunnelServer(
 	config *Config,
-	psinetDatabase *PsinetDatabase,
+	psinetDatabase *psinet.Database,
 	shutdownBroadcast <-chan struct{}) (*TunnelServer, error) {
 
 	sshServer, err := newSSHServer(
@@ -183,7 +184,7 @@ type sshClientID uint64
 
 type sshServer struct {
 	config            *Config
-	psinetDatabase    *PsinetDatabase
+	psinetDatabase    *psinet.Database
 	shutdownBroadcast <-chan struct{}
 	sshHostKey        ssh.Signer
 	nextClientID      sshClientID
@@ -194,7 +195,7 @@ type sshServer struct {
 
 func newSSHServer(
 	config *Config,
-	psinetDatabase *PsinetDatabase,
+	psinetDatabase *psinet.Database,
 	shutdownBroadcast <-chan struct{}) (*sshServer, error) {
 
 	privateKey, err := ssh.ParseRawPrivateKey([]byte(config.SSHPrivateKey))

+ 3 - 2
psiphon/server/webServer.go

@@ -30,12 +30,13 @@ import (
 	"sync"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server/psinet"
 )
 
 type webServer struct {
 	serveMux       *http.ServeMux
 	config         *Config
-	psinetDatabase *PsinetDatabase
+	psinetDatabase *psinet.Database
 }
 
 // RunWebServer runs a web server which supports tunneled and untunneled
@@ -54,7 +55,7 @@ type webServer struct {
 //
 func RunWebServer(
 	config *Config,
-	psinetDatabase *PsinetDatabase,
+	psinetDatabase *psinet.Database,
 	shutdownBroadcast <-chan struct{}) error {
 
 	webServer := &webServer{