Просмотр исходного кода

Updated mobile library enabling streaming embedded server entries

Amir Khan 8 лет назад
Родитель
Сommit
a951abce52

+ 6 - 0
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.h

@@ -123,6 +123,12 @@ typedef NS_ENUM(NSInteger, PsiphonConnectionState)
  */
 - (NSString * _Nullable)getEmbeddedServerEntries;
 
+/*!
+  Called when the tunnel is starting to get the initial server entries (typically embedded in the app) that will be used to bootstrap the Psiphon tunnel connection. This value is in a particular format and will be supplied by Psiphon Inc. 
+  @return File path where embedded server entries file is located. This file should be accessible by the Network Extension.
+ */
+- (NSString * _Nullable)getEmbeddedServerEntriesPath;
+
 //
 // Optional delegate methods. Note that some of these are probably necessary for
 // for a functioning app to implement, for example `onConnected`.

+ 17 - 5
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.m

@@ -115,14 +115,25 @@
             return FALSE;
         }
 
+        __block NSString *embeddedServerEntriesPath = nil;
         __block NSString *embeddedServerEntries = nil;
+        
         dispatch_sync(self->callbackQueue, ^{
-            embeddedServerEntries = [self.tunneledAppDelegate getEmbeddedServerEntries];
+            embeddedServerEntriesPath = [self.tunneledAppDelegate getEmbeddedServerEntriesPath];
         });
-
-        if (embeddedServerEntries == nil) {
-            [self logMessage:@"Error getting embedded server entries from delegate"];
-            return FALSE;
+        
+        // If getEmbeddedServerEntriesPath returns nil or empty string,
+        // call getEmbeddedServerEntries
+        if (embeddedServerEntriesPath == nil || [embeddedServerEntriesPath length] == 0) {
+            
+            dispatch_sync(self->callbackQueue, ^{
+                embeddedServerEntries = [self.tunneledAppDelegate getEmbeddedServerEntries];
+            });
+            
+            if (embeddedServerEntries == nil) {
+                [self logMessage:@"Error getting embedded server entries from delegate"];
+                return FALSE;
+            }
         }
 
         [self changeConnectionStateTo:PsiphonConnectionStateConnecting evenIfSameState:NO];
@@ -133,6 +144,7 @@
             BOOL res = GoPsiStart(
                            configStr,
                            embeddedServerEntries,
+                           embeddedServerEntriesPath,
                            self,
                            self->tunnelWholeDevice, // useDeviceBinder
                            useIPv6Synthesizer,

+ 29 - 11
MobileLibrary/psi/psi.go

@@ -32,6 +32,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tun"
+	"os"
 )
 
 type PsiphonProvider interface {
@@ -49,7 +50,8 @@ var shutdownBroadcast chan struct{}
 var controllerWaitGroup *sync.WaitGroup
 
 func Start(
-	configJson, embeddedServerEntryList string,
+	configJson, embeddedServerEntryList,
+	embeddedServerEntryListFileName string,
 	provider PsiphonProvider,
 	useDeviceBinder bool, useIPv6Synthesizer bool) error {
 
@@ -89,16 +91,32 @@ func Start(
 		return fmt.Errorf("error initializing datastore: %s", err)
 	}
 
-	serverEntries, err := protocol.DecodeServerEntryList(
-		embeddedServerEntryList,
-		common.GetCurrentTimestamp(),
-		protocol.SERVER_ENTRY_SOURCE_EMBEDDED)
-	if err != nil {
-		return fmt.Errorf("error decoding embedded server entry list: %s", err)
-	}
-	err = psiphon.StoreServerEntries(serverEntries, false)
-	if err != nil {
-		return fmt.Errorf("error storing embedded server entry list: %s", err)
+	// if embeddedServerEntryListFileName is not empty, ignore embeddedServerEntryList.
+	if embeddedServerEntryListFileName != "" {
+
+		serverEntriesFile, err := os.Open(embeddedServerEntryListFileName)
+		if err != nil {
+			return fmt.Errorf("failed to read remote server list: %s", common.ContextError(err))
+		}
+		defer serverEntriesFile.Close()
+
+		err = psiphon.StreamingStoreServerEntriesWithIOReader(serverEntriesFile, protocol.SERVER_ENTRY_SOURCE_EMBEDDED)
+		if err != nil {
+			return fmt.Errorf("failed to store common remote server list: %s", common.ContextError(err))
+		}
+	} else {
+
+		serverEntries, err := protocol.DecodeServerEntryList(
+			embeddedServerEntryList,
+			common.GetCurrentTimestamp(),
+			protocol.SERVER_ENTRY_SOURCE_EMBEDDED)
+		if err != nil {
+			return fmt.Errorf("error decoding embedded server entry list: %s", err)
+		}
+		err = psiphon.StoreServerEntries(serverEntries, false)
+		if err != nil {
+			return fmt.Errorf("error storing embedded server entry list: %s", err)
+		}
 	}
 
 	controller, err = psiphon.NewController(config)

+ 20 - 0
psiphon/dataStore.go

@@ -30,6 +30,7 @@ import (
 	"strings"
 	"sync"
 	"time"
+	"io"
 
 	"github.com/Psiphon-Inc/bolt"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
@@ -268,6 +269,25 @@ func StoreServerEntries(serverEntries []*protocol.ServerEntry, replaceIfExists b
 	return nil
 }
 
+// Wrapper around StreamingStoreServerEntries
+// an io.Reader is passed instead of an instance of StreamingServerEntryDecoder
+func StreamingStoreServerEntriesWithIOReader(serverListReader io.Reader, serverEntrySource string) error {
+
+	serverEntries := protocol.NewStreamingServerEntryDecoder(
+		serverListReader,
+		common.GetCurrentTimestamp(),
+		serverEntrySource)
+
+	// TODO: record stats for newly discovered servers
+
+	err := StreamingStoreServerEntries(serverEntries, true)
+	if err != nil {
+		return common.ContextError(err)
+	}
+
+	return nil
+}
+
 // StreamingStoreServerEntries stores a list of server entries.
 // There is an independent transaction for each entry insert/update.
 func StreamingStoreServerEntries(

+ 1 - 19
psiphon/remoteServerList.go

@@ -23,7 +23,6 @@ import (
 	"encoding/hex"
 	"errors"
 	"fmt"
-	"io"
 	"io/ioutil"
 	"time"
 
@@ -78,7 +77,7 @@ func FetchCommonRemoteServerList(
 	}
 	defer serverListPayload.Close()
 
-	err = streamingStoreServerEntries(serverListPayload, protocol.SERVER_ENTRY_SOURCE_REMOTE)
+	err = StreamingStoreServerEntriesWithIOReader(serverListPayload, protocol.SERVER_ENTRY_SOURCE_REMOTE)
 	if err != nil {
 		return fmt.Errorf("failed to store common remote server list: %s", common.ContextError(err))
 	}
@@ -378,20 +377,3 @@ func storeServerEntries(serverList, serverEntrySource string) error {
 
 	return nil
 }
-
-func streamingStoreServerEntries(serverListReader io.Reader, serverEntrySource string) error {
-
-	serverEntries := protocol.NewStreamingServerEntryDecoder(
-		serverListReader,
-		common.GetCurrentTimestamp(),
-		serverEntrySource)
-
-	// TODO: record stats for newly discovered servers
-
-	err := StreamingStoreServerEntries(serverEntries, true)
-	if err != nil {
-		return common.ContextError(err)
-	}
-
-	return nil
-}