Add Nfdc functionality to enable working with FaceID rather than FaceURI exclusively

refs: #5130

Change-Id: I1b7ca1846cafdde8e959663ba53d5bd50b455b39
diff --git a/docs/hackathon.rst b/docs/hackathon.rst
index 242f974..625e3d6 100644
--- a/docs/hackathon.rst
+++ b/docs/hackathon.rst
@@ -7,5 +7,4 @@
 - 4th NDN Hackathon: `Mini-NDN wifi <https://github.com/4th-ndn-hackathon/Mini-NDN-Wi-Fi>`_.
 - 7th NDN Hackathon: `Mini-NDN documentation <https://github.com/7th-ndn-hackathon/mini-ndn-documentation>`_.
 - 11th NDN Hackathon: `Mini-NDN improvements <https://11th-ndn-hackathon.named-data.net/hacks.html#8-mini-ndn-improvements>`_.
-- 12th NDN Hackathon: `Mini-NDN improvements and Refactoring <https://12th-ndn-hackathon.named-data.net/hacks.html#7-mini-ndn-improvements>`_.
-
+- 12th NDN Hackathon: `Mini-NDN improvements and Refactoring <https://12th-ndn-hackathon.named-data.net/hacks.html#7-mini-ndn-improvements>`_.
\ No newline at end of file
diff --git a/examples/psync/full_sync.py b/examples/psync/full_sync.py
index 1a54a73..d256a3b 100644
--- a/examples/psync/full_sync.py
+++ b/examples/psync/full_sync.py
@@ -35,8 +35,8 @@
     for node in ndn.net.hosts:
         for neighbor in node.connectionsTo(host):
             ip = node.IP(neighbor[0])
-            Nfdc.createFace(host, ip)
-            Nfdc.registerRoute(host, syncPrefix, ip)
+            faceID = Nfdc.createFace(host, ip)
+            Nfdc.registerRoute(host, syncPrefix, faceID)
 
 if __name__ == '__main__':
     setLogLevel('info')
diff --git a/examples/wifi/wifi_ping.py b/examples/wifi/wifi_ping.py
index 6ba0531..16fd62d 100644
--- a/examples/wifi/wifi_ping.py
+++ b/examples/wifi/wifi_ping.py
@@ -65,8 +65,8 @@
 
     info("Starting pingserver...")
     NDNPing.startPingServer(b, "/example")
-    Nfdc.createFace(a, b.IP())
-    Nfdc.registerRoute(a, "/example", b.IP())
+    faceID = Nfdc.createFace(a, b.IP())
+    Nfdc.registerRoute(a, "/example", faceID)
 
     info("Starting ping...")
     NDNPing.ping(a, "/example", nPings=10)
diff --git a/minindn/helpers/ndn_routing_helper.py b/minindn/helpers/ndn_routing_helper.py
index 1ae5930..6eeb40d 100644
--- a/minindn/helpers/ndn_routing_helper.py
+++ b/minindn/helpers/ndn_routing_helper.py
@@ -357,8 +357,8 @@
             prefixes = [defaultPrefix] + self.namePrefixes[destination]
             for prefix in prefixes:
                 # Register routes to all the available destination name prefix/s
-                nfdc.registerRoute(node, prefix, neighborIPs[nextHop], \
-                                   nfdc.PROTOCOL_UDP, cost=cost)
+                faceID = nfdc.createFace(node, neighborIPs[nextHop])
+                nfdc.registerRoute(node, prefix, faceID, cost=cost)
     @staticmethod
     def getNeighbor(node):
         # Nodes to IP mapping
diff --git a/minindn/helpers/nfdc.py b/minindn/helpers/nfdc.py
index 4fc9240..1ba926f 100644
--- a/minindn/helpers/nfdc.py
+++ b/minindn/helpers/nfdc.py
@@ -36,41 +36,65 @@
     PROTOCOL_ETHER = 'ether'
 
     @staticmethod
-    def registerRoute(node, namePrefix, remoteNodeAddress, protocol=PROTOCOL_UDP, origin=255,
+    def registerRoute(node, namePrefix, remoteNode, protocol=PROTOCOL_UDP, origin=255,
                       cost=0, inheritFlag=True, captureFlag=False, expirationInMillis=None):
-        cmd = ('nfdc route add {} {}://{} origin {} cost {} {}{}{}').format(
-            namePrefix,
-            protocol,
-            remoteNodeAddress,
-            origin,
-            cost,
-            'no-inherit ' if not inheritFlag else '',
-            'capture ' if captureFlag else '',
-            'expires {}'.format(expirationInMillis) if expirationInMillis else ''
-        )
-
+        cmd = ""
+        if remoteNode.isdigit() and not protocol == "fd":
+            cmd = ('nfdc route add {} {} origin {} cost {} {}{}{}').format(
+                namePrefix,
+                remoteNode,
+                origin,
+                cost,
+                'no-inherit ' if not inheritFlag else '',
+                'capture ' if captureFlag else '',
+                'expires {}'.format(expirationInMillis) if expirationInMillis else ''
+            )
+        else:
+            cmd = ('nfdc route add {} {}://{} origin {} cost {} {}{}{}').format(
+                namePrefix,
+                protocol,
+                remoteNode,
+                origin,
+                cost,
+                'no-inherit ' if not inheritFlag else '',
+                'capture ' if captureFlag else '',
+                'expires {}'.format(expirationInMillis) if expirationInMillis else ''
+            )
         debug(node.cmd(cmd))
         Minindn.sleep(SLEEP_TIME)
 
     @staticmethod
-    def unregisterRoute(node, namePrefix, remoteNodeAddress, origin=255):
-        cmd = 'nfdc route remove {} {} {}'.format(namePrefix, remoteNodeAddress, origin)
+    def unregisterRoute(node, namePrefix, remoteNode, origin=255):
+        cmd = ""
+        if remoteNode.isdigit() and not protocol == "fd":
+            cmd = 'nfdc route remove {} {} {}'.format(namePrefix, remoteNode, origin)
+        else:
+            cmd = 'nfdc route remove {} {} {}'.format(namePrefix, remoteNode, origin)
         debug(node.cmd(cmd))
         Minindn.sleep(SLEEP_TIME)
 
     @staticmethod
     def createFace(node, remoteNodeAddress, protocol='udp', isPermanent=False):
+        '''Create face in node's NFD instance. Returns FaceID of created face or -1 if failed.'''
         cmd = ('nfdc face create {}://{} {}'.format(
             protocol,
             remoteNodeAddress,
             'permanent' if isPermanent else 'persistent'
         ))
-        debug(node.cmd(cmd))
+        output = node.cmd(cmd)
+        debug(output)
         Minindn.sleep(SLEEP_TIME)
+        if "face-created" not in output:
+            return -1
+        faceID = output.split(" ")[1][3:]
+        return faceID
 
     @staticmethod
-    def destroyFace(node, remoteNodeAddress, protocol='udp'):
-        debug(node.cmd('nfdc face destroy {}://{}'.format(protocol, remoteNodeAddress)))
+    def destroyFace(node, remoteNode, protocol='udp'):
+        if remoteNode.isdigit() and not protocol == "fd":
+            debug(node.cmd('nfdc face destroy {}'.format(protocol, remoteNode)))
+        else:
+            debug(node.cmd('nfdc face destroy {}://{}'.format(protocol, remoteNode)))
         Minindn.sleep(SLEEP_TIME)
 
     @staticmethod
@@ -83,3 +107,19 @@
     def unsetStrategy(node, namePrefix):
         debug(node.cmd("nfdc strategy unset {}".format(namePrefix)))
         Minindn.sleep(SLEEP_TIME)
+
+    @staticmethod
+    def getFaceId(node, remoteNodeAddress, localEndpoint=None, protocol="udp", portNum="6363"):
+        '''Returns the faceId for a remote node based on FaceURI, or -1 if a face is not found'''
+        #Should this be cached or is the hit not worth it?
+        local = ""
+        if localEndpoint:
+            local = " local {}".format(localEndpoint)
+        output = node.cmd("nfdc face list remote {}://{}:{}{}".format(protocol, remoteNodeAddress, portNum, local))
+        debug(output)
+        Minindn.sleep(SLEEP_TIME)
+        # This is fragile but we don't have that many better options
+        if "faceid=" not in output:
+            return -1
+        faceId = output.split(" ")[0][7:]
+        return faceId
\ No newline at end of file