friend.py :  » Network » Rufus-BitTorrent-Client » Rufus_0.7.0_src » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Rufus BitTorrent Client 
Rufus BitTorrent Client » Rufus_0.7.0_src » friend.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------------
# Name:        friend.py
# Purpose:     
#
# Author:      Jeremy Arendt
#
# Created:     2004/24/02
# RCS-ID:      $Id: friend.py,v 1.6 2005/10/23 21:38:03 Inigo Exp $
# Copyright:   (c) 2002
# Licence:     See G3.LICENCE
#-----------------------------------------------------------------------------

#from g3peerid import *
from traceback import print_exc
from random import random,shuffle
from time import time
from os.path import join
import ConfigParser
from g3rpcclient import T_G3RPCCLient
from threading import Lock
from socket import gethostbyname
import re
import sys
import os
import os.path

if sys.platform == "win32":   
    win32_flag = True
else:
    win32_flag = False

ADDFRIENDTEMP = 12
ADDFOETEMP  = 10
REMOVEFOE = 11
GOTANNOUNCE = 0
GOTRENOUNCE = 9


class Friend:
    def __init__(self, ip, peerid):
        self.lastupdate = time()
        self.name = peerid
        self.peerid = peerid
        self.ip = ip

        self.sharedfiles = []
        self.total_up = 0
        self.total_down = 0
        self.type = 0
        self.online = False
        self.temp = False

    def AddSharedFile(self, port, infohash):
        self.lastupdate = time()
        for file in self.sharedfiles:
            if file[0] == infohash and file[1] == port:
                return
            elif file[0] == infohash:
                file[1] = port
                return
            elif file[1] == port:
                file[0] = infohash
                return
            
        self.sharedfiles.append( [infohash, port] )
    
    def RemoveSharedFile(self, port, infohash):
        self.lastupdate = time()
        for file in self.sharedfiles:
            if file[0] == infohash and file[1] == port:
                self.sharedfiles.remove(file)
                return
            
    def HasFile(self, infohash):
        for hash, port in self.sharedfiles:
            if hash == infohash:
                return (hash, port)
        return None
                
    def PrintInfo(self):
        print "name: %s" % GetPeerName(self.peerid)
        print "ip: %s" % self.ip
        print "id: %s" % self.peerid
        print "sharedfiles: %s" % self.sharedfiles
    
    def IsMyFriend(self):
        return self.type


class Foe:
    def __init__(self, ip, name, temp=True):
        self.ip = ip
        self.temp = temp
        self.name = name
    
class MyFriend(Friend, T_G3RPCCLient):
    def __init__(self, ip, peerid, btconfig):
        Friend.__init__(self, ip, peerid)
        T_G3RPCCLient.__init__(self, btconfig, ip)
        self.type = 1
        
    def AnnounceHashes(self, infohashes):
        for h in infohashes:
            self.Announce(self.ip, h[2], h[1], h[0])
    
    def RenounceHashes(self, infohashes):
        for h in infohashes:
            self.Renounce(self.ip, h[2], h[1], h[0])

class FriendList:
    def __init__(self, btconfig):
        self.config = {'timeout': 90}
        self.friends = []
        self.foes = []
        self.last_live_files = []
        self.btconfig = btconfig
        path = self.btconfig.Get("path")

        if win32_flag:
            self.friends_file = join(path, "friends.ini")
        else:
            self.friends_file = join(os.path.expanduser('~/.Rufus'), 'friends.ini')        
        
        self.index = 0
        self.mod_lock = Lock()
        self.rr_pivot = 0
        
    def __iter__(self):
        self.index = 0

        return self
    
    def __len__(self):
        return len(self.friends)
    
    def next(self):
        i = self.index
        if len(self.friends) == 0 or i == len(self.friends):

            raise StopIteration
            return
        
        self.index += 1
        return self.friends[i]
    
    
    def StartBroadcaster(self):
        self.broadcaster.Start()
    
    def StopBroadcaster(self):
        self.broadcaster.Stop()
        
    def Save(self):
        # write out to file
        print 'Saving Friend List'
        try:
            cp = ConfigParser.ConfigParser()

            cp.add_section('friends')
            i = 0
            for f in self.friends:
                if f.IsMyFriend() and not f.temp:
                    cp.set('friends', str(i), [f.name, f.ip])
                    i += 1
            
            cp.add_section('foes')
            i = 0
            for f in self.foes:
                if not f.temp:
                    cp.set('foes', str(i), [f.name, f.ip])
                    i += 1
                    
            file = open(self.friends_file, 'w')
            cp.write(file)
            file.close()
        except IOError, e:
            print "ERROR: writing to friends ini file -", str(e)
        except:
            print "ERROR: writing to friends ini file"
    
    def Load(self):
        if os.path.exists(self.friends_file):
            #regex to check for IP address 
            ipregex = re.compile("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
            # load from file
            print 'Loading Friend List'
            try:
                cp = ConfigParser.ConfigParser()
                file = open(self.friends_file, 'r')
                cp.readfp(file)
                items = cp.items('friends')
                
                for key, param in items:
                    param = eval(param)
                    name = param[0]
                    ip = param[1]
                    if not ipregex.match( param[1] ):
                        try:
                            ip = gethostbyname(param[1])
                        except:
                            ip = "0.0.0.0" #if error with DNS lookup set ip to this
                    self.AddFriend(ip, CreatePeerId(name), True, False)
                
                items = cp.items('foes')
                
                for key, param in items:
                    param = eval(param)
                    name = param[0]
                    ip = param[1]
                    if not ipregex.match( param[1] ):
                        try:
                            ip = gethostbyname(param[1])
                        except:
                            ip = "0.0.0.0" #if error with DNS lookup set ip to this
                    self.AddFoe(ip, name, False)
                        
                file.close()
            except IOError, e:
                print "ERROR: accessing friends.ini - ", str(e)
            except (ConfigParser.MissingSectionHeaderError, ConfigParser.NoSectionError), e:
                print "ERROR: processing friends.ini - ", str(e)
            
    
    def GotUpdate(self, ip, peerid, msgtype, data):
        if msgtype == GOTANNOUNCE:
            friend = self.AddFriend(ip, peerid)
            friend.AddSharedFile(data[0], data[1])

        elif msgtype == GOTRENOUNCE:
            friend = self.AddFriend(ip, peerid)
            friend.RemoveSharedFile(data[0], data[1])
            if len(friend.sharedfiles) == 0 and not friend.IsMyFriend():
                 self.friends.remove(friend)
            else:
                friend.online = False
        
        elif msgtype == ADDFOETEMP:
            foe = self.AddFoe(ip, peerid, True)
        
        elif msgtype == REMOVEFOE:
            foe = self.RemoveFoe(ip)

        elif msgtype == ADDFRIENDTEMP:
            friend = self.AddFriend(ip, peerid, myfriend=True, online=True, temp=True)
            friend.AddSharedFile(data[0], data[1])
            
    def RemoveFoe(self, ip):
        self.mod_lock.acquire(True)
        for f in self.foes:
            if f.ip == ip:
                self.foes.remove(f)
                break
        self.mod_lock.release()
                
    def AddFoe(self, ip, name, temp=True):
        self.mod_lock.acquire(True)
        foe = None
        # check if already in list
        for f in self.foes:
            if f.ip == ip:
                foe = f
                break
        
        if foe == None:
            foe = Foe(ip, name, temp)
            self.foes.append(foe)
            
        foe.temp = temp
        self.mod_lock.release()
        return foe
            
    def AddFriend(self, ip, peerid, myfriend=False, online=True, temp=False):
        self.mod_lock.acquire(True)
        friend = None
        # check if already in list
        for f in self.friends:
            if f.ip == ip:
                if f.type == 0 and myfriend == True:
                    #remove Friend if upgrading to MyFriend
                    self.friends.remove(f)
                else:
                    friend = f
                break
        
        if friend == None:
            if myfriend:
                friend = MyFriend(ip, peerid, self.btconfig)
            else:
                friend = Friend(ip, peerid)
            
            friend.temp = temp
            self.friends.append(friend)
        
        friend.online = online
        self.mod_lock.release()
        return friend

    def RemoveFriend(self, friend):
        self.mod_lock.acquire(True)
        for f in self.friends:
            if f.ip == friend.ip:
                self.friends.remove(f)
                break
                
        self.mod_lock.release()
            
    def RemoveByIP(self, ip):
        self.mod_lock.acquire(True)
        for f in self.friends:
            if ip == f.ip:
                self.friends.remove(f)
                break

        self.mod_lock.release()


    # removes friends who haven't checked in recently
    def Purge(self, live_files):
        self.mod_lock.acquire(True)
        i = 0
        live_hashes = [h[0] for h in live_files]
        
        while i < len(self.friends):
            f = self.friends[i]
            if f.lastupdate + self.config['timeout'] < time():
                if f.temp:
                    found = False
                    #peerid, port, infohash
                    for h in f.sharedfiles:
                        if h[0] in live_hashes:
                            found = True
                    if not found:
                        self.friends.remove(f)
                elif f.IsMyFriend():
                    f.online = False
                    f.sharedfiles = []
                else:
                    self.friends.remove(f)
                    continue
            i += 1
            
        self.mod_lock.release()
    
    
    # broadcasts live and dead infohashes
    def Broadcast(self, live_files):
        self.Purge(live_files)
        self.mod_lock.acquire(True)
        dead_files = []
        
        for h in self.last_live_files:
            if not h in live_files:
                dead_files.append(h)
        
        if len(live_files) > 0:
            for f in self.friends:
                if f.IsMyFriend() and not f.temp:
                    f.AnnounceHashes(live_files)
                            
        if len(dead_files) > 0:
            for f in self.friends:
                if f.IsMyFriend() and not f.temp:
                    f.RenounceHashes(dead_files)
                        
        self.last_live_files = live_files
        self.mod_lock.release()
    
    # The friends connections we need to stay connected to
    def GetNeedsConnection(self, infohash):
        self.mod_lock.acquire(True)
        plist = []
        
        for f in self.friends:
            hash_port = f.HasFile(infohash)
            if f.IsMyFriend() and f.online and not f.temp and hash_port:
                plist.append((f.ip, hash_port[1], f.peerid))
        
        self.mod_lock.release()
        return plist


    # returns a copy of a list of friends that are sharing the file specified in infohash
    # this func is called from a the DL thread - use care
    def GetInterested(self, infohash):
        if not self.mod_lock.acquire(False):
            return ({}, {})

        friendlist = {}
        foelist = {}

        #round robin
        j = len(self.friends)
        i = self.rr_pivot
        rotated_friends = self.friends[i:j] + self.friends[0:i]
        self.rr_pivot += 1
        
        for f in self.friends:
            if f.IsMyFriend(): # and f.HasFile(infohash):
                friendlist[f.ip] = True
       
        for f in self.foes:
            foelist[f.ip] = True
        
        self.mod_lock.release()
        return (friendlist, foelist)
        
        
            
if __name__ == "__main__":
    pass

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.