Build basic working structure of NDN-HOME

Change-Id: I56cdbac58407192ed9e79ec55f2196c20c2e952d
diff --git a/device.py b/device.py
new file mode 100644
index 0000000..4fa3540
--- /dev/null
+++ b/device.py
@@ -0,0 +1,177 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Regents of the University of California.
+# Author: Teng Liang <philoliang2011@gmail.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU General Public License is in the file COPYING.
+
+"""
+This module defines Device class, which contains core modules of end device, including device discovery protocol, syncronization protocol, and access control manager.
+"""
+
+
+import time
+import json
+from pyndn import Name, Face, Interest, Data
+from pyndn.threadsafe_face import ThreadsafeFace
+from pyndn import KeyLocator, KeyLocatorType
+from base_node import BaseNode
+from hmac_helper import HmacHelper 
+from pyndn.security.security_exception import SecurityException
+from pyndn.util import Blob
+try:
+    import asyncio
+except ImportError:
+    import trollius as asyncio
+
+def dump(*list):
+    result = ""
+    for element in list:
+        result += (element if type(element) is str else repr(element)) + " "
+    print(result)
+
+class Device(BaseNode):
+    def __init__(self,configFileName=None):
+        super(Device, self).__init__(configFileName)
+        
+        self._deviceSerial = self.getSerial()
+        self._callbackCount = 0
+        self._symKey = "symmetricKeyForBootstrapping"
+        self._category = "sensors"
+        self._id = "T9273659"
+        self._hmacHelper = HmacHelper(self._symKey)
+
+
+    def expressBootstrapInterest(self):
+        
+        #generate bootstrap name /home/controller/bootstrap/<device-parameters>
+        bootstrapName = Name(self._bootstrapPrefix)
+
+        deviceParameters = {}
+        deviceParameters["category"] = self._category
+        deviceParameters["id"] = self._id
+        bootstrapName.append(json.dumps(deviceParameters))
+
+        bootstrapInterest = Interest(bootstrapName)
+        bootstrapInterest.setInterestLifetimeMilliseconds(3000)
+        self._hmacHelper.signInterest(bootstrapInterest)
+
+        dump("Express bootstrap interest : ",bootstrapInterest.toUri())
+        self.face.expressInterest(bootstrapInterest, self.onBootstrapData, self.onTimeout)
+    
+    def onBootstrapData(self, interest, data):
+        dump("Bootstrap data received.")
+
+        if (self._hmacHelper.verifyData(data)):
+            self.log.info("Bootstrap data is verified")
+            content = json.loads(data.getContent().toRawStr(), encoding="latin-1")
+            deviceNewIdentity = Name(content["deviceNewIdentity"])
+            controllerIdentity = Name(content["controllerIdentity"])
+            controllerPublicKeyInfo = content["controllerPublicKey"]
+
+            self.face.registerPrefix(content["deviceNewIdentity"],self.onInterest,self.onRegisterFailed)
+            #set new identity as default and generate default key-pair with KSK Certificate
+            self._identityStorage.addIdentity(deviceNewIdentity)
+            self._identityManager.setDefaultIdentity(deviceNewIdentity)
+            try:
+                self._identityManager.getDefaultKeyNameForIdentity(deviceNewIdentity)
+            except SecurityException:
+                #generate new key-pair and certificate for new identity
+                dump("Install new identity as default\nGenerate new key-pair and self signed certificate")
+                newKey = self._identityManager.generateRSAKeyPairAsDefault(Name(deviceNewIdentity), isKsk=True)
+                newCert = self._identityManager.selfSign(newKey)
+                self._identityManager.addCertificateAsIdentityDefault(newCert)
+            
+            #add controller's identity and public key
+            keyType = controllerPublicKeyInfo["keyType"]
+            keyName = Name(controllerPublicKeyInfo["keyName"])
+            keyDer = Blob().fromRawStr(controllerPublicKeyInfo["publicKeyDer"])
+            dump("Controller's KeyType: ",keyType)
+            dump("Controller's keyName: ",keyName)
+            dump("Controller public key der : ",keyDer)
+
+            self._identityStorage.addIdentity(controllerIdentity)
+            try:
+                self._identityStorage.addKey(keyName, keyType, keyDer)
+                dump("Controller's identity, key and certificate installled.")
+            except SecurityException:
+                dump("Controller's identity, key, certificate already exists.")
+
+            #express an certificate request interest
+            defaultKeyName = self._identityManager.getDefaultKeyNameForIdentity(self._keyChain.getDefaultIdentity() )
+            self.requestCertificate(defaultKeyName)
+        else:
+            self.log.info("Bootstrap data is not verified")
+        
+        
+
+
+    def beforeLoopStart(self):
+        #self.face.registerPrefix('/home', self.onInterest, self.onRegisterFailed)
+        self.expressBootstrapInterest()
+        
+    def onTimeout(self, interest):
+        self._callbackCount += 1
+        dump("Time out for interest", interest.getName().toUri())
+
+    def onInterest():
+        pass
+    def onRegisterFailed():
+	pass
+
+#    def requestCertificate(self, keyIdentity):
+        """
+        We compose a command interest with our public key info so the controller
+        can sign us a certificate that can be used with other nodes in the network.
+        Name format : /home/<device-category>/KEY/<device-id>/<key-id>/<publickey>/ID-CERT/<version-number>
+        """
+"""        certificateRequestName = self._keyChain.getDefaultIdentity()
+        deviceIdComponent = certificateRequestName.get(-1)
+        keyIdComponent = keyIdentity.get(-1)
+
+        certificateRequestName = certificateRequestName
+        certificateRequestName.append("KEY")
+        #certificateRequestName.append(deviceIdComponent)
+        certificateRequestName.append(keyIdComponent)
+
+        key = self._identityManager.getPublicKey(keyIdentity)
+        keyInfo = {}
+        keyInfo["keyType"] = key.getKeyType()
+        keyInfo["keyDer"] = key.getKeyDer().toRawStr()
+
+        certificateRequestName.append(json.dumps(keyInfo, encoding="latin-1"))
+
+        certificateRequestName.append("ID-CERT")
+
+        certificateRequest = Interest(certificateRequestName)
+        certificateRequest.setInterestLifetimeMilliseconds(5000)
+        self._hmacHelper.signInterest(certificateRequest)
+        
+        dump("Sending certificate request : ",certificateRequestName)
+
+        self.face.expressInterest(certificateRequest, self.onCertificateData, self.onTimeout)
+        #TODO use symmetric key to sign
+        
+    def onCertificateData(self, interest, data):
+        dump("OnCertificateData : ",data)
+"""        
+
+if __name__ == '__main__':
+
+    device = Device()
+    device.start()
+    
+    
+