Skip to Content.
Sympa Menu

ndt-dev - [ndt-dev] [ndt] r1179 committed - Merge newest trunk into MultiplePorts branch

Subject: NDT-DEV email list created

List archive

[ndt-dev] [ndt] r1179 committed - Merge newest trunk into MultiplePorts branch


Chronological Thread 
  • From:
  • To:
  • Subject: [ndt-dev] [ndt] r1179 committed - Merge newest trunk into MultiplePorts branch
  • Date: Thu, 12 Feb 2015 14:56:00 +0000

Revision: 1179
Author:

Date: Thu Feb 12 14:55:28 2015 UTC
Log: Merge newest trunk into MultiplePorts branch
https://code.google.com/p/ndt/source/detail?r=1179

Added:
/branches/MultiplePorts/HTML5-frontend/Makefile.am
/branches/MultiplePorts/flash-client/precompiled
/branches/MultiplePorts/flashpolicy.xml
/branches/MultiplePorts/ndt-flashpolicyd
/branches/MultiplePorts/src/unit_testing.c
/branches/MultiplePorts/src/unit_testing.h
/branches/MultiplePorts/src/web100srv_unit_tests.c
Modified:
/branches/MultiplePorts
/branches/MultiplePorts/Applet/MANIFEST.MF
/branches/MultiplePorts/Applet/precompiled/Tcpbw100.jar
/branches/MultiplePorts/HTML5-frontend/script.js
/branches/MultiplePorts/HTML5-frontend/set-active-client.sh
/branches/MultiplePorts/HTML5-frontend/style.css
/branches/MultiplePorts/HTML5-frontend/widget.html
/branches/MultiplePorts/Makefile.am
/branches/MultiplePorts/conf/ndt-apache.conf
/branches/MultiplePorts/conf/ndt-init
/branches/MultiplePorts/conf/ndt-sysconfig
/branches/MultiplePorts/configure.ac
/branches/MultiplePorts/flash-client/Makefile.am
/branches/MultiplePorts/flash-client/ndt-flash-config.xml
/branches/MultiplePorts/flash-client/src/TestResultsUtils.as
/branches/MultiplePorts/ndt.spec
/branches/MultiplePorts/src/Makefile.am
/branches/MultiplePorts/src/fakewww.c
/branches/MultiplePorts/src/web100srv.c

=======================================
--- /dev/null
+++ /branches/MultiplePorts/HTML5-frontend/Makefile.am Thu Feb 12 14:55:28 2015 UTC
@@ -0,0 +1,26 @@
+#########################################################################
+# #
+# Copyright (C) 2014 #
+# Internet2 #
+# All Rights Reserved #
+# #
+#########################################################################
+#
+# File: Makefile.am
+#
+# Author: PaweĊ‚ Gesek
+#
+# Date: Thu Nov 6 16:23:02 CET 2014
+#
+# Description: Makefile for the new HTML5 frontend
+
+TEMPDIRS = dist
+
+ndtdir = $(prefix)/ndt
+
+nobase_ndt_DATA = jquery-1.4.4.min.js ie.css style.css gauge.min.js widget.html \
+ images/mlab-logo.png images/mlab-logo-small.png script.js \
+ fonts/digital-7-mono.ttf fonts/League_Gothic.otf \
+ fonts/League_Gothic.eot embed.html set-active-client.sh
+
+EXTRA_DIST = $(nobase_ndt_DATA)
=======================================
--- /dev/null
+++ /branches/MultiplePorts/flashpolicy.xml Thu Feb 12 14:55:28 2015 UTC
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+ <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd";>
+ <cross-domain-policy>
+ <site-control permitted-cross-domain-policies="master-only"/>
+ <allow-access-from domain="*" to-ports="*" />
+ </cross-domain-policy>
=======================================
--- /dev/null
+++ /branches/MultiplePorts/ndt-flashpolicyd Thu Feb 12 14:55:28 2015 UTC
@@ -0,0 +1,95 @@
+#!/usr/bin/python
+#
+# flashpolicyd.py
+# Simple socket policy file server for Flash
+#
+# Usage: flashpolicyd.py [--port=N] --file=FILE
+#
+# Logs to stderr
+# Requires Python 2.5 or later
+
+from __future__ import with_statement
+
+import sys
+import optparse
+import socket
+import thread
+import exceptions
+import contextlib
+
+VERSION = 0.1
+PORT = 843 # Listen on PORT.
+FILE = '/usr/local/ndt/flashpolicy.xml' # Full path to the default server policy file.
+
+class policy_server(object):
+ def __init__(self, port, path):
+ self.port = port
+ self.path = path
+ self.policy = self.read_policy(path)
+ self.log('Listening on port %d\n' % port)
+ try:
+ self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+ except AttributeError:
+ # AttributeError catches Python built without IPv6
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ except socket.error:
+ # socket.error catches OS with IPv6 disabled
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.sock.bind(('', port))
+ self.sock.listen(5)
+ def read_policy(self, path):
+ with file(path, 'rb') as f:
+ policy = f.read(10001)
+ if len(policy) > 10000:
+ raise exceptions.RuntimeError('File probably too large to be a policy file',
+ path)
+ if 'cross-domain-policy' not in policy:
+ raise exceptions.RuntimeError('Not a valid policy file',
+ path)
+ return policy
+ def run(self):
+ try:
+ while True:
+ thread.start_new_thread(self.handle, self.sock.accept())
+ except socket.error, e:
+ self.log('Error accepting connection: %s' % (e[1],))
+ def handle(self, conn, addr):
+ addrstr = '%s:%s' % (addr[0],addr[1])
+ try:
+ self.log('Connection from %s' % (addrstr,))
+ with contextlib.closing(conn):
+ # It's possible that we won't get the entire request in
+ # a single recv, but very unlikely.
+ request = conn.recv(1024).strip()
+ if request != '<policy-file-request/>\0':
+ self.log('Unrecognized request from %s: %s' % (addrstr, request))
+ return
+ self.log('Valid request received from %s' % (addrstr,))
+ conn.sendall(self.policy)
+ self.log('Sent policy file to %s' % (addrstr,))
+ except socket.error, e:
+ self.log('Error handling connection from %s: %s' % (addrstr, e[1]))
+ except Exception, e:
+ self.log('Error handling connection from %s: %s' % (addrstr, e[1]))
+ def log(self, str):
+ print >>sys.stderr, str
+
+def main():
+ try:
+ usage = "usage: %prog [options]"
+
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option("-f", "--file", dest="file", help="The flashpolicy.xml file that will be served", metavar="FILE", default = FILE)
+
+ (options, args) = parser.parse_args()
+
+ policy_server(PORT, options.file).run()
+ except Exception, e:
+ print >> sys.stderr, e
+ sys.exit(1)
+ except KeyboardInterrupt:
+ pass
+
+if __name__ == '__main__':
+ main()
=======================================
--- /dev/null
+++ /branches/MultiplePorts/src/unit_testing.c Thu Feb 12 14:55:28 2015 UTC
@@ -0,0 +1,49 @@
+#include "unit_testing.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+/**
+ * The workhorse method of the test framework. Due to this framework's
+ * minimality, the run_test() method must be explicitly called in main() for
+ * each test you want to run. Also, there is no timeout for tests, which means
+ * an infinite loop will hang the testing framework.
+ *
+ * @param *test_name The displayed name of the test to be run
+ * @param *test_func A pointer to the void() test function
+ * */
+int run_test(const char* test_name, const void (*test_func)()) {
+ int test_exit_code;
+ pid_t child_test_pid;
+ fprintf(stderr, "Running test %s...\n", test_name);
+ // Run each child test in its own subprocess to help prevent tests from
+ // interfering with one another.
+ if ((child_test_pid = fork()) == 0) {
+ // Run the test in the child process.
+ (*test_func)();
+ // The child test process didn't crash or exit(), so exit with success!
+ exit(0);
+ } else {
+ // Wait for the child process to exit, hopefully successfully.
+ waitpid(child_test_pid, &test_exit_code, 0);
+ if (WIFEXITED(test_exit_code) && WEXITSTATUS(test_exit_code) == 0) {
+ fprintf(stderr, " ...Success!\n");
+ return 0;
+ } else {
+ if (WIFEXITED(test_exit_code) &&
+ WEXITSTATUS(test_exit_code) == FAILURE_EXIT_CODE) {
+ fprintf(stderr, " ...TEST FAILED.\n");
+ } else {
+ fprintf(stderr, " ...TEST CRASHED (return code=%d, %s).\n",
+ test_exit_code, strerror(test_exit_code));
+ }
+ // Make sure at least one of the bottom 7 bits is set. Some systems only
+ // pay attention to the bottom 7 bits of the process return code.
+ return (test_exit_code & 127) ? test_exit_code : (1 | test_exit_code);
+ }
+ }
+}
=======================================
--- /dev/null
+++ /branches/MultiplePorts/src/unit_testing.h Thu Feb 12 14:55:28 2015 UTC
@@ -0,0 +1,58 @@
+/* A minimal unit testing framework. Runs a test, prints debug output, returns
+ * the return value from the test. If non-zero, then the test failed.
+ * */
+
+#ifndef SRC_UNIT_TESTING_H
+#define SRC_UNIT_TESTING_H
+
+#include <stdio.h>
+
+/** We chose exit code 125 as a magic number to mean "test failed". All other
+ * error codes correspond to the test crashing. If the test crashes with error
+ * code 125, then the error message will be wrong. */
+#define FAILURE_EXIT_CODE 125
+
+/**
+ * Asserts a condition and with an asssociated error message and subsequent
+ * arguments to fprintf. You must supply both the condition and the error
+ * message, but subsequent arguments are optional. If you want to assert a
+ * condition and have a nice default error message, use CHECK instead.
+ *
+ * @param COND The condition being asserted. The condition will be avaluated in
+ * a boolean context.
+ * @param ... The message and associated data to be printed out on error. The
+ * first argument (required) is a char* holding the message to be
+ * printed. The char* and all subsequent arguments are passed
+ * directly to fprintf, which allows you to do things like:
+ * ASSERT(the_answer == 42, "Bad the_answer: %d", the_answer);
+ * in order to create nice error messages.
+ * */
+#define ASSERT(COND, ...) \
+ do { \
+ if (!(COND)) { \
+ fprintf(stderr, "Error at line %d in %s: ", __LINE__, __FILE__); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ exit(FAILURE_EXIT_CODE); \
+ } \
+ } while (0)
+
+/**
+ * Asserts a condition using the text of the condition as the error message.
+ *
+ * @param COND The condition being asserted.
+ * */
+#define CHECK(COND) ASSERT(COND, #COND)
+
+/**
+ * Unconditionally causes the test to fail. Useful in error-handling code and
+ * for ensuring certain code paths are never taken.
+ *
+ * @param ... The message and arguments for fprintf indicating why the failure
+ * occurred
+ * */
+#define FAIL(...) ASSERT(0, __VA_ARGS__)
+
+int run_test(const char* test_name, const void (*test_func)());
+
+#endif // SRC_UNIT_TESTING_H
=======================================
--- /dev/null
+++ /branches/MultiplePorts/src/web100srv_unit_tests.c Thu Feb 12 14:55:28 2015 UTC
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "unit_testing.h"
+
+/** Runs an end-to-end test of the server and client code. */
+void test_e2e() {
+ pid_t server_pid;
+ pid_t client_pid;
+ int client_exit_code;
+ char hostname[1024];
+ fprintf(stderr, "Starting the server\n");
+ if ((server_pid = fork()) == 0) {
+ execl("./web100srv", "./web100srv", "--port=5555", NULL);
+ perror("Server start error");
+ exit(1); // Children can't FAIL
+ }
+ // Wait until the server port (hopefully) becomes available
+ sleep(1);
+ // Find out the hostname. We can't use "localhost" because then the test
+ // won't go through the TCP stack and so web100 won't work.
+ gethostname(hostname, (sizeof(hostname) / sizeof(char)) - 1);
+ fprintf(stderr, "Starting the client, will attach to %s\n", hostname);
+ if ((client_pid = fork()) == 0) {
+ execl("./web100clt", "./web100clt", "--name", hostname, "--port=5555",
+ NULL);
+ perror("Client start error");
+ exit(1); // Children can't FAIL
+ }
+ waitpid(client_pid, &client_exit_code, 0);
+ kill(server_pid, SIGKILL);
+ ASSERT(WIFEXITED(client_exit_code) && WEXITSTATUS(client_exit_code) == 0,
+ "client exit code was %d", WEXITSTATUS(client_exit_code));
+}
+
+/** Runs each test, returns non-zero to the shell if any tests fail. */
+int main() {
+ int success = 0;
+ success |= run_test("end to end test", &test_e2e);
+ return success;
+}
=======================================
--- /branches/MultiplePorts/Applet/MANIFEST.MF Thu Nov 13 14:19:45 2014 UTC
+++ /branches/MultiplePorts/Applet/MANIFEST.MF Thu Feb 12 14:55:28 2015 UTC
@@ -3,5 +3,5 @@
Created-By: Rich Carlson
Application-Name: NDT
Main-Class: edu.internet2.ndt.Tcpbw100
-Permissions: sandbox
+Permissions: all-permissions
Caller-Allowable-Codebase: *
=======================================
--- /branches/MultiplePorts/Applet/precompiled/Tcpbw100.jar Wed Jun 25 18:48:32 2014 UTC
+++ /branches/MultiplePorts/Applet/precompiled/Tcpbw100.jar Thu Feb 12 14:55:28 2015 UTC
Binary file, no diff available.
=======================================
--- /branches/MultiplePorts/HTML5-frontend/script.js Wed Nov 12 13:49:44 2014 UTC
+++ /branches/MultiplePorts/HTML5-frontend/script.js Thu Feb 12 14:55:28 2015 UTC
@@ -56,6 +56,11 @@
function startTest(evt) {
evt.stopPropagation();
evt.preventDefault();
+ if (!isPluginLoaded()) {
+ $('#warning').show();
+ return;
+ }
+ $('#warning').hide();
document.getElementById('javaButton').disabled = true;
document.getElementById('flashButton').disabled = true;
showPage('test', resetGauges);
@@ -472,7 +477,6 @@

// BACKEND METHODS
function useJavaAsBackend() {
- //document.getElementById('javaButton').toggleClass('active');
var backendContainer = document.getElementById('backendContainer');
while (backendContainer.firstChild) {
backendContainer.removeChild(backendContainer.firstChild);
@@ -483,9 +487,11 @@
app.name = 'NDT';
app.archive = 'Tcpbw100.jar';
app.code = 'edu.internet2.ndt.Tcpbw100.class';
- app.width = '400';
- app.height = '400';
+ app.width = '600';
+ app.height = '10';
document.getElementById('backendContainer').appendChild(app);
+ $('#flashButton').removeClass("active");
+ $('#javaButton').addClass("active");
}

function useFlashAsBackend() {
@@ -500,8 +506,10 @@
embed.type = 'application/x-shockwave-flash';
embed.src = 'FlashClt.swf';
embed.width = '600';
- embed.height = '400';
- document.getElementById('backendContainer').appendChild(embed);
+ embed.height = '10';
+ document.getElementById('backendContainer').appendChild(embed);
+ $('#javaButton').removeClass("active");
+ $('#flashButton').addClass("active");
}

// UTILITIES
@@ -509,9 +517,20 @@
function debug(message) {
if (allowDebug && window.console) console.debug(message);
}
+
+function isPluginLoaded() {
+ try {
+ testStatus();
+ return true;
+ } catch(e) {
+ return false;
+ }
+}

function checkInstalledPlugins() {
var hasFlash = false, hasJava = false;
+
+ $('#warning').hide();
try {
var activeXObject = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
if(activeXObject) hasFlash = true;
@@ -520,7 +539,7 @@
}

if (!hasFlash) {
- document.getElementById('flashButton').disabled = true
+ document.getElementById('flashButton').disabled = true;
}

if (deployJava.getJREs() == '') {
@@ -531,6 +550,8 @@

if (hasJava) {
useJavaAsBackend();
+ } else if (hasFlash) {
+ useFlashAsBackend();
}
}

=======================================
--- /branches/MultiplePorts/HTML5-frontend/set-active-client.sh Fri Mar 21 10:33:50 2014 UTC
+++ /branches/MultiplePorts/HTML5-frontend/set-active-client.sh Thu Feb 12 14:55:28 2015 UTC
@@ -6,8 +6,8 @@
flash="flash"
java="java"
widget="widget.html"
-embed_tag="<embed id=\"NDT\" name=\"NDT\" type=\"application\/x-shockwave-flash\" src=\"FlashClt.swf\" width=\"600\" height=\"400\" \/>"
-applet_tag="<applet id=\"NDT\" name=\"NDT\" code=\"edu.internet2.ndt.Tcpbw100.class\" codebase=\"<?php print \$applet_url ?>\" archive=\"Tcpbw100.jar\" width=\"400\" height=\"400\"><\/applet>"
+embed_tag="<embed id=\"NDT\" name=\"NDT\" type=\"application\/x-shockwave-flash\" src=\"FlashClt.swf\" width=\"600\" height=\"10\" \/>"
+applet_tag="<applet id=\"NDT\" name=\"NDT\" code=\"edu.internet2.ndt.Tcpbw100.class\" codebase=\"<?php print \$applet_url ?>\" archive=\"Tcpbw100.jar\" width=\"400\" height=\"10\"><\/applet>"

echo "This script allows you to change NDT client being used in $widget page."
if test ! -f "$widget"; then
=======================================
--- /branches/MultiplePorts/HTML5-frontend/style.css Wed Nov 12 13:49:44 2014 UTC
+++ /branches/MultiplePorts/HTML5-frontend/style.css Thu Feb 12 14:55:28 2015 UTC
@@ -12,6 +12,7 @@
padding: 0;
border: 0;
overflow: hidden;
+ height: 2000px;
}
a img {
border: 0;
@@ -26,6 +27,14 @@
text-transform: uppercase;
font-size: 36px;
font-family: "League Gothic", Impact, "Arial Narrow", sans-serif;
+ margin-bottom: 15px;
+}
+.header {
+ margin: 10px;
+}
+#warning {
+ color: red;
+ margin: 10px;
}
.page {
width: 640px;
@@ -98,8 +107,8 @@
margin: 10px;
}

-.backendButton .active {
- background-color:blue;
+.active {
+ background-color:black;
}

.backendButton:disabled {
@@ -128,7 +137,7 @@
}

#welcome .info {
- padding-top: 50px;
+ padding-top: 10px;
text-transform: none;
font: 13px/18px verdana, helvetica, arial, sans-serif;
}
=======================================
--- /branches/MultiplePorts/HTML5-frontend/widget.html Wed Nov 12 13:49:44 2014 UTC
+++ /branches/MultiplePorts/HTML5-frontend/widget.html Thu Feb 12 14:55:28 2015 UTC
@@ -17,16 +17,29 @@
</script>
</head>
<body class="initializing">
+<div class="header">
+</div>
<div id="widget">
<div id="welcome" class="page">
<div class="info">

- <p class="mlab logo"><a href="http://www.measurementlab.net/";><img src="images/mlab-logo.png" alt="Measurement Lab" /></a></p>
+ <p>The Network Diagnostic Tool (NDT) provides a sophisticated speed and diagnostic test. An NDT test reports more than just the upload and download speeds &mdash; it also attempts to determine what, if any, problems limited these speeds, differentiating between computer configuration and network infrastructure problems. While the diagnostic messages are most useful for expert users, they can also help novice users by allowing them to provide detailed trouble reports to their network&nbsp;administrator.</p>

- <p>Network Diagnostic Tool (NDT) provides a sophisticated speed and diagnostic test. An NDT test reports more than just the upload and download speeds &mdash; it also attempts to determine what, if any, problems limited these speeds, differentiating between computer configuration and network infrastructure problems. While the diagnostic messages are most useful for expert users, they can also help novice users by allowing them to provide detailed trouble reports to their network&nbsp;administrator.</p>
+ <p>NDT makes use of either Flash or Java plugins to perform the test. Make sure that the plugin you choose is not blocked by your browser</p>

- <p class="mlab logo"><a href="http://www.measurementlab.net/";>Learn more about Measurement Lab</a></p>
+ <div id="warning">
+ <p>Selected plugin was not loaded properly. Make sure that you have proper plugin installed, and is not being blocked by your browser.</p>
+ </div>

+ <div>
+ <button id="javaButton" class="backendButton button" onclick="useJavaAsBackend()" type="button">Use Java</button>
+ <button id="flashButton" class="backendButton button" onclick="useFlashAsBackend()" type="button">Use Flash</button>
+ </div>
+
+ <div is="learn_more">
+ <a href="http://software.internet2.edu/ndt/";>Learn more about NDT</a> &ndash; <a href="http://www.measurementlab.net/";>Learn more about Measurement Lab</a>
+ </div>
+
</div>
<div class="status">
Initializing...
@@ -108,11 +121,9 @@
</div>

<div class="branding">
- <div class="logo">
- <a href="http://measurementlab.net/about"; target="_blank"><img src="images/mlab-logo-small.png" /></a>
- </div>
<div class="text">
- <a href="http://measurementlab.net/about"; target="_blank">More information about M-Lab</a>
+ <a href="http://software.internet2.edu/ndt/"; target="_blank">More information about NDT</a> <br />
+ <a href="http://measurementlab.net/about"; target="_blank">More information about Measurement Lab</a>
</div>
</div>

@@ -123,16 +134,11 @@
</div>
</div>

-<div>
- <button id="javaButton" class="backendButton button" onclick="useJavaAsBackend()" type="button">Use java</button>
- <button id="flashButton" class="backendButton button" onclick="useFlashAsBackend()" type="button">Use flash</button>
-</div>
-
<div id="backendContainer">
<!--Use embed tag to have flash client being background for JS UI or applet tag if you want to use java applet instead. -->
- <embed id="NDT" name="NDT" type="application/x-shockwave-flash" src="FlashClt.swf" width="600" height="400" />
+ <embed id="NDT" name="NDT" type="application/x-shockwave-flash" src="FlashClt.swf" width="600" height="10" />

- <!--<applet id="NDT" name="NDT" code="edu.internet2.ndt.Tcpbw100.class" codebase="<?php print $applet_url ?>" archive="Tcpbw100.jar" width="400" height="400"></applet>-->
+ <!--<applet id="NDT" width="600" height="10" name="NDT" code="edu.internet2.ndt.Tcpbw100.class" codebase="<?php print $applet_url ?>" archive="Tcpbw100.jar" width="400" height="10"></applet>-->
</div>

</body>
=======================================
--- /branches/MultiplePorts/Makefile.am Thu Jun 26 15:32:26 2014 UTC
+++ /branches/MultiplePorts/Makefile.am Thu Feb 12 14:55:28 2015 UTC
@@ -16,20 +16,26 @@
# Description: toplevel build for bwctl
#

-SUBDIRS = @TOP_BUILD_DIRS@ src conf doc
+SUBDIRS = @TOP_BUILD_DIRS@ src conf doc HTML5-frontend

if INCLUDE_APPLET
SUBDIRS += Applet
endif

+if INCLUDE_FLASH
+SUBDIRS += flash-client
+endif
+
if HAVE_GCJ
SUBDIRS += Admin janalyze
-if HAVE_MXMLC
-if BUILD_FLASH_CLT
-SUBDIRS += flash-client
endif
-endif
-endif
+
+sbin_SCRIPTS = ndt-flashpolicyd
+
+
+ndtdir = $(prefix)/ndt
+ndt_DATA = admin_description.html admin.html flashpolicy.xml \
+ copyright.html web100variables.html web100_variables

EXTRA_DIST = admin_description.html admin.html \
tcpbw100.template tcpbw100-java.template copyright.html web100variables.html \
@@ -38,21 +44,10 @@
contrib/README contrib/loadmap.intro contrib/loadmap.js \
contrib/loadmap.txt contrib/Tcpbw1001.java \
tfw/client.py tfw/communication.py tfw/hosts.py tfw/network.py \
- tfw/Readme tfw/scenarios.py tfw/server.py tfw/traffics.py
tfw/widgets.py
-
-ndtdir = $(prefix)/ndt
-ndt_DATA = admin_description.html admin.html \
- copyright.html web100variables.html web100_variables
+ tfw/Readme tfw/scenarios.py tfw/server.py tfw/traffics.py
tfw/widgets.py \
+ $(sbin_SCRIPTS) $(ndt_DATA)

sdatadir:
test -z "$(DESTDIR)$(ndtdir)/serverdata" || $(mkdir_p) "$(DESTDIR)$(ndtdir)/serverdata"

install: sdatadir install-recursive
-
-# uncomment this when we stop using broken automake 1.5
-# (then remove from DIST_EXTRA in subdir)
-#nobase_include_HEADERS = bwlib/bwlib.h
-
-#EXTRA_DIST = bootstrap
-#MAINTAINERCLEANFILES = aclocal.m4 Makefile.in configure config.log \
-# config.status
=======================================
--- /branches/MultiplePorts/conf/ndt-apache.conf Mon Jun 23 20:04:04 2014 UTC
+++ /branches/MultiplePorts/conf/ndt-apache.conf Thu Feb 12 14:55:28 2015 UTC
@@ -3,7 +3,7 @@
<VirtualHost *:7123>
DocumentRoot /usr/ndt
<Directory /usr/ndt>
- DirectoryIndex tcpbw100.html
+ DirectoryIndex widget.html
AllowOverride None
</Directory>

=======================================
--- /branches/MultiplePorts/conf/ndt-init Fri Jun 20 14:26:21 2014 UTC
+++ /branches/MultiplePorts/conf/ndt-init Thu Feb 12 14:55:28 2015 UTC
@@ -27,6 +27,7 @@

[ -f $path/web100srv ] || exit 0
[ -f $path/fakewww ] || exit 0
+[ -f $path/ndt-flashpolicyd ] || exit 0

RETVAL=0

@@ -70,6 +71,30 @@
echo "fakewww disabled - see /etc/sysconfig/ndt"
fi
}
+
+start_flashpolicyd ()
+{
+if [ ! $USE_FLASHPOLICYD = 0 ]
+then
+ if [ ! -n "`pidof -x $path/ndt-flashpolicyd`" ]; then
+ echo -n "Starting flashpolicyd:"
+ $path/ndt-flashpolicyd $FLASHPOLICYD_OPTIONS 2>/dev/null &
+ RETVAL=$?
+ if [ $RETVAL = 0 ]
+ then
+ success
+ touch /var/lock/subsys/ndt-flashpolicyd
+ else
+ failure
+ fi
+ echo
+ fi
+else
+ warning
+ echo "flashpolicyd disabled - see /etc/sysconfig/ndt"
+fi
+}
+

stop_web100srv ()
{
@@ -103,20 +128,46 @@
fi
}

+stop_flashpolicyd ()
+{
+ if [ ! $USE_FLASHPOLICYD = 0 ]
+ then
+ echo -n "Stopping flashpolicyd:"
+ killproc ndt-flashpolicyd -TERM
+ RETVAL=$?
+ echo
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/ndt-flashpolicyd
+ else
+ status ndt-flashpolicyd 2>/dev/null
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ]
+ then
+ warning
+ echo "flashpolicyd disabled, but is running"
+ else
+ success
+ echo "flashpolicyd disabled, not running"
+ fi
+ fi
+}
+

rhstatus() {
status web100srv
status fakewww
+ status ndt-flashpolicyd
}

stop() {
stop_web100srv
stop_fakewww
+ stop_flashpolicyd
}

start () {
start_web100srv
start_fakewww
+ start_flashpolicyd
}

restart() {
=======================================
--- /branches/MultiplePorts/conf/ndt-sysconfig Fri Jun 20 14:26:21 2014 UTC
+++ /branches/MultiplePorts/conf/ndt-sysconfig Thu Feb 12 14:55:28 2015 UTC
@@ -113,3 +113,10 @@
# extra options for fakewww - ignored unless USE_FAKEWWW is set to '1'
#FAKEWWW_OPTIONS="-f /index.html"
FAKEWWW_OPTIONS="-f /index.html -s -l /var/log/ndt/fakewww_access.log -e /var/log/ndt/fakewww_error.log"
+
+# Flash policy daemon options
+# -f FILE, --file=FILE The flashpolicy.xml file that will be served
+#
+# Whether to use the flash policy daemon; null or 0 to disable, 1 to enable
+USE_FLASHPOLICYD="1"
+FLASHPOLICYD_OPTIONS="-f /usr/ndt/flashpolicy.xml"
=======================================
--- /branches/MultiplePorts/configure.ac Wed Nov 12 13:49:44 2014 UTC
+++ /branches/MultiplePorts/configure.ac Thu Feb 12 14:55:28 2015 UTC
@@ -159,18 +159,41 @@


# Enabling/disabling flash client build
-AC_ARG_ENABLE(flash, [ --enable-flash=[yes/no] turn on flash client build
- [default=yes]],, enable_flash=yes)
+AC_ARG_WITH(flash, [ --enable-flash=[yes/no/precompiled/auto] turn on flash client build
+ [default=auto]],, with_flash=auto)

-if test "x$enable_flash" != "xno"; then
- AM_CONDITIONAL(BUILD_FLASH_CLT, true)
+if test "x$with_flash" == "xauto"; then
+ AC_CHECK_PROGS(NDTMXMLC, mxmlc)
+ if test -n "$NDTMXMLC"; then
+ with_flash=yes
+ else
+ with_flash=precompiled
+ fi
+fi
+
+if test "x$with_flash" == "xyes"; then
+ AC_CHECK_PROGS(NDTMXMLC, mxmlc)
+ if test -z "$NDTMXMLC"; then
+ AC_MSG_FAILURE([mxmlc required to rebuild flash client but not available])
+ fi
+fi
+
+if test "x$with_flash" != "xno"; then
+ AM_CONDITIONAL(INCLUDE_FLASH, true)
else
- AM_CONDITIONAL(BUILD_FLASH_CLT, false)
+ AM_CONDITIONAL(INCLUDE_FLASH, false)
fi

+if test "x$with_flash" != "xprecompiled"; then
+ AM_CONDITIONAL(BUILD_FLASH, true)
+else
+ AM_CONDITIONAL(BUILD_FLASH, false)
+fi
+
+
AC_ARG_WITH(I2util,
AC_HELP_STRING([--with-I2util=<dir>],
- [defaults to building I2util under owamp if
exists]),
+ [defaults to building I2util under NDT if
exists]),
with_I2util=$withval, with_I2util=yes)

#
@@ -201,20 +224,30 @@
I2UTILINCS="-I$I2util_dir $I2UTILINCS"
I2UTILLDFLAGS="-L$I2util_dir/I2util $I2UTILLDFLAGS"
I2UTILLIBDEPS="$I2util_dir/I2util/libI2util.a"
- I2UTILLIBMAKE="cd $I2util_dir; make"
+ I2UTILLIBMAKE="cd $I2util_dir; make"

# now, check for installed I2util
elif test -d /usr/local/I2util; then
I2UTILINCS="-I/usr/local/I2util/include $I2UTILINCS"
I2UTILLDFLAGS="-L/usr/local/I2util/lib $I2UTILLDFLAGS"
I2UTILLIBDEPS="/usr/local/I2util/lib/libI2util.a"
+
fi

- if test -z "$I2UTILLDFLAGS"; then
- AC_MSG_ERROR([couldn't find I2util library])
- else
- I2UTILLIBS="$I2UTILLDFLAGS -lI2util"
- fi
+ # Save the old CFLAGS and LDFLAGS
+ OLD_LDFLAGS="$LDFLAGS"
+ OLD_CFLAGS="$CFLAGS"
+
+ CFLAGS="$CFLAGS $I2UTILINCS"
+ LDFLAGS="$CFLAGS $I2UTILLDFLAGS"
+
+ AC_SEARCH_LIBS([I2AddrByNode],I2util, ,AC_MSG_ERROR([Couldn't find I2util library]))
+ AC_CHECK_HEADERS([I2util/util.h I2util/conf.h], ,AC_MSG_ERROR([Couldn't find I2util header files]), [AC_INCLUDES_DEFAULT])
+
+ LDFLAGS="$OLD_LDFLAGS"
+ CFLAGS="$OLD_CFLAGS"
+
+ I2UTILLIBS="$I2UTILLDFLAGS -lI2util"
fi

AC_SUBST(I2UTILLDFLAGS)
@@ -388,7 +421,7 @@
AC_SUBST(ac_aux_dir)
AC_CONFIG_FILES([Makefile
src/Makefile Admin/Makefile Applet/Makefile
- conf/Makefile doc/Makefile janalyze/Makefile
flash-client/Makefile])
+ conf/Makefile doc/Makefile janalyze/Makefile flash-client/Makefile HTML5-frontend/Makefile])
AC_OUTPUT

echo ""
@@ -469,14 +502,10 @@
SUMMARY_JANALYZEJAR="NO (missing java compiler)"
fi

-if test -z "$HAVE_MXMLC_TRUE" && test -n "$HAVE_MXMLC_FALSE"; then
-if test "x$enable_flash" != "xno"; then
+if test "x$with_flash" != "xno"; then
SUMMARY_FLASHCLT="YES"
else
-SUMMARY_FLASHCLT="NO (disabled by user)"
-fi
-else
-SUMMARY_FLASHCLT="NO (missing action script compiler)"
+SUMMARY_FLASHCLT="NO"
fi

if test "$SUMMARY_WEB100CLT" = "YES" && test "$SUMMARY_FLASHCLT" = "YES" && test "$SUMMARY_TCPBW100JAR" = "YES"; then
=======================================
--- /branches/MultiplePorts/flash-client/Makefile.am Wed Feb 5 13:31:05 2014 UTC
+++ /branches/MultiplePorts/flash-client/Makefile.am Thu Feb 12 14:55:28 2015 UTC
@@ -34,7 +34,11 @@
mkdir -p dist

FlashClt.swf: $(TEMPDIRS)
+if BUILD_FLASH
$(NDTMXMLC) src/Main.as $(NDTMXMLCFLAGS);
+else
+ cp precompiled/FlashClt.swf dist
+endif

mostlyclean-generic:
rm -rf $(TEMPDIRS) *~
@@ -43,5 +47,6 @@
src/locale/ca_ES/DisplayMessages.properties src/locale/el_GR/DisplayMessages.properties \
src/locale/en_US/DisplayMessages.properties src/locale/fr_FR/DisplayMessages.properties \
src/locale/nb_NO/DisplayMessages.properties src/locale/nl_NL/DisplayMessages.properties \
- src/locale/pt_BR/DisplayMessages.properties src/locale/ru_RU/DisplayMessages.properties
+ src/locale/pt_BR/DisplayMessages.properties src/locale/ru_RU/DisplayMessages.properties \
+ precompiled/FlashClt.swf

=======================================
--- /branches/MultiplePorts/flash-client/ndt-flash-config.xml Sun Feb 2 19:14:17 2014 UTC
+++ /branches/MultiplePorts/flash-client/ndt-flash-config.xml Thu Feb 12 14:55:28 2015 UTC
@@ -8,7 +8,7 @@
<define append="true">
<name>CONFIG::debug</name>
<!--TODO(tiziana): Change to false, right before the first public release. -->
- <value>true</value>
+ <value>false</value>
</define>
<define append="true">
<name>CONFIG::release</name>
@@ -27,7 +27,7 @@
<!-- The current NDT version -->
<define append="true">
<name>CONFIG::serverVersion</name>
- <value>"v3.6.5.2"</value>
+ <value>"v3.7.0-rc1"</value>
</define>
<define append="true">
<name>CONFIG::clientVersion</name>
=======================================
--- /branches/MultiplePorts/flash-client/src/TestResultsUtils.as Thu Nov 13 14:19:45 2014 UTC
+++ /branches/MultiplePorts/flash-client/src/TestResultsUtils.as Thu Feb 12 14:55:28 2015 UTC
@@ -688,9 +688,9 @@
// https://code.google.com/p/ndt/issues/detail?id=98
if (TestResults.ndt_test_results::ss2cSpeed
> TestResults.ndt_test_results::s2cSpeed) {
- var s2cQueue:Number = (TestResults.ndt_test_results::c2sSpeed
- - TestResults.ndt_test_results::sc2sSpeed)
- / TestResults.ndt_test_results::c2sSpeed;
+ var s2cQueue:Number = (TestResults.ndt_test_results::s2cSpeed
+ - TestResults.ndt_test_results::ss2cSpeed)
+ / TestResults.ndt_test_results::s2cSpeed;
TestResults.appendResultDetails(
ResourceManager.getInstance().getString(
NDTConstants.BUNDLE_NAME, "s2c", null, Main.locale)
=======================================
--- /branches/MultiplePorts/ndt.spec Fri Jun 27 13:41:49 2014 UTC
+++ /branches/MultiplePorts/ndt.spec Thu Feb 12 14:55:28 2015 UTC
@@ -2,7 +2,7 @@

Name: ndt
Version: 3.7.0
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: Network Diagnostic Tool

Group: Applications/Networking
@@ -41,6 +41,7 @@
Requires: I2util, chkconfig, initscripts, shadow-utils, coreutils
Requires: web100_userland, libpcap
Requires: jansson
+Requires: python >= 2.5

%description server
NDT server that enables end users to run performance tests
@@ -59,9 +60,9 @@

%build
%if "%{?CERT_FILE}" == ""
-%configure --with-I2util=%{_libdir} --enable-fakewww --with-java=precompiled
+%configure --enable-fakewww --with-java=precompiled --with-flash=precompiled
%else
-%configure --with-I2util=%{_libdir} --enable-fakewww --with-java=precompiled --with-cert="%{CERT_FILE}" --with-alias="%{CERT_ALIAS}"
+%configure --enable-fakewww --with-java=precompiled --with-cert="%{CERT_FILE}" --with-alias="%{CERT_ALIAS}" --with-flash=precompiled
%endif

#make %{?_smp_mflags}
@@ -109,13 +110,13 @@
%files server
%defattr(-,root,root,-)
%{_sbindir}/*
-%config(noreplace) %{_initrddir}/%{name}
+%{_initrddir}/%{name}
%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
%dir %{_prefix}/%{name}
%dir %{_localstatedir}/lib/%{name}
%dir %{_localstatedir}/log/%{name}
-%{_prefix}/%{name}/[^d]*
+%{_prefix}/%{name}/*
%{_mandir}/man5/*
%{_mandir}/man8/*
%{_mandir}/man1/analyze.1.gz
@@ -137,6 +138,9 @@
%{_bindir}/ndtclt

%changelog
+* Wed Nov 12 2014 Aaron Brown
<>
- 3.7.0-1
+- Initial NDT 3.7.0 release candidate RPM
+
* Tue Sep 25 2012 Kavitha Kumar
<>
- 3.6.5.2
- Change NDT version to 3.6.5.2_rc2

=======================================
--- /branches/MultiplePorts/src/Makefile.am Wed Nov 12 13:49:44 2014 UTC
+++ /branches/MultiplePorts/src/Makefile.am Thu Feb 12 14:55:28 2015 UTC
@@ -28,6 +28,8 @@

bin_PROGRAMS =
sbin_PROGRAMS = $(ADD_FAKEWWW)
+noinst_PROGRAMS =
+TESTS =

if HAVE_WEB100
bin_PROGRAMS += analyze viewtrace tr-mkmap genplot
@@ -37,6 +39,8 @@
if HAVE_PCAP_H
if HAVE_JANSSON
sbin_PROGRAMS += web100srv
+noinst_PROGRAMS += web100srv_unit_tests
+TESTS += web100srv_unit_tests
endif
endif
endif
@@ -45,6 +49,7 @@
bin_PROGRAMS += genplot10g
if HAVE_PCAP_H
if HAVE_JANSSON
+bin_PROGRAMS += web100clt
sbin_PROGRAMS += web10gsrv
endif
endif
@@ -85,6 +90,12 @@
web100srv_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' -DFORCE_WEB100
web100srv_DEPENDENCIES = $(I2UTILLIBDEPS)

+web100srv_unit_tests_SOURCES = web100srv_unit_tests.c unit_testing.c
+web100srv_unit_tests_LDFLAGS = $(NDTLDFLAGS) $(I2UTILLDFLAGS)
+web100srv_unit_tests_LDADD = $(NDTLIBS) $(I2UTILLIBS) $(I2UTILLIBDEPS) -lpthread $(ZLIB) $(JSONLIB)
+web100srv_unit_tests_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' -DFORCE_WEB100
+web100srv_unit_tests_DEPENDENCIES = $(I2UTILLIBDEPS)
+
web10gsrv_SOURCES = web100srv.c web100-util.c web100-pcap.c web100-admin.c runningtest.c \
network.c usage.c utils.c mrange.c logging.c testoptions.c ndtptestconstants.c \
protocol.c test_sfw_srv.c test_meta_srv.c ndt_odbc.c strlutils.c heuristics.c \
@@ -120,5 +131,5 @@

EXTRA_DIST = clt_tests.h logging.h mrange.h network.h protocol.h testoptions.h test_sfw.h test_meta.h \
troute.h tr-tree.h usage.h utils.h varinfo.h web100-admin.h web100srv.h ndt_odbc.h runningtest.h ndtptestconstants.h \
- heuristics.h strlutils.h test_results_clt.h tests_srv.h jsonutils.h
+ heuristics.h strlutils.h test_results_clt.h tests_srv.h jsonutils.h unit_testing.h

=======================================
--- /branches/MultiplePorts/src/fakewww.c Mon Jun 23 19:06:26 2014 UTC
+++ /branches/MultiplePorts/src/fakewww.c Thu Feb 12 14:55:28 2015 UTC
@@ -64,8 +64,8 @@
"automatically redirected in the next 2 seconds.\n "
"</font></BODY>\n</HTML>";

-char *Mypagefile = "/tcpbw100.html"; /* we throw the slash away */
-char *okfile[] = { "/tcpbw100.html", "/Tcpbw100.class", "/Tcpbw100$1.class",
+char *Mypagefile = "/widget.html"; /* we throw the slash away */
+char *okfile[] = { "/widget.html", "/Tcpbw100.class", "/Tcpbw100$1.class",
"/Tcpbw100$clsFrame.class", "/Tcpbw100.jar", "/copyright.html",
"/web100variables.html", "/"ADMINFILE, "/Admin.class", "/tr.sh",
"/traceroute.pl", "/Tcpbw100$MyTextPane.class",
@@ -73,7 +73,11 @@
"/Tcpbw100$3.class", "/Tcpbw100$OsfwWorker.class",
"/Tcpbw100$Message.class", "/Tcpbw100$StatusPanel$1.class",
"/Tcpbw100$clsFrame$1.class", "/Tcpbw100$TestWorker.class",
- "/lib/json-simple-1.1.1.jar", "/crossdomain.xml", 0 };
+ "/lib/json-simple-1.1.1.jar", "/crossdomain.xml",
+ "/embed.html", "/tcpbw100.html", "/FlashClt.swf", "/script.js", "/ie.css",
+ "/gauge.min.js", "/jquery-1.4.4.min.js", "/style.css",
+ "/fonts/digital-7-mono.ttf", "/fonts/League_Gothic.eot",
"/fonts/League_Gothic.otf",
+ "/images/mlab-logo.png", "/images/mlab-logo-small.png", 0 };

typedef struct allowed {
char* filename;
@@ -495,7 +499,7 @@

writen(sd, MsgRedir1, strlen(MsgRedir1));
writen(sd, MsgRedir2, strlen(MsgRedir2));
- snprintf(line, sizeof(line), "http://%u.%u.%u.%u:%s/tcpbw100.html";,
+ snprintf(line, sizeof(line), "http://%u.%u.%u.%u:%s/widget.html";,
srv_addr & 0xff, (srv_addr >> 8) & 0xff,
(srv_addr >> 16) & 0xff, (srv_addr >> 24) & 0xff,
port);
@@ -504,7 +508,7 @@
writen(sd, MsgRedir4, strlen(MsgRedir4));
answerSize = strlen(MsgRedir4);
snprintf(line, sizeof(line),
- "url=http://%u.%u.%u.%u:%s/tcpbw100.html";,
+ "url=http://%u.%u.%u.%u:%s/widget.html";,
srv_addr & 0xff, (srv_addr >> 8) & 0xff,
(srv_addr >> 16) & 0xff, (srv_addr >> 24) & 0xff,
port);
@@ -513,7 +517,7 @@
writen(sd, MsgRedir5, strlen(MsgRedir5));
answerSize += strlen(MsgRedir5);
snprintf(line, sizeof(line),
- "href=\"http://%u.%u.%u.%u:%s/tcpbw100.html\"";,
+ "href=\"http://%u.%u.%u.%u:%s/widget.html\"";,
srv_addr & 0xff, (srv_addr >> 8) & 0xff,
(srv_addr >> 16) & 0xff, (srv_addr >> 24) & 0xff,
port);
@@ -586,19 +590,19 @@

writen(sd, MsgRedir1, strlen(MsgRedir1));
writen(sd, MsgRedir2, strlen(MsgRedir2));
- snprintf(line, sizeof(line), "http://[%s]:%s/tcpbw100.html";,
+ snprintf(line, sizeof(line), "http://[%s]:%s/widget.html";,
onenodename, port);
writen(sd, line, strlen(line));
writen(sd, MsgRedir3, strlen(MsgRedir3));
writen(sd, MsgRedir4, strlen(MsgRedir4));
answerSize = strlen(MsgRedir4);
- snprintf(line, sizeof(line), "url=http://[%s]:%s/tcpbw100.html";,
+ snprintf(line, sizeof(line), "url=http://[%s]:%s/widget.html";,
onenodename, port);
writen(sd, line, strlen(line));
answerSize += strlen(line);
writen(sd, MsgRedir5, strlen(MsgRedir5));
answerSize += strlen(MsgRedir5);
- snprintf(line, sizeof(line), "href=\"http://[%s]:%s/tcpbw100.html\"";,
+ snprintf(line, sizeof(line), "href=\"http://[%s]:%s/widget.html\"";,
onenodename, port);
writen(sd, line, strlen(line));
answerSize += strlen(line);
@@ -622,7 +626,7 @@
tt = time(0);
ok = 0;
if (strcmp(filename, "/") == 0)
- strncpy(filename, "/tcpbw100.html", 15);
+ strncpy(filename, "/widget.html", 15);
for (i = 0; okfile[i]; i++) {
/* restrict file access */
if (strcmp(okfile[i], filename) == 0) {
=======================================
--- /branches/MultiplePorts/src/web100srv.c Wed Nov 5 13:15:12 2014 UTC
+++ /branches/MultiplePorts/src/web100srv.c Thu Feb 12 14:55:28 2015 UTC
@@ -2248,22 +2248,21 @@
sel_tv.tv_sec = 3; // 3 seconds == WAIT_TIME_SRVR
sel_tv.tv_usec = 0;
log_println(3, "Waiting for new connection, timer running");
-sel_11: retcode = select(listenfd + 1, &rfd, NULL, NULL, &sel_tv);
- if ((retcode == -1) && (errno == EINTR))
- /* continue; */ // a signal caused the select() to exit, re-enter
- // loop & check
- goto sel_11;
- tt = time(0);
+ do {
+ retcode = select(listenfd + 1, &rfd, NULL, NULL, &sel_tv);
+ // retry if a signal caused select() to exit.
+ } while ((retcode == -1) && (errno == EINTR));
+ tt = time(0);

} else {
// Nothing is in the queue, so wait forever until a new connection
// request arrives
log_println(3, "Timer not running, waiting for new connection");
mclients = 0;
-sel_12: retcode = select(listenfd + 1, &rfd, NULL, NULL, NULL);
- if ((retcode == -1) && (errno == EINTR))
- goto sel_12;
- // a signal caused the select() to exit, re-enter loop & check
+ do {
+ retcode = select(listenfd + 1, &rfd, NULL, NULL, NULL);
+ // retry if a signal caused the select() to exit
+ } while ((retcode == -1) && (errno == EINTR));
}

if (retcode < 0) {


  • [ndt-dev] [ndt] r1179 committed - Merge newest trunk into MultiplePorts branch, ndt, 02/12/2015

Archive powered by MHonArc 2.6.16.

Top of Page