Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
    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~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
Ejemplo n.º 3
0
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"
Ejemplo n.º 4
0
#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()
Ejemplo n.º 5
0
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,
        )
Ejemplo n.º 6
0
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,
        )