Move to using infoconv to modify NFD configuration file

This also resolves issue #5316, which was causing crashes
due to PPAs not being up to date with changes to the
default socket path.

Refs #5318

Change-Id: I02ccfe1698f2a07c501c400a8de80e52be3ddead
diff --git a/minindn/apps/nfd.py b/minindn/apps/nfd.py
index 084dcf4..44978e7 100644
--- a/minindn/apps/nfd.py
+++ b/minindn/apps/nfd.py
@@ -20,52 +20,62 @@
 # 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 json
+import os
 
 from minindn.apps.application import Application
 from minindn.util import copyExistentFile
 from minindn.minindn import Minindn
 
 class Nfd(Application):
-
     def __init__(self, node, logLevel='NONE', csSize=65536,
-                 csPolicy='lru', csUnsolicitedPolicy='drop-all',
-                 defaultSocketLocation='/run/nfd'):
+                 csPolicy='lru', csUnsolicitedPolicy='drop-all'):
         Application.__init__(self, node)
-
         self.logLevel = node.params['params'].get('nfd-log-level', logLevel)
 
         self.confFile = '{}/nfd.conf'.format(self.homeDir)
         self.logFile = 'nfd.log'
-        self.sockFile = '{}/{}.sock'.format(defaultSocketLocation, node.name)
         self.ndnFolder = '{}/.ndn'.format(self.homeDir)
         self.clientConf = '{}/client.conf'.format(self.ndnFolder)
-
         # Copy nfd.conf file from /usr/local/etc/ndn or /etc/ndn to the node's home directory
         # Use nfd.conf as default configuration for NFD, else use the sample
-        possibleConfPaths = ['/usr/local/etc/ndn/nfd.conf.sample', '/usr/local/etc/ndn/nfd.conf',
-                             '/etc/ndn/nfd.conf.sample', '/etc/ndn/nfd.conf']
+        possibleConfPaths = ['/usr/local/etc/ndn/nfd.conf', '/usr/local/etc/ndn/nfd.conf.sample',
+                             '/etc/ndn/nfd.conf', '/etc/ndn/nfd.conf.sample']
         copyExistentFile(node, possibleConfPaths, self.confFile)
 
+        # Using infoconv, we convert the local nfd.conf file to JSON and parse it into an object
+        conf_file = json.loads(node.cmd("infoconv info2json < {}".format(self.confFile)))
+
         # Set log level
-        node.cmd('infoedit -f {} -s log.default_level -v {}'.format(self.confFile, self.logLevel))
-        # Open the conf file and change socket file name
-        node.cmd('infoedit -f {} -s face_system.unix.path -v {}'.format(self.confFile, self.sockFile))
+        conf_file["log"]["default_level"] = self.logLevel
+
+        # Set socket file name and path
+        # Retrieve the default socket path from the conf file; this avoids issues from #5316
+        default_socket_path = os.path.dirname(conf_file["face_system"]["unix"]["path"])
+        self.sockFile = '{}/{}.sock'.format(default_socket_path, node.name)
+        # Set socket path in conf file to new socket
+        conf_file["face_system"]["unix"]["path"] = self.sockFile
+        # Create client configuration for host to ensure socket path is consistent
+        # Suppress error if working directory exists from prior run
+        os.makedirs(self.ndnFolder, exist_ok=True)
+        # This will overwrite any existing client.conf files, which should not be an issue
+        with open(self.clientConf, "w") as client_conf_file:
+            client_conf_file.write("transport=unix://{}\n".format(self.sockFile))
 
         # Set CS parameters
-        node.cmd('infoedit -f {} -s tables.cs_max_packets -v {}'.format(self.confFile, csSize))
-        node.cmd('infoedit -f {} -s tables.cs_policy -v {}'.format(self.confFile, csPolicy))
-        node.cmd('infoedit -f {} -s tables.cs_unsolicited_policy -v {}'.format(self.confFile, csUnsolicitedPolicy))
+        conf_file["tables"]["cs_max_packets"] = csSize
+        conf_file["tables"]["cs_policy"] = csPolicy
+        conf_file["tables"]["cs_unsolicited_policy"] = csUnsolicitedPolicy
 
-        # Make NDN folder
-        node.cmd('mkdir -p {}'.format(self.ndnFolder))
+        # To avoid complicated Bash piping, we write the JSON to a temporary file
+        with open("{}/temp_nfd_conf.json".format(self.homeDir), "w") as temp_file:
+            json.dump(conf_file, temp_file)
 
-        # Copy client configuration to host
-        possibleClientConfPaths = ['/usr/local/etc/ndn/client.conf.sample', '/etc/ndn/client.conf.sample']
-        copyExistentFile(node, possibleClientConfPaths, self.clientConf)
+        # Convert our modified intermediate file and write to the new conf file
+        node.cmd("infoconv json2info < {}/temp_nfd_conf.json > {}".format(self.homeDir, self.confFile))
 
-        # Change the unix socket
-        node.cmd('sudo sed -i "s|;transport|transport|g" {}'.format(self.clientConf))
-        node.cmd('sudo sed -i "s|nfd.sock|{}.sock|g" {}'.format(node.name, self.clientConf))
+        # Remove the intermediate JSON file
+        os.remove("{}/temp_nfd_conf.json".format(self.homeDir))
 
         if not Minindn.ndnSecurityDisabled:
             # Generate key and install cert for /localhost/operator to be used by NFD