def __init__(self,my_keypair,hostname,port,opensock=None,mylistenport=481,myoversion=None): """ If opensock is not None, we assume this is a connection we accepted, and he initiates the Challenge/Response """ self.my_keypair = my_keypair self.b = BTConnection(hostname,port,opensock,mylistenport=mylistenport,myoversion=myoversion) if opensock: self.b.read_handshake_medium_rare() # Read challenge msg = self.b.recv() assert(msg[0] == CHALLENGE) randomB = bdecode(msg[1:]) [randomA,resp1_data] = self.create_good_response1(randomB,self.b.get_his_id()) self.b.send(resp1_data) # Read response2 msg = self.b.recv() assert(msg[0] == RESPONSE2) else: self.b.read_handshake() [rB,chal_data] = self.create_good_challenge() self.b.send(chal_data) resp1_data = self.b.recv() if DEBUG: print >>sys.stderr,"olconn: recv",len(resp1_data),"bytes" resp1_dict = bdecode(resp1_data[1:]) resp2_data = self.create_good_response2(rB,resp1_dict,self.b.get_his_id()) self.b.send(resp2_data) if DEBUG: print >>sys.stderr,"olconn: sent",len(resp2_data),"bytes"
def subtest_channelcast(self): print >>sys.stderr,time.asctime(),'-', "test: channelcast----------------------" s = OLConnection(self.my_keypair,'localhost',self.hisport) chcast = ChannelCastCore(None, s, self.session, None, log = '', dnsindb = None) #Send Empty ChannelCast message chdata = {} print >> sys.stderr, time.asctime(),'-', "Test Good ChannelCast", `chdata` msg = CHANNELCAST+bencode(chdata) s.send(msg) resp = s.recv() if len(resp) > 0: print >>sys.stderr,time.asctime(),'-', "test: channelcast: got",getMessageName(resp[0]) self.assert_(resp[0]==CHANNELCAST) print >>sys.stderr, time.asctime(),'-', "test: channelcast: got msg", `bdecode(resp[1:])` chdata_rcvd = bdecode(resp[1:]) self.assert_(validChannelCastMsg(chdata_rcvd)==True) s.close() #Now, send a bad ChannelCast message. # The other side should close the connection # Create bad message by manipulating a good one #bad infohash chdata = deepcopy(chdata_rcvd) for k,v in chdata.items(): v['infohash'] = 234 self.subtest_bad_channelcast(chdata) #bad torrentname chdata = deepcopy(chdata_rcvd) for k,v in chdata.items(): v['torrentname'] = 1231 self.subtest_bad_channelcast(chdata) #bad signature.. temporarily disabled. # Got to enable when signature validation in validChannelCastMsg are enabled # chdata = deepcopy(chdata_rcvd) # value_list = chdata.values() # if len(value_list)>0: # chdata['sdfg234sadf'] = value_list[0] # self.subtest_bad_channelcast(chdata) #Bad message format chdata = {'2343ww34':''} self.subtest_bad_channelcast(chdata) #Bad print>>sys.stderr, time.asctime(),'-', "End of channelcast test---------------------------"
def check_friendship(self,data,mtype,fwd,resp,dobdecode=True,source=None,dest=None): if dobdecode: d = bdecode(data) else: d = data print >>sys.stderr,"test: Got FRIENDSHIP",`d`,type(d) self.assert_(type(d) == DictType) self.assert_('msg type' in d) self.assert_(type(d['msg type']) == StringType) self.assert_(d['msg type'] == mtype) if mtype == RESP: self.assert_('response' in d) self.assert_(type(d['response']) == IntType) print >>sys.stderr,"test: COMPARE",`d['response']`,`resp` self.assert_(d['response'] == resp) elif mtype == FWD: self.assert_('source' in d) self.check_peer(d['source'],permid=source) self.assert_('dest' in d) self.check_peer(d['dest'],permid=dest) self.assert_('msg' in d) self.check_friendship(d['msg'],fwd,None,resp,dobdecode=False)
def subtest_good_friendship_req_fromhim(self,mtype,fwd=None,mresp=None): print >>sys.stderr,"test: good FRIENDSHIP req from him",mtype,fwd # He should try to forward the request to us, his friend try: self.destss.settimeout(330.0) conn, addr = self.destss.accept() s = OLConnection(self.dest_keypair,'',0,conn,self.destport) while True: resp = s.recv() self.assert_(len(resp) > 0) print >>sys.stderr,"test: good FRIENDSHIP fwd: Dest got reply",getMessageName(resp[0]) if resp[0] == FRIENDSHIP: break elif resp[0] == SOCIAL_OVERLAP: d = bdecode(resp[1:]) print >>sys.stderr,"test: SOCIAL OVERLAP",`d` pass else: self.assert_(False) except socket.timeout: print >> sys.stderr,"test: Timeout, bad, peer didn't connect to FWD dest" self.assert_(False) self.check_friendship(resp[1:],mtype,fwd,mresp,source=self.hispermid,dest=self.mypermid)
def got_proxy_have(self, permid, message, selversion): """ Handle the PROXY_HAVE message. @param permid: The permid of the peer who sent the message @param message: The message received @param selversion: """ if DEBUG: print >>sys.stderr, time.asctime(), "-", "coordinator: network_got_proxy_have: got_proxy_have" try: infohash = message[1:21] aggregated_string = bdecode(message[21:]) except: print >>sys.stderr, time.asctime(), "-", "coordinator: network_got_proxy_have: warning - bad data in PROXY_HAVE" return False # Add a task to find the appropriate Coordinator object method network_got_proxy_have_lambda = lambda: self.network_got_proxy_have( permid, infohash, selversion, aggregated_string ) self.launchmany.rawserver.add_task(network_got_proxy_have_lambda, 0) return True
def subtest_good_friendship_stats(self): """ Send a valid message-id from a registered crawler peer """ print >> sys.stderr, "-" * 80, "\ntest: good friendship stats" s = OLConnection(self.my_keypair, "localhost", self.hisport) t = time.time() - 100.0 msg_dict = {'current time': int(t)} payload = bencode(msg_dict) self.send_crawler_request(s, CRAWLER_FRIENDSHIP_STATS, 0, 0, payload) error, payload = self.receive_crawler_reply(s, CRAWLER_FRIENDSHIP_STATS, 0) assert error == 0 d = bdecode(payload) if DEBUG: print >> sys.stderr, "test: Got FRIENDSHIPSTATISTICS", ` d ` stats = d['stats'] self.assert_(len(stats) == 1) record = d['stats'][0] self.assert_(record[0] == bin2str(self.his_permid)) # source_permid self.assert_(record[1] == bin2str(self.some_permid)) # target_permid self.assert_(record[2] == 0) # isForwarder time.sleep(1) s.close()
def handle_crawler_request(self, permid, selversion, channel_id, message, reply_callback): """ Received a CRAWLER_FRIENDSHIP_QUERY request. @param permid The Crawler permid @param selversion The overlay protocol version @param channel_id Identifies a CRAWLER_REQUEST/CRAWLER_REPLY pair @param message The message payload @param reply_callback Call this function once to send the reply: reply_callback(payload [, error=123]) """ if DEBUG: print >> sys.stderr, "FriendshipCrawler: handle_friendship_crawler_database_query_request", message try: d = bdecode(message) stats = self.getStaticsFromFriendshipStatisticsTable( self.session.get_permid(), d['current time']) msg_dict = {'current time': d['current time'], 'stats': stats} msg = bencode(msg_dict) reply_callback(msg) except Exception, e: print_exc() reply_callback(str(e), 1)
def recv_query(self,permid,message,selversion): if selversion < OLPROTO_VER_SIXTH: return False # Unpack try: d = bdecode(message[1:]) except: if DEBUG: print >>sys.stderr,"rquery: Cannot bdecode QUERY message" #print_exc() return False if not isValidQuery(d,selversion): if DEBUG: print >>sys.stderr,"rquery: QUERY invalid",`d` return False # ACCESS CONTROL, INCLUDING CHECKING IF PEER HAS NOT EXCEEDED # QUERY QUOTUM IS DONE in Tribler/Core/RequestPolicy.py # # Process self.process_query(permid, d, selversion) return True
def check_response1(self, resp1_data, rB, myid): resp1 = bdecode(resp1_data) self.assert_(type(resp1) == DictType) self.assert_(resp1.has_key("certA")) self.assert_(resp1.has_key("rA")) self.assert_(resp1.has_key("B")) self.assert_(resp1.has_key("SA")) # show throw exception when key no good pubA = EC.pub_key_from_der(resp1["certA"]) rA = resp1["rA"] self.assert_(type(rA) == StringType) self.assert_(len(rA) == random_size) B = resp1["B"] self.assert_(type(B) == StringType) self.assert_(B, myid) SA = resp1["SA"] self.assert_(type(SA) == StringType) # verify signature sig_list = [rA, rB, myid] sig_data = bencode(sig_list) sig_hash = sha(sig_data).digest() self.assert_(pubA.verify_dsa_asn1(sig_hash, SA)) # Cannot resign the data with his keypair to double check. Signing # appears to yield different, supposedly valid sigs each time. return resp1
def check_chquery_reply(self,data): d = bdecode(data) self.assert_(type(d) == DictType) self.assert_(d.has_key('a')) self.assert_(d.has_key('id')) id = d['id'] self.assert_(type(id) == StringType)
def convert_BartercastDB(self): print >>sys.stderr, "convert_BartercastDB" db_path = os.path.join(self.bsddb_dir, 'bartercast.bsd') if not os.path.isfile(db_path): return bc_db = BarterCastDB.getInstance(self.bsddb_dir) insert_bc_sql = """ INSERT INTO BarterCast (peer_id_from, peer_id_to, downloaded, uploaded, last_seen, value) VALUES (?,?,?,?,?,?) """ values = [] for key,db_data in bc_db._data.iteritems(): try: permid_from, permid_to = bdecode(key) permid_id_from = self._getPeerID(permid_from) if permid_id_from is None: self._addPeerToDB(permid_from) permid_id_from = self._getPeerID(permid_from) permid_id_to = self._getPeerID(permid_to) if permid_id_to is None: self._addPeerToDB(permid_to) permid_id_to = self._getPeerID(permid_to) downloaded = db_data.get('downloaded', 0) uploaded = db_data.get('uploaded', 0) last_seen = db_data.get('last_seen', 0) value = db_data.get('value', 0) values.append((permid_id_from, permid_id_to, downloaded, uploaded, last_seen, value)) except Exception, msg: print >> sys.stderr, "error input for convert_BartercastDB:", key, db_data, Exception, msg
def gotBarterCastMessage(self, recv_msg, sender_permid, selversion): """ Received a bartercast message and handle it. Reply if needed """ if DEBUG: print >>sys.stderr,'bartercast: %s Received a BarterCast msg from %s'% (ctime(now()), self.bartercastdb.getName(sender_permid)) if not sender_permid or sender_permid == self.bartercastdb.my_permid: print >> sys.stderr, "bartercast: error - got BarterCastMsg from a None peer", \ sender_permid, recv_msg return False if MAX_BARTERCAST_LENGTH > 0 and len(recv_msg) > MAX_BARTERCAST_LENGTH: print >> sys.stderr, "bartercast: warning - got large BarterCastMsg", len(t) return False bartercast_data = {} try: bartercast_data = bdecode(recv_msg) except: print >> sys.stderr, "bartercast: warning, invalid bencoded data" return False try: # check bartercast message self.validBarterCastMsg(bartercast_data) except RuntimeError, msg: print >> sys.stderr, msg return False
def _test_response1(self,ss,gen_resp1,good): print >>sys.stderr,"test: myserver running:",gen_resp1 conn, addr = ss.accept() s = BTConnection('',0,conn) s.read_handshake_medium_rare() # Read challenge msg = s.recv() self.testcase.assert_(msg[0] == CHALLENGE) randomB = bdecode(msg[1:]) self.testcase.assert_(type(randomB) == StringType) self.testcase.assert_(len(randomB) == random_size) [randomA,resp1_data] = gen_resp1(randomB,s.get_his_id()) s.send(resp1_data) if good: # Read response2 msg = s.recv() self.testcase.assert_(msg[0] == RESPONSE2) self.check_response2(msg[1:],randomA,randomB,s.get_my_id()) # the connection should be intact, so this should not throw an # exception: time.sleep(5) s.send('bla') s.close() else: time.sleep(5) # the other side should not our bad RESPONSE1 this and close the # connection msg = s.recv() self.testcase.assert_(len(msg)==0) s.close()
def serialize(self): if self.signature is None: raise SerializationException("The content must be signed") pack = bdecode(self._packData()) pack.append(self.signature) return pack
def check_buddycast(self,data,oversion): d = bdecode(data) print >>sys.stderr,"test: Got BUDDYCAST",d.keys() #print >>sys.stderr,"test: Got CONTENT",`d` self.assert_(type(d) == DictType) self.assert_('ip' in d) self.assert_(type(d['ip']) == StringType) self.assert_('port' in d) self.assert_(type(d['port']) == IntType) self.assert_('name' in d) self.assert_(type(d['name']) == StringType) self.assert_('preferences' in d) self.check_preferences(d['preferences'],oversion) self.assert_('taste buddies' in d) self.check_taste_buddies(d['taste buddies'],oversion) self.assert_('random peers' in d) self.check_random_peers(d['random peers'],oversion ) if oversion >= 3: self.assert_('connectable' in d) #print >>sys.stderr,"CONNECTABLE TYPE",type(d['connectable']) self.assert_(type(d['connectable']) == IntType) if oversion >= 4: self.assert_('collected torrents' in d) self.check_collected_torrents(d['collected torrents'],oversion) if oversion >= 6: self.assert_('npeers' in d) self.assert_(type(d['npeers']) == IntType) self.assert_('nfiles' in d) self.assert_(type(d['nfiles']) == IntType) self.assert_('ndls' in d) self.assert_(type(d['ndls']) == IntType)
def check_get_metadata(self,data): infohash = bdecode(data) self.check_infohash(infohash) # Extra check: he can only ask us for metadata for an infohash we # gave him. self.assert_(infohash in self.myprefs)
def check_response1(self, resp1_data, rB, myid): resp1 = bdecode(resp1_data) self.assert_(type(resp1) == DictType) self.assert_(resp1.has_key('certA')) self.assert_(resp1.has_key('rA')) self.assert_(resp1.has_key('B')) self.assert_(resp1.has_key('SA')) # show throw exception when key no good pubA = EC.pub_key_from_der(resp1['certA']) rA = resp1['rA'] self.assert_(type(rA) == StringType) self.assert_(len(rA) == random_size) B = resp1['B'] self.assert_(type(B) == StringType) self.assert_(B, myid) SA = resp1['SA'] self.assert_(type(SA) == StringType) # verify signature sig_list = [rA, rB, myid] sig_data = bencode(sig_list) sig_hash = sha(sig_data).digest() self.assert_(pubA.verify_dsa_asn1(sig_hash, SA)) # Cannot resign the data with his keypair to double check. Signing # appears to yield different, supposedly valid sigs each time. return resp1
def recv_query(self, permid, message, selversion): if selversion < OLPROTO_VER_SIXTH: return False # Unpack try: d = bdecode(message[1:]) except: if DEBUG: print >> sys.stderr, "rquery: Cannot bdecode QUERY message" #print_exc() return False if not isValidQuery(d, selversion): if DEBUG: print >> sys.stderr, "rquery: QUERY invalid", ` d ` return False # ACCESS CONTROL, INCLUDING CHECKING IF PEER HAS NOT EXCEEDED # QUERY QUOTUM IS DONE in Tribler/Core/RequestPolicy.py # # Process self.process_query(permid, d, selversion) return True
def subtest_good_friendship_req_fromhim(self,mtype,fwd=None,mresp=None): print >>sys.stderr,time.asctime(),'-', "test: good FRIENDSHIP req from him",mtype,fwd # He should try to forward the request to us, his friend try: self.destss.settimeout(330.0) conn, addr = self.destss.accept() s = OLConnection(self.dest_keypair,'',0,conn,self.destport) while True: resp = s.recv() self.assert_(len(resp) > 0) print >>sys.stderr,time.asctime(),'-', "test: good FRIENDSHIP fwd: Dest got reply",getMessageName(resp[0]) if resp[0] == FRIENDSHIP: break elif resp[0] == SOCIAL_OVERLAP: d = bdecode(resp[1:]) print >>sys.stderr,time.asctime(),'-', "test: SOCIAL OVERLAP",`d` pass else: self.assert_(False) except socket.timeout: print >> sys.stderr,time.asctime(),'-', "test: Timeout, bad, peer didn't connect to FWD dest" self.assert_(False) self.check_friendship(resp[1:],mtype,fwd,mresp,source=self.hispermid,dest=self.mypermid)
def convert_BartercastDB(self): print >> sys.stderr, "convert_BartercastDB" db_path = os.path.join(self.bsddb_dir, 'bartercast.bsd') if not os.path.isfile(db_path): return bc_db = BarterCastDB.getInstance(self.bsddb_dir) insert_bc_sql = """ INSERT INTO BarterCast (peer_id_from, peer_id_to, downloaded, uploaded, last_seen, value) VALUES (?,?,?,?,?,?) """ values = [] for key, db_data in bc_db._data.iteritems(): try: permid_from, permid_to = bdecode(key) permid_id_from = self._getPeerID(permid_from) if permid_id_from is None: self._addPeerToDB(permid_from) permid_id_from = self._getPeerID(permid_from) permid_id_to = self._getPeerID(permid_to) if permid_id_to is None: self._addPeerToDB(permid_to) permid_id_to = self._getPeerID(permid_to) downloaded = db_data.get('downloaded', 0) uploaded = db_data.get('uploaded', 0) last_seen = db_data.get('last_seen', 0) value = db_data.get('value', 0) values.append((permid_id_from, permid_id_to, downloaded, uploaded, last_seen, value)) except Exception, msg: print >> sys.stderr, "error input for convert_BartercastDB:", key, db_data, Exception, msg
def check_rquery_reply(self,querytype,data,goodtorrents): d = bdecode(data) print >>sys.stderr,time.asctime(),'-', "test: Got reply",`d` self.assert_(type(d) == DictType) self.assert_(d.has_key('a')) self.check_adict(d['a']) self.assert_(d.has_key('id')) id = d['id'] self.assert_(type(id) == StringType) k = d['a'].keys() self.assert_(len(k) == 2) var1 = k[0] == goodtorrents.keys()[0] and k[1] == goodtorrents.keys()[1] var2 = k[0] == goodtorrents.keys()[1] and k[1] == goodtorrents.keys()[0] self.assert_(var1 or var2) # OLPROTO_VER_NINETH must contain torrent_size for infohash, torrent in d['a'].iteritems(): self.assert_(torrent['torrent_size'], goodtorrents[infohash]) if querytype.startswith("SIMPLE+METADATA"): for infohash, torrent in d['a'].iteritems(): self.assert_('metadata' in torrent) bmetainfo = torrent['metadata'] self.assert_(bmetainfo == goodtorrents[infohash])
def check_chquery_reply(self, data): d = bdecode(data) self.assert_(type(d) == DictType) self.assert_(d.has_key('a')) self.assert_(d.has_key('id')) id = d['id'] self.assert_(type(id) == StringType)
def StringToValue(self, value, type): # Assume that the value is already in the proper form # if it's not a string # (the case for some defaults) if value is not None: if not isinstance(value, unicode) and not isinstance(value, str): return value try: if type == "boolean": if value == "1": value = True else: value = False elif type == "int": value = int(value) elif type == "float": value = float(value) elif type == "color": red = int(value[0:3]) green = int(value[3:6]) blue = int(value[6:9]) value = wx.Colour(red, green, blue) elif type.startswith("bencode"): value = bdecode(value) except: value = None if value is None: value = self.defaultvalues[type] return value
def subtest_valid_nat_check(self): """ Send a CRAWLER_NATCHECK message to the Tribler instance. A reply containing a nat type should be returned. """ print >>sys.stderr, "-"*80, "\ntest: subtest_valid_nat_check" # make sure that the OLConnection IS in the crawler_db crawler_db = CrawlerDBHandler.getInstance() crawler_db.temporarilyAddCrawler(self.my_permid) s = OLConnection(self.my_keypair, "localhost", self.hisport, mylistenport=self.listen_port) self.send_crawler_request(s, CRAWLER_NATCHECK, 42, 0, "") s.close() if DEBUG: print >>sys.stderr, "test_natcheck: the nat-check code allows for a 10 minute delay in reporting the nat stats" self.listen_socket.settimeout(11 * 60) # wait for reply try: conn, addr = self.listen_socket.accept() except socket.timeout: if DEBUG: print >> sys.stderr,"test_natcheck: timeout, bad, peer didn't connect to send the crawler reply" assert False, "test_natcheck: timeout, bad, peer didn't connect to send the crawler reply" s = OLConnection(self.my_keypair, "", 0, conn, mylistenport=self.listen_port) # read reply error, payload = self.receive_crawler_reply(s, CRAWLER_NATCHECK, 42) assert error == 0 if DEBUG: print >>sys.stderr, "test_natcheck:", bdecode(payload) time.sleep(1)
def check_friendship(self,data,mtype,fwd,resp,dobdecode=True,source=None,dest=None): if dobdecode: d = bdecode(data) else: d = data print >>sys.stderr,time.asctime(),'-', "test: Got FRIENDSHIP",`d`,type(d) self.assert_(type(d) == DictType) self.assert_('msg type' in d) self.assert_(type(d['msg type']) == StringType) self.assert_(d['msg type'] == mtype) if mtype == RESP: self.assert_('response' in d) self.assert_(type(d['response']) == IntType) print >>sys.stderr,time.asctime(),'-', "test: COMPARE",`d['response']`,`resp` self.assert_(d['response'] == resp) elif mtype == FWD: self.assert_('source' in d) self.check_peer(d['source'],permid=source) self.assert_('dest' in d) self.check_peer(d['dest'],permid=dest) self.assert_('msg' in d) self.check_friendship(d['msg'],fwd,None,resp,dobdecode=False)
def handle_crawler_reply(self, permid, selversion, channel_id, channel_data, error, message, request_callback): """ Received a CRAWLER_FRIENDSHIP_STATS request. @param permid The Crawler permid @param selversion The overlay protocol version @param channel_id Identifies a CRAWLER_REQUEST/CRAWLER_REPLY pair @param error The error value. 0 indicates success. @param message The message payload @param request_callback Call this function one or more times to send the requests: request_callback(message_id, payload) """ if error: if DEBUG: print >> sys.stderr, "friendshipcrawler: handle_crawler_reply" print >> sys.stderr, "friendshipcrawler: error", error, message else: try: d = bdecode(message) except Exception: print_exc() else: if DEBUG: print >> sys.stderr, "friendshipcrawler: handle_crawler_reply" print >> sys.stderr, "friendshipcrawler: friendship: Got",`d` self.saveFriendshipStatistics(permid,d['current time'],d['stats']) return True
def run(self): announce = self._tracker + "?" + urlencode({"info_hash":self._swarm.get_info_hash(), "peer_id":self._swarm.get_peer_id(), "port":"12345", "compact":"1", "uploaded":"0", "downloaded":"0", "left":"-1", "event":"started"}) handle = urlopen(announce) if handle: body = handle.read() if body: try: body = bdecode(body) except: pass else: # using low-bandwidth binary format peers = [] peer_data = body["peers"] for x in range(0, len(peer_data), 6): key = peer_data[x:x+6] ip = ".".join([str(ord(i)) for i in peer_data[x:x+4]]) port = (ord(peer_data[x+4]) << 8) | ord(peer_data[x+5]) peers.append((ip, port)) if DEBUG: print >> sys.stderr, time.asctime(),'-', "MiniTracker.run() received", len(peers), "peer addresses from tracker" self._swarm.add_potential_peers(peers)
def test_createSingleResponseMessage(self): langUtil = LanguagesProvider.getLanguagesInstance() data = { 'permid' : testDestPermId, 'channel_id' : testChannelId, 'infohash' : testInfohash, 'subtitles' : {"eng" : "This is content 1", "nld": "This is content 2", "ita" : "This is content 3"}, 'selversion' : OLPROTO_VER_FOURTEENTH } langs = data['subtitles'].keys() bitmask = langUtil.langCodesToMask(langs) binaryBitmask = uintToBinaryString(bitmask, length=4) expextedMessage = SUBS + \ bencode(( data['channel_id'], data['infohash'], binaryBitmask, [data['subtitles']['eng'], data['subtitles']['ita'], data['subtitles']['nld']] )) msg = self.underTest._createSingleResponseMessage(data) decoded = bdecode(msg[1:]) self.assertEquals(expextedMessage, msg)
def handle_crawler_reply(self, permid, selversion, channel_id, channel_data, error, message, request_callback): """ Received a CRAWLER_FRIENDSHIP_STATS request. @param permid The Crawler permid @param selversion The overlay protocol version @param channel_id Identifies a CRAWLER_REQUEST/CRAWLER_REPLY pair @param error The error value. 0 indicates success. @param message The message payload @param request_callback Call this function one or more times to send the requests: request_callback(message_id, payload) """ if error: if DEBUG: print >> sys.stderr, "friendshipcrawler: handle_crawler_reply" print >> sys.stderr, "friendshipcrawler: error", error, message else: try: d = bdecode(message) except Exception: print_exc() else: if DEBUG: print >> sys.stderr, "friendshipcrawler: handle_crawler_reply" print >> sys.stderr, "friendshipcrawler: friendship: Got", ` d ` self.saveFriendshipStatistics(permid, d['current time'], d['stats']) return True
def setUpPostSession(self): """ override TestAsServer """ TestAsServer.setUpPostSession(self) self.mypermid = str(self.my_keypair.pub().get_der()) self.hispermid = str(self.his_keypair.pub().get_der()) # Calculating the infohash for proxyservice.test.torrent self.torrentfile = os.path.join('extend_hs_dir','proxyservice.test.torrent') # Read torrentfile to calculate the infohash torrentfile_content = open(self.torrentfile, "rb") # Decode all the file metainfo = bdecode(torrentfile_content.read()) # Re-encode only the info section self.infohash = hashlib.sha1(bencode(metainfo['info'])).digest() # Close the torrentfile torrentfile_content.close() # Add us as friend, so he will accept the ASK_FOR_HELP if False: # TEMP friendsdb = FriendDBHandler.getInstance() friendsdb.addFriend(self.mypermid) else: self.session.set_overlay_request_policy(AllowAllRequestPolicy()) self.session.set_download_states_callback(self.states_callback)
def subtest_good_friendship_stats(self): """ Send a valid message-id from a registered crawler peer """ print >>sys.stderr, time.asctime(),'-', "-"*80, "\ntest: good friendship stats" s = OLConnection(self.my_keypair, "localhost", self.hisport) t = time.time() - 100.0 msg_dict = {'current time':int(t)} payload = bencode(msg_dict) self.send_crawler_request(s, CRAWLER_FRIENDSHIP_STATS, 0, 0, payload) error, payload = self.receive_crawler_reply(s, CRAWLER_FRIENDSHIP_STATS, 0) assert error == 0 d = bdecode(payload) if DEBUG: print >>sys.stderr, time.asctime(),'-', "test: Got FRIENDSHIPSTATISTICS",`d` stats = d['stats'] self.assert_(len(stats) == 1) record = d['stats'][0] self.assert_(record[0] == bin2str(self.his_permid)) # source_permid self.assert_(record[1] == bin2str(self.some_permid)) # target_permid self.assert_(record[2] == 0) # isForwarder time.sleep(1) s.close()
def gotBarterCastMessage(self, recv_msg, sender_permid, selversion): """ Received a bartercast message and handle it. Reply if needed """ if DEBUG: print >> sys.stderr, 'bartercast: %s Received a BarterCast msg from %s' % ( ctime(now()), self.bartercastdb.getName(sender_permid)) if not sender_permid or sender_permid == self.bartercastdb.my_permid: print >> sys.stderr, "bartercast: error - got BarterCastMsg from a None peer", \ sender_permid, recv_msg return False if MAX_BARTERCAST_LENGTH > 0 and len(recv_msg) > MAX_BARTERCAST_LENGTH: print >> sys.stderr, "bartercast: warning - got large BarterCastMsg", len( t) return False bartercast_data = {} try: bartercast_data = bdecode(recv_msg) except: print >> sys.stderr, "bartercast: warning, invalid bencoded data" return False try: # check bartercast message self.validBarterCastMsg(bartercast_data) except RuntimeError, msg: print >> sys.stderr, msg return False
def read_and_send_metadata(self, permid, infohash, torrent_path, selversion): torrent_data = self.read_torrent(torrent_path) if torrent_data: # Arno: Don't send private torrents try: metainfo = bdecode(torrent_data) if 'info' in metainfo and 'private' in metainfo[ 'info'] and metainfo['info']['private']: if DEBUG: print >> sys.stderr, "metadata: Not sending torrent", ` torrent_path `, "because it is private" return 0 except: print_exc() return 0 if DEBUG: print >> sys.stderr, "metadata: sending torrent", ` torrent_path `, len( torrent_data) torrent = {} torrent['torrent_hash'] = infohash # P2PURLs: If URL compat then send URL tdef = TorrentDef.load_from_dict(metainfo) if selversion >= OLPROTO_VER_ELEVENTH and tdef.get_url_compat(): torrent['metatype'] = URL_MIME_TYPE torrent['metadata'] = tdef.get_url() else: torrent['metatype'] = TSTREAM_MIME_TYPE torrent['metadata'] = torrent_data if selversion >= OLPROTO_VER_FOURTH: data = self.torrent_db.getTorrent(infohash) if data is None: # DB inconsistency return 0 nleechers = data.get('leecher', -1) nseeders = data.get('seeder', -1) last_check_ago = int(time()) - data.get('last_check_time', 0) # relative time if last_check_ago < 0: last_check_ago = 0 status = data.get('status', 'unknown') torrent.update({ 'leecher': nleechers, 'seeder': nseeders, 'last_check_time': last_check_ago, 'status': status }) return self.do_send_metadata(permid, torrent, selversion) else: # deleted before sending it self.torrent_db.deleteTorrent(infohash, delete_file=True, updateFlag=True) if DEBUG: print >> sys.stderr, "metadata: GET_METADATA: no torrent data to send" return 0
def subtest_channel_keyword_query(self,nickname): print >>sys.stderr,time.asctime(),'-', "test: chquery keyword-----------------------------" s = OLConnection(self.my_keypair,'localhost',self.hisport) data = {} uq = u'CHANNEL k '+nickname data['q'] = uq.encode("UTF-8") data['id'] = 'b' * 20 msg = QUERY + bencode(data) s.send(msg) resp = s.recv() #print >> sys.stderr, time.asctime(),'-', "printing resp", resp if len(resp) > 0: print >>sys.stderr,time.asctime(),'-', "test: chquery: got",getMessageName(resp[0]) self.assert_(resp[0]==QUERY_REPLY) self.check_chquery_reply(resp[1:],nickname) print >>sys.stderr,time.asctime(),'-', "test:",`bdecode(resp[1:])` s.close()
def check_metadata(self,bdata,tdef): data = bdecode(bdata) # selversion >= OLPROTO_VER_ELEVENTH: for key in ['torrent_hash','metatype','metadata','last_check_time','status','leecher','seeder']: self.assert_(key in data) self.assertEqual(data['metatype'],URL_MIME_TYPE) self.assertEqual(data['torrent_hash'],tdef.get_infohash()) url = data['metadata'] cidx = url.find(':') self.assert_(cidx != -1) scheme = url[0:cidx] if url[cidx+1] == '/': # hierarchical URL qidx = url.find('?') self.assert_(qidx != -1) tracker = "http"+url[cidx:qidx] else: # Not yet supported by TorrentDef tracker = None qidx = cidx+1 query = url[qidx+1:] kvs = query.split('&') pt = {} for kv in kvs: if not '=' in kv: k = 'n' v = kv else: (k,v) = kv.split('=') if k == 'l': #length v = p2purl_decode_nnumber(v) elif k == 's': # piece size v = p2purl_decode_piecelength(v) elif k == 'r': # root hash v = p2purl_decode_base64url(v) elif k == 'k': # live key v = p2purl_decode_base64url(v) elif k == 'a': # live auth method pass elif k == 'b': # bitrate v = p2purl_decode_nnumber(v) pt[k] = v # Compare: self.assertEqual(P2PURL_SCHEME,scheme) self.assertEqual(tdef.get_tracker(),tracker) self.assertEqual(tdef.get_name(),pt['n']) self.assertEqual(tdef.get_length(),pt['l']) self.assertEqual(tdef.get_piece_length(),pt['s']) if 'r' in pt: self.assertEqual(tdef.get_infohash(),pt['r']) else: self.assertEqual(tdef.get_live_pubkey(),pt['k']) self.assertEqual(tdef.get_live_authmethod(),pt['a']) self.assertEqual(tdef.get_bitrate(),pt['b'])
def check_challenge(cdata): try: randomB = bdecode(cdata) except: return None if len(randomB) != num_random_bits/8: return None else: return randomB
def isValidRemoteVal(d, selversion): if not isinstance(d, dict): if DEBUG: print >> sys.stderr, "rqmh: reply: a: value not dict" return False if selversion >= OLPROTO_VER_TWELFTH: if not ('content_name' in d and 'length' in d and 'leecher' in d and 'seeder' in d and 'category' in d and 'torrent_size' in d and 'channel_permid' in d and 'channel_name' in d): if DEBUG: print >> sys.stderr, "rqmh: reply: torrentrec12: key missing, got", d.keys( ) return False if 'metatype' in d and 'metadata' in d: try: metatype = d['metatype'] metadata = d['metadata'] if metatype == URL_MIME_TYPE: tdef = TorrentDef.load_from_url(metadata) else: metainfo = bdecode(metadata) tdef = TorrentDef.load_from_dict(metainfo) except: if DEBUG: print >> sys.stderr, "rqmh: reply: torrentrec12: metadata invalid" print_exc() return False elif selversion >= OLPROTO_VER_ELEVENTH: if not ('content_name' in d and 'length' in d and 'leecher' in d and 'seeder' in d and 'category' in d and 'torrent_size' in d and 'channel_permid' in d and 'channel_name' in d): if DEBUG: print >> sys.stderr, "rqmh: reply: torrentrec11: key missing, got", d.keys( ) return False elif selversion >= OLPROTO_VER_NINETH: if not ('content_name' in d and 'length' in d and 'leecher' in d and 'seeder' in d and 'category' in d and 'torrent_size' in d): if DEBUG: print >> sys.stderr, "rqmh: reply: torrentrec9: key missing, got", d.keys( ) return False else: if not ('content_name' in d and 'length' in d and 'leecher' in d and 'seeder' in d and 'category' in d): if DEBUG: print >> sys.stderr, "rqmh: reply: torrentrec6: key missing, got", d.keys( ) return False # if not (isinstance(d['content_name'],str) and isinstance(d['length'],int) and isinstance(d['leecher'],int) and isinstance(d['seeder'],int)): # return False # if len(d) > 4: # no other keys # return False return True
def _read(stream): """ Internal class method that reads a torrent file from stream, checks it for correctness and sets self.input and self.metainfo accordingly. """ bdata = stream.read() stream.close() data = bdecode(bdata) #print >>sys.stderr,data return TorrentDef._create(data)
def check_bartercast(self, data): d = bdecode(data) print "Received data:" print d self.assert_(type(d) == DictType) self.assert_(d.has_key('data')) self.check_bartercast_data(d['data'])
def check_bartercast(self,data): d = bdecode(data) print "Received data:" print d self.assert_(type(d) == DictType) self.assert_(d.has_key('data')) self.check_bartercast_data(d['data'])
def olthread_process_dialback_reply(self, dns, message): # Called by overlay thread # 1. Yes, we're reachable, now just matter of determining ext IP self.dbreach = True # 2. Authentication: did I ask this peer? permid = self.olthread_permid_of_asked_peer(dns) if permid is None: if DEBUG: print >> sys.stderr, "dialback: DIALBACK_REPLY: Got reply from peer I didn't ask", dns return False del self.peers_asked[permid] # 3. See what he sent us try: myip = bdecode(message[1:]) except: print_exc() if DEBUG: print >> sys.stderr, "dialback: DIALBACK_REPLY: error becoding" return False if not isValidIP(myip): if DEBUG: print >> sys.stderr, "dialback: DIALBACK_REPLY: invalid IP" return False # 4. See if superpeer, then we're done, trusted source if self.trust_superpeers: superpeers = self.superpeer_db.getSuperPeers() if permid in superpeers: if DEBUG: print >> sys.stderr, "dialback: DIALBACK_REPLY: superpeer said my IP address is", myip, "setting it to that" self.consensusip = myip self.fromsuperpeer = True else: # 5, 6. 7, 8. Record this peers opinion and see if we get a # majority vote. # self.myips, consensusip = tally_opinion(myip, self.myips, PEERS_TO_AGREE) if self.consensusip is None: self.consensusip = consensusip # 8. Change IP address if different if self.consensusip is not None: self.launchmany.dialback_got_ext_ip_callback(self.consensusip) if DEBUG: print >> sys.stderr, "dialback: DIALBACK_REPLY: I think my IP address is", self.old_ext_ip, "others say", self.consensusip, ", setting it to latter" # 9. Notify GUI that we are connectable self.launchmany.dialback_reachable_callback() return True
def olthread_process_dialback_reply(self,dns,message): # Called by overlay thread # 1. Yes, we're reachable, now just matter of determining ext IP self.dbreach = True # 2. Authentication: did I ask this peer? permid = self.olthread_permid_of_asked_peer(dns) if permid is None: if DEBUG: print >> sys.stderr,"dialback: DIALBACK_REPLY: Got reply from peer I didn't ask",dns return False del self.peers_asked[permid] # 3. See what he sent us try: myip = bdecode(message[1:]) except: print_exc() if DEBUG: print >> sys.stderr,"dialback: DIALBACK_REPLY: error becoding" return False if not isValidIP(myip): if DEBUG: print >> sys.stderr,"dialback: DIALBACK_REPLY: invalid IP" return False # 4. See if superpeer, then we're done, trusted source if self.trust_superpeers: superpeers = self.superpeer_db.getSuperPeers() if permid in superpeers: if DEBUG: print >> sys.stderr,"dialback: DIALBACK_REPLY: superpeer said my IP address is",myip,"setting it to that" self.consensusip = myip self.fromsuperpeer = True else: # 5, 6. 7, 8. Record this peers opinion and see if we get a # majority vote. # self.myips,consensusip = tally_opinion(myip,self.myips,PEERS_TO_AGREE) if self.consensusip is None: self.consensusip = consensusip # 8. Change IP address if different if self.consensusip is not None: self.launchmany.dialback_got_ext_ip_callback(self.consensusip) if DEBUG: print >> sys.stderr,"dialback: DIALBACK_REPLY: I think my IP address is",self.old_ext_ip,"others say",self.consensusip,", setting it to latter" # 9. Notify GUI that we are connectable self.launchmany.dialback_reachable_callback() return True
def check_reserve_pieces(self, data): # torrent_hash + 1-byte all_or_nothing + bencode([piece num,...]) self.assert_(len(data) > 21) infohash = data[0:20] allflag = data[20] plist = bdecode(data[21:]) self.assert_(infohash == self.infohash) self.assert_(type(plist) == ListType) return plist
def __init__(self, my_keypair, hostname, port, opensock=None, mylistenport=481, myoversion=None): """ If opensock is not None, we assume this is a connection we accepted, and he initiates the Challenge/Response """ self.my_keypair = my_keypair self.b = BTConnection(hostname, port, opensock, mylistenport=mylistenport, myoversion=myoversion) if opensock: self.b.read_handshake_medium_rare() # Read challenge msg = self.b.recv() assert (msg[0] == CHALLENGE) randomB = bdecode(msg[1:]) [randomA, resp1_data] = self.create_good_response1(randomB, self.b.get_his_id()) self.b.send(resp1_data) # Read response2 msg = self.b.recv() assert (msg[0] == RESPONSE2) else: self.b.read_handshake() [rB, chal_data] = self.create_good_challenge() self.b.send(chal_data) resp1_data = self.b.recv() if DEBUG: print >> sys.stderr, "olconn: recv", len(resp1_data), "bytes" resp1_dict = bdecode(resp1_data[1:]) resp2_data = self.create_good_response2(rB, resp1_dict, self.b.get_his_id()) self.b.send(resp2_data) if DEBUG: print >> sys.stderr, "olconn: sent", len(resp2_data), "bytes"
def check_tribler_extend_hs(self,data): self.assert_(data[0] == chr(0)) d = bdecode(data[1:]) self.assert_(type(d) == DictType) self.assert_('m' in d.keys()) m = d['m'] self.assert_(type(m) == DictType) self.assert_('Tr_hashpiece' in m.keys()) val = m['Tr_hashpiece'] self.assert_(type(val) == IntType) self.assert_(val == 250)
def metadata_id_from_extend_handshake(self, data): assert data[0] == chr(0) d = bdecode(data[1:]) assert isinstance(d, dict) assert 'm' in d.keys() m = d['m'] assert isinstance(m, dict) assert "ut_metadata" in m.keys() val = m["ut_metadata"] assert isinstance(val, int) return val
def check_g2g_v2(self, data, g2g_id): self.assert_(data[0] == chr(g2g_id)) d = bdecode(data[1:]) print >> sys.stderr, "test: l is", ` d ` self.assert_(type(d) == DictType) for k, v in d.iteritems(): self.assert_(type(k) == StringType) self.assert_(type(v) == StringType) self.assert_(ord(k) > 0) self.assert_(ord(v) <= 100)
def check_rquery(self, data): d = bdecode(data) self.assert_(type(d) == DictType) self.assert_(d.has_key('q')) q = d['q'] self.assert_(type(q) == StringType) self.assert_(d.has_key('id')) id = d['id'] self.assert_(type(id) == StringType) self.assert_(q == self.query) return d['id']
def deserialize(encoded): if not encoded: raise InvalidPOAException("Cannot deserialize nothing") try: list = bdecode(encoded) if len(list) < 5: raise InvalidPOAException("Too few entries (got %d, expected 5)"%len(list)) return POA(list[0], list[1], list[2], expire_time=list[3], signature=list[4]) except Exception,e: raise InvalidPOAException("De-serialization failed (%s)"%e)
def check_tribler_extend_hs(self, data): self.assert_(data[0] == chr(0)) d = bdecode(data[1:]) self.assert_(type(d) == DictType) self.assert_('m' in d.keys()) m = d['m'] self.assert_(type(m) == DictType) self.assert_('Tr_OVERLAYSWARM' in m.keys()) val = m['Tr_OVERLAYSWARM'] self.assert_(type(val) == IntType) self.assert_(val == 253) print >> sys.stderr, "test: Reply is", ` d `
def gotUdpConnectReply(self, permid, selversion, channel_id, channel_data, error, mhr_msg, request_callback): if DEBUG: print >> sys.stderr, "NatCheckMsgHandler: gotMakeHoleReplyMessage" try: mhr_data = bdecode(mhr_msg) except: print_exc() print >> sys.stderr, "NatCheckMsgHandler: bad encoded data:", mhr_msg return False if DEBUG: print >> sys.stderr, "NatCheckMsgHandler: message is", mhr_data try: request_id, reply = mhr_data.split(":") except: print_exc() print >> sys.stderr, "NatCheckMsgHandler: error in received data:", mhr_data return False if DEBUG: print >> sys.stderr, "NatCheckMsgHandler: request_id is", request_id if request_id in self.trav: if DEBUG: print >> sys.stderr, "NatCheckMsgHandler: request_id is in the list" peer, value = self.trav[request_id] if peer == None: # first peer reply if DEBUG: print >> sys.stderr, "NatCheckMsgHandler: first peer reply" self.trav[request_id] = (( permid, self._secure_overlay.get_dns_from_peerdb(permid)), reply) elif type(peer) == TupleType: # second peer reply if DEBUG: print >> sys.stderr, "NatCheckMsgHandler: second peer reply" # Register peerinfo on file self._file2.write("; ".join( (strftime("%Y/%m/%d %H:%M:%S"), " REPLY", request_id, show_permid(peer[0]), str(peer[1]), value, show_permid(permid), str(self._secure_overlay.get_dns_from_peerdb(permid)), reply, "\n"))) del self.trav[request_id] self._file2.flush()
def gotChannelCastMessage(self, recv_msg, sender_permid, selversion): """ Receive and handle a ChannelCast message """ # ChannelCast feature starts from eleventh version; hence, do not receive from lower version peers if selversion < OLPROTO_VER_ELEVENTH: if DEBUG: print >> sys.stderr, "Do not receive from lower version peer:", selversion return if DEBUG: print >> sys.stderr, 'channelcast: Received a msg from ', permid_for_user( sender_permid) print >> sys.stderr, " my_permid=", permid_for_user(self.my_permid) if not sender_permid or sender_permid == self.my_permid: if DEBUG: print >> sys.stderr, "channelcast: warning - got channelcastMsg from a None/Self peer", \ permid_for_user(sender_permid), recv_msg return False #if len(recv_msg) > self.max_length: # if DEBUG: # print >> sys.stderr, "channelcast: warning - got large channelCastHaveMsg", len(recv_msg) # return False channelcast_data = {} try: channelcast_data = bdecode(recv_msg) except: print >> sys.stderr, "channelcast: warning, invalid bencoded data" return False # check message-structure if not validChannelCastMsg(channelcast_data): print >> sys.stderr, "channelcast: invalid channelcast_message" return False self.handleChannelCastMsg(sender_permid, channelcast_data) #Log RECV_MSG of uncompressed message if self.log: dns = self.dnsindb(sender_permid) if dns: ip, port = dns MSG_ID = "CHANNELCAST" msg = repr(channelcast_data) self.overlay_log('RECV_MSG', ip, port, show_permid(sender_permid), selversion, MSG_ID, msg) return True
def got_pieces_reserved(self, permid, message, selversion): try: infohash = message[1:21] pieces = bdecode(message[21:]) except: print >> sys.stderr, "helper: warning: bad data in PIECES_RESERVED message" return False network_got_pieces_reserved_lambda = lambda: self.network_got_pieces_reserved( permid, message, selversion, infohash, pieces) self.session.lm.rawserver.add_task(network_got_pieces_reserved_lambda, 0) return True
def valid_metadata(self, infohash, metadata): try: metainfo = bdecode(metadata) tdef = TorrentDef.load_from_dict(metainfo) got_infohash = tdef.get_infohash() if infohash != got_infohash: print >> sys.stderr, "metadata: infohash doesn't match the torrent " + \ "hash. Required: " + `infohash` + ", but got: " + `got_infohash` return False return True except: print_exc() #print >> sys.stderr, "problem metadata:", repr(metadata) return False
def check_response2(rdata2,randomA,peeridA,randomB,peeridB): try: response2 = bdecode(rdata2) except: return None if response2['A'] != peeridA: return None pubB_der = response2['certB'] pubB = EC.pub_key_from_der(pubB_der) sigB = response2['SB'] if verify_response(randomB,randomA,peeridA,pubB,sigB): return pubB else: return None