class BaseNode(object): """ This class contains methods/attributes common to both node and controller. """ def __init__(self, transport = None, conn = None): """ Initialize the network and security classes for the node """ super(BaseNode, self).__init__() self.faceTransport = transport self.faceConn = conn self._identityStorage = IotIdentityStorage() self._identityManager = IotIdentityManager(self._identityStorage) self._policyManager = IotPolicyManager(self._identityStorage) # hopefully there is some private/public key pair available self._keyChain = KeyChain(self._identityManager, self._policyManager) self._registrationFailures = 0 self._prepareLogging() self._setupComplete = False ## # Logging ## def _prepareLogging(self): self.log = logging.getLogger(str(self.__class__)) self.log.setLevel(logging.DEBUG) logFormat = "%(asctime)-15s %(name)-20s %(funcName)-20s (%(levelname)-8s):\n\t%(message)s" self._console = logging.StreamHandler() self._console.setFormatter(logging.Formatter(logFormat)) self._console.setLevel(logging.INFO) # without this, a lot of ThreadsafeFace errors get swallowed up logging.getLogger("trollius").addHandler(self._console) self.log.addHandler(self._console) def setLogLevel(self, level): """ Set the log level that will be output to standard error :param level: A log level constant defined in the logging module (e.g. logging.INFO) """ self._console.setLevel(level) def getLogger(self): """ :return: The logger associated with this node :rtype: logging.Logger """ return self.log ### # Startup and shutdown ### def beforeLoopStart(self): """ Called before the event loop starts. """ pass def getDefaultCertificateName(self): try: certName = self._identityStorage.getDefaultCertificateNameForIdentity( self._policyManager.getDeviceIdentity()) except SecurityException as e: # zhehao: in the case of producer's /localhop prefixes, the default key is not defined in ndnsec-public-info.db #print(e) certName = self._keyChain.getDefaultCertificateName() return certName def start(self): """ Begins the event loop. After this, the node's Face is set up and it can send/receive interests+data """ self.log.info("Starting up") self.loop = asyncio.get_event_loop() if (self.faceTransport == None or self.faceTransport == ''): self.face = ThreadsafeFace(self.loop) else: self.face = ThreadsafeFace(self.loop, self.faceTransport, self.faceConn) self.face.setCommandSigningInfo(self._keyChain, self.getDefaultCertificateName()) self._keyChain.setFace(self.face) self._isStopped = False self.beforeLoopStart() try: self.loop.run_forever() except Exception as e: self.log.exception(exc_info=True) finally: self.stop() def stop(self): """ Stops the node, taking it off the network """ self.log.info("Shutting down") self._isStopped = True self.loop.stop() ### # Data handling ### def signData(self, data): """ Sign the data with our network certificate :param pyndn.Data data: The data to sign """ self._keyChain.sign(data, self.getDefaultCertificateName()) def sendData(self, data, transport, sign=True): """ Reply to an interest with a data packet, optionally signing it. :param pyndn.Data data: The response data packet :param pyndn.Transport transport: The transport to send the data through. This is obtained from an incoming interest handler :param boolean sign: (optional, default=True) Whether the response must be signed. """ if sign: self.signData(data) transport.send(data.wireEncode().buf()) ### # # ## def onRegisterFailed(self, prefix): """ Called when the node cannot register its name with the forwarder :param pyndn.Name prefix: The network name that failed registration """ if self.faceTransport != None and self.faceConn != None: self.log.warn("Explicit face transport and connectionInfo: Could not register {}; expect a manual or autoreg on the other side.".format(prefix.toUri())) elif self._registrationFailures < 5: self._registrationFailures += 1 self.log.warn("Could not register {}, retry: {}/{}".format(prefix.toUri(), self._registrationFailures, 5)) self.face.registerPrefix(self.prefix, self._onCommandReceived, self.onRegisterFailed) else: self.log.info("Prefix registration failed") self.stop() def verificationFailed(self, dataOrInterest): """ Called when verification of a data packet or command interest fails. :param pyndn.Data or pyndn.Interest: The packet that could not be verified """ self.log.info("Received invalid" + dataOrInterest.getName().toUri()) @staticmethod def getSerial(): """ Find and return the serial number of the Raspberry Pi. Provided in case you wish to distinguish data from nodes with the same name by serial. :return: The serial number extracted from device information in /proc/cpuinfo :rtype: str """ with open('/proc/cpuinfo') as f: for line in f: if line.startswith('Serial'): return line.split(':')[1].strip()
url = urlparse(hub['site']) if (hub['shortname'] not in ['UCLA', 'LIP6']): continue print("Registering", hub['shortname'], "hostname:", url.hostname) face = ThreadsafeFace(loop, url.hostname) face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) facePrefix = Name(PREFIX + hub['shortname']) print("Face:", facePrefix) #shadowing to replace the default PyNDN function that does not support passing options # setOrigin(65) must be included to propagate the prefix to other nodes face._node._nfdRegisterPrefix = types.MethodType(nfdRegisterPrefix, face._node) face.registerPrefix(facePrefix, onInterest, onRegisterFailed, onRegisterSuccess=onRegisterSuccess) faces[facePrefix] = face #schedule pings later, so that prefixes have some time to register and propagate print("Starting pinging") loop.call_later(30, schedulePings) #signal handling for clean shutdown signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT) for s in signals: loop.add_signal_handler(s, lambda s=s: loop.create_task(shutdown(s, loop))) loop.run_forever() print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~FINISHING~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
class BaseNode(object): """ This class contains methods/attributes common to both node and controller. """ def __init__(self, transport = None, conn = None): """ Initialize the network and security classes for the node """ super(BaseNode, self).__init__() self.faceTransport = transport self.faceConn = conn self._identityStorage = BasicIdentityStorage() self._identityManager = IdentityManager(self._identityStorage, FilePrivateKeyStorage()) self._policyManager = IotPolicyManager(self._identityStorage) # hopefully there is some private/public key pair available self._keyChain = KeyChain(self._identityManager, self._policyManager) self._registrationFailures = 0 self._prepareLogging() self._setupComplete = False ## # Logging ## def _prepareLogging(self): self.log = logging.getLogger(str(self.__class__)) self.log.setLevel(logging.DEBUG) logFormat = "%(asctime)-15s %(name)-20s %(funcName)-20s (%(levelname)-8s):\n\t%(message)s" self._console = logging.StreamHandler() self._console.setFormatter(logging.Formatter(logFormat)) self._console.setLevel(logging.INFO) # without this, a lot of ThreadsafeFace errors get swallowed up logging.getLogger("trollius").addHandler(self._console) self.log.addHandler(self._console) def setLogLevel(self, level): """ Set the log level that will be output to standard error :param level: A log level constant defined in the logging module (e.g. logging.INFO) """ self._console.setLevel(level) def getLogger(self): """ :return: The logger associated with this node :rtype: logging.Logger """ return self.log ### # Startup and shutdown ### def beforeLoopStart(self): """ Called before the event loop starts. """ pass def getDefaultCertificateName(self): try: certName = self._identityStorage.getDefaultCertificateNameForIdentity( self._policyManager.getDeviceIdentity()) except SecurityException as e: # zhehao: in the case of producer's /localhop prefixes, the default key is not defined in ndnsec-public-info.db certName = self._keyChain.createIdentityAndCertificate(self._policyManager.getDeviceIdentity()) #certName = self._keyChain.getDefaultCertificateName() #print(certName.toUri()) return certName def start(self): """ Begins the event loop. After this, the node's Face is set up and it can send/receive interests+data """ self.log.info("Starting up") self.loop = asyncio.get_event_loop() if (self.faceTransport == None or self.faceTransport == ''): self.face = ThreadsafeFace(self.loop) else: self.face = ThreadsafeFace(self.loop, self.faceTransport, self.faceConn) self.face.setCommandSigningInfo(self._keyChain, self.getDefaultCertificateName()) self._keyChain.setFace(self.face) self._isStopped = False self.beforeLoopStart() try: self.loop.run_forever() except Exception as e: self.log.exception(exc_info=True) finally: self.stop() def stop(self): """ Stops the node, taking it off the network """ self.log.info("Shutting down") self._isStopped = True self.loop.stop() ### # Data handling ### def signData(self, data): """ Sign the data with our network certificate :param pyndn.Data data: The data to sign """ self._keyChain.sign(data, self.getDefaultCertificateName()) def sendData(self, data, sign=True): """ Reply to an interest with a data packet, optionally signing it. :param pyndn.Data data: The response data packet :param boolean sign: (optional, default=True) Whether the response must be signed. """ if sign: self.signData(data) self.face.putData(data) ### # # ## def onRegisterFailed(self, prefix): """ Called when the node cannot register its name with the forwarder :param pyndn.Name prefix: The network name that failed registration """ if self.faceTransport != None and self.faceConn != None: self.log.warn("Explicit face transport and connectionInfo: Could not register {}; expect a manual or autoreg on the other side.".format(prefix.toUri())) elif self._registrationFailures < 5: self._registrationFailures += 1 self.log.warn("Could not register {}, retry: {}/{}".format(prefix.toUri(), self._registrationFailures, 5)) self.face.registerPrefix(self.prefix, self._onCommandReceived, self.onRegisterFailed) else: self.log.info("Prefix registration failed") self.stop() def verificationFailed(self, dataOrInterest): """ Called when verification of a data packet or command interest fails. :param pyndn.Data or pyndn.Interest: The packet that could not be verified """ self.log.info("Received invalid" + dataOrInterest.getName().toUri()) @staticmethod def getSerial(): """ Find and return the serial number of the Raspberry Pi. Provided in case you wish to distinguish data from nodes with the same name by serial. :return: The serial number extracted from device information in /proc/cpuinfo :rtype: str """ try: with open('/proc/cpuinfo') as f: for line in f: if line.startswith('Serial'): return line.split(':')[1].strip() except NameError: return "todo"
#TODO: Test if DB not initialized, else do #first_run() timestamp = int(time.time()) #sys.exit(1) testbed_json = json.load(open(request.urlretrieve("http://ndndemo.arl.wustl.edu/testbed-nodes.json")[0], "r")) #Initialize keychain keychain = KeyChain() loop = asyncio.get_event_loop() # loop.call_soon(destroy) # loop.run_forever() for hub_name in testbed_json.keys(): hub = testbed_json[hub_name] valid_prefixes = Name(PREFIX + hub["shortname"]) for hub_name in testbed_json.keys(): hub = testbed_json[hub_name] print("Adding faces to hub: {}".format(hub["name"])) face_base = hub["site"].strip("http").replace(":80/",":6363") for protocol in PROTOCOLS: face = ThreadsafeFace(loop, "{}{}".format(protocol, hub)) face.setCommandSigningInfo(keychain, keychain.getDefaultCertificateName()) prefix = Name(PREFIX + hub["shortname"]) options = RegistrationOptions().setOrigin(65) face.registerPrefix(prefix, onInterest, onRegisterFailed, onRegisterSuccess=registration, registrationOptions=options) time.sleep(2) print("Begin ping") loop.call_soon(schedulePings, prefix) loop.run_forever() #time.sleep(30) conn.close()
class Flask(): def __init__(self, host): self.__name__ = __name__ self.keyChain = KeyChain() self.isDone = False self.counter = 0 loop = asyncio.get_event_loop() self.face = ThreadsafeFace(loop, host) self.a = {} self.methods = {} def route(self, uri, methods): self.baseName = ndn.Name(uri) self.methods[self.baseName] = methods[0] return self.dec def onInterest(self, prefix, interest, *k): print >> sys.stderr, "<< PyNDN %s" % interest.name print prefix d = self.a[prefix] if self.methods[prefix] == "POST": content = json.dumps( d(interest.getContent().toRawStr().decode('string_escape'))) else: content = json.dumps(d()) self.counter += 1 #print interest.getContent().toRawStr().decode('string_escape') data = ndn.Data(interest.getName()) meta = ndn.MetaInfo() meta.setFreshnessPeriod(5000) data.setMetaInfo(meta) data.setContent(content) self.keyChain.sign(data, self.keyChain.getDefaultCertificateName()) self.face.putData(data) def _onRegisterFailed(self, prefix): print >> sys.stderr, "<< PyNDN: failed to register prefix" def run(self): root = logging.getLogger() root.setLevel(logging.DEBUG) ch = logging.StreamHandler(sys.stdout) ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) root.addHandler(ch) loop = asyncio.get_event_loop() #face = ThreadsafeFace(loop, "172.17.0.1") #face = ndn.Face("172.17.0.1","6363") server = Server(self.face) loop.run_forever() face.shutdown() def dec(self, func): self.a[self.baseName] = func print self.a self.face.registerPrefix( self.baseName, self.onInterest, self._onRegisterFailed, )
class Flask(): def __init__(self, host): self.__name__ = __name__ self.keyChain = KeyChain() self.isDone = False self.counter = 0 loop = asyncio.get_event_loop() self.face = ThreadsafeFace(loop, host) self.a = {} self.methods = {} def route(self, uri, methods): prefix = uri if bool(re.search('<(.*)>', prefix)): self.baseName = ndn.Name( re.sub('<(.*)>', methods[0] + '/<data>', prefix)) else: self.baseName = ndn.Name(prefix + "/" + methods[0]) self.methods[self.baseName.toUri()] = methods[0] return self.dec def onInterest(self, prefix, interest, *k): print >> sys.stderr, "<< PyNDN %s" % interest.name intrestUri = interest.name.toUri() prefixUri = prefix.toUri() parameters = '' if intrestUri != prefixUri: parameters = intrestUri[len(prefixUri) + 1:] print prefixUri += "/%3Cdata%3E" d = self.a[prefixUri] if self.methods[prefixUri] == "POST": content = json.dumps( d(interest.getContent().toRawStr().decode('string_escape'))) else: if parameters: content = json.dumps(d(parameters)) else: content = json.dumps(d()) self.counter += 1 data = ndn.Data(interest.getName()) meta = ndn.MetaInfo() meta.setFreshnessPeriod(5000) data.setMetaInfo(meta) data.setContent(content) self.keyChain.sign(data, self.keyChain.getDefaultCertificateName()) self.face.putData(data) def _onRegisterFailed(self, prefix): print >> sys.stderr, "<< PyNDN: failed to register prefix" def run(self): root = logging.getLogger() root.setLevel(logging.DEBUG) ch = logging.StreamHandler(sys.stdout) ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) root.addHandler(ch) loop = asyncio.get_event_loop() server = Server(self.face) loop.run_forever() self.face.shutdown() def dec(self, func): self.a[self.baseName.toUri()] = func self.face.registerPrefix( self.baseName, self.onInterest, self._onRegisterFailed, )