modified:   controller.py
	modified:   end-device.py
	new file:   test_get_async_threadsafe.py
diff --git a/controller.py b/controller.py
index 64d4119..d41bb1d 100644
--- a/controller.py
+++ b/controller.py
@@ -20,16 +20,16 @@
 
 import time
 import json
-from pyndn import Name
-from pyndn import Data
-from pyndn import Face
+from pyndn import Name, Face, Interest, Data
 from pyndn.key_locator import KeyLocator, KeyLocatorType
+from hmac_helper import HmacHelper 
 
 from pyndn.security import KeyChain
 from base_node import BaseNode
 from pyndn.security import SecurityException
 from pyndn.util import Blob
 
+
 def dump(*list):
     result = ""
     for element in list:
@@ -43,14 +43,19 @@
         self._symmetricKey = "symmetricKeyForBootstrapping"
         self._prefix = "/home"
         self._identity = "/home/controller/id999"
+        self._hmacHelper = HmacHelper(self._symmetricKey)
+
+    def setFace(self,face):
+        self.face = face
 
     def onInterest(self, prefix, interest, transport, registeredPrefixId):
         self._responseCount += 1
-
         interestName = interest.getName()
+	dump("received interest : ",interestName.toUri())
 
         #for bootstrap interest
-        if(interestName.toUri().startswith(self._bootstrapPrefix) and interest.getKeyLocator().getKeyData().toRawStr() == self._symmetricKey):
+        #if(interestName.toUri().startswith(self._bootstrapPrefix) and interest.getKeyLocator().getKeyData().toRawStr() == self._symmetricKey):
+        if(interestName.toUri().startswith(self._bootstrapPrefix) and self._hmacHelper.verifyInterest(interest)):
             dump("Reveived bootstrap interest")
 	    self.onBootstrapInterest(prefix, interest, transport, registeredPrefixId)   
         
@@ -59,69 +64,87 @@
             self.onCertificateRequest(prefix, interest, transport, registeredPrefixId)
 
     def onBootstrapInterest(self, prefix, interest, transport, registeredPrefixId):
+        if (self._hmacHelper.verifyInterest(interest)):
+            self.log.info("Bootstrap interest verified")
+            interestName = interest.getName()
+            deviceParameters = json.loads(interestName.get(3).getValue().toRawStr())
+            deviceNewIdentity = Name("/home")
+                
+            #create new identity for device
+            deviceNewIdentity.append(deviceParameters["category"])
+            deviceNewIdentity.append(deviceParameters["id"])
+                
+            #generate content
+            content = {}
+            content["deviceNewIdentity"] = deviceNewIdentity.toUri()
+            content["controllerIdentity"] = self._identity
+
+            #get public key of controller
+            pKeyName = self._identityManager.getDefaultKeyNameForIdentity(self._identityManager.getDefaultIdentity())
+            pKey = self._identityManager.getPublicKey(pKeyName)
+
+            pKeyInfo = content["controllerPublicKey"] = {}
+            pKeyInfo["keyName"] = pKeyName.toUri()
+            pKeyInfo["keyType"] = pKey.getKeyType()
+            pKeyInfo["publicKeyDer"] = pKey.getKeyDer().toRawStr()
+            dump("Sent content : ",content)
+                  
+            #TODO generate signature for data
+                
+            #generate data package
+            data = Data(interestName)
+            data.setContent(json.dumps(content,encoding="latin-1"))
+            #data.setSignature(signature)
+	    self._hmacHelper.signData(data)
+
+            #encodedData = data.wireEncode()
+            #transport.send(encodedData.toBuffer())
+            self.sendData(data,transport,sign=False)
+        else: 
+            self.log.info("Bootstrap interest not verified")
         
-        interestName = interest.getName()
-        deviceParameters = json.loads(interestName.get(3).getValue().toRawStr())
-        deviceNewIdentity = Name("/home")
-            
-        #create new identity for device
-        deviceNewIdentity.append(deviceParameters["category"])
-        deviceNewIdentity.append(deviceParameters["id"])
-            
-        #generate content
-        content = {}
-        content["deviceNewIdentity"] = deviceNewIdentity.toUri()
-        content["controllerIdentity"] = self._identity
-
-        #get public key of controller
-        pKeyName = self._identityManager.getDefaultKeyNameForIdentity(self._identityManager.getDefaultIdentity())
-        pKey = self._identityManager.getPublicKey(pKeyName)
-
-        pKeyInfo = content["controllerPublicKey"] = {}
-        pKeyInfo["keyName"] = pKeyName.toUri()
-        pKeyInfo["keyType"] = pKey.getKeyType()
-        pKeyInfo["publicKeyDer"] = pKey.getKeyDer().toRawStr()
-        dump("Sent content : ",content)
-              
-        #TODO generate signature for data
-            
-        #generate data package
-        data = Data(interestName)
-        data.setContent(json.dumps(content,encoding="latin-1"))
-        #data.setSignature(signature)
-        encodedData = data.wireEncode()
-        transport.send(encodedData.toBuffer())
+    
 
 
     def onCertificateRequest(self, prefix, interest, transport, registeredPrefixId):
-        interestName = interest.getName()
-        dump("interest name : ",interestName)
+        if (self._hmacHelper.verifyInterest(interest)):
+            self.log.info("certificate request interest verified")
+            interestName = interest.getName()
+            dump("interest name : ",interestName)
+            
+            keyName = interestName[:3]
+            keyId = interestName.get(4)
+            keyName.append(keyId)
+            keyInfo = json.loads(interestName.get(5).getValue().toRawStr(),encoding="latin-1")
+            keyType = keyInfo['keyType']
+            keyDer = Blob().fromRawStr(keyInfo['keyDer'])
+
+            #dump("keyname: ",keyName)
+            dump("keyType ",keyInfo['keyType'])
+            dump("keyDer string",keyInfo['keyDer'])
+            dump("keyDer",keyDer)
+
+            #device and controller are on one mechine, so it needs to be done.
+            self._identityManager.setDefaultIdentity(Name(self._identity))
+            try:
+                self._identityStorage.addKey(keyName, keyType, keyDer)
+            except SecurityException:
+                dump("The public key for device already exists ")
+
+            signedCertificate = self._identityManager._generateCertificateForKey(keyName)
+            self._keyChain.sign(signedCertificate, self._identityManager.getDefaultCertificateName())
+            self._identityManager.addCertificate(signedCertificate)
+            #self._hmacHelper.signData()
+
+            #encodedData = signedCertificate.wireEncode()
+            #transport.send(encodedData.toBuffer())
+	    self.sendData(signedCertificate,transport,sign=False)
+
+	    self.log.info("Certificate sent back : {}".format(signedCertificate.__str__))
+	    print(signedCertificate)
+        else:
+            self.log.info("certificate request interest not verified")
         
-        keyName = interestName[:3]
-        keyId = interestName.get(4)
-        keyName.append(keyId)
-        keyInfo = json.loads(interestName.get(5).getValue().toRawStr(),encoding="latin-1")
-        keyType = keyInfo['keyType']
-        keyDer = Blob().fromRawStr(keyInfo['keyDer'])
-
-        dump("keyname: ",keyName)
-        dump("keyType ",keyInfo['keyType'])
-        dump("keyDer string",keyInfo['keyDer'])
-        dump("keyDer",keyDer)
-
-        #device and controller are on one mechine, so it needs to be done.
-        self._identityManager.setDefaultIdentity(Name(self._identity))
-        try:
-            self._identityStorage.addKey(keyName, keyType, keyDer)
-        except SecurityException:
-            dump("The public key for device already exists ")
-
-        signedCertificate = self._identityManager._generateCertificateForKey(keyName)
-        self._keyChain.sign(signedCertificate, self._identityManager.getDefaultCertificateName())
-        self._identityManager.addCertificate(signedCertificate)
-        
-        encodedData = signedCertificate.wireEncode()
-        transport.send(encodedData.toBuffer())
 
 
     def onRegisterFailed(self, prefix):
@@ -154,28 +177,34 @@
                 dump("generated new KSK certificate ", newCert)
                 self._identityManager.addCertificateAsIdentityDefault(newCert)
 
-        
+        #self.face.setCommandSigningInfo(self._keyChain, self.getDefaultCertificateName())
         #self.face.registerPrefix(self._prefix, self.onInterest, self.onRegisterFailed)
+        
+        
 
 
 if __name__ == '__main__':
 
     controller = Controller("default.conf")
+    #controller.start()
     controller.beforeLoopStart()
+    
 
     face = Face()
-    face.setCommandSigningInfo(controller._keyChain, controller._keyChain.getDefaultCertificateName())
-    dump("Register prefix : ", controller._prefix)
-    face.registerPrefix(controller._prefix, controller.onInterest, controller.onRegisterFailed)
+    controller.setFace(face)
 
+    face.setCommandSigningInfo(controller._keyChain, controller.getDefaultCertificateName())
+    face.registerPrefix(controller._prefix, controller.onInterest, controller.onRegisterFailed)
+    dump("Register prefix : ",controller._prefix)
     while True:
         face.processEvents()
-        # We need to sleep for a few milliseconds so we don't use 100% of the CPU.
-        time.sleep(0.01)
+	time.sleep(0.05)
 
     face.shutdown()
 
 
+
+
     
 
 
diff --git a/end-device.py b/end-device.py
index fb97a23..a77dc47 100644
--- a/end-device.py
+++ b/end-device.py
@@ -22,6 +22,7 @@
 from pyndn import Name, Face, Interest, Data, 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:
@@ -44,6 +45,7 @@
         self._symKey = "symmetricKeyForBootstrapping"
         self._category = "sensors"
         self._id = "T9273659"
+        self._hmacHelper = HmacHelper(self._symKey)
 
 
     def expressBootstrapInterest(self):
@@ -53,59 +55,73 @@
 
         deviceParameters = {}
         deviceParameters["category"] = self._category
-        deviceParameters["id"] = self._deviceSerial
+        deviceParameters["id"] = self._id
         bootstrapName.append(json.dumps(deviceParameters))
 
         bootstrapInterest = Interest(bootstrapName)
         bootstrapInterest.setInterestLifetimeMilliseconds(5000)
-        bootstrapKeyLocator = KeyLocator()
-        bootstrapKeyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST)
-        bootstrapKeyLocator.setKeyData(self._symKey)
-        bootstrapInterest.setKeyLocator(bootstrapKeyLocator)
+        #bootstrapKeyLocator = KeyLocator()
+        #bootstrapKeyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST)
+        #bootstrapKeyLocator.setKeyData(self._symKey)
+        #bootstrapInterest.setKeyLocator(bootstrapKeyLocator)
+        self._hmacHelper.signInterest(bootstrapInterest)
 
         dump("Express bootstrap interest : ",bootstrapInterest.toUri())
         self.face.expressInterest(bootstrapInterest, self.onBootstrapData, self.onTimeout)
+    def onInterest():
+        pass
+    def onRegisterFailed():
+	pass
     
     def onBootstrapData(self, interest, data):
         dump("Bootstrap data received.")
-        content = json.loads(data.getContent().toRawStr(), encoding="latin-1")
-        deviceNewIdentity = Name(content["deviceNewIdentity"])
-        controllerIdentity = Name(content["controllerIdentity"])
-        controllerPublicKeyInfo = content["controllerPublicKey"]
 
-        #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)
+        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")
         
-        #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)
+        
 
 
     def beforeLoopStart(self):
+        #self.face.registerPrefix('/', self.onInterest, self.onRegisterFailed)
         self.expressBootstrapInterest()
         
     def onTimeout(self, interest):
@@ -135,10 +151,14 @@
         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(Interest(certificateRequestName), self.onCertificateData, self.onTimeout)
+        self.face.expressInterest(certificateRequest, self.onCertificateData, self.onTimeout)
         #TODO use symmetric key to sign
         
     def onCertificateData(self, interest, data):
@@ -147,7 +167,7 @@
 
 if __name__ == '__main__':
 
-    device = Device("default.conf")
+    device = Device("tmp.conf")
     device.start()
     
     
diff --git a/test_get_async_threadsafe.py b/test_get_async_threadsafe.py
new file mode 100644
index 0000000..fd1602e
--- /dev/null
+++ b/test_get_async_threadsafe.py
@@ -0,0 +1,73 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014-2015 Regents of the University of California.
+# Author: Jeff Thompson <jefft0@remap.ucla.edu>
+#
+# 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU Lesser General Public License is in the file COPYING.
+
+try:
+    # Use builtin asyncio on Python 3.4+, or Tulip on Python 3.3
+    import asyncio
+except ImportError:
+    # Use Trollius on Python <= 3.2
+    import trollius as asyncio
+from pyndn import Name
+from pyndn import ThreadsafeFace
+
+def dump(*list):
+    result = ""
+    for element in list:
+        result += (element if type(element) is str else repr(element)) + " "
+    print(result)
+
+class Counter(object):
+    def __init__(self):
+        self._callbackCount = 0
+
+    def onData(self, interest, data):
+        self._callbackCount += 1
+        dump("Got data packet with name", data.getName().toUri())
+        # Use join to convert each byte to chr.
+        dump(data.getContent().toRawStr())
+
+    def onTimeout(self, interest):
+        self._callbackCount += 1
+        dump("Time out for interest", interest.getName().toUri())
+    
+    def onInterest(self,prefix,interest,face,interestFilterId,filter):
+        self._callbackCount+=1
+	dump("Receive interest", interest.toUri())
+
+    def onRegisterFailed(self,prefix):
+        dump("Register failed for prefix")
+
+def main():
+    loop = asyncio.get_event_loop()
+    face = ThreadsafeFace(loop, "aleph.ndn.ucla.edu")
+
+    counter = Counter()
+    face.stopWhen(lambda: counter._callbackCount >= 10)
+	
+    face.registerPrefix("/home",counter.onInterest,counter.onRegisterFailed)
+    #name1 = Name("/")
+    #dump("Express name ", name1.toUri())
+    # This call to exressIinterest is thread safe because face is a ThreadsafeFace.
+    #face.expressInterest(name1, counter.onData, counter.onTimeout)
+
+    # Run until stopWhen stops the loop.
+    loop.run_forever()
+    face.shutdown()
+
+main()