Skip to Content.
Sympa Menu

ndt-dev - Re: [ndt-dev] Re: Issue 162 in ndt: New NDT release

Subject: NDT-DEV email list created

List archive

Re: [ndt-dev] Re: Issue 162 in ndt: New NDT release


Chronological Thread 
  • From: Jordan McCarthy <>
  • To:
  • Subject: Re: [ndt-dev] Re: Issue 162 in ndt: New NDT release
  • Date: Fri, 07 Nov 2014 13:36:17 -0500

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

I'm not sure if this should be handled separately, but the M-Lab team
has a series of changes that we would like to add to the flash client
to handle the fact that the Adobe flash runtime for Mac OS X and Linux
is severely performance-limited.

Here's the description of what we did:

Our patch (attached) adds a customizable feature for dealing with
performance-limited flash runtimes. In a nutshell, the patch allows
anyone who hosts an NDT test to specify (via an HTML parameter)
whether performance-limited flash runtimes should (a) be treated the
same as non-limited ones, (b) only be allowed to run against a
"fallback" server, or (c) not allowed to run the NDT test via flash at
all. Measurement Lab will generally use option (c), because we are
primarily interested in identifying and measuring bottlenecks in the
performance of networks, rather than clients. However, we completely
understand the argument that some researchers might actually want the
speed limitations introduced by particular runtimes to be captured in
experimental data, and our patch makes it very easy to switch between
these two approaches, depending on experimenters' needs.

The patch has been tested extensively on all major web browsers on
Windows, Mac OS X, and Linux, and appears to work well in all
environments except for Safari (where the flash client doesn't work at
all).


Thanks,
Jordan

Jordan McCarthy
Open Technology Institute | New America Foundation
Public Key: 0xC08D8042 | 4A61 3D39 4125 127D 65EA DDC2 BFBD A2E9 C08D 8042

On 11/07/2014 11:00 AM,

wrote:
>
> Comment #3 on issue 162 by
> :
> New NDT release
> https://code.google.com/p/ndt/issues/detail?id=162
>
> All flash client related improvements have been fixed and changes
> are available on FlashClientFixes branch. Please feel free to
> review them and if all will look ok then I will merge them into
> trunk in nearest time.
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)

iQEcBAEBCgAGBQJUXREhAAoJEL+9ounAjYBCf4EH/AhhGKcQftzx0ySUP63ZLdy+
gXgrrB+d/d/bb3/1Kn9EizsYzdaeRo7faLWNKeiO3ePjX8cfcAP8idBJko1E+COZ
O4C1gkXkcVdeG3vN5JvF3gHcnRpC1pvfFVixJ3q9L6pWPVT4be3NtZDQ46xR9XxS
iu3n3E2kP/C5vowm+coyuEZ9jVZvX74tyGxfc5vNDrJLE4Y9evXui9pJkh6vQ9nL
CqkjCQMhuYadFZmiDdrZC5Fut8cSoirgq8prNY+odnoHKFOZFG1mL2O52/RWD/JH
1wFZxqJFo+lLgrTMhC/0n7Qg+k9fUW2tXTt7hVfKoEP/p/3F8Ml9aWQXEgAqWgA=
=wgkG
-----END PGP SIGNATURE-----
Index: src/NDTUtils.as
===================================================================
--- src/NDTUtils.as	(revision 1129)
+++ src/NDTUtils.as	(working copy)
@@ -63,19 +63,20 @@
     /**
      * Function that initializes the NDT server variable.
      */
-    public static function hostnameFromJS():String {
+    public static function hostnameFromJS(queryFn:String):String {
       try {
-        var js_server_hostname:String = ExternalInterface.call("getNDTServer");
+        var js_server_hostname:String = ExternalInterface.call(queryFn);
         if (js_server_hostname) {
           TestResults.appendDebugMsg(
-            "Initialized server from JavaScript. Server hostname:"
+            "Initialized server from " + queryFn 
+            + " JavaScript function. Server hostname: " 
             + Main.server_hostname);
         } else {
 	  js_server_hostname = null;
 	}
 	return js_server_hostname;
       } catch(e:Error) {
-        TestResults.appendDebugMsg("Failed to call getNDTServer(): "
+        TestResults.appendDebugMsg("Failed to call " + queryFn + "(): "
                                    + e.toString());
         return null;
       }
@@ -118,7 +119,7 @@
                                    + e.toString());
       }
 
-      var js_server_hostname:String = hostnameFromJS();
+      var js_server_hostname:String = hostnameFromJS("getNDTServer");
       if (js_server_hostname) {
         Main.server_hostname = js_server_hostname;
       }
@@ -152,6 +153,14 @@
         TestResults.appendDebugMsg("Failed to call getNDTDescription(): "
                                    + e.toString());
       }
+      if (NDTConstants.HTML_BAD_ENV_ACTION in paramObject) {
+         var validParams:Array = new Array(NDTConstants.BAD_ENV_WARN, 
+         NDTConstants.BAD_ENV_WARN_AND_LIMIT, NDTConstants.BAD_ENV_ERROR);
+        if (validParams.indexOf(paramObject[NDTConstants.HTML_BAD_ENV_ACTION]) > -1) 
+          Main.bad_runtime_action = paramObject[NDTConstants.HTML_BAD_ENV_ACTION];
+     // else keep the default value (NDTConstants.BAD_ENV_ACTION).
+      }
+
     }
 
     /**
@@ -201,6 +210,8 @@
             "get_PcBuffSpdLimit", TestResults.getPcLimit);
         ExternalInterface.addCallback(
             "getNDTvar", TestResultsUtils.getNDTVariable);
+        ExternalInterface.addCallback(
+            "set_host", Main.setHost);
       } catch (e:Error) {
         // TODO(tiziana): Find out why ExternalInterface.available does not work
         // in some cases and this exception is raised.
Index: src/NDTPController.as
===================================================================
--- src/NDTPController.as	(revision 1129)
+++ src/NDTPController.as	(working copy)
@@ -72,11 +72,34 @@
         TestResults.clearResults();
       }
 
-      var js_server_hostname:String = NDTUtils.hostnameFromJS();
+      var hostnameQueryFn:String = "getNDTServer";
+      if (Main.bad_runtime_action != NDTConstants.ENV_OK) {
+        TestResults.appendDebugMsg("Download-limited Flash Runtime detected");
+        if (Main.bad_runtime_action == NDTConstants.BAD_ENV_WARN_AND_LIMIT) {
+          hostnameQueryFn = "getFallbackNDTServer"
+          TestResults.appendDebugMsg("Reverting to fallback " 
+              + "test server due to bad flash runtime");
+        }
+        if (Main.bad_runtime_action == NDTConstants.BAD_ENV_ERROR) {
+          failNDTTest();
+          TestResults.appendErrMsg(NDTConstants.BAD_ENV_MESG);
+          return;
+        }
+      }
+
+      var js_server_hostname:String = NDTUtils.hostnameFromJS(hostnameQueryFn);
       if (js_server_hostname) {
         Main.server_hostname = js_server_hostname;
         _hostname = Main.server_hostname;
-      }
+      } else if (Main.bad_runtime_action == NDTConstants.BAD_ENV_WARN_AND_LIMIT) {
+	  TestResults.appendErrMsg("This Flash runtime is download-limited, client is "
+	    + "set to restrict limited runtimes to fallback servers only, and no "
+	    + "getFallbackNDTServer JavaScript function was defined.");
+	  failNDTTest();
+	  return;
+      } else if (Main.server_hostname) {
+		_hostname = Main.server_hostname;
+        }
 
       TestResults.recordStartTime();
       TestResults.ndt_test_results::ndtTestFailed = false;
Index: src/UserAgentTools.as
===================================================================
--- src/UserAgentTools.as	(revision 1129)
+++ src/UserAgentTools.as	(working copy)
@@ -20,6 +20,7 @@
 package  {
   import mx.resources.ResourceManager;
   import mx.utils.StringUtil;
+  import flash.system.Capabilities;
   /**
    * This class is use to obtain information about who is accessing a web-server.
    * When a web browser accesses a web-server, it usually transmits a "User-Agent"
@@ -275,6 +276,17 @@
         return ["?", "?", "?"];
       return res;
     }
+    public static function goodRuntimeCheck(userAgent:String):Boolean {
+       if (getBrowser(userAgent)[1] == 'KHTML(Chrome)') {
+         return true;
+       }
+       var os:String = flash.system.Capabilities.os.substr(0, 3);
+       if (os == "Win") {
+         return true;
+       }
+       else 
+         return false;
+    }
   }
 }
 
Index: src/NDTConstants.as
===================================================================
--- src/NDTConstants.as	(revision 1129)
+++ src/NDTConstants.as	(working copy)
@@ -21,6 +21,8 @@
     // The current version of the protocol is backward compatible to v3.3.12.
     public static const LAST_VALID_SERVER_VERSION:String = "v3.3.12";
     public static const CLIENT_ID:String = "swf";
+    public static const LIMITED_CLIENT_ID:String = "swf-ltd";
+    public static const BAD_ENV_ACTION:String = "error";
     // Client MUST request the TEST_STATUS.
     public static const TESTS_REQUESTED_BY_CLIENT:int =
         TestType.C2S | TestType.S2C | TestType.META | TestType.STATUS;
@@ -41,7 +43,6 @@
         + "users, they can also help novice users by "
         + "allowing them to provide detailed trouble "
         + "reports to their network administrator.";
-
     public static const PROTOCOL_MSG_READ_SUCCESS:int = 0;
     public static const PROTOCOL_MSG_READ_ERROR:int = 1;
     public static const MSG_HEADER_LENGTH:int = 3;
@@ -162,6 +163,7 @@
     public static const HTML_LOCALE:String = "Locale";
     public static const HTML_USERAGENT:String = "UserAgentString";
     public static const HTML_SERVER_HOSTNAME:String = "ServerHostname";
+    public static const HTML_BAD_ENV_ACTION:String = "BadRuntimeAction";
 
     // Names of NDT variables sent by the server.
     public static const MSSSENT:String = "MSSSent";
@@ -231,6 +233,21 @@
     public static const SPD:String = "spd";
     public static const ASPD:String = "aspd";
     public static const OPTRCVRBUFF:String = "optimalRcvrBuffer";
+
+    //Bad environment handlers
+    public static const ENV_OK:String = "none"
+    public static const BAD_ENV_WARN:String = "warn"
+    public static const BAD_ENV_WARN_AND_LIMIT:String = "warn-limit"
+    public static const BAD_ENV_ERROR:String = "error"
+    public static const BAD_ENV_MESG:String = 
+        "Due to performance limitations in the Adobe Flash "
+        + "Runtime, the NDT flash test cannot measure "
+        + "high-speed connections accurately unless "
+        + "it is run within Google Chrome "
+        + "on Mac OS and Linux, or any web-browser running "
+        + "on Windows operating systems. Please use one of "
+        + "these platforms or run the NDT Java client "
+        + "to obtain precise measurements.";
   }
 }
 
Index: src/GUI.as
===================================================================
--- src/GUI.as	(revision 1129)
+++ src/GUI.as	(working copy)
@@ -73,8 +73,8 @@
       aboutNDTTextFormat.color = 0x000000;
       _aboutNDTText = new TextField();
       _aboutNDTText.defaultTextFormat = aboutNDTTextFormat;
-      _aboutNDTText.width = 0.75 * _stageWidth;
-      _aboutNDTText.height = 0.40 * _stageHeight;
+      _aboutNDTText.width = 0.80 * _stageWidth;
+      _aboutNDTText.height = 0.35 * _stageHeight;
       _aboutNDTText.wordWrap = true;
       _aboutNDTText.selectable = false;
       _aboutNDTText.text = Main.ndt_description;
@@ -95,24 +95,45 @@
       _learnMoreLink.buttonMode = true;
       _learnMoreLink.mouseChildren = false;
       _learnMoreLink.width = 0.50 * _stageWidth;
+      _learnMoreLink.height = 0.17 * _stageWidth;
 
-      // 4) Start button
+      // 4) Bad runtime warning/error
+      var badRuntimeMessageFormat:TextFormat = new TextFormat();
+      badRuntimeMessageFormat.size = 14;
+      badRuntimeMessageFormat.font = "Verdana";
+      badRuntimeMessageFormat.align = TextFormatAlign.CENTER;
+      badRuntimeMessageFormat.color = 0xB02B08;
+      var _badRuntimeMessage:TextField = new TextField();
+      _badRuntimeMessage.defaultTextFormat = badRuntimeMessageFormat;
+      _badRuntimeMessage.width = 0.90 * _stageWidth;
+      _badRuntimeMessage.height = 0.35 * _stageHeight;
+      //_badRuntimeMessage.opaqueBackground = 0x000000;
+      _badRuntimeMessage.wordWrap = true;
+      _badRuntimeMessage.selectable = false;
+      _badRuntimeMessage.text = NDTConstants.BAD_ENV_MESG;
+      if (Main.bad_runtime_action == NDTConstants.ENV_OK) {
+        _badRuntimeMessage.height = 0;
+      }
+
+      // 5) Start button
       _startButton = new NDTButton("START", 30, 45, 0.4);
 
       // Position objects within initial screen, using a relative layout.
       _mlabLogo.x = (_stageWidth / 2) - (_mlabLogo.width / 2);
       _aboutNDTText.x = _stageWidth / 2 - _aboutNDTText.width / 2;
       _learnMoreLink.x = _stageWidth / 2 - _learnMoreLink.width / 2;
+      _badRuntimeMessage.x = _stageWidth / 2 - _badRuntimeMessage.width / 2;
       _startButton.x = _stageWidth / 2;
       var verticalMargin:Number = (_stageHeight - (
           _mlabLogo.height + _aboutNDTText.height + _learnMoreLink.height
-          + _startButton.height)) / 5;
-      _mlabLogo.y = verticalMargin;
-      _aboutNDTText.y = _mlabLogo.y + _mlabLogo.height + verticalMargin;
+          + _badRuntimeMessage.height + _startButton.height)) / 6;
+      _mlabLogo.y = 0;
+      _aboutNDTText.y = _mlabLogo.y + _mlabLogo.height;
       _learnMoreLink.y = _aboutNDTText.y + _aboutNDTText.height;
+      _badRuntimeMessage.y = _learnMoreLink.y + _learnMoreLink.height
+                         + verticalMargin*3;
+      _startButton.y = _badRuntimeMessage.y + _badRuntimeMessage.height
                          + verticalMargin;
-      _startButton.y = _learnMoreLink.y + _learnMoreLink.height
-                         + verticalMargin;
 
       // Add initial event listeners.
       _learnMoreLink.addEventListener(MouseEvent.CLICK, clickLearnMoreLink);
@@ -124,7 +145,15 @@
       this.addChild(_mlabLogo);
       this.addChild(_aboutNDTText);
       this.addChild(_learnMoreLink);
-      this.addChild(_startButton);
+      if (Main.bad_runtime_action != NDTConstants.ENV_OK) {
+        this.addChild(_badRuntimeMessage);
+        TestResults.appendDebugMsg("Bad Runtime detected");
+      }
+      if (Main.bad_runtime_action != NDTConstants.BAD_ENV_ERROR) {
+        this.addChild(_startButton);
+      }
+      else 
+        TestResults.appendErrMsg("Halting test due to bad runtime");
     }
 
     private function clickLearnMoreLink(e:MouseEvent):void {
Index: src/Main.as
===================================================================
--- src/Main.as	(revision 1129)
+++ src/Main.as	(working copy)
@@ -30,6 +30,8 @@
     public static var client_application:String = NDTConstants.CLIENT_ID;
     public static var ndt_description:String = NDTConstants.NDT_DESCRIPTION;
     public static var jsonSupport:Boolean = true;
+    public static var bad_runtime_action:String = NDTConstants.BAD_ENV_ACTION;
+    //Options are warn, warn-limit, and error (default)
 
     public function Main():void {
       if (stage)
@@ -53,6 +55,12 @@
       // Set the properties of the SWF from HTML tags.
       NDTUtils.initializeFromHTML(this.root.loaderInfo.parameters);
 
+      //User Agent string is stored in a TestResults var by initFromHTML
+      if (UserAgentTools.goodRuntimeCheck(TestResults.ndt_test_results::userAgent)) {
+        bad_runtime_action = NDTConstants.ENV_OK;
+      } else
+        client_application = NDTConstants.LIMITED_CLIENT_ID; 
+
       var frame:NDTPController = NDTPController.getInstance();
 
       stage.showDefaultContextMenu = false;
@@ -66,5 +74,21 @@
     public static function getHost():String {
       return server_hostname;
     }
+    
+    /**
+     * Function that initializes the NDT server variable set directly through JS.
+     */
+    public static function setHost(hostname:String):String {
+        var js_server_hostname:String = hostname;
+        if (js_server_hostname) {
+          server_hostname = js_server_hostname;
+          TestResults.appendDebugMsg(
+            "Initialized server from JavaScript. Server hostname:"
+            + Main.server_hostname);
+        } else {
+	  js_server_hostname = null;
+	}
+	return js_server_hostname;
+    }
   }
 }
Index: src/TestC2S.as
===================================================================
--- src/TestC2S.as	(revision 1129)
+++ src/TestC2S.as	(working copy)
@@ -87,7 +87,7 @@
       TestResults.appendDebugMsg(ResourceManager.getInstance().getString(
           NDTConstants.BUNDLE_NAME, "runningOutboundTest", null,
           Main.locale));
-      TestResults.ndt_test_results::ndtTestStatus = "runningOutboundTest";
+      TestResults.ndt_test_results::ndtTestStatus = "preparingOutboundTest";
 
       addCtlSocketOnReceivedDataListener();
       _msg = new Message();
@@ -316,6 +316,7 @@
       // Record start time right before it starts sending data, to be as
       // accurate as possible.
       _c2sTestStartTime = getTimer();
+      TestResults.ndt_test_results::ndtTestStatus = "runningOutboundTest";
 
       _testStage = SEND_DATA;
       TestResults.appendDebugMsg("C2S test: SEND_DATA stage.");
Index: src/TestS2C.as
===================================================================
--- src/TestS2C.as	(revision 1129)
+++ src/TestS2C.as	(working copy)
@@ -84,12 +84,12 @@
               NDTConstants.BUNDLE_NAME, "startingTest", null, Main.locale) +
           ResourceManager.getInstance().getString(
               NDTConstants.BUNDLE_NAME, "s2cThroughput", null, Main.locale))
-      NDTUtils.callExternalFunction("startTested", "ServerToClientThroughput");
+      NDTUtils.callExternalFunction("testStarted", "ServerToClientThroughput");
       TestResults.appendDebugMsg("S2C test: PREPARE_TEST stage.");
       TestResults.appendDebugMsg(
         ResourceManager.getInstance().getString(
             NDTConstants.BUNDLE_NAME, "runningInboundTest", null, Main.locale));
-      TestResults.ndt_test_results::ndtTestStatus = "runningInboundTest";
+      TestResults.ndt_test_results::ndtTestStatus = "preparingInboundTest";
 
       addCtlSocketOnReceivedDataListener();
       _msg = new Message();
@@ -294,6 +294,7 @@
       // Record start time right before it starts receiving data, to be as
       // accurate as possible.
       _s2cTestStartTime = getTimer();
+      TestResults.ndt_test_results::ndtTestStatus = "runningInboundTest";
 
       _testStage = RECEIVE_DATA;
       TestResults.appendDebugMsg("S2C test: RECEIVE_DATA stage.");



Archive powered by MHonArc 2.6.16.

Top of Page