PyNDN: Finishing basic implementation of PyNDN emulation

Not yet fully tested

Refs #1010 (http://redmine.named-data.net/issues/1010)
diff --git a/PyNDN/ContentObject.py b/PyNDN/ContentObject.py
deleted file mode 100644
index 5af7b0c..0000000
--- a/PyNDN/ContentObject.py
+++ /dev/null
@@ -1,263 +0,0 @@
-## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-# 
-# Copyright (c) 2011-2013, Regents of the University of California
-#                          Alexander Afanasyev
-# 
-# GNU 3.0 license, See the LICENSE file for more information
-# 
-# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
-# 
-
-#
-# Based on PyCCN code, copyrighted and licensed as follows
-#
-# Copyright (c) 2011-2013, Regents of the University of California
-# BSD license, See the COPYING file for more information
-# Written by: Derek Kulinski <takeda@takeda.tk>
-#             Jeff Burke <jburke@ucla.edu>
-#
-
-from . import _ndn
-import utils
-
-class ContentType(utils.Enum):
-    _prefix = "ndn"
-
-CONTENT_DATA = ContentType.new_flag('CONTENT_DATA', 0x0C04C0)
-CONTENT_ENCR = ContentType.new_flag('CONTENT_ENCR', 0x10D091)
-CONTENT_GONE = ContentType.new_flag('CONTENT_GONE', 0x18E344)
-CONTENT_KEY = ContentType.new_flag('CONTENT_KEY', 0x28463F)
-CONTENT_LINK = ContentType.new_flag('CONTENT_LINK', 0x2C834A)
-CONTENT_NACK = ContentType.new_flag('CONTENT_NACK', 0x34008A)
-
-class ContentObject(object):
-    def __init__(self, name = None, content = None, signed_info = None):
-        self.name = name
-        self.content = content
-
-        self.signedInfo = signed_info or SignedInfo()
-        self.digestAlgorithm = None # Default
-
-        # generated
-        self.signature = None
-        self.verified = False
-
-        # py-ndn
-        self.ccn = None # Reference to CCN object
-        self.ccn_data_dirty = True
-        self.ccn_data = None  # backing charbuf
-
-    # this is the finalization step
-    # must pass a key here, there is no "default key" because
-    # an NDN Face is not required to create the content object
-    # thus there is no access to the ccn library keystore.
-    #
-    def sign(self, key):
-        self.ccn_data = _ndn.encode_ContentObject(self, self.name.ccn_data, \
-            self.content, self.signedInfo.ccn_data, key)
-        self.ccn_data_dirty = False
-
-    def digest(self):
-        return _ndn.digest_contentobject(self.ccn_data)
-
-    def verify_content(self, handle):
-        return _ndn.verify_content(handle.ccn_data, self.ccn_data)
-
-    def verify_signature(self, key):
-        return _ndn.verify_signature(self.ccn_data, key.ccn_data_public)
-
-    def matchesInterest(self, interest):
-        return _ndn.content_matches_interest(self.ccn_data, interest.ccn_data)
-
-    def __setattr__(self, name, value):
-        if name == 'name' or name == 'content' or name == 'signedInfo' or name == 'digestAlgorithm':
-            self.ccn_data_dirty = True
-
-        if name == 'content':
-            object.__setattr__(self, name, _ndn.content_to_bytes(value))
-        else:
-            object.__setattr__(self, name, value)
-
-    def __getattribute__(self, name):
-        if name == "ccn_data":
-            if object.__getattribute__(self, 'ccn_data_dirty'):
-                raise _ndn.CCNContentObjectError("Call sign() to finalize \
-                    before accessing ccn_data for a ContentObject")
-        return object.__getattribute__(self, name)
-
-    # Where do we support versioning and segmentation?
-
-    def __str__(self):
-        ret = []
-        ret.append("Name: %s" % self.name)
-        ret.append("Content: %r" % self.content)
-        ret.append("DigestAlg: %r" % self.digestAlgorithm)
-        ret.append("SignedInfo: %s" % self.signedInfo)
-        ret.append("Signature: %s" % self.signature)
-        return "\n".join(ret)
-
-    def __repr__(self):
-        args = []
-
-        if self.name is not None:
-            args += ["name=%r" % self.name]
-
-        if self.content is not None:
-            args += ["content=%r" % self.content]
-
-        if self.signedInfo is not None:
-            args += ["signed_info=%r" % self.signedInfo]
-
-        if self.signature is not None:
-            args += ["<signed>"]
-
-        return "ndn.ContentObject(%s)" % ", ".join(args)
-
-    def get_ccnb(self):
-        return _ndn.dump_charbuf(self.ccn_data)
-
-        @staticmethod
-        def from_ccnb (ccnb):
-                return _ndn.ContentObject_obj_from_ccn_buffer (ccnb)
-
-class Signature(object):
-    def __init__(self):
-        self.digestAlgorithm = None
-        self.witness = None
-        self.signatureBits = None
-
-        # py-ndn
-        self.ccn_data_dirty = False
-        self.ccn_data = None
-
-    def __setattr__(self, name, value):
-        if name == 'witness' or name == 'signatureBits' or name == 'digestAlgorithm':
-            self.ccn_data_dirty = True
-        object.__setattr__(self, name, value)
-
-    def __getattribute__(self, name):
-        if name == "ccn_data":
-            if object.__getattribute__(self, 'ccn_data_dirty'):
-                self.ccn_data = _ndn.Signature_obj_to_ccn(self)
-                self.ccn_data_dirty = False
-        return object.__getattribute__(self, name)
-
-    def __str__(self):
-        res = []
-        res.append("digestAlgorithm = %s" % self.digestAlgorithm)
-        res.append("witness = %s" % self.witness)
-        res.append("signatureBits = %r" % self.signatureBits)
-        return "\n".join(res)
-
-class SignedInfo(object):
-    def __init__(self, key_digest = None, key_locator = None, type = CONTENT_DATA,
-            freshness = None, final_block = None, py_timestamp = None,
-            timestamp = None):
-
-        self.publisherPublicKeyDigest = key_digest
-
-        if py_timestamp is not None:
-            if timestamp:
-                raise ValueError("You can define only timestamp or py_timestamp")
-            self.timeStamp = utils.py2ccn_time(py_timestamp)
-        else:
-            self.timeStamp = timestamp
-
-        self.type = type
-        self.freshnessSeconds = freshness
-        self.finalBlockID = final_block
-        self.keyLocator = key_locator
-
-        # py-ndn
-        self.ccn_data_dirty = True
-        self.ccn_data = None  # backing charbuf
-
-    def __setattr__(self, name, value):
-        if name != "ccn_data" and name != "ccn_data_dirty":
-            self.ccn_data_dirty = True
-
-        if name == "type" and type(value) is not ContentType:
-            value = ContentType(value)
-
-        object.__setattr__(self, name, value)
-
-    def __getattribute__(self, name):
-        if name == "ccn_data":
-            if object.__getattribute__(self, 'ccn_data_dirty'):
-                key_locator = self.keyLocator.ccn_data if self.keyLocator else None
-                self.ccn_data = _ndn.SignedInfo_to_ccn(\
-                    self.publisherPublicKeyDigest, self.type, self.timeStamp, \
-                    self.freshnessSeconds or (-1), self.finalBlockID, key_locator)
-                self.ccn_data_dirty = False
-
-        if name == "py_timestamp":
-            ts = self.timeStamp
-            if ts is None:
-                return None
-            return None if ts is None else utils.ccn2py_time(ts)
-
-        return object.__getattribute__(self, name)
-
-    def __repr__(self):
-        args = []
-
-        if self.publisherPublicKeyDigest is not None:
-            args += ["key_digest=%r" % self.publisherPublicKeyDigest]
-        if self.keyLocator is not None:
-            args += ["key_locator=%r" % self.keyLocator]
-        if self.type is not None:
-            args += ["type=%r" % self.type]
-        if self.freshnessSeconds is not None:
-            args += ["freshness=%r" % self.freshnessSeconds]
-        if self.finalBlockID is not None:
-            args += ["final_block=%r" % self.finalBlockID]
-        if self.timeStamp is not None:
-            args += ["py_timestamp=%r" % self.py_timestamp]
-
-        return "ndn.SignedInfo(%s)" % ", ".join(args)
-
-#
-#
-# These are not used in signing in Python (all the info needed is in SignedInfo)
-# But it is here in case the parsing of the c library version of signing params
-# is needed.
-
-class SigningParams(object):
-    CCN_SP_TEMPL_TIMESTAMP = 0x0001
-    CCN_SP_TEMPL_FINAL_BLOCK_ID = 0x0002
-    CCN_SP_TEMPL_FRESHNESS = 0x0004
-    CCN_SP_TEMPL_KEY_LOCATOR = 0x0008
-    CCN_SP_FINAL_BLOCK = 0x0010
-    CCN_SP_OMIT_KEY_LOCATOR = 0x0020
-
-    def __init__(self):
-        self.flags;       # Use the CCN_SP flags above
-        self.type;        # Content type, really should be somewhere else, it's not that related to signing
-        self.freshness;
-
-        # These three are only relevant, for now, if they are coming *from* a c object
-        # otherwise, API version is filled in from CCN_SIGNING_PARAMS_INIT and
-        # both template and key will come from the ContentObject's SignedInfo object
-        self.apiVersion;
-        self.template;    # SignedInfo referred to by this content object,
-        self.key;         # Key to use - this should filled by a lookup against content object's signedinfo,
-
-        # py-ndn
-        self.ccn_data_dirty = False
-        self.ccn_data = None  # backing ccn_signing_params
-
-    def __setattr__(self, name, value):
-        if name != "ccn_data" and name != "ccn_data_dirty":
-            self.ccn_data_dirty = True
-        object.__setattr__(self, name, value)
-
-    def __getattribute__(self, name):
-        if name == "ccn_data":
-            if object.__getattribute__(self, 'ccn_data_dirty'):
-                self.ccn_data = _ndn._ndn_SigningParams_to_ccn(self)
-                self.ccn_data_dirty = False
-        return object.__getattribute__(self, name)
-
-    def __get_ccn(self):
-        pass
-        # Call ccn_signed_info_create
diff --git a/PyNDN/Data.py b/PyNDN/Data.py
new file mode 100644
index 0000000..8d92201
--- /dev/null
+++ b/PyNDN/Data.py
@@ -0,0 +1,126 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+# 
+# Copyright (c) 2011-2013, Regents of the University of California
+#                          Alexander Afanasyev
+# 
+# GNU 3.0 license, See the LICENSE file for more information
+# 
+# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+# 
+
+#
+# Based on PyCCN code, copyrighted and licensed as follows
+#
+# Copyright (c) 2011-2013, Regents of the University of California
+# BSD license, See the COPYING file for more information
+# Written by: Derek Kulinski <takeda@takeda.tk>
+#             Jeff Burke <jburke@ucla.edu>
+#
+
+import ns.ndnSIM
+from Name import Name
+
+class Data (object):
+    _data = None
+
+    def __init__(self,
+                 name = None, content = None, signed_info = None,
+                 data = None):
+        if data:
+            if type (data) is Data:
+                self._data = data._data
+            elif type (data) is ns.ndnSIM.ndn.ContentObject:
+                self._data = data
+            else:
+                raise TypeError ("Invalid type supplied for 'data' parameter [%s]" % type (data))
+        else:
+            self._data = ns.ndnSIM.ndn.ContentObject ()
+
+            self.name = name
+            self.content = content
+            self.signedInfo = signed_info or SignedInfo ()
+
+    def sign (self, key):
+        """There is no actual signing in ndnSIM for now, but we will assign signature bits based on key"""
+        self._data.SetSignature (key.fakeKey)
+
+    def verify_signature (self, key):
+        """There is no actual signing in ndnSIM for now, but we will check if signature matches the key"""
+        return self._data.GetSignature () == key.fakeKey
+
+    def __getattr__ (self, name):
+        if name == "signedInfo":
+            return object.__getattr__ (self, name)
+        elif name == "name":
+            return Name (self._data.GetName ())
+        elif name == "scope":
+            return self._data.GetScope ()
+        elif name == "interestLifetime":
+            return self._data.GetInterestLifetime ().ToDouble (ns.core.Time.S)
+        else:
+            return self._data.__getattribute__ (name)
+
+    def __setattr__(self, name, value):
+        if name == "_data":
+            return object.__setattr__ (self, name, value)
+        elif name == 'signedInfo':
+            if not value:
+                return
+            if type (value) is SignedInfo:
+                object.__setattr__ (self, name, value)
+                
+                if value.timestamp:
+                    pass
+                if value.freshnessSeconds:
+                    pass
+                if value.keyLocator:
+                    pass
+            else:
+                raise TypeError ("signedInfo can be assigned either None or SignedInfo object, [%s] supplied" % type (value))
+        elif name == "name":
+            if not value:
+                return self._data.SetName (ns.ndnSIM.ndn.Name ())
+            elif type (value) is Name:
+                return self._data.SetName (value._name)
+            elif type (value) is ns.ndnSIM.ndn.Name:
+                return self._data.SetName (value)
+            elif type (value) is str:
+                return self._data.SetName (ns.ndnSIM.ndn.Name (value))
+            else:
+                raise ValueError ("Invalid name parameter")
+        elif name == "content":
+            if not value:
+                pkt = ns.network.Packet ()
+                self._data.SetPayload (pkt)
+            else:
+                pkt = ns.network.Packet (bytes (value))
+                self._data.SetPayload (pkt)
+        else:
+            raise NameError ("Unknown attribute [%s]" % name)
+
+    def __repr__(self):
+        return "ndn.Data(%s)" % str (self._data)
+
+class SignedInfo (object):
+    def __init__(self, keyLocator = None, freshness = None, timestamp = None):
+
+        self.timestamp = timestamp
+        self.freshnessSeconds = freshness
+        self.keyLocator = keyLocator
+
+    def __repr__(self):
+        args = []
+
+        if self.keyLocator is not None:
+            args += ["keyLocator=%r" % self.keyLocator]
+        if self.freshnessSeconds is not None:
+            args += ["freshness=%r" % self.freshnessSeconds]
+        if self.timeStamp is not None:
+            args += ["timestamp=%r" % self.timestamp]
+
+        return "ndn.SignedInfo(%s)" % ", ".join(args)
+
+class ContentObject (Data):
+    """For backwards compatibility"""
+    pass
+
diff --git a/PyNDN/Face.py b/PyNDN/Face.py
index ebfeb5d..6186569 100644
--- a/PyNDN/Face.py
+++ b/PyNDN/Face.py
@@ -18,12 +18,17 @@
 #
 
 import ns.core
+import ns.network
 import ns.ndnSIM
+from Data import Data
+from Interest import Interest
+
+import functools
 
 class Face (ns.ndnSIM.ndn.ApiFace):
     def __init__(self):
         self.nodeId = ns.core.Simulator.GetContext ()
-        self.node = ns.core.NodeList.GetNode (self.nodeId)
+        self.node = ns.network.NodeList.GetNode (self.nodeId)
         super(Face, self).__init__ (self.node)
 
     def connect (self):
@@ -36,30 +41,58 @@
         pass
 
     def expressInterestSimple (self, name, onData, onTimeout, template = None):
-        if template:
-            interest = ns.ndnSIM.ndn.Interest (template)
-        else:
-            interest = ns.ndnSIM.ndn.Interest ()
+        """
+        onData:    void <interest, name>
+        onTimeout: void <interest>
+        """
 
-        interest.SetName (name)
-        self.ExpressInterest (interest, onData, onTimeout)
+        interest = Interest (interest = template)
+        interest.name = name
+
+        class OnDataConvert:
+            def __init__ (self, onData):
+                self.onData = onData
+            def __call__ (self, interest, data):
+                if self.onData:
+                    return self.onData (Interest (interest=interest), Data (data = data))
+        
+        class OnTimeoutConvert:
+            def __init__ (self, onTimeout):
+                self.onTimeout = onTimeout
+            def __call__ (self, interest):
+                if self.onTimeout:
+                    self.onTimeout (Interest (interest=interest))
+
+        self.ExpressInterest (interest, OnDataConvert (onData), OnTimeoutConvert (onTimeout))
 
     def setInterestFilterSimple (self, name, onInterest, flags = None):
-        self.SetInterestFilter (name, onInterest)
+        """
+        onInterest: void <name, interest>
+        """
 
-    def clearInterestFilter(self, name):
-        self.ClearInterestFilter (name)
+        class OnInterestConvert:
+            def __init__ (self, onInterest):
+                self.onInterest = onInterest
+            def __call__ (self, name, interest):
+                if self.onInterest:
+                    self.onInterest (Name (name = name), Interest (interest = interest))
 
-    def get(self, name, template = None, timeoutms = 3000):
-        raise ("NS-3 simulation cannot have syncrhonous operations")
+        self.SetInterestFilter (name, OnInterestConvert (onInterest))
 
-    def put(self, data):
+    def clearInterestFilter (self, name):
+        if type (name) is Name:
+            self.ClearInterestFilter (name._name)
+        elif type (name) is ns.ndnSIM.ndn.Name:
+            self.ClearInterestFilter (name)
+        else:
+            raise TypeError ("Wrong type for 'name' parameter [%s]" % type (name))
+
+    def get (self, name, template = None, timeoutms = 3000):
+        raise NotImplementedError ("NS-3 simulation cannot have syncrhonous operations")
+
+    def put (self, data):
         self.Put (data)
 
-    @staticmethod
-    def getDefaultKey ():
-        return None
-
 class EventLoop(object):
     def execute (self, event):
         ns.core.Simulator.ScheduleNow (event)
diff --git a/PyNDN/Interest.py b/PyNDN/Interest.py
index ddafb65..be1eacc 100644
--- a/PyNDN/Interest.py
+++ b/PyNDN/Interest.py
@@ -19,18 +19,27 @@
 
 import ns.ndnSIM
 import ns.core
-import Name
+from Name import Name
 
 class Interest (object):
     _interest = None
 
-    def __init__(self, name = None, 
-                 scope = None, interestLifetime = None):
-        self._interest = ns.ndnSIM.ndn.Interest ()
+    def __init__(self,
+                 name = None, scope = None, interestLifetime = None,
+                 interest = None):
+        if interest:
+            if type (interest) is Interest:
+                self._interest = interest._interest
+            elif type (interest) is ns.ndnSIM.ndn.Interest:
+                self._interest = interest
+            else:
+                raise TypeError ("Invalid type supplied for 'interest' parameter [%s]" % type (interest))
+        else:
+            self._interest = ns.ndnSIM.ndn.Interest ()
         
-        self.name = name
-        self.scope = scope
-        self.interestLifetime = interestLifetime
+            self.name = name
+            self.scope = scope
+            self.interestLifetime = interestLifetime
 
     def __getattr__ (self, name):
         if name == "name":
diff --git a/PyNDN/Key.py b/PyNDN/Key.py
index e57a846..b5c065b 100644
--- a/PyNDN/Key.py
+++ b/PyNDN/Key.py
@@ -17,128 +17,82 @@
 #             Jeff Burke <jburke@ucla.edu>
 #
 
-# Fronts ccn_pkey.
-from . import _ndn
-from . import Name
+import ns.core
+import ns.ndnSIM
+from Name import Name
 
 class Key(object):
-    def __init__(self):
-        self.type = None
-        self.publicKeyID = None # SHA256 hash
-        # ndn
-        self.ccn_data_dirty = False
-        self.ccn_data_public = None  # backing pkey
-        self.ccn_data_private = None # backing pkey
-
-    def __get_ccn(self):
-        pass
+    def __init__ (self):
+        # self.publicKeyID = None # SHA256 hash
+        self.fakeKey = None
 
     def generateRSA(self, numbits):
-        _ndn.generate_RSA_key(self, numbits)
+        randVar = ns.core.UniformVariable ()
+        self.fakeKey = randVar.GetInteger (0, 2147483647)
 
     def privateToDER(self):
-        if not self.ccn_data_private:
-            raise _ndn.CCNKeyError("Key is not private")
-        return _ndn.DER_write_key(self.ccn_data_private)
+        return self.fakeKey
 
     def publicToDER(self):
-        return _ndn.DER_write_key(self.ccn_data_public)
+        return self.privateToDER ()
 
     def privateToPEM(self, filename = None, password = None):
-        if not self.ccn_data_private:
-            raise _ndn.CCNKeyError("Key is not private")
-
         if filename:
             f = open(filename, 'w')
-            _ndn.PEM_write_key(self.ccn_data_private, file=f, password = password)
+            f.write (self.fakeKey)
             f.close()
         else:
-            return _ndn.PEM_write_key(self.ccn_data_private, password = password)
+            return self.fakeKey
 
     def publicToPEM(self, filename = None):
-        if filename:
-            f = open(filename, 'w')
-            _ndn.PEM_write_key(self.ccn_data_public, file=f)
-            f.close()
-        else:
-            return _ndn.PEM_write_key(self.ccn_data_public)
+        return privateToPEM (filename)
 
     def fromDER(self, private = None, public = None):
         if private:
-            (self.ccn_data_private, self.ccn_data_public, self.publicKeyID) = \
-                _ndn.DER_read_key(private=private)
-            return
-        if public:
-            (self.ccn_data_private, self.ccn_data_public, self.publicKeyID) = \
-                _ndn.DER_read_key(public=public)
-            return
+            self.fakeKey = private
+        elif public:
+            self.fakeKey = public
 
     def fromPEM(self, filename = None, private = None, public = None, password = None):
         if filename:
             f = open(filename, 'r')
-            (self.ccn_data_private, self.ccn_data_public, self.publicKeyID) = \
-                _ndn.PEM_read_key(file=f, password = password)
+            self.fakeKey = f.read ()
             f.close()
         elif private:
-            (self.ccn_data_private, self.ccn_data_public, self.publicKeyID) = \
-                _ndn.PEM_read_key(private=private, password = password)
+            self.fakeKey = private
         elif public:
-            (self.ccn_data_private, self.ccn_data_public, self.publicKeyID) = \
-                _ndn.PEM_read_key(public=public)
-
-        @staticmethod
-        def createFromDER (private = None, public = None):
-                key = Key ()
-                key.fromDER (private, public)
-                return key
-
-        @staticmethod
-        def createFromPEM (filename = None, private = None, public = None, password = None):
-                key = Key ()
-                key.fromPEM (filename, private, public, password)
-                return key
+            self.fakeKey = public
 
     @staticmethod
-    def getDefaultKey():
-        return _ndn.get_default_key()
+    def createFromDER (private = None, public = None):
+        key = Key ()
+        key.fromDER (private, public)
+        return key
 
-# plus library helper functions to generate and serialize keys?
+    @staticmethod
+    def createFromPEM (filename = None, private = None, public = None, password = None):
+        key = Key ()
+        key.fromPEM (filename, private, public, password)
+        return key
+
+    @staticmethod
+    def getDefaultKey ():
+        context = ns.core.Simulator.GetContext ()
+        key = Key ()
+        key.fakeKey = context
+        return key
+
 
 class KeyLocator(object):
-    def __init__(self, arg=None):
-        #whichever one is not none will be used
-        #if multiple set, checking order is: keyName, key, certificate
-        self.key = arg if type(arg) is Key else None
-        self.keyName = arg if type(arg) is Name.Name else None
-        self.certificate = None
+    def __init__(self, keyName = None):
+        self.keyName = keyName
 
-        # ndn
-        self.ccn_data_dirty = True
-        self.ccn_data = None  # backing charbuf
+    @staticmethod
+    def getDefaultKeyLocator():
+        context = ns.core.Simulator.GetContext ()
+        keyLocator = ns.ndnSIM.ndn.Name ()
+        keyLocator.\
+            append ("default-key").\
+            append (str (context))
 
-    def __setattr__(self, name, value):
-        if name != "ccn_data" and name != "ccn_data_dirty":
-            self.ccn_data_dirty = True
-        object.__setattr__(self, name, value)
-
-    def __getattribute__(self, name):
-        if name=="ccn_data":
-            if object.__getattribute__(self, 'ccn_data_dirty'):
-                if object.__getattribute__(self, 'keyName'):
-                    self.ccn_data = _ndn.KeyLocator_to_ccn(
-                        name=self.keyName.ccn_data)
-                elif object.__getattribute__(self, 'key'):
-                    self.ccn_data = _ndn.KeyLocator_to_ccn(
-                        key=self.key.ccn_data_public)
-                elif object.__getattribute__(self, 'certificate'):
-                    #same but with cert= arg
-                    raise NotImplementedError("certificate support is not implemented")
-                else:
-                    raise TypeError("No name, key nor certificate defined")
-
-                self.ccn_data_dirty = False
-        return object.__getattribute__(self, name)
-        
-        @staticmethod
-        def getDefaultKeyLocator():
-                return KeyLocator (_ndn.get_default_key_name ())
+        return Name (keyLocator)
diff --git a/PyNDN/Name.py b/PyNDN/Name.py
index a9aaa31..9112f0d 100644
--- a/PyNDN/Name.py
+++ b/PyNDN/Name.py
@@ -22,11 +22,21 @@
 class Name ():
     _name = None
 
-    def __init__ (self, value = None):
-        if value:
-            self._name = ns.ndnSIM.ndn.Name (value)
+    def __init__ (self, 
+                  value = None,
+                  name = None):
+        if name:
+            if type (name) is ns.ndnSIM.ndn.Name:
+                self._name = name
+            elif type (name) is Name:
+                self._name = name._name
+            else:
+                raise TypeError ("Incorrect type for 'name' parameter [%s]" % type (name))
         else:
-            self._name = ns.ndnSIM.ndn.Name ()
+            if value:
+                self._name = ns.ndnSIM.ndn.Name (value)
+            else:
+                self._name = ns.ndnSIM.ndn.Name ()
 
     @staticmethod
     def fromWire (wire):
diff --git a/PyNDN/NameCrypto.py b/PyNDN/NameCrypto.py
deleted file mode 100644
index 427db09..0000000
--- a/PyNDN/NameCrypto.py
+++ /dev/null
@@ -1,41 +0,0 @@
-## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-# 
-# Copyright (c) 2011-2013, Regents of the University of California
-#                          Alexander Afanasyev
-# 
-# GNU 3.0 license, See the LICENSE file for more information
-# 
-# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
-# 
-
-#
-# Based on PyCCN code, copyrighted and licensed as follows
-#
-# Copyright (c) 2011-2013, Regents of the University of California
-# BSD license, See the COPYING file for more information
-# Written by: Derek Kulinski <takeda@takeda.tk>
-#             Jeff Burke <jburke@ucla.edu>
-#
-
-from . import _ndn, Name
-
-def new_state():
-    return _ndn.nc_new_state()
-
-def generate_application_key(fixture_key, app_name):
-    app_id = _ndn.nc_app_id(app_name)
-    app_key = _ndn.nc_app_key(fixture_key, app_id)
-    return app_key
-
-def authenticate_command(state, name, app_name, app_key):
-    signed_name = _ndn.nc_authenticate_command(state, name.ccn_data, app_name, app_key)
-    return Name(ccn_data = signed_name)
-
-def authenticate_command_sig(state, name, app_name, key):
-    signed_name = _ndn.nc_authenticate_command_sig(state, name.ccn_data, app_name, key.ccn_data_private)
-    return Name(ccn_data = signed_name)
-
-def verify_command(state, name, max_time, **args):
-    if args.has_key('pub_key'): # TODO: use magic bytes to detect signature type, instead of asking caller to explicitly specify key type
-        args['pub_key'] = args['pub_key'].ccn_data_public
-    return _ndn.nc_verify_command(state, name.ccn_data, max_time, **args)
diff --git a/PyNDN/__init__.py b/PyNDN/__init__.py
index 8281cc1..0c0e288 100644
--- a/PyNDN/__init__.py
+++ b/PyNDN/__init__.py
@@ -17,22 +17,20 @@
 #             Jeff Burke <jburke@ucla.edu>
 #
 
-__all__ = ['Face', 'Closure', 'ContentObject', 'Interest', 'Key', 'Name']
+__all__ = ['Face', 'Name', 'Interest', 'Data', 'Key', 'ContentObject']
 
 VERSION = 0.3
+NDNSIM = True
 
-# import sys as _sys
+import sys as _sys
 
-# try:
-# 	from ndn.Face import *
-# 	from ndn.Closure import *
-# 	from ndn.ContentObject import *
-# 	from ndn.Interest import *
-# 	from ndn.Key import *
-# 	from ndn.Name import *
-# 	from ndn import NameCrypto
-#     from ndn.LocalPrefixDiscovery import *
+try:
+    from Face import Face, EventLoop
+    from Name import Name
+    from Interest import Interest
+    from Data import Data, ContentObject, SignedInfo
+    from Key import Key
 
-# except ImportError:
-# 	del _sys.modules[__name__]
-# 	raise
+except ImportError:
+    del _sys.modules[__name__]
+    raise