PyNDN: Initial changes of PyNDN emulation in ndnSIM

The biggest problem so far, which I cannot solve at all, is exception
handling.  NDN.cxx throws many exceptions when something bad happens,
with are not handled by python bindings

Refs #1008 (http://redmine.named-data.net/issues/1008)
Refs #1011 (http://redmine.named-data.net/issues/1011)
diff --git a/PyNDN/Face.py b/PyNDN/Face.py
index 54803db..ebfeb5d 100644
--- a/PyNDN/Face.py
+++ b/PyNDN/Face.py
@@ -20,140 +20,51 @@
 import ns.core
 import ns.ndnSIM
 
-# from ns3.ndnSIM import ApiFace, Interest, Name
-
-class Face (object):
-    def __init__(self, node):
-        self._face = ns.ndnSIM.ndn.ApiFace (node)
+class Face (ns.ndnSIM.ndn.ApiFace):
+    def __init__(self):
+        self.nodeId = ns.core.Simulator.GetContext ()
+        self.node = ns.core.NodeList.GetNode (self.nodeId)
+        super(Face, self).__init__ (self.node)
 
     def connect (self):
         pass
 
     def disconnect (self):
-        pass
+        self.Shutdown ()
 
     def defer_verification (self, deferVerification = True):
         pass
 
     def expressInterestSimple (self, name, onData, onTimeout, template = None):
-        
-        pass
-        # class TrivialExpressClosure (Closure.Closure):
-        #     __slots__ = ["_baseName", "_onData", "_onTimeout"];
+        if template:
+            interest = ns.ndnSIM.ndn.Interest (template)
+        else:
+            interest = ns.ndnSIM.ndn.Interest ()
 
-        #     def __init__ (self, baseName, onData, onTimeout):
-        #         self._baseName = baseName
-        #         self._onData = onData
-        #         self._onTimeout = onTimeout
-
-        #     def upcall(self, kind, upcallInfo):
-        #         if (kind == Closure.UPCALL_CONTENT or
-        #             kind == Closure.UPCALL_CONTENT_UNVERIFIED or
-        #             kind == Closure.UPCALL_CONTENT_UNVERIFIED or
-        #             kind == Closure.UPCALL_CONTENT_KEYMISSING or
-        #             kind == Closure.UPCALL_CONTENT_RAW):
-        #             return self._onData (self._baseName, upcallInfo.Interest, upcallInfo.ContentObject, kind)
-        #         elif (kind == Closure.UPCALL_INTEREST_TIMED_OUT):
-        #             return self._onTimeout (self._baseName, upcallInfo.Interest)
-        #         return Closure.RESULT_OK
-
-        # trivial_closure = TrivialExpressClosure (name, onData, onTimeout)
-        # self.expressInterest (name, trivial_closure, template)
+        interest.SetName (name)
+        self.ExpressInterest (interest, onData, onTimeout)
 
     def setInterestFilterSimple (self, name, onInterest, flags = None):
-        pass
-        # class TrivialFilterClosure (Closure.Closure):
-        #     # __slots__ = ["_baseName", "_onInterest"];
-
-        #     def __init__ (self, baseName, onInterest):
-        #         self._baseName = baseName
-        #         self._onInterest = onInterest
-
-        #     def upcall(self, kind, upcallInfo):
-        #         if (kind == Closure.UPCALL_INTEREST):
-        #             return self._onInterest (self._baseName, upcallInfo.Interest)
-        #         return Closure.RESULT_OK
-
-        # trivial_closure = TrivialFilterClosure (name, onInterest)
-        # self.setInterestFilter (name, trivial_closure, flags)
+        self.SetInterestFilter (name, onInterest)
 
     def clearInterestFilter(self, name):
-        pass
+        self.ClearInterestFilter (name)
 
-    # Blocking!
     def get(self, name, template = None, timeoutms = 3000):
-    # self._acquire_lock("get")
-    # try:
-    #     return _ndn.get(self, name, template, timeoutms)
-    # finally:
-    #     self._release_lock("get")
+        raise ("NS-3 simulation cannot have syncrhonous operations")
 
-    # def put(self, contentObject):
-    #     self._acquire_lock("put")
-    #     try:
-    #     return _ndn.put(self, contentObject)
-    #     finally:
-    #     self._release_lock("put")
+    def put(self, data):
+        self.Put (data)
 
     @staticmethod
-    def getDefaultKey():
-        pass
-    # return _ndn.get_default_key()
+    def getDefaultKey ():
+        return None
 
-# class EventLoop(object):
-#     def __init__(self, *handles):
-#     self.running = False
-#     self.fds = {}
-#     for handle in handles:
-#         self.fds[handle.fileno()] = handle
-#         self.eventLock = threading.Lock ()
-#         self.events = []
+class EventLoop(object):
+    def execute (self, event):
+        ns.core.Simulator.ScheduleNow (event)
 
-#     def execute (self, event):
-#         self.eventLock.acquire ()
-#         self.events.append (event)
-#         self.eventLock.release ()
-
-#     def run_scheduled(self):
-#     wait = {}
-#     for fd, handle in zip(self.fds.keys(), self.fds.values()):
-#         wait[fd] = handle.process_scheduled()
-#     return wait[sorted(wait, key=wait.get)[0]] / 1000.0
-
-#     def run_once(self):
-#     fd_read = self.fds.values()
-#     fd_write = []
-#     for handle in self.fds.values():
-#         if handle.output_is_pending():
-#         fd_write.append(handle)
-
-#     timeout = min(self.run_scheduled(), 1.000)
-
-#         res = select.select(fd_read, fd_write, [], timeout)
-
-#     handles = set(res[0]).union(res[1])
-#     for handle in handles:
-#         handle.run(0)
-
-#     def run(self):
-#     self.running = True
-#         while self.running:
-#             try:
-#                 self.eventLock.acquire ()
-#                 for event in self.events:
-#                     event ()
-#                 self.events = []
-#                 self.eventLock.release ()
-
-#                 self.run_once()
-#             except select.error, e:
-#                 if e[0] == 4:
-#                     continue
-#                 else:
-#                     raise
-#         self.running = False
-
-#     def stop(self):
-#     self.running = False
-#         for fd, handle in zip(self.fds.keys(), self.fds.values()):
-#             handle.disconnect ()
+    def run (self, timeoutMs):
+        ns.core.Simulator.Stop (ns.core.MilliSeconds (timeoutMs))
+        ns.core.Simulator.Run ()
+        ns.core.Simulator.Destroy ()
diff --git a/PyNDN/Interest.py b/PyNDN/Interest.py
index 7ebee01..3256a7c 100644
--- a/PyNDN/Interest.py
+++ b/PyNDN/Interest.py
@@ -33,7 +33,7 @@
 CHILD_SELECTOR_LEFT = 0
 CHILD_SELECTOR_RIGHT = 1
 
-class Interest(object):
+class Interest (object):
     def __init__(self, name = None, minSuffixComponents = None,
              maxSuffixComponents = None, publisherPublicKeyDigest = None,
              exclude = None, childSelector = None, answerOriginKind = None,
diff --git a/PyNDN/Name.py b/PyNDN/Name.py
index ccb7c6a..aed9113 100644
--- a/PyNDN/Name.py
+++ b/PyNDN/Name.py
@@ -17,96 +17,39 @@
 #             Jeff Burke <jburke@ucla.edu>
 #
 
-import ndn
-from . import _ndn
+def toWire (name):
+    buf = ns.network.Buffer (ns.ndnSIM.ndn.Wire.FromNameSize (name))
+    ns.ndnSIM.ndn.Wire.FromName (buf.Begin (), name)
+    
+    output = bytearray (buf.GetSize ())
+    buf.CopyData (output, buf.GetSize ())
+    
+    return buf
+
+import ns.ndnSIM
+import ns.network
 
 from copy import copy
 import time, struct, random
 
-NAME_NORMAL = 0
-NAME_ANY    = 1
+class Name (ns.ndnSIM.ndn.Name):
+    def __init__(self, name=None):
+        super (Name, self).__init__ (name)
 
-class Name(object):
-    def __init__(self, components=[], name_type=NAME_NORMAL, ccn_data=None, ccnb_buffer=None):
-        self._setattr('type', name_type)
+    @staticmethod
+    def fromWire (wire):
+        return ns.ndnSIM.ndn.Wire.ToName (wire)
 
-        # py-ndn
-        #self._setattr('ccn_data_dirty', True)
-        self._setattr('ccn_data', ccn_data)
+    @staticmethod
+    def toWire (name):
+        buf = ns.network.Buffer ()
+        buf.AddToStart (ns.ndnSIM.ndn.Wire.FromNameSize (name))
+        ns.ndnSIM.ndn.Wire.FromName (buf.Begin (), name)
 
-                # Name from simple buffer containing name in ccnb encoding
-                if ccnb_buffer:
-                        self._setattr('components', _ndn.name_comps_from_ccn_buffer (bytes (ccnb_buffer)))
-
-        # Name from CCN
-        elif ccn_data:
-            self._setattr('components', _ndn.name_comps_from_ccn(ccn_data))
-            self._setattr('ccn_data_dirty', False)
-
-        # Copy Name from another Name object
-        elif isinstance(components, self.__class__):
-            self._setattr('components', copy(components.components))
-            if not components.ccn_data_dirty:
-                self._setattr('ccn_data', components.ccn_data)
-                self._setattr('ccn_data_dirty', False)
-
-        # Name as string (URI)
-        elif type(components) is str:
-            ccn_data = _ndn.name_from_uri(components)
-            self._setattr('components', _ndn.name_comps_from_ccn(ccn_data))
-            self._setattr('ccn_data', ccn_data)
-            self._setattr('ccn_data_dirty', False)
-
-        # Otherwise assume name is a list
-        else:
-            self._setattr('components', copy(components))
-
-    def _setattr(self, name, value):
-        if name == 'components' or name == 'ccn_data':
-            self._setattr('ccn_data_dirty', True)
-        super(Name, self).__setattr__(name, value)
-
-    def _append(self, component):
-        components = copy(self.components)
-        components.append(component)
-
-        return Name(components)
-
-    def append(self, value):
-        components = copy(self.components)
-                if isinstance (value, Name):
-                        components.extend (value.components)
-                else:   
-                        components.append (bytes (value))
-        return Name(components)
-
-    def appendKeyID(self, digest):
-        if isinstance(digest, ndn.Key):
-            digest = digest.publicKeyID
-
-        component = b'\xc1.M.K\x00'
-        component += digest
-
-        return self._append(component)
-
-    def appendVersion(self, version = None):
-        if not version:
-            inttime = int(time.time() * 4096 + 0.5)
-            bintime = struct.pack("!Q", inttime)
-            version = bintime.lstrip(b'\x00')
-        component = b'\xfd' + version
-
-        return self._append(component)
-
-    def appendSegment(self, segment):
-        return self._append(self.num2seg(segment))
-
-    def appendNonce(self):
-        val = random.getrandbits(64)
-        component = b'\xc1.N\x00' + struct.pack("@Q", val)
-
-        return self._append(component)
-
+        output = bytearray (buf.GetSize ())
+        buf.CopyData (output, buf.GetSize ())
+        return output
+    
     def get_ccnb(self):
         return _ndn.dump_charbuf(self.ccn_data)
 
@@ -156,40 +99,11 @@
         else:
             raise ValueError("Unknown __getitem__ type: %s" % type(key))
 
-    def __setitem__(self, key, value):
-        self.components[key] = value
+    # def __setitem__(self, key, value):
+    #     self.components[key] = value
 
-    def __delitem__(self, key):
-        del self.components[key]
+    # def __delitem__(self, key):
+    #     del self.components[key]
 
-    def __len__(self):
-        return len(self.components)
-
-    def __lt__(self, other):
-        return _ndn.compare_names(self.ccn_data, other.ccn_data) < 0
-
-    def __gt__(self, other):
-        return _ndn.compare_names(self.ccn_data, other.ccn_data) > 0
-
-    def __eq__(self, other):
-        return _ndn.compare_names(self.ccn_data, other.ccn_data) == 0
-
-    def __le__(self, other):
-        return _ndn.compare_names(self.ccn_data, other.ccn_data) <= 0
-
-    def __ge__(self, other):
-        return _ndn.compare_names(self.ccn_data, other.ccn_data) >= 0
-
-    def __ne__(self, other):
-        return _ndn.compare_names(self.ccn_data, other.ccn_data) != 0
-
-    @staticmethod
-    def num2seg(num):
-        return b'\x00' + struct.pack('!Q', num).lstrip(b'\x00')
-
-    @staticmethod
-    def seg2num(segment):
-        return long(struct.unpack("!Q", (8 - len(segment)) * "\x00" + segment)[0])
-
-        def isPrefixOf (self, other):
-                return self[:] == other[:len(self)]
+    # def __len__(self):
+    #     return len(self.components)