class CcnxSocket(object): ''' A socket like handler for ccnx operations. Runs a simple event loop and handles set interest filter, send interest, and publish data. Current only one ccnx handle is used, we can use multiple handles if needed, but there is no such need as of now. ''' __logger = Logger.get_logger('CcnxSocket') def __init__(self, *args, **kwargs): ''' Creates a socket. As of now, we try to get the ccnx key from the default location ''' super(CcnxSocket, self).__init__() self.ccnx_key = CCN.getDefaultKey() self.ccnx_key_locator = pyccn.KeyLocator(self.ccnx_key) self.ccnx_handle = CCN() self.event_loop = CcnxLoop(self.ccnx_handle) def get_signed_info(self, freshness): ''' Get signed info to be included in the Content Object Args: freshness (int): the freshness of the Content Object in seconds Returns: a PyCCN.SignedInfo object ''' si = pyccn.SignedInfo() si.publisherPublicKeyDigest = self.ccnx_key.publicKeyID si.type = pyccn.CONTENT_DATA si.freshnessSeconds = freshness si.keyLocator = self.ccnx_key_locator return si def get_pyccn_name(self, name): '''Get a valid name for PyCCN. This is useful when the name string is encoded as unicode, as is the usual case in Python. However, PyCCN has problem handling unicode names, raising TypeError as a result. Args: name (str): the name string Returns: An ascii encoded name string ''' if isinstance(name, unicode): return Name(name.encode('ascii', 'ignore')) else: return Name(name) def publish_content(self, name, content, freshness = 5): '''Publish the data as a Content Object Args: name (str): the name string content (bytes): the data bytes Kwargs: freshness (int): the freshness in seconds for the Content Object ''' co = ContentObject() co.name = self.get_pyccn_name(name) co.content = content si = self.get_signed_info(freshness) co.signedInfo = si co.sign(self.ccnx_key) self.ccnx_handle.put(co) def send_interest(self, name, closure, template = None): '''Send Interest Args: name (str): the name string closure (PyCCN.Closure): the closure that includes the callbacks to be used by PyCCN for this Interest Kwargs: template (PyCCN.Interest): the template for the additional field to be carried in the Interest, such as ChildSelector, Lifetime, AnswerOrigin, etc.. ''' n = self.get_pyccn_name(name) self.ccnx_handle.expressInterest(n, closure, template) def register_prefix(self, prefix, closure): '''Register the prefix under which the user wishes to receive Interests Args: prefix (str): the prefix name string closure (PyCCN.Closure): the closure that includes the callbacks to be used by PyCCN when an Interest with such prefix comes ''' p = self.get_pyccn_name(prefix) self.ccnx_handle.setInterestFilter(p, closure) def start(self): '''Start the CcnxLoop ''' start_new_thread(self.event_loop.run, ()) def stop(self): '''Stop the CcnxLoop ''' self.event_loop.stop()
upcall_called = True #receiver_handle.setRunTimeout(0) event_loop.stop() return pyccn.RESULT_OK senderclosure = SenderClosure() receiverclosure = ReceiverClosure() sender_handle = CCN() receiver_handle = CCN() #Looks like the CCNx API doesn't deliver messages #that we sent to ourselves, so we just push it sender_handle.setInterestFilter(n, senderclosure) #senderclosure.upcall(1, None) i = Interest() receiver_handle.expressInterest(n, receiverclosure, i) upcall_called = False print("Running loops") #So sender closure is called #sender_handle.run(500) #So receiver closure is called #receiver_handle.run(500)
class CcnxSocket(object): ''' A socket like handler for ccnx operations. Runs a simple event loop and handles set interest filter, send interest, and publish data. Current only one ccnx handle is used, we can use multiple handles if needed, but there is no such need as of now. ''' __logger = Logger.get_logger('CcnxSocket') def __init__(self, *args, **kwargs): ''' Creates a socket. As of now, we try to get the ccnx key from the default location ''' super(CcnxSocket, self).__init__() self.ccnx_key = CCN.getDefaultKey() self.ccnx_key_locator = pyccn.KeyLocator(self.ccnx_key) self.ccnx_handle = CCN() self.event_loop = CcnxLoop(self.ccnx_handle) def get_signed_info(self, freshness): ''' Get signed info to be included in the Content Object Args: freshness (int): the freshness of the Content Object in seconds Returns: a PyCCN.SignedInfo object ''' si = pyccn.SignedInfo() si.publisherPublicKeyDigest = self.ccnx_key.publicKeyID si.type = pyccn.CONTENT_DATA si.freshnessSeconds = freshness si.keyLocator = self.ccnx_key_locator return si def get_pyccn_name(self, name): '''Get a valid name for PyCCN. This is useful when the name string is encoded as unicode, as is the usual case in Python. However, PyCCN has problem handling unicode names, raising TypeError as a result. Args: name (str): the name string Returns: An ascii encoded name string ''' if isinstance(name, unicode): return Name(name.encode('ascii', 'ignore')) else: return Name(name) def publish_content(self, name, content, freshness=5): '''Publish the data as a Content Object Args: name (str): the name string content (bytes): the data bytes Kwargs: freshness (int): the freshness in seconds for the Content Object ''' co = ContentObject() co.name = self.get_pyccn_name(name) co.content = content si = self.get_signed_info(freshness) co.signedInfo = si co.sign(self.ccnx_key) self.ccnx_handle.put(co) def send_interest(self, name, closure, template=None): '''Send Interest Args: name (str): the name string closure (PyCCN.Closure): the closure that includes the callbacks to be used by PyCCN for this Interest Kwargs: template (PyCCN.Interest): the template for the additional field to be carried in the Interest, such as ChildSelector, Lifetime, AnswerOrigin, etc.. ''' n = self.get_pyccn_name(name) self.ccnx_handle.expressInterest(n, closure, template) def register_prefix(self, prefix, closure): '''Register the prefix under which the user wishes to receive Interests Args: prefix (str): the prefix name string closure (PyCCN.Closure): the closure that includes the callbacks to be used by PyCCN when an Interest with such prefix comes ''' p = self.get_pyccn_name(prefix) self.ccnx_handle.setInterestFilter(p, closure) def start(self): '''Start the CcnxLoop ''' start_new_thread(self.event_loop.run, ()) def stop(self): '''Stop the CcnxLoop ''' self.event_loop.stop()
class TyzxServer(Closure): def __init__(self, prefixstr ): self.handle = CCN() #XXX: temporary, until we allow fetching key from key storage self.key = self.handle.getDefaultKey() self.keylocator = KeyLocator(self.key) self.prefix = Name(prefixstr) # member_name = Name.Name(self.members_uri) # member_name.appendKeyID(fix_digest(self.key.publicKeyID)) # self.member_message = self.publish(member_name, nick) def listen(self): #listen to requests in namespace self.handle.setInterestFilter(self.prefix, self) self.handle.run(-1) def publish(self, name, content): # Name #print name # SignedInfo si = pyccn.SignedInfo() #si.type = pyccn.CCN_CONTENT_DATA si.type = 0x0C04C0 # content type si.finalBlockID = b'\x00' si.publisherPublicKeyDigest = self.key.publicKeyID si.keyLocator = self.keylocator si.freshnessSeconds = FRESHNESS_SECONDS # ContentObject co = ContentObject() co.content = content co.name = name co.signedInfo = si co.sign(self.key) return co def upcall(self, kind, upcallInfo): global lasttime if lasttime is None: # can't answer yet return pyccn.RESULT_OK if len(tyzxObjs.objs)<1: return pyccn.RESULT_OK interest = upcallInfo.Interest #print "Interest", interest.name, time.time() # CALL content matches interest to check exclusion on versions # #print interest.exclude name = interest.name #print name if name==self.prefix: # root #print "Request for root: %s" % str(name) if interest.exclude is None: freshids = tyzxObjs.objs.keys()[0:1] else: if len(interest.exclude.components) > 0: ids = set(tyzxObjs.objs.keys())# new stuff we have suffixes = set([int(str(s)[1:]) for s in interest.exclude.components]) freshids = list(ids.difference(suffixes)) # do we need this conversion? #print "ids", ids #print "suffixes", suffixes #print "freshids", freshids else: freshids = tyzxObjs.objs.keys()[0:1] if len(freshids)>0: child = freshids[0] else: return pyccn.RESULT_OK # no new content else: # should check what we're receiving! take next component child = int(name.components[-1:][0]) # why not be able to do this on name? #print "Request for child: %s" % child, time.time() #print "child - ", child if tyzxObjs.objs.has_key(child): O = tyzxObjs.objs[child] else: # Don't want to respond with a nonexistent. NDN way is to not answer interest. # If we've just started, we may not even know what the content store knows. # But, we do want to answer "exits" that we know about. #print "child", child, "is not present" if tyzxObjs.objExits.has_key(child): #print "child", child, "is exited" O = tyzxObjs.objExits[child] else: return pyccn.RESULT_OK #O = CompositeObject(BaseObject()) #O.time = lasttime.time #O.id = int(child) #O.status = "nonexistent" msgname = Name(self.prefix) msgname += str(child) msgname.components.append(versionFromTime (O.time)) # should have msgname.append #msgname.ccn_data_dirty=True - now handled within PyCCN # need binary add component self.message = self.publish(msgname, O.toJSON()) #print "Publishing", msgname, O.toJSON() #print "Present:", tyzxObjs.objs.keys(), time.time() self.handle.put(self.message) return pyccn.RESULT_INTEREST_CONSUMED return pyccn.RESULT_OK
class TyzxServer(Closure): def __init__(self, prefixstr): self.handle = CCN() #XXX: temporary, until we allow fetching key from key storage self.key = self.handle.getDefaultKey() self.keylocator = KeyLocator(self.key) self.prefix = Name(prefixstr) # member_name = Name.Name(self.members_uri) # member_name.appendKeyID(fix_digest(self.key.publicKeyID)) # self.member_message = self.publish(member_name, nick) def listen(self): #listen to requests in namespace self.handle.setInterestFilter(self.prefix, self) self.handle.run(-1) def publish(self, name, content): # Name #print name # SignedInfo si = pyccn.SignedInfo() #si.type = pyccn.CCN_CONTENT_DATA si.type = 0x0C04C0 # content type si.finalBlockID = b'\x00' si.publisherPublicKeyDigest = self.key.publicKeyID si.keyLocator = self.keylocator si.freshnessSeconds = FRESHNESS_SECONDS # ContentObject co = ContentObject() co.content = content co.name = name co.signedInfo = si co.sign(self.key) return co def upcall(self, kind, upcallInfo): global lasttime if lasttime is None: # can't answer yet return pyccn.RESULT_OK if len(tyzxObjs.objs) < 1: return pyccn.RESULT_OK interest = upcallInfo.Interest #print "Interest", interest.name, time.time() # CALL content matches interest to check exclusion on versions # #print interest.exclude name = interest.name #print name if name == self.prefix: # root #print "Request for root: %s" % str(name) if interest.exclude is None: freshids = tyzxObjs.objs.keys()[0:1] else: if len(interest.exclude.components) > 0: ids = set(tyzxObjs.objs.keys()) # new stuff we have suffixes = set( [int(str(s)[1:]) for s in interest.exclude.components]) freshids = list(ids.difference( suffixes)) # do we need this conversion? #print "ids", ids #print "suffixes", suffixes #print "freshids", freshids else: freshids = tyzxObjs.objs.keys()[0:1] if len(freshids) > 0: child = freshids[0] else: return pyccn.RESULT_OK # no new content else: # should check what we're receiving! take next component child = int( name.components[-1:][0]) # why not be able to do this on name? #print "Request for child: %s" % child, time.time() #print "child - ", child if tyzxObjs.objs.has_key(child): O = tyzxObjs.objs[child] else: # Don't want to respond with a nonexistent. NDN way is to not answer interest. # If we've just started, we may not even know what the content store knows. # But, we do want to answer "exits" that we know about. #print "child", child, "is not present" if tyzxObjs.objExits.has_key(child): #print "child", child, "is exited" O = tyzxObjs.objExits[child] else: return pyccn.RESULT_OK #O = CompositeObject(BaseObject()) #O.time = lasttime.time #O.id = int(child) #O.status = "nonexistent" msgname = Name(self.prefix) msgname += str(child) msgname.components.append(versionFromTime( O.time)) # should have msgname.append #msgname.ccn_data_dirty=True - now handled within PyCCN # need binary add component self.message = self.publish(msgname, O.toJSON()) #print "Publishing", msgname, O.toJSON() #print "Present:", tyzxObjs.objs.keys(), time.time() self.handle.put(self.message) return pyccn.RESULT_INTEREST_CONSUMED return pyccn.RESULT_OK