Bug fix on ndnpingclient and experiment script

Mininet host object is passed as a prefix from experiment
to ndnpingclient, string replacement operation on the
prefix fails at the client which crashes the Mini-NDN

Change-Id: I36c1f9e2e455321d8c650fd9711088b7e5ef2b22
diff --git a/minindn/helpers/experiment.py b/minindn/helpers/experiment.py
index a29272a..910b239 100644
--- a/minindn/helpers/experiment.py
+++ b/minindn/helpers/experiment.py
@@ -28,7 +28,8 @@
 from mininet.log import info
 
 from minindn.helpers.nfdc import Nfdc
-from minindn.helpers.ndnpingclient import NDNPingClient
+from minindn.helpers.ndnping import NDNPing
+from minindn.util import getSafeName
 
 class Experiment(object):
     @staticmethod
@@ -70,7 +71,8 @@
         for host in hosts:
             host.cmd('mkdir -p ping-data')
             Nfdc.setStrategy(host, '/ndn/', strategy)
-            host.cmd('ndnpingserver /ndn/{}-site/{} > ping-server &'.format(host.name, host.name))
+            prefix = getSafeName('/ndn/{}-site/{}'.format(host.name, host.name))
+            NDNPing.startPingServer(host, prefix)
 
     @staticmethod
     def startPctPings(net, nPings, pctTraffic=1.0):
@@ -95,7 +97,8 @@
 
                 # Do not ping self
                 if host.name != other.name:
-                    NDNPingClient.ping(host, other, nPings)
+                    destPrefix = getSafeName('/ndn/{}-site/{}'.format(other.name, other.name))
+                    NDNPing.ping(host, destPrefix, other.name, nPings)
                     nodesPingedList.append(other)
 
                 # Always increment because in 100% case a node should not ping itself
diff --git a/minindn/helpers/ndnping.py b/minindn/helpers/ndnping.py
new file mode 100644
index 0000000..5d2f3d4
--- /dev/null
+++ b/minindn/helpers/ndnping.py
@@ -0,0 +1,71 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2020, The University of Memphis,
+#                          Arizona Board of Regents,
+#                          Regents of the University of California.
+#
+# This file is part of Mini-NDN.
+# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
+#
+# Mini-NDN 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.
+#
+# Mini-NDN 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 Mini-NDN, e.g., in COPYING.md file.
+# If not, see <http://www.gnu.org/licenses/>.
+
+import time
+
+# Todo: convert to app
+
+class NDNPing(object):
+    @staticmethod
+    def ping(source, prefix, pingDataFile="output-client", nPings=1, interval=None, timeout=None,
+            starting_seq_num=None, identifier=None, allow_stale_data=False, print_timestamp=True, sleepTime=0.2):
+        print('Scheduling ping(s) from {} for {}'.format(source.name, prefix))
+        # Use '&' to run in background and perform parallel pings
+        source.cmd("mkdir -p ping-data")
+        source.cmd('ndnping{1}{2}{3}{4}{5}{6}{7} {0} >> ping-data/{8}.txt &'
+        .format(
+            prefix,
+            ' -c {}'.format(nPings),
+            ' -i {}'.format(interval) if interval else '',
+            ' -o {}'.format(timeout) if timeout  else '',
+            ' -n {}'.format(starting_seq_num) if starting_seq_num else '',
+            ' -p {}'.format(identifier) if identifier else '',
+            ' -a' if allow_stale_data else '',
+            ' -t' if print_timestamp else '',
+            pingDataFile
+        ))
+        time.sleep(sleepTime)
+
+    def startPingServer(source, prefix, pingDataFile="output-server", freshness=None, satisfy=None, 
+            size=None, timestamp=False, quiet=False):
+        """
+        Start a pingserver
+         :param string preifx: prefix to start pingserver on
+         :param int freshness: FreshnessPeriod of the ping response, in milliseconds
+         :param int satisfy: maximum number of pings to satisfy
+         :param int size: size of response payload
+         :param boolean timestamp: prepend a timestamp to each log message
+         :param boolean quite: do not print a log message each time a ping packet is received
+        """
+        print('Staring ping server on prefix {}'.format(prefix))
+        source.cmd("mkdir -p ping-data")
+        cmd = 'ndnpingserver {1}{2}{3}{4}{5} {0}>> ping-data/{6}.txt &'.format(
+            prefix,
+            '-f {}'.format(freshness) if freshness else '',
+            '-p {}'.format(satisfy) if satisfy else '',
+            '-s {}'.format(size) if size else '',
+            '{}'.format('-t') if timestamp else '',
+            '{}'.format('-q') if quiet else '',
+            pingDataFile
+        )
+        source.cmd(cmd)
\ No newline at end of file
diff --git a/minindn/helpers/ndnpingclient.py b/minindn/helpers/ndnpingclient.py
deleted file mode 100644
index a252a58..0000000
--- a/minindn/helpers/ndnpingclient.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2020, The University of Memphis,
-#                          Arizona Board of Regents,
-#                          Regents of the University of California.
-#
-# This file is part of Mini-NDN.
-# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
-#
-# Mini-NDN 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.
-#
-# Mini-NDN 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 Mini-NDN, e.g., in COPYING.md file.
-# If not, see <http://www.gnu.org/licenses/>.
-
-import time
-
-# Todo: convert to app
-
-class NDNPingClient(object):
-    @staticmethod
-    def ping(source, prefix, nPings=1, interval=None, timeout=None, starting_seq_num=None,
-             identifier=None, allow_stale_data=False, print_timestamp=True, sleepTime=0.2):
-        print('Scheduling ping(s) from {} for {}'.format(source.name, prefix))
-        # Use '&' to run in background and perform parallel pings
-        source.cmd("mkdir ping-data")
-        source.cmd('ndnping{1}{2}{3}{4}{5}{6}{7} {0} >> ping-data/{8}.txt &'
-        .format(
-            prefix,
-            ' -c {}'.format(nPings),
-            ' -i {}'.format(interval) if interval else '',
-            ' -o {}'.format(timeout) if timeout  else '',
-            ' -n {}'.format(starting_seq_num) if starting_seq_num else '',
-            ' -p {}'.format(identifier) if identifier else '',
-            ' -a' if allow_stale_data else '',
-            ' -t' if print_timestamp else '',
-            str.replace(prefix[1:], "/", "-")
-        ))
-        time.sleep(sleepTime)
diff --git a/minindn/util.py b/minindn/util.py
index 82fcdac..b7d060c 100644
--- a/minindn/util.py
+++ b/minindn/util.py
@@ -24,6 +24,8 @@
 import sys
 from os.path import isfile
 from subprocess import call
+from six.moves.urllib.parse import quote
+
 from mininet.cli import CLI
 from mn_wifi.cli import CLI as CLI_wifi
 
@@ -31,6 +33,17 @@
 scpbase = ['scp', '-i', '/home/mininet/.ssh/id_rsa']
 devnull = open('/dev/null', 'w')
 
+def getSafeName(namePrefix):
+    """
+    Check if the prefix/string is safe to use with ndn commands or not.
+        return safe prefix.
+    :param namePrefix: name of the prefix
+    """
+    # remove redundant "/"es, multiple "/"es are an invalid representation for empty name component
+    # https://named-data.net/doc/NDN-packet-spec/current/changelog.html#version-0-3
+    namePrefix= "/" + ("/".join(filter(None, namePrefix.split("/"))))
+    return quote(namePrefix, safe='/')
+
 def ssh(login, cmd):
     rcmd = sshbase + [login, cmd]
     call(rcmd, stdout=devnull, stderr=devnull)
@@ -80,4 +93,4 @@
 class MiniNDNWifiCLI(CLI_wifi):
     prompt = 'mini-ndn-wifi> '
     def __init__(self, mininet, stdin=sys.stdin, script=None):
-        CLI_wifi.__init__(self, mininet, stdin, script)
\ No newline at end of file
+        CLI_wifi.__init__(self, mininet, stdin, script)