# Written by Jie Yang # see LICENSE.txt for license information import os import socket import sys import cPickle from ipinfo import IPInfo from threading import Timer class MyPeer: """ This class presents the user himself """ def __init__(self, ABCTorrent): self.torrent = ABCTorrent self.statistics = None self.ip = str(socket.gethostbyname(socket.gethostname())) self.ip_info = IPInfo.lookupIPInfo(self.ip) self.display = False #print "create my peer" def updateStatistics(self, statistics): self.statistics = statistics class BTPeer: """ This class presents an actived peer. It contains all information about this peer, displays this peer in the world map, and manages the popup info window """ def __init__(self, bt_info, ABCTorrent, rawserver = None, permid=''): self.torrent = ABCTorrent self.bt_info = bt_info self.active = True self.ip = bt_info['ip'] self.permid = permid # When a peer comes can I get its PermID?? if self.permid: # Use PermID by default self.id_type = 'permid' else: self.id_type = 'ip' self.id = self.ip self.ip_info = None self.torrent.peer_swarm[self.ip] = self ## Arno: using the raw server doesn't work. It delays normal ## communication too much. HACK IT! FIXME if too much timers allocated #rawserver.add_task(self.lookupIPInfo, 0) try: t = Timer(0,self.lookupIPInfo) t.setDaemon(True) # make them stop on exit, don't wait t.start() except: pass def updateBTInfo(self, bt_info): self.bt_info.update(bt_info) def lookupIPInfo(self): self.ip_info = IPInfo.lookupIPInfo(self.ip) class BTBuddy: """ This class presents a bater buddy who used/is using a same bittorrent file as you and was seen by you. """ # Buddy_swarm = {} # all the buddies which the user has ever seen def __init__(self): self.peer = {} self.peer['peer_id'] = btpeer.id self.peer['contact'] = {} # msn:'', skype:'', email:[], phone:[] etc. self.peer['dtotal'] = 0 self.peer['utotal'] = 0 self.peer['max_uprate'] = 0 self.peer['max_downrate'] = 0 self.peer['max_speed'] = 0 self.peer['meet_times'] = 0 # Times we meet again self.peer['friend_layer'] = 0 # 0: not friend, 1: your friend, 2: friend of your friend, etc. self.peer['torrents'] = self.torrents = [] # All torrents this buddy ever used self.peer['lastfile'] = '' # All files this buddy ever downloaded self.dtotal = {} # total download, each item is a torrent self.utotal = {} self.old_dtotal = 0 self.old_utotal = 0 PeerList.append(self.peer) def updateByOpen(self, record): """ restore the buddy's values by reading saved file """ self.peer_id = record['peer_id'] self.peer['contact'] = record['contact'] self.old_dtotal = self.peer['dtotal'] = record['dtotal'] self.old_utotal = self.peer['utotal'] = record['utotal'] self.peer['max_uprate'] = record['max_uprate'] self.peer['max_downrate'] = record['max_downrate'] self.peer['max_speed'] = record['max_speed'] self.peer['meet_times'] = record['meet_times'] self.peer['friend_layer'] = record['friend_layer'] self.peer['torrents'] = record['torrents'] self.peer['lastfile'] = record['lastfile'] def updateByBTPeer(self, btpeer, torrent_id): """ update the buddy by yourself """ self.dtotal[torrent_id] = btpeer.dtotal self.utotal[torrent_id] = btpeer.utotal self.peer['dtotal'] = self.old_dtotal + sum(self.dtotal.values()) self.peer['utotal'] = self.old_utotal + sum(self.utotal.values()) if btpeer.speed > self.peer['max_speed']: self.peer['max_speed'] = btpeer.speed if btpeer.uprate > self.peer['max_uprate']: self.peer['max_uprate'] = btpeer.uprate if btpeer.downrate > self.peer['max_downrate']: self.peer['max_downrate'] = btpeer.downrate def updateByFriend(self, friend): """ update the buddy by your friends """ self.peer_id = friend['peer_id'] self.peer['contact'] = friend['contact'] self.peer['max_uprate'] = friend['max_uprate'] self.peer['max_downrate'] = friend['max_downrate'] self.peer['max_speed'] = friend['max_speed'] self.peer['friend_layer'] = friend['friend_layer'] + 1 # friend of friend self.peer['torrents'] = friend['torrents'] self.peer['lastfile'] = friend['lastfile'] def addTorrent(self, ABCTorrent): """ add a torrent into the buddy's torrent list """ self.peer['lastfile'] = ABCTorrent.filename try: idx = self.torrents.index(ABCTorrent.id) # test if this torrent appeared before return except: pass BTTorrent(torrent) # add a new torrent and insert it into Torrent_list self.torrents.append(torrent.id) def meetAgain(self, torrent=None): self.peer['meet_times'] += 1 if torrent is not None: self.addTorrent(torrent) #TODO: after lunch.... def update_info(self, bt_id, bt_info): assert self.torrents.has_key(bt_id) self.torrents[bt_id].update_info(bt_info) def statistics(self): self.filelist = [] self.total_up = 0 self.total_down = 0 self.max_uprate = 0 self.max_downrate = 0 for torrent in self.torrents.values(): self.filelist.append(torrent.filename) self.total_up += torrent.total_up self.total_down += torrent.total_down if torrent.max_uprate > self.max_uprate: self.max_uprate = torrent.max_uprate if torrent.max_downrate > self.max_downrate: self.max_downrate = torrent.max_downrate def loadBuddySwarm(): """ Load Buddy_swarm from disk """ file_path = "buddy.dat" print "Loading buddy list from", file_path, "..." try: buddy_file = open(file_path, "r") BTBuddy.Buddy_swarm = cPickle.load(buddy_file) buddy_file.close() except: pass loadBuddySwarm = staticmethod(loadBuddySwarm) def saveBuddySwarm(): """ Save Buddy_swarm on disk """ file_path = "buddy.dat" try: buddy_file = open(file_path, "w") except IOError, message: print >> sys.stderr, "Buddy file", file_path, "could not be opened:", message return try: cPickle.dump(BTBuddy.Buddy_swarm, buddy_file) except Exception, message: pass buddy_file.close() saveBuddySwarm = staticmethod(saveBuddySwarm) class BTTorrent: """ Torrent information of each buddy """ def __init__(self, ABCTorrent): self.torrent = {} self.torrent['id'] = ABCTorrent.id self.torrent['filename'] = ABCTorrent.filename self.torrent['description'] = '' self.torrent['tags'] = [] # for future extension self.torrent['size'] = ABCTorrent.realsize self.torrent['time'] = os.time() def __str__(self): return self.filename def update_info(self, bt_info): self.total_up = bt_info['utotal'] self.total_down = bt_info['dtotal'] #TODO: find stable up/down rate, avg rate, total if bt_info['uprate'] > self.max_uprate: self.max_uprate = bt_info['uprate'] if bt_info['downrate'] > self.max_downrate: self.max_downrate = bt_info['downrate'] def loadTorrentStore(): """ Load Torrent_store from disk """ file_path = "torrent.dat" print "Loading torrent list from", file_path, "..." try: torrent_file = open(file_path, "r") BTTorrent.Torrent_store = cPickle.load(torrent_file) torrent_file.close() except: pass loadTorrentStore = staticmethod(loadTorrentStore) def saveTorrentStore(): """ Save Torrent_store on disk """ file_path = "torrent.dat" print "saving torrent store ... " try: torrent_file = open(file_path, "w") except Exception, message: print "Error in saveTorrentStore, open:", message pass try: cPickle.dump(BTTorrent.Torrent_store, torrent_file) except Exception, message: print "Error in saveTorrentStore, dump:", message pass torrent_file.close() saveTorrentStore = staticmethod(saveTorrentStore) class BTFriend: """ This class presents a friend of you. You trusts him/her and can upload or download his/her files. """ def __init__(self, id_type, id): self.id_type = id_type self.id = id self.your_trust = 8.0 self.general_trust = 8.0 self.buddy = None Friend_swarm = {} def getBuddy(self): if BTBuddy.Buddy_swarm.has_key(self.id): return BTBuddy.Buddy_swarm[self.id] else: pass # error! if __name__ == '__main__': class ABCTorrent: def __init__(self, id): self.id = id self.peer_swarm = {} self.filename = str(id) BTBuddy.loadBuddySwarm() if not BTBuddy.Buddy_swarm: for i in range(30): num_ip = 7 num_torrent = 23 bt = ABCTorrent(i % num_torrent) bt_info = {'ip':str(i % num_ip)} peer = BTPeer(bt_info, bt) # print Buddy_swarm for buddy_id in BTBuddy.Buddy_swarm: print BTBuddy.Buddy_swarm[buddy_id].id, BTBuddy.Buddy_swarm[buddy_id].torrents.keys() BTBuddy.saveBuddySwarm()