def __init__(self, main, parent_n): self.main = main self.parent_n = parent_n self.blocks = {} # {hash: [None | data]} self.hashlist = [] self.status_pktnum = None self.topic_flag = False self.moderated = False self.last_assembled_pktnum = None self.nicks = {} # {nick: NickNode()} self.bans = {} # {(ip,mask): Ban()} # Tuple of info strings; indices match up with the nick modes self.infostrings = () self.req_blocks = RandSet() self.requestBlocks_dcall = None # Register me in BridgeClientManager self.main.osm.bcm.bridges.add(self)
class BridgeNodeData(object): class Ban(object): def __init__(self, ipmask, enable, pktnum): self.ipmask = ipmask self.enable = enable self.pktnum = pktnum def __init__(self, main, parent_n): self.main = main self.parent_n = parent_n self.blocks = {} # {hash: [None | data]} self.hashlist = [] self.status_pktnum = None self.topic_flag = False self.moderated = False self.last_assembled_pktnum = None self.nicks = {} # {nick: NickNode()} self.bans = {} # {(ip,mask): Ban()} # Tuple of info strings; indices match up with the nick modes self.infostrings = () self.req_blocks = RandSet() self.requestBlocks_dcall = None # Register me in BridgeClientManager self.main.osm.bcm.bridges.add(self) def setHashList(self, hashlist, do_request): self.hashlist = hashlist self.blocks = dict.fromkeys(self.hashlist, None) bcm = self.main.osm.bcm # Start with no requested blocks self.req_blocks.clear() for bhash in self.blocks: try: bk = bcm.unclaimed_blocks.pop((self.parent_n.ipp, bhash)) except KeyError: # If we're requesting blocks, then add this to the list if do_request: self.req_blocks.add(bhash) else: bk.expire_dcall.cancel() self.blocks[bhash] = bk.data self.assembleBlocks() # Start requesting blocks (if any) self.scheduleRequestBlocks() def scheduleRequestBlocks(self): # After we receive a sync reply from the bridge, individually # request the full data for each block hash. dcall_discard(self, 'requestBlocks_dcall') if not self.req_blocks: return def cb(timeout): self.requestBlocks_dcall = None # Pick one of the hashes randomly try: bhash = self.req_blocks.peek() except KeyError: return # Build request packet packet = ['bQ'] packet.append(self.main.osm.me.ipp) packet.append(bhash) # Send to bridge ad = Ad().setRawIPPort(self.parent_n.ipp) self.main.ph.sendPacket(''.join(packet), ad.getAddrTuple()) # Too many failures, just give up if timeout > 30.0: self.req_blocks.clear() return # Schedule next request. # This will become immediate if a reply arrives. when = random.uniform(0.9, 1.1) * timeout timeout *= 1.2 self.requestBlocks_dcall = reactor.callLater(when, cb, timeout) self.requestBlocks_dcall = reactor.callLater(0, cb, 1.0) def addDataBlock(self, bhash, data): # Return True if the block was accepted, False otherwise if bhash not in self.blocks: return False # If we're requesting blocks, then mark this one off # and possibly ask for more. if bhash in self.req_blocks: self.req_blocks.discard(bhash) self.scheduleRequestBlocks() # Record the block data, and check if it's time to assemble # all the blocks together. if self.blocks[bhash] is None: self.blocks[bhash] = data self.assembleBlocks() return True def assembleBlocks(self): osm = self.main.osm # DEBUG i=0 for bk in self.blocks.itervalues(): if bk is None: i+=1 # Check if all the blocks exist yet if None in self.blocks.itervalues(): return data = ''.join([self.blocks[bhash] for bhash in self.hashlist]) self.hashlist = [] self.blocks = {} # This will be toggled back to True if the topic is set self.topic_flag = False # Default to disabled self.moderated = False try: self.processChunks(data, self.status_pktnum) except ChunkError, e: self.main.logPacket("Couldn't assemble blocks: %s" % e) # Remove any nicks who aren't mentioned in this update dead_nicks = [] for n in self.nicks.values(): if n.pktnum < self.status_pktnum: del self.nicks[n.nick] if n.mode != 0xFF: dead_nicks.append(n) # Report all the nicks that we deleted dead_nicks.sort() for n in dead_nicks: osm.nkm.removeNode(n, "Dead") # Remove any bans which aren't mentioned in this update for b in self.bans.values(): if b.pktnum < self.status_pktnum: del self.bans[b.ipmask] # If not topic was set, release control of it if not self.topic_flag: osm.tm.checkLeavingNode(self.parent_n) self.last_assembled_pktnum = self.status_pktnum
class BridgeNodeData(object): class Ban(object): def __init__(self, ipmask, enable, pktnum): self.ipmask = ipmask self.enable = enable self.pktnum = pktnum def __init__(self, main, parent_n): self.main = main self.parent_n = parent_n self.blocks = {} # {hash: [None | data]} self.hashlist = [] self.status_pktnum = None self.topic_flag = False self.moderated = False self.last_assembled_pktnum = None self.nicks = {} # {nick: NickNode()} self.bans = {} # {(ip,mask): Ban()} # Tuple of info strings; indices match up with the nick modes self.infostrings = () self.req_blocks = RandSet() self.requestBlocks_dcall = None # Register me in BridgeClientManager self.main.osm.bcm.bridges.add(self) def setHashList(self, hashlist, do_request): self.hashlist = hashlist self.blocks = dict.fromkeys(self.hashlist, None) bcm = self.main.osm.bcm # Start with no requested blocks self.req_blocks.clear() for bhash in self.blocks: try: bk = bcm.unclaimed_blocks.pop((self.parent_n.ipp, bhash)) except KeyError: # If we're requesting blocks, then add this to the list if do_request: self.req_blocks.add(bhash) else: bk.expire_dcall.cancel() self.blocks[bhash] = bk.data self.assembleBlocks() # Start requesting blocks (if any) self.scheduleRequestBlocks() def scheduleRequestBlocks(self): # After we receive a sync reply from the bridge, individually # request the full data for each block hash. dcall_discard(self, 'requestBlocks_dcall') if not self.req_blocks: return def cb(timeout): self.requestBlocks_dcall = None # Pick one of the hashes randomly try: bhash = self.req_blocks.peek() except KeyError: return # Build request packet packet = ['bQ'] packet.append(self.main.osm.me.ipp) packet.append(bhash) # Send to bridge ad = Ad().setRawIPPort(self.parent_n.ipp) self.main.ph.sendPacket(''.join(packet), ad.getAddrTuple()) # Too many failures, just give up if timeout > 30.0: self.req_blocks.clear() return # Schedule next request. # This will become immediate if a reply arrives. when = random.uniform(0.9, 1.1) * timeout timeout *= 1.2 self.requestBlocks_dcall = reactor.callLater(when, cb, timeout) self.requestBlocks_dcall = reactor.callLater(0, cb, 1.0) def addDataBlock(self, bhash, data): # Return True if the block was accepted, False otherwise if bhash not in self.blocks: return False # If we're requesting blocks, then mark this one off # and possibly ask for more. if bhash in self.req_blocks: self.req_blocks.discard(bhash) self.scheduleRequestBlocks() # Record the block data, and check if it's time to assemble # all the blocks together. if self.blocks[bhash] is None: self.blocks[bhash] = data self.assembleBlocks() return True def assembleBlocks(self): osm = self.main.osm # DEBUG i = 0 for bk in self.blocks.itervalues(): if bk is None: i += 1 # Check if all the blocks exist yet if None in self.blocks.itervalues(): return data = ''.join([self.blocks[bhash] for bhash in self.hashlist]) self.hashlist = [] self.blocks = {} # This will be toggled back to True if the topic is set self.topic_flag = False # Default to disabled self.moderated = False try: self.processChunks(data, self.status_pktnum) except ChunkError, e: self.main.logPacket("Couldn't assemble blocks: %s" % e) # Remove any nicks who aren't mentioned in this update dead_nicks = [] for n in self.nicks.values(): if n.pktnum < self.status_pktnum: del self.nicks[n.nick] if n.mode != 0xFF: dead_nicks.append(n) # Report all the nicks that we deleted dead_nicks.sort() for n in dead_nicks: osm.nkm.removeNode(n, "Dead") # Remove any bans which aren't mentioned in this update for b in self.bans.values(): if b.pktnum < self.status_pktnum: del self.bans[b.ipmask] # If not topic was set, release control of it if not self.topic_flag: osm.tm.checkLeavingNode(self.parent_n) self.last_assembled_pktnum = self.status_pktnum