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

Emit ApplicationParameters as a single object

This allows the outer clients to more easily detect when an individual
ApplicationParameters value has been removed, as compared with the previous
scheme which would emit no notice for the removed field.

Duplicate ApplicationParameters notices are still skipped, but the entire
ApplicationParameters object is emitted if any field is changed, added, or
removed.
Rod Hynes 3 лет назад
Родитель
Сommit
7480f4d23a

+ 4 - 5
MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java

@@ -127,7 +127,7 @@ public class PsiphonTunnel {
         default public void onStoppedWaitingForNetworkConnectivity() {}
         default public void onActiveAuthorizationIDs(List<String> authorizations) {}
         default public void onTrafficRateLimits(long upstreamBytesPerSecond, long downstreamBytesPerSecond) {}
-        default public void onApplicationParameter(String key, Object value) {}
+        default public void onApplicationParameters(Object parameters) {}
         default public void onServerAlert(String reason, String subject, List<String> actionURLs) {}
         default public void onExiting() {}
     }
@@ -1011,10 +1011,9 @@ public class PsiphonTunnel {
                       enableUdpGwKeepalive();
                     }
                 }
-            } else if (noticeType.equals("ApplicationParameter")) {
-                mHostService.onApplicationParameter(
-                    notice.getJSONObject("data").getString("key"),
-                    notice.getJSONObject("data").get("value"));
+            } else if (noticeType.equals("ApplicationParameters")) {
+                mHostService.onApplicationParameters(
+                    notice.getJSONObject("data").get("parameters"));
             } else if (noticeType.equals("ServerAlert")) {
                 JSONArray actionURLs = notice.getJSONObject("data").getJSONArray("actionURLs");
                 ArrayList<String> actionURLsList = new ArrayList<String>();

+ 1 - 1
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.h

@@ -297,7 +297,7 @@ WWAN or vice versa or VPN state changed
 /*!
  Called when tunnel-core receives "ApplicationParameters" from the server.
  */
-- (void)onApplicationParameter:(NSString * _Nonnull)key :(id _Nonnull)value;
+- (void)onApplicationParameters:(NSDictionary * _Nonnull)parameters;
 
 @end
 

+ 6 - 15
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.m

@@ -1146,26 +1146,17 @@ typedef NS_ERROR_ENUM(PsiphonTunnelErrorDomain, PsiphonTunnelErrorCode) {
             });
         }
     }
-    else if ([noticeType isEqualToString:@"ApplicationParameter"]) {
+    else if ([noticeType isEqualToString:@"ApplicationParameters"]) {
         
-        id key = [notice valueForKeyPath:@"data.key"];
-        if (![key isKindOfClass:[NSString class]]) {
-            [self logMessage:[NSString stringWithFormat: @"ApplicationParameter notice missing data.key: %@", noticeJSON]];
+        id parameters = [notice valueForKeyPath:@"data.parameters"];
+        if (![parameters isKindOfClass:[NSDictionary class]]) {
+            [self logMessage:[NSString stringWithFormat: @"ApplicationParameters notice missing data.parameters: %@", noticeJSON]];
             return;
         }
 
-        id maybeValue = [notice valueForKeyPath:@"data.value"];
-        if (!maybeValue) {
-            [self logMessage:[NSString stringWithFormat: @"ApplicationParameter notice missing data.value: %@", noticeJSON]];
-            return;
-        }
-
-        // value is nil if data.value is NSNull.
-        id value = maybeValue == [NSNull null] ? nil : maybeValue;
-
-        if ([self.tunneledAppDelegate respondsToSelector:@selector(onApplicationParameter::)]) {
+        if ([self.tunneledAppDelegate respondsToSelector:@selector(onApplicationParameters:)]) {
             dispatch_sync(self->callbackQueue, ^{
-                [self.tunneledAppDelegate onApplicationParameter:(NSString *)key :value];
+                [self.tunneledAppDelegate onApplicationParameters:parameters];
             });
         }
     }

+ 23 - 25
psiphon/notice.go

@@ -111,7 +111,6 @@ func GetEmitNetworkParameters() bool {
 // - "timestamp": UTC timezone, RFC3339Milli format timestamp for notice event
 //
 // See the Notice* functions for details on each notice meaning and payload.
-//
 func SetNoticeWriter(writer io.Writer) {
 
 	singletonNoticeLogger.mutex.Lock()
@@ -122,25 +121,24 @@ func SetNoticeWriter(writer io.Writer) {
 
 // setNoticeFiles configures files for notice writing.
 //
-// - When homepageFilename is not "", homepages are written to the specified file
-//   and omitted from the writer. The file may be read after the Tunnels notice
-//   with count of 1. The file should be opened read-only for reading.
+//   - When homepageFilename is not "", homepages are written to the specified file
+//     and omitted from the writer. The file may be read after the Tunnels notice
+//     with count of 1. The file should be opened read-only for reading.
 //
-// - When rotatingFilename is not "", all notices are are written to the specified
-//   file. Diagnostic notices are omitted from the writer. The file is rotated
-//   when its size exceeds rotatingFileSize. One rotated older file,
-//   <rotatingFilename>.1, is retained. The files may be read at any time; and
-//   should be opened read-only for reading. rotatingSyncFrequency specifies how
-//   many notices are written before syncing the file.
-//   If either rotatingFileSize or rotatingSyncFrequency are <= 0, default values
-//   are used.
+//   - When rotatingFilename is not "", all notices are are written to the specified
+//     file. Diagnostic notices are omitted from the writer. The file is rotated
+//     when its size exceeds rotatingFileSize. One rotated older file,
+//     <rotatingFilename>.1, is retained. The files may be read at any time; and
+//     should be opened read-only for reading. rotatingSyncFrequency specifies how
+//     many notices are written before syncing the file.
+//     If either rotatingFileSize or rotatingSyncFrequency are <= 0, default values
+//     are used.
 //
-// - If an error occurs when writing to a file, an InternalError notice is emitted to
-//   the writer.
+//   - If an error occurs when writing to a file, an InternalError notice is emitted to
+//     the writer.
 //
 // setNoticeFiles closes open homepage or rotating files before applying the new
 // configuration.
-//
 func setNoticeFiles(
 	homepageFilename string,
 	rotatingFilename string,
@@ -952,18 +950,18 @@ func NoticeFragmentor(diagnosticID string, message string) {
 	}
 }
 
-// NoticeApplicationParameters reports application parameters. Each key/value
-// parameter pair is emitted in a distinct notice, and each key/value pair is
-// reported at most once per session for a fixed value.
+// NoticeApplicationParameters reports application parameters.
 func NoticeApplicationParameters(keyValues parameters.KeyValues) {
-	for key, value := range keyValues {
-		repetitionKey := fmt.Sprintf("ApplicationParameterKey-%s", key)
-		outputRepetitiveNotice(
-			repetitionKey, string(value), 0,
-			"ApplicationParameter", 0,
-			"key", key,
-			"value", value)
+
+	// Never emit 'null' instead of empty object
+	if keyValues == nil {
+		keyValues = parameters.KeyValues{}
 	}
+
+	outputRepetitiveNotice(
+		"ApplicationParameters", fmt.Sprintf("%+v", keyValues), 0,
+		"ApplicationParameters", 0,
+		"parameters", keyValues)
 }
 
 // NoticeServerAlert reports server alerts. Each distinct server alert is