def _test_LRU_has_key(self, C): c = C(maxsize=10) c._assert_invariants() for i in range(11): c._assert_invariants() c[i] = i c._assert_invariants() self.assertTrue(len(c) == 10) self.assertTrue(10 in list(c.values())) self.assertTrue(0 not in list(c.values())) # c.has_key(1) # this touches `1' and makes it fresher so that it will live and `2' will die next time we overfill. c[1] = 1 # this touches `1' and makes it fresher so that it will live and `2' will die next time we overfill. c._assert_invariants() c[99] = 99 c._assert_invariants() self.assertTrue(len(c) == 10) self.assertTrue( 1 in list(c.values()), "C: %s, c.values(): %s" % ( hr(C), hr(list(c.values()), ), )) self.assertTrue(not 2 in list(c.values())) self.assertTrue(99 in list(c.values()))
def __repr__(self): try: if self._closed: state="closed" elif self._closing: state="closing" elif not self._everconnected: state="connecting" elif self._readthrottled: if self._writethrottled: state="throttled in/out" else: state="throttled in" elif self._writethrottled: state="throttled out" else: state="connected" try: pn = self.getpeername() return '<%s %s to %s at %s:%s, %x>' % (self.__class__.__name__, state, hr(self._cid_for_debugging), pn[0], pn[1], id(self)) except: # `getpeername()' raises an exception sometimes, for example if the socket isn't connected yet. That's a pretty silly interface, isn't it? --Zooko 2001-06-17 return '<%s %s to %s, %x>' % (self.__class__.__name__, state, hr(self._cid_for_debugging), id(self)) except: debugprint("exception in TCPConnection.__repr__():\n") traceback.print_exc(file=debugstream) raise
def decode_int(s, index): n, index = decode_raw_string(s, index) if not _int_re.match(n): raise MencodeError, "non canonical integer: %s" % humanreadable.hr(n) try: return int(n), index except (OverflowError, ValueError), le: return long(n), index
def findmagiccards_price(c): page = None mo = None try: page = findmagiccards_page(c) mo = FMC_PRICE_RE.search(page) if mo is None: return None return mo.group(1) except exceptions.StandardError, le: raise exceptions.StandardError, { 'cause': humanreadable.hr(le), 'c': c, 'page': page, 'mo': mo, 'mo.group(0)': (mo is not None) and mo.group(0), }
def _test_LRU_has_key(self, C): c = C(maxsize=10) c._assert_invariants() for i in xrange(11): c._assert_invariants() c[i] = i c._assert_invariants() self.failUnless(len(c) == 10) self.failUnless(10 in c.values()) self.failUnless(0 not in c.values()) # c.has_key(1) # this touches `1' and makes it fresher so that it will live and `2' will die next time we overfill. c[1] = 1 # this touches `1' and makes it fresher so that it will live and `2' will die next time we overfill. c._assert_invariants() c[99] = 99 c._assert_invariants() self.failUnless(len(c) == 10) self.failUnless(1 in c.values(), "C: %s, c.values(): %s" % (hr(C), hr(c.values(),),)) self.failUnless(not 2 in c.values()) self.failUnless(99 in c.values())
def getnameofhandicapper(thingie): if hasattr(thingie, '__name__'): if thingie.__name__ != "compute_handicap": return thingie.__name__ if hasattr(thingie, 'im_class'): return getnameofhandicapper(thingie.im_class) if hasattr(thingie, '__class__'): return getnameofhandicapper(thingie.__class__) return hr(thingie)
def _test_has_key(self, C): c = C() c._assert_invariants() for i in xrange(11): c._assert_invariants() c[i] = i c._assert_invariants() del c[0] self.failUnless(len(c) == 10) self.failUnless(10 in c.values()) self.failUnless(0 not in c.values()) c.has_key(1) # this touches `1' but does not make it fresher so that it will get popped next time we pop. c[1] = 1 # this touches `1' but does not make it fresher so that it will get popped. c._assert_invariants() x = c.pop() self.failUnlessEqual(x, 10) c[99] = 99 c._assert_invariants() self.failUnless(len(c) == 10) self.failUnless(1 in c.values(), "C: %s, c.values(): %s" % (hr(C), hr(c.values(),),)) self.failUnless(2 in c.values(), "C: %s, c.values(): %s" % (hr(C), hr(c.values(),),)) self.failIf(10 in c.values(), "C: %s, c.values(): %s" % (hr(C), hr(c.values(),),)) self.failUnless(99 in c.values())
def _test_has_key(self, C): c = C() c._assert_invariants() for i in range(11): c._assert_invariants() c[i] = i c._assert_invariants() del c[0] self.assertTrue(len(c) == 10) self.assertTrue(10 in list(c.values())) self.assertTrue(0 not in list(c.values())) 1 in c # this touches `1' but does not make it fresher so that it will get popped next time we pop. c[1] = 1 # this touches `1' but does not make it fresher so that it will get popped. c._assert_invariants() x = c.pop() self.assertEqual(x, 10) c[99] = 99 c._assert_invariants() self.assertTrue(len(c) == 10) self.assertTrue(1 in list(c.values()), "C: %s, c.values(): %s" % (hr(C), hr(list(c.values()), ),)) self.assertTrue(2 in list(c.values()), "C: %s, c.values(): %s" % (hr(C), hr(list(c.values()), ),)) self.assertFalse(10 in list(c.values()), "C: %s, c.values(): %s" % (hr(C), hr(list(c.values()), ),)) self.assertTrue(99 in list(c.values()))
def _update(self): """ Make sure this card instance uses all new terminology. """ for old, new in UPDATE_NAMES.items(): if self.has_key(old): self[new] = self[old] del self[old] assert self.has_key('Rarity'), "self: %s" % dict.__repr__(self) mo = RARITY_RE.match(self['Rarity']) assert mo is not None, { 'Rarity': self['Rarity'], 'self': self, } self['Rarity'] = UPDATE_RARITIES[mo.group(1)] + (mo.group(2) or "") # Different spoiler lists do different things for the "Mana Cost" of a land. What *we* do is remove it from the dict entirely. # (When exporting a spoiler list, it will be printed as "n/a", which is how the new spoiler lists do it.) try: if LAND_TYPE_AND_CLASS_RE.search(self["Type & Class"]): self.del_if_present("Mana Cost") except exceptions.StandardError, le: print humanreadable.hr(le) print humanreadable.hr(self) raise exceptions.StandardError, { 'cause': le, 'self': self }
def inner_check_noverbose(thing, templ, FunctionType=types.FunctionType, MethodType=types.MethodType, DictType=types.DictType, StringType=types.StringType, LongType=types.LongType, IntType=types.IntType, ListType=types.ListType, TupleType=types.TupleType): # The following isn't really used right now, but I'm leaving the commented-out code for evidence. --Zooko 2001-06-07 # if isinstance(thing, mencode.PreEncodedThing): # thing = thing.getvalue() templtype = type(templ) if templtype is FunctionType or templtype is MethodType: templ(thing, false) elif templtype is DictType: if not type(thing) is DictType: raise BadFormatError, 'target is not a dict' for key in templ.keys(): if not thing.has_key(key): if not isinstance(templ[key], OptionMarker) : raise BadFormatError, "lacks required key" else: if isinstance(templ[key], OptionMarker) : inner_check_noverbose(thing[key], templ[key].template) else: inner_check_noverbose(thing[key], templ[key]) elif templtype is StringType: if type(thing) is not StringType: raise BadFormatError, "no match - target is not a string" if thing != templ: raise BadFormatError, "strings do not match" elif templ == 0 or templ == -1 or templ == 1: if type(thing) is not LongType and type(thing) is not IntType: raise BadFormatError, 'expected int' if templ == 0: if thing < 0: raise BadFormatError, 'template called for non-negative value' elif templ == -1: return else: assert templ == 1 if thing <= 0: raise BadFormatError, 'template called for strictly positive value' elif templtype is ListType or templtype is TupleType: for i in templ: try: inner_check_noverbose(thing, i) return except BadFormatError: pass raise BadFormatError, "did not match any possible templates" elif templ is None: if thing is not None: raise BadFormatError, 'expected None' else: assert false, "bad template - " + humanreadable.hr(templ)
def func(thing, verbose, template = template, ListType=ListType, TupleType=TupleType): if type(thing) not in (ListType, TupleType,): raise BadFormatError, 'not a list' if verbose: try: i = 0 while i < len(thing): if verbose: inner_check_verbose(thing[i], template) else: inner_check_noverbose(thing[i], template) i = i + 1 except BadFormatError, reason: raise BadFormatError, 'mismatch at index ' + humanreadable.hr(i) + ': ' + str(reason)
def inner_check_verbose(thing, templ, FunctionType=types.FunctionType, MethodType=types.MethodType, DictType=types.DictType, StringType=types.StringType, LongType=types.LongType, IntType=types.IntType, ListType=types.ListType, TupleType=types.TupleType): # The following isn't really used right now, but I'm leaving the commented-out code for evidence. --Zooko 2001-06-07 # if isinstance(thing, mencode.PreEncodedThing): # thing = thing.getvalue() templtype = type(templ) if templtype is FunctionType or templtype is MethodType: templ(thing, true) elif templtype is DictType: if not type(thing) is DictType: raise BadFormatError, 'target is not a dict' for key in templ.keys(): if not thing.has_key(key): if not isinstance(templ[key], OptionMarker) : raise BadFormatError, "lacks required key: (" + humanreadable.hr(key) + ")" else: try: if isinstance(templ[key], OptionMarker) : inner_check_verbose(thing[key], templ[key].template) else : inner_check_verbose(thing[key], templ[key]) except BadFormatError, reason: raise BadFormatError, 'mismatch in key (' + humanreadable.hr(key) + '): ' + str(reason)
def traceorcountit(func, dotrace, docount, countfuncs): global tracedone tracedone.clear() debugprint("xxxxxxxxxxxxxxxxxxxx %s, countfuncs: %s\n", args=(func, countfuncs,), v=0, vs="debug") t = trace.Trace(trace=dotrace, count=docount, countfuncs=countfuncs, infile="/tmp/trace", outfile="/tmp/trace", ignoredirs=(sys.prefix, sys.exec_prefix,)) # run the new command using the given trace try: result = t.runfunc(func) debugprint("yyyyyyyyyyyyyyyyyyyy %s\n", args=(func,), v=0, vs="debug") finally: tmpfname = fileutil.mktemp(prefix=humanreadable.hr(func)) debugprint("zzzzzzzzzzzzzzzzzzzz %s\n", args=(func,), v=0, vs="debug") # make a report, telling it where you want output t.results().write_results(show_missing=1) tracedone.set() return result
def mdecode(s): """ Does the opposite of mencode. Raises a mencode.MencodeError if the string is not a proper Python data structure encoding. @precondition `s' must be a string.: type(s) is types.StringType: "s: %s :: %s" % (humanreadable.hr(s), humanreadable.hr(type(s)),) """ assert type(s) is types.StringType, "precondition: `s' must be a string." + " -- " + "s: %s :: %s" % (humanreadable.hr(s), humanreadable.hr(type(s)),) try: result, index = mdecode_index(s, 0) if index != len(s): raise MencodeError, 'garbage at end of s' if result == UNKNOWN_TYPE: raise UnknownTypeError, 'unknown type in required part of message' return result except IndexError, e: raise MencodeError, 'unexpected end of s ' + humanreadable.hr(e)
def _dont_enable_if_you_want_speed_profit(func): result = None p = profile.Profile() try: debugprint("xxxxxxxxxxxxxxxxxxxx %s\n", args=(func,), v=0, vs="debug") result = p.runcall(func) debugprint("yyyyyyyyyyyyyyyyyyyy %s\n", args=(func,), v=0, vs="debug") finally: tmpfname = fileutil.mktemp(prefix=humanreadable.hr(func)) debugprint("zzzzzzzzzzzzzzzzzzzz %s\n", args=(tmpfname,), v=0, vs="debug") p.dump_stats(tmpfname) p = None del p stats = pstats.Stats(tmpfname) stats.strip_dirs().sort_stats('time').print_stats() return result
def coverageit(func): global tracedone tracedone.clear() debugprint("xxxxxxxxxxxxxxxxxxxx %s\n", args=(func,), v=0, vs="debug") coverage.the_coverage.start() # run the new command using the given trace try: result = apply(func) debugprint("yyyyyyyyyyyyyyyyyyyy %s\n", args=(func,), v=0, vs="debug") finally: coverage.the_coverage.stop() tmpfname = fileutil.mktemp(prefix=humanreadable.hr(func)) debugprint("zzzzzzzzzzzzzzzzzzzz %s\n", args=(func,), v=0, vs="debug") # make a report, telling it where you want output res = coverage.the_coverage.analysis('/home/zooko/playground/evil-SF-unstable/common/MojoTransaction.py') print res tracedone.set() return result
def _test_has_key(self, C): c = C() c._assert_invariants() for i in xrange(11): c._assert_invariants() c[i] = i c._assert_invariants() del c[0] self.failUnless(len(c) == 10) self.failUnless(10 in c.values()) self.failUnless(0 not in c.values()) c.has_key( 1 ) # this touches `1' but does not make it fresher so that it will get popped next time we pop. c[1] = 1 # this touches `1' but does not make it fresher so that it will get popped. c._assert_invariants() x = c.pop() self.failUnlessEqual(x, 10) c[99] = 99 c._assert_invariants() self.failUnless(len(c) == 10) self.failUnless(1 in c.values(), "C: %s, c.values(): %s" % ( hr(C), hr(c.values(), ), )) self.failUnless(2 in c.values(), "C: %s, c.values(): %s" % ( hr(C), hr(c.values(), ), )) self.failIf(10 in c.values(), "C: %s, c.values(): %s" % ( hr(C), hr(c.values(), ), )) self.failUnless(99 in c.values())
def send(self, recipid, mtype, msg, response_handler_func=None, post_timeout_outcome_func=None): """ Send a message to another EGTP node. @param recipid: EGTP node address to send to. @param mtype: Message type. Possible message types found in OurMessages.py @param msg: Message payload @param response_handler_func: function to call when we get an answer @param post_timeout_outcome_func: function to call on a timeout @precondition: `recipid' must be an id.: idlib.is_id(recipid): "recipid: %s :: %s" % (hr(recipid), hr(type(recipid)),) """ assert idlib.is_id(recipid), "precondition: `recipid' must be an id." + " -- " + "recipid: %s :: %s" % (hr(recipid), hr(type(recipid)),) self.mtm.initiate(recipid, mtype, msg, outcome_func=response_handler_func, post_timeout_outcome_func=post_timeout_outcome_func)
def set_handler_func(self, mtype, handler_func): """ @param mtype: a string @param handler_func: func to be invoked to handle any incoming messages with the `mtype' string in their "message type" field @precondition: `mtype' must be a string.: type(mtype) is types.StringType: "mtype: %s :: %s" % (hr(mtype), hr(type(mtype)),) @precondition: `handler_func' must be callable.: callable(handler_func): "handler_func: %s :: %s" % (hr(handler_func), hr(type(handler_func)),) """ assert type(mtype) is types.StringType, "precondition: `mtype' must be a string." + " -- " + "mtype: %s :: %s" % (hr(mtype), hr(type(mtype)),) assert callable(handler_func), "precondition: `handler_func' must be callable." + " -- " + "handler_func: %s :: %s" % (hr(handler_func), hr(type(handler_func)),) self.mtm.add_handler_funcs({mtype: handler_func})
def lookup(self, key, lookuphand): """ @precondition: key must be well-formed according to the verifier.: self.verifier.verify_key(key): "key: %s" % hr(key) """ assert self.verifier.verify_key(key), "precondition: key must be well-formed according to the verifier." + " -- " + "key: %s" % hr(key) oldkey=hexlify(key) key="mnet-node-id:"+oldkey token=self.server.search.search("<"+key+">", "", "", "file:nodes") results=self.server.search.fetch(token) val={} for part in results: pred=part[1] pred=split(pred, '#')[1] pred=self.decap(pred) otype=part[2][0] obj=part[2][1] if(otype==LITERAL): if pred=="sequence num": val[pred]=int(obj) else: val[pred]=obj elif pred=="broker id": obj=split(obj, ':')[1] obj=unhexlify(obj) val[pred]=obj elif pred=="connection strategies": key=oldkey+"-0" token=self.server.search.search("_:"+key, "", "", "file:nodes") results=self.server.search.fetch(token) subval={} for subpart in results: subpred=subpart[1] subpred=split(subpred, '#')[1] subpred=self.decap(subpred) otype=subpart[2][0] obj=subpart[2][1] if(otype==LITERAL): if subpred=='ip address': subval['IP address']=obj elif subpred=='comm strat sequence num': subval[subpred]=int(obj) else: subval[subpred]=obj elif subpred=="broker id": obj=split(obj, ':')[1] obj=unhexlify(obj) subval[subpred]=obj elif subpred=="pubkey": key=oldkey+"-0-pubkey" token=self.server.search.search("_:"+key, "", "", "file:nodes") results=self.server.search.fetch(token) pubval={} for pubpart in results: pubpred=pubpart[1] pubpred=split(pubpred, '#')[1] pubpred=self.decap(pubpred) otype=pubpart[2][0] obj=pubpart[2][1] if(otype==LITERAL): pubval[pubpred]=obj elif pubpred=="key header": key=oldkey+"-0-pubkey-header" token=self.server.search.search("_:"+key, "", "", "file:nodes") results=self.server.search.fetch(token) headval={} for headpart in results: headpred=headpart[1] headpred=split(headpred, '#')[1] headpred=self.decap(headpred) otype=headpart[2][0] obj=headpart[2][1] if otype==LITERAL: headval[headpred]=obj else: print 'Unsupported header field:', headpred pubval[pubpred]=headval elif pubpred=="key values": key=oldkey+"-0-pubkey-value" token=self.server.search.search("_:"+key, "", "", "file:nodes") results=self.server.search.fetch(token) valval={} for valpart in results: valpred=valpart[1] valpred=split(valpred, '#')[1] valpred=self.decap(valpred) otype=valpart[2][0] obj=valpart[2][1] if otype==LITERAL: valval[valpred]=obj else: print 'Unsupported value field:', valpred pubval[pubpred]=valval else: print 'Unsupported comm pub field:', pubpred subval[subpred]=pubval elif subpred=="lowerstrategy": key=oldkey+"-0-lower" token=self.server.search.search("_:"+key, "", "", "file:nodes") results=self.server.search.fetch(token) lowval={} for lowpart in results: lowpred=lowpart[1] lowpred=split(lowpred, '#')[1] lowpred=self.decap(lowpred) otype=lowpart[2][0] obj=lowpart[2][1] if(otype==LITERAL): if lowpred=='ip address': lowval['IP address']=obj else: lowval[lowpred]=obj elif lowpred=="broker id": obj=split(obj, ':')[1] obj=unhexlify(obj) lowval[lowpred]=obj elif lowpred=="pubkey": key=oldkey+"-0-pubkey" token=self.server.search.search("_:"+key, "", "", "file:nodes") results=self.server.search.fetch(token) pubval={} for pubpart in results: pubpred=pubpart[1] pubpred=split(pubpred, '#')[1] pubpred=self.decap(pubpred) otype=pubpart[2][0] obj=pubpart[2][1] if(otype==LITERAL): puvval[pubpred]=obj else: print 'Unsupported pub field:', pubpred else: print 'Unsupported low field:', lowpred subval[subpred]=lowval else: print 'Unsupported comm field:', subpred val[pred]=[subval] else: print 'Unsupported field:', pred lookuphand.result(val)
def publish(self, key, object): """ @precondition: key must be well-formed according to the verifier.: self.verifier.verify_key(key): "key: %s" % hr(key) @precondition: key-object pair must be valid mapping according to the verifier.: self.verifier.verify_mapping(key, object): "key: %s, object: %s" % (hr(key), hr(object),) """ assert self.verifier.verify_key(key), "precondition: key must be well-formed according to the verifier." + " -- " + "key: %s" % hr(key) assert self.verifier.verify_mapping(key, object), "precondition: key-object pair must be valid mapping according to the verifier." + " -- " + "key: %s, object: %s" % (hr(key), hr(object),) idStr=hexlify(key) id="mnet-node-id:"+idStr for key in object.keys(): val=object[key]; key=nodeSchema+join(split(key.title(), ' '), '') t=type(val) if(key==nodeSchema+"ConnectionStrategies"): for x in range(len(val)): subId=idStr+"-"+str(x) self.store(RESOURCE, id, key, NODE, subId) for subkey in val[x].keys(): subval=val[x][subkey] subkey=commSchema+join(split(subkey.title(), ' '), '') if(subkey==commSchema+"BrokerId"): self.store(NODE, subId, subkey, RESOURCE, 'mnet-node-id:'+hexlify(subval)) elif(type(subval)==type('str')): self.store(NODE, subId, subkey, LITERAL, subval) elif(type(subval)==type(1)): self.store(NODE, subId, subkey, LITERAL, str(subval)) elif(subkey==commSchema+"Lowerstrategy"): lowId=subId+"-lower" self.store(NODE, subId, subkey, NODE, lowId) for lowkey in subval.keys(): lowval=subval[lowkey] lowkey=lowerSchema+join(split(lowkey.title(), ' '), '') if(lowkey==lowerSchema+'BrokerId'): self.store(NODE, lowId, lowkey, RESOURCE, "mnet-node-id:"+hexlify(lowval)) elif(type(lowval)==type('str')): self.store(NODE, lowId, lowkey, LITERAL, lowval) elif(type(lowval)==type(1)): self.store(NODE, lowId, lowkey, LITERAL, str(lowval)) else: print 'Unsupported entry:', lowkey, type(lowval) elif(subkey==commSchema+"Pubkey"): subsubId=subId+"-pubkey" self.store(NODE, subId, subkey, NODE, subsubId) for subsubkey in subval.keys(): subsubval=subval[subsubkey] subsubkey=pubkeySchema+join(split(subsubkey.title(), ' '), '') if(subsubkey==pubkeySchema+"KeyHeader"): headId=subsubId+"-header" self.store(NODE, subsubId, subsubkey, NODE, headId) for headkey in subsubval.keys(): headval=subsubval[headkey] headkey=keyHeaderSchema+join(split(headkey.title(), ' '), '') if(type(headval)==type('str')): self.store(NODE, headId, headkey, LITERAL, headval) else: print 'Unsupported entry:', headkey elif(subsubkey==pubkeySchema+"KeyValues"): valId=subsubId+"-value" self.store(NODE, subsubId, subsubkey, NODE, valId) for valkey in subsubval.keys(): valval=subsubval[valkey] valkey=keyValueSchema+join(split(valkey.title(), ' '), '') if(type(valval)==type('str')): self.store(NODE, valId, valkey, LITERAL, valval) else: print 'Unsupported entry:', valkey else: print 'Unsupported entry:', subsubkey else: print 'Unsupported entry:', subkey elif(t==type('str')): self.store(RESOURCE, id, key, LITERAL, val) elif(t==type(1)): self.store(RESOURCE, id, key, LITERAL, str(val)) else: print 'Unsupported entry:', key
def send_msg(self, counterparty_id, msg, fast_fail_handler, hint=HINT_NO_HINT, timeout=None, commstratseqno=None): """ @param commstratseqno: the sequence number of the comm strat which has already been tried; If you attempt a recursive delivery mechanism (relay), then you can avoid loops by ensuring that the next comm strategy you try has seqno > than this one. @precondition: `counterparty_id' must be an id.: idlib.is_sloppy_id(counterparty_id): "counterparty_id: %s" % humanreadable.hr(counterparty_id) @precondition: `msg' must be a string.: type(msg) == types.StringType """ assert idlib.is_sloppy_id(counterparty_id), "precondition: `counterparty_id' must be an id." + " -- " + "counterparty_id: %s" % humanreadable.hr(counterparty_id) assert type(msg) == types.StringType, "precondition: `msg' must be a string." assert idlib.is_sloppy_id(counterparty_id), "precondition: `counterparty_id' must be an id." + " -- " + "counterparty_id: %s" % humanreadable.hr(counterparty_id) assert type(msg) == types.StringType, "precondition: `msg' must be a string." # debugprint("CryptoCommsHandler.send_msg()\n") if idlib.equal(counterparty_id, self.get_id()): DoQ.doq.add_task(self._upward_inmsg_handler, args=(counterparty_id, msg, None)) else: try: cs = self._cid_to_cs.get(counterparty_id) if not cs: fast_fail_handler(msgId=idlib.make_id(msg, 'msg'), failure_reason="no CommStrat.Crypto for this counterparty") return llstrat = cs._lowerstrategy if not llstrat: fast_fail_handler(msgId=idlib.make_id(msg, 'msg'), failure_reason="no llstrat for this counterparty") return assert idlib.equal(llstrat._broker_id, counterparty_id), "counterparty_id: %s, cs: %s, llstrat: %s, llstrat._broker_id: %s" % (humanreadable.hr(counterparty_id), humanreadable.hr(cs), humanreadable.hr(llstrat), humanreadable.hr(llstrat._broker_id),) if not hasattr(llstrat, 'send'): fast_fail_handler(msgId=idlib.make_id(msg, 'msg'), failure_reason="CommStrat lacks a `send()' method.: %s" % humanreadable.hr(llstrat)) return if len(msg) > MAX_CLEARTEXT_LEN : raise CommsError.CannotSendError, "message too long: %s bytes" % len(msg) origmsglen = len(msg) try: msg = zlib.compress(msg, 3) debugprint("CryptoCommsHandler.send_msg(): sending compressed msg (%s bytes, orig %s)\n", args=(len(msg), origmsglen), v=14, vs="crypto") except zlib.error, e: debugprint("CryptoCommsHandler.send_msg(): got `%s' during compression (%s bytes)\n", args=(e, origmsglen), v=5, vs="crypto") # verbose cyphertext = self._mesgen.generate_message(recipient_id = counterparty_id, message = msg) del msg # we're done with it, encourage faster gc except mesgen.NoCounterpartyInfo, le: raise CommsError.CannotSendError, ("no counterparty public key", le)
def sort_by_preference(self, counterparties, message_type, message_body): """ @param counterparties: a sequence of (counterparty_id, service_info_dict); It is okay to be an empty list. Cogitates on the possibility of sending each counterparty in counterparties the given message and returns a list sorted by order of preference of which counterparties to try to use. Disqualified counterparties are not included in the list at all. @precondition: `counterparties' must be a sequence of (id, infodict,) tuples.: (type(counterparties) in (types.ListType, types.TupleType,)) and (len(filter(lambda x: not ((type(x) in (types.TupleType, types.DictType,)) and (len(x) == 2) and idlib.is_sloppy_id(x[0])), counterparties)) == 0): "counterparties: %s" % humanreadable.hr(counterparties) @precondition: `message_type' must be a string.: type(message_type) == types.StringType """ assert (type(counterparties) in (types.ListType, types.TupleType,)) and (len(filter(lambda x: not ((type(x) in (types.TupleType, types.DictType,)) and (len(x) == 2) and idlib.is_sloppy_id(x[0])), counterparties)) == 0), "precondition: `counterparties' must be a sequence of (id, infodict,) tuples." + " -- " + "counterparties: %s" % hr(counterparties) assert type(message_type) == types.StringType, "precondition: `message_type' must be a string." # debugprint("sort_by_preference(counterparties: %s, message_type:%s, message_body: %s)\n", args=(counterparties, message_type, message_body,), v=2, vs="MojoHandicapper") # contains (counterparty_id, cost) unsorted = [] for i in counterparties : cost = self._compute_handicap(i[0], i[1], message_type=message_type, message_body=message_body) if cost is not DISQUALIFIED : unsorted.append((cost, i)) unsorted.sort() return map(lambda x: x[1], unsorted)
def strip_leading_zeroes(numstr): """ @param numstr: the string to be stripped @return: `numstr' minus any leading zero bytes @precondition: `numstr' must be a string.: type(numstr) == types.StringType: "numstr: %s :: %s" % (humanreadable.hr(numstr), `type(numstr)`) """ assert type(numstr) == types.StringType, "precondition: `numstr' must be a string." + " -- " + "numstr: %s :: %s" % (humanreadable.hr(numstr), `type(numstr)`) if len(numstr) == 0: return numstr # When we are done `i' will point to the first non-zero byte. i = 0 while (i < len(numstr)) and (numstr[i] == '\000'): i = i + 1 return numstr[i:]
# if it is an UnknownSession error, attempt to send a note back down the lowerstrategy if it happens to be a two way connection if isinstance(e, mesgen.UnknownSession) and lowerstrategy: # XXX if all CommStrats are updated in the future to have a send() method, just use it if the CommStrat has a "twowaycomms" flag? if isinstance(lowerstrategy, CommStrat.TCP) and lowerstrategy.asyncsock: debugprint("sending an 'invalidate session' note back on the TCP connection\n", v=1, vs="CryptoCommsHandler") # send e.invalidate_session_msg back out this TCP Connection lowerstrategy.asyncsock.send(e.invalidate_session_msg) else: debugprint("message did not come via a two way CommStrat, cannot send an 'invalidate session'\n", v=3, vs="CryptoCommsHandler") return # drop it on the floor counterparty_id = idlib.string_to_id(counterparty_pub_key) assert keyutil.publicRSAKeyForCommunicationSecurityIsWellFormed(counterparty_pub_key), "postcondition of `mesgen.parse()': `counterparty_pub_key' is a public key." + " -- " + "counterparty_pub_key: %s" % humanreadable.hr(counterparty_pub_key) if len(cleartext) > MAX_CLEARTEXT_LEN : debugprint("msg from %s dropped due to length: %s\n", args=(counterparty_id, len(cleartext)), v=0, vs="ERROR") return try: decomptext = zlibutil.safe_zlib_decompress_to_retval(cleartext, maxlen=MAX_CLEARTEXT_LEN) except (zlibutil.UnsafeDecompressError, zlibutil.TooBigError), le: debugprint("msg from %s dropped. le: %s\n", args=(counterparty_id, le), v=0, vs="ERROR") return except zlibutil.ZlibError, le: debugprint("msg from %s not zlib encoded. processing it anyway for backwards compatibility. le: %s\n", args=(counterparty_id, le,), v=3, vs="debug") decomptext = cleartext if lowerstrategy is not None: assert (lowerstrategy._broker_id is None) or idlib.equal(lowerstrategy._broker_id, counterparty_id), "counterparty_id: %s, lowerstrategy: %s, lowerstrategy._broker_id: %s" % (humanreadable.hr(counterparty_id), humanreadable.hr(lowerstrategy), humanreadable.hr(lowerstrategy._broker_id),)
def pick_best(self, counterparties, message_type, message_body): """ @return: the id of the best (lowest handicap, not DISQUALIFIED) counterparty, or `None' if none (i.e., they were all disqualified, or the input `counterparties' was of length 0) @param counterparties: a sequence of C{(counterparty_id, service_info_dict)}. It is okay to be an empty list. @precondition: `counterparties' must be a sequence of (id, infodict,) tuples.: (type(counterparties) in (types.ListType, types.TupleType,)) and (len(filter(lambda x: not ((type(x) in (types.TupleType, types.DictType,)) and (len(x) == 2) and idlib.is_sloppy_id(x[0])), counterparties)) == 0): "counterparties: %s" % humanreadable.hr(counterparties) """ assert (type(counterparties) in (types.ListType, types.TupleType,)) and (len(filter(lambda x: not ((type(x) in (types.TupleType, types.DictType,)) and (len(x) == 2) and idlib.is_sloppy_id(x[0])), counterparties)) == 0), "precondition: `counterparties' must be a sequence of (id, infodict,) tuples." + " -- " + "counterparties: %s" % hr(counterparties) best = None bestcost = None for (cpid, info,) in counterparties: cost = self._compute_handicap(cpid, info, message_type=message_type, message_body=message_body) if cost is not DISQUALIFIED : if (bestcost is None) or (cost < bestcost): bestcost = cost best = cpid return best
def _compute_handicap(self, counterparty_id, metainfo, message_type, message_body): """ Computes the 'handicap', or estimated real cost including risk of failure, of sending the message to the counterparty. @precondition: This method must be called on the DoQ.: DoQ.doq.is_currently_doq() @precondition: `counterparty_id' must be a binary id.: idlib.is_binary_id(counterparty_id): "counterparty_id: %s" % humanreadable.hr(counterparty_id) """ assert DoQ.doq.is_currently_doq(), "precondition: This method must be called on the DoQ." assert idlib.is_binary_id(counterparty_id), "precondition: `counterparty_id' must be a binary id." + " -- " + "counterparty_id: %s" % hr(counterparty_id) handicap = 0.0 _hmap = self.__handicappers_map for h in (_hmap.get(message_type, []) + _hmap[None]) : try: amount = h(counterparty_id = counterparty_id, metainfo = metainfo, message_type = message_type, message_body = message_body) except: debugprint("WARNING: counterparty %s disqualified due to exception:\n Handicapper Params (message_type=%s, message_body=%s, metainfo=%s)\n:", args=(counterparty_id, message_type, message_body, metainfo), v=2, vs="business logic") traceback.print_exc(file=debugstream) return DISQUALIFIED assert amount is DISQUALIFIED or (type(amount) is types.FloatType), "Handicapper function must return certain type. -- func: %s, result: %s, counterparty_id: %s, metainfo: %s type: %s\n" % (hr(h), hr(amount), hr(counterparty_id), hr(metainfo), type(amount)) # postcondition if amount is DISQUALIFIED : # debugprint("Handicap %s DISQUALIFIED for %s on %s\n", args=(getnameofhandicapper(h), counterparty_id, message_type), v=2, vs="business logic") return DISQUALIFIED else: assert amount >= 0.0 # debugprint("Handicap %s additive %s for %s on %s\n", args=(getnameofhandicapper(h), "%0.0f" % amount, counterparty_id, message_type), v=2, vs="business logic") handicap = handicap + (amount**2) # debugprint("Handicap %s for %s on %s\n", args=("%0.0f" % handicap, counterparty_id, message_type), v=2, vs="business logic") return handicap
def add_handicapper(self, handicapper, mtypes=None) : """ Adds a handicap computing function to the list of all of them. A handicap function must take the parameters counterparty_id, message_type, and message_body and return a float value or DISQUALIFIED. @param mtypes: if specified is a list of message types this handicapper should be applied to (None indicates all message types). [message type specific handicappers will always be evaulated before generic handicappers] Sum of squares addition is used: All results are squared before being used. Numerical values will be added to produce a total handicap. DISQUALIFIED will completely disqualify the given counterparty. A sophisticated reputation system could be plugged in here -- if you had information from friends of friends indicating that a given counterparty is unreliable, you could make a handicapper which returns your friend's friend's opinion, and it will be factored in along with the other considerations. @precondition: `handicapper' must be a callable.: callable(handicapper): "handicapper: %s :: %s" % (humanreadable.hr(handicapper), `type(handicapper)`) @precondition: `mtypes' must be None or a sequence.: (mtypes is None) or (type(mtypes) in (types.ListType, types.TupleType,)) """ assert callable(handicapper), "precondition: `handicapper' must be a callable." + " -- " + "handicapper: %s :: %s" % (hr(handicapper), `type(handicapper)`) assert (mtypes is None) or (type(mtypes) in (types.ListType, types.TupleType,)), "precondition: `mtypes' must be None or a sequence." if mtypes is None: self.__handicappers_map[None].append(handicapper) else: for mtype in mtypes: setdefault(self.__handicappers_map, mtype, []).append(handicapper)
def sort_by_preference_from_dict_of_Peers(self, counterparties, message_type, message_body): """ Cogitates on the possibility of sending each peer in counterparties the given message and returns a list sorted by order of preference of which counterparties to try to use. Disqualified counterparties are not included in the list at all. @param counterparties: a dict of key: counterparty_id, value: service_info_dict, where service_info_dict contains a key 'Peer Object' whose value is an instance of Peer.Peer. It is okay to be an empty dict. @returns: a list of Peer.Peer instances sorted into descending order of preference @precondition: `counterparties' must be a dict.: type(counterparties) is types.DictType: "counterparties: %s :: %s" % (hr(counterparties), hr(type(counterparties)),) @precondition: `message_type' must be a string.: type(message_type) == types.StringType """ assert type(counterparties) is types.DictType, "precondition: `counterparties' must be a dict." + " -- " + "counterparties: %s :: %s" % (hr(counterparties), hr(type(counterparties)),) assert type(message_type) == types.StringType, "precondition: `message_type' must be a string." # debugprint("sort_by_preference_from_dict_of_Peers(counterparties: %s, message_type:%s, message_body: %s)\n", args=(counterparties, message_type, message_body,), v=2, vs="MojoHandicapper") # contains (cost, Peer Object,) workinglist = [] for counterpartyid, contactinfo in counterparties.items(): cost = self._compute_handicap(counterpartyid, contactinfo, message_type=message_type, message_body=message_body) if cost is not DISQUALIFIED : workinglist.append((cost, contactinfo['Peer Object'],)) workinglist.sort() return map(lambda x: x[1], workinglist)
def _canon(numstr, size): """ @param numstr: the string representation of an integer which will be canonicalized @param size: the size in 8-bit bytes (octets) that numbers of this kind should have; This number should almost always be EGTPConstants.SIZE_OF_UNIQS or EGTPConstants.SIZE_OF_MODULAR_VALUES @return: the canonical version of `numstr' for numbers of its type @precondition: `numstr' must be a string.: type(numstr) == types.StringType: "numstr: %s :: %s" % (humanreadable.hr(numstr), `type(numstr)`) @precondition: `numstr', not counting leading zeroes, is not too large.: len(strip_leading_zeroes(numstr)) <= size: "numstr: %s" % humanreadable.hr(numstr) """ assert type(numstr) == types.StringType, "precondition: `numstr' must be a string." + " -- " + "numstr: %s :: %s" % (humanreadable.hr(numstr), `type(numstr)`) assert len(strip_leading_zeroes(numstr)) <= size, "precondition: `numstr', not counting leading zeroes, is not too large." + " -- " + "numstr: %s" % humanreadable.hr(numstr) if len(numstr) >= size: return numstr[len(numstr) - size:] return operator.repeat('\000', size - len(numstr)) + numstr
def inmsg_handler(self, msg, lowerstrategy, strategy_id_for_debug): """ Processes an incoming message. @param lowerstrategy: a comm strategy which is suggested by the caller; Currently if the caller is a TCP comms handler, then this is a strategy for using the extant TCP connection, upon which `msg' arrived, to send further messages to the counterparty. If the caller is a Relay comms handler, then this is `None'. TODO: make it so that you consider using the same relay server to send back @param strategy_id_for_debug: is a unique identifier which the *lower-level* comms handler uses to identify `lowerstrategy'; This is only used for diagnostic output. Currently if the lower-level comms is TCP, and we don't yet know a public key which has signed messages that were sent over this TCP connection, then it is a random id, else it is the id of the public key which has signed messages that were sent over this TCP connection. If the lower-level comms is Relay, then this is `None'. @precondition: `msg' must be a string.: type(msg) == types.StringType: "msg: %s :: %s" % (humanreadable.hr(msg), humanreadable.hr(type(msg))) @precondition: `strategy_id_for_debug' must be None if and only if `lowerstrategy' is None.: (strategy_id_for_debug is None) == (lowerstrategy is None): "strategy_id_for_debug: %s, lowerstrategy: %s" % (humanreadable.hr(strategy_id_for_debug), humanreadable.hr(lowerstrategy)) """ assert type(msg) == types.StringType, "precondition: `msg' must be a string." + " -- " + "msg: %s :: %s" % (humanreadable.hr(msg), humanreadable.hr(type(msg))) assert (strategy_id_for_debug is None) == (lowerstrategy is None), "precondition: `strategy_id_for_debug' must be None if and only if `lowerstrategy' is None." + " -- " + "strategy_id_for_debug: %s, lowerstrategy: %s" % (humanreadable.hr(strategy_id_for_debug), humanreadable.hr(lowerstrategy)) try: counterparty_pub_key, cleartext = self._mesgen.parse(msg) except mesgen.Error, e: if isinstance(e, mesgen.SessionInvalidated): debugprint("%s.inmsg_handler(msg: %s, lowerstrategy: %s, strategy_id_for_debug: %s) got exceptions: %s\n", args=(self, msg, lowerstrategy, strategy_id_for_debug, e,), v=3, vs="crypto") return if lowerstrategy: if hasattr(lowerstrategy, 'asyncsock'): if config.REALLY_SLOW_DEBUG_MODE: debugprint("WARNING: a message arrived with suggested lowerstrategy %s, asyncsock: %s, strategy_id_for_debug: %s, that couldn't be decrypted. Perhaps it was cleartext, or garbled. The message was %s. The error was: %s, traceback: %s\n", args= (lowerstrategy.to_dict(), lowerstrategy.asyncsock, strategy_id_for_debug, msg, e, traceback.extract_stack(),), v=1, vs="crypto") else: debugprint("WARNING: a message arrived with suggested lowerstrategy %s, asyncsock: %s, strategy_id_for_debug: %s, that couldn't be decrypted. Perhaps it was cleartext, or garbled. The message was %s. The error was: %s\n", args= (lowerstrategy.to_dict(), lowerstrategy.asyncsock, strategy_id_for_debug, msg, e), v=1, vs="crypto") else: if config.REALLY_SLOW_DEBUG_MODE: debugprint("WARNING: a message arrived with suggested lowerstrategy %s, strategy_id_for_debug: %s, that couldn't be decrypted. Perhaps it was cleartext, or garbled. The message was %s. The error was: %s, traceback: %s\n", args=(lowerstrategy.to_dict(), strategy_id_for_debug, msg, e, traceback.extract_stack(),), v=1, vs="crypto") else: debugprint("WARNING: a message arrived with suggested lowerstrategy %s, strategy_id_for_debug: %s, that couldn't be decrypted. Perhaps it was cleartext, or garbled. The message was %s. The error was: %s\n", args=(lowerstrategy.to_dict(), strategy_id_for_debug, msg, e), v=1, vs="crypto") else: if config.REALLY_SLOW_DEBUG_MODE: debugprint("WARNING: a message arrived with suggested strategy_id_for_debug %s that couldn't be decrypted. Perhaps it was cleartext, or garbled. The message was %s. The error was: %s, traceback: %s\n", args=(strategy_id_for_debug, msg, e, traceback.extract_stack(),), v=1, vs="crypto") else: debugprint("WARNING: a message arrived with suggested strategy_id_for_debug %s that couldn't be decrypted. Perhaps it was cleartext, or garbled. The message was %s. The error was: %s\n", args=(strategy_id_for_debug, msg, e), v=1, vs="crypto") # if it is an UnknownSession error, attempt to send a note back down the lowerstrategy if it happens to be a two way connection if isinstance(e, mesgen.UnknownSession) and lowerstrategy: # XXX if all CommStrats are updated in the future to have a send() method, just use it if the CommStrat has a "twowaycomms" flag? if isinstance(lowerstrategy, CommStrat.TCP) and lowerstrategy.asyncsock: debugprint("sending an 'invalidate session' note back on the TCP connection\n", v=1, vs="CryptoCommsHandler") # send e.invalidate_session_msg back out this TCP Connection lowerstrategy.asyncsock.send(e.invalidate_session_msg) else: debugprint("message did not come via a two way CommStrat, cannot send an 'invalidate session'\n", v=3, vs="CryptoCommsHandler") return # drop it on the floor
def use_comm_strategy(self, counterparty_id, commstrat, orig_cs=None): """ There are several things to do to with this new suggested the comm strat. First, make sure that CryptoCommsHandler has a CommStrat.Crypto for this counterparty. Second, choose your favourite among available lowerstrategies. Third, if you are replacing the current one with the new one then forget the current one. Fourth, start using the new one. @param commstrat: a CommStrat.Crypto which is suggested to use; The `_lowerstrategy' may or may not be adopted depending on whether it is better than the current one. If you want to force adoption of a new strategy, call `forget_comm_strategy()' first. @precondition: This thread must be the DoQ thread.: DoQ.doq.is_currently_doq() @precondition: `counterparty_id' must be a binary id.: idlib.is_binary_id(counterparty_id): "counterparty_id: %s" % humanreadable.hr(counterparty_id) @precondition: `commstrat' must be a CommStrat.: isinstance(commstrat, CommStrat.CommStrat): "commstrat: %s :: %s" % (humanreadable.hr(commstrat), humanreadable.hr(type(commstrat)),) @precondition: `counterparty_id' must match the commstrat public key.: idlib.equals(idlib.make_id(commstrat._pubkey, 'broker'), counterparty_id): "counterparty_id: %s, commstrat: %s" % (humanreadable.hr(counterparty_id), humanreadable.hr(commstrat),) """ assert DoQ.doq.is_currently_doq(), "precondition: This thread must be the DoQ thread." assert idlib.is_binary_id(counterparty_id), "precondition: `counterparty_id' must be a binary id." + " -- " + "counterparty_id: %s" % humanreadable.hr(counterparty_id) assert isinstance(commstrat, CommStrat.CommStrat), "precondition: `commstrat' must be a CommStrat." + " -- " + "commstrat: %s :: %s" % (humanreadable.hr(commstrat), humanreadable.hr(type(commstrat)),) assert idlib.equals(idlib.make_id(commstrat._pubkey, 'broker'), counterparty_id), "precondition: `counterparty_id' must match the commstrat public key." + " -- " + "counterparty_id: %s, commstrat: %s" % (humanreadable.hr(counterparty_id), humanreadable.hr(commstrat),) # If we already have a CommStrat.Crypto object then we'll continue to use it (it might # have useful hint information in it) instead of the new one, but we'll examine the new # one in order to consider taking the newly suggested lowerstrategy. curcs = self._cid_to_cs.get(counterparty_id) if curcs: assert curcs._pubkey == commstrat._pubkey # This call to `choose_best_strategy()' choosing between the newly suggested lowerstrat and the one that is current stored in CryptoCommsHandler's _cid_to_cs dict. # The winner gets passed down to TCPCh (if it is a TCP comm strat), where `choose_best_strategy()' will be called again, to choose between it and the one that is current in TCPCommsHandler's _cid_to_cs dict. preferredlcs = CommStrat.choose_best_strategy(curcs._lowerstrategy, commstrat._lowerstrategy) curcs._lowerstrategy = preferredlcs # XXX why the dependency on the type? # answer: in the future, this will go away, when the CommStrat.TCP itself manages itself and we don't need to inform the _tcpch about it. if isinstance(curcs._lowerstrategy, CommStrat.TCP): self._tcpch.use_comm_strategy(counterparty_id, curcs._lowerstrategy) else: # New crypto comm strat! self._cid_to_cs[counterparty_id] = commstrat self._mesgen.store_key(commstrat._pubkey) if isinstance(commstrat._lowerstrategy, CommStrat.TCP): self._tcpch.use_comm_strategy(counterparty_id, commstrat._lowerstrategy)
def sort_by_preference_from_dict(self, counterparties, message_type, message_body): """ Cogitates on the possibility of sending each counterparty in counterparties the given message and returns a list sorted by order of preference of which counterparties to try to use. Disqualified counterparties are not included in the list at all. @param counterparties: a dict of key: counterparty_id, value: service_info_dict; It is okay to be an empty dict. @return: a list of (counterpartyid, info) tuples sorted into descending order of preference @precondition: `counterparties' must be a dict.: type(counterparties) is types.DictType: "counterparties: %s :: %s" % (humanreadable.hr(counterparties), humanreadable.hr(type(counterparties)),) @precondition: `message_type' must be a string.: type(message_type) == types.StringType """ assert type(counterparties) is types.DictType, "precondition: `counterparties' must be a dict." + " -- " + "counterparties: %s :: %s" % (hr(counterparties), hr(type(counterparties)),) assert type(message_type) == types.StringType, "precondition: `message_type' must be a string." # debugprint("sort_by_preference_dict(counterparties: %s, message_type:%s, message_body: %s)\n", args=(counterparties, message_type, message_body,), v=2, vs="MojoHandicapper") # contains (counterparty_id, cost) unsorted = [] for counterpartyid, contactinfo in counterparties.items(): cost = self._compute_handicap(counterpartyid, contactinfo, message_type=message_type, message_body=message_body) if cost is not DISQUALIFIED : unsorted.append((cost, i)) unsorted.sort() return map(lambda x: x[1], unsorted)