OverlaySwarm.py :  » Network » Torrent-Swapper » swapper » Swapper » Overlay » 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 » Torrent Swapper 
Torrent Swapper » swapper » Swapper » Overlay » OverlaySwarm.py
# Written by Jie Yang
# see LICENSE.txt for license information
import sys
from threading import Event,currentThread
from sha import sha
from time import time
from struct import pack
from traceback import print_exc

from BitTornado.__init__ import createPeerID
from BitTornado.bencode import bencode,bdecode
from BitTornado.BT1.MessageID import *

from Swapper.__init__ import GLOBAL
from Swapper.utilities import show_permid2
from permid import ChallengeResponse
from OverlayEncrypter import OverlayEncoder
from OverlayConnecter import OverlayConnecter

protocol_name = 'BitTorrent protocol'    #TODO: 'BitTorrent+ protocol'
overlay_infohash = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

from __init__ import CurrentVersion,LowestVersion,SupportedVersions

DEBUG = False

def show(s):
    text = []
    for i in xrange(len(s)): 
        text.append(ord(s[i]))
    return text

def tobinary(i):
    return (chr(i >> 24) + chr((i >> 16) & 0xFF) + 
        chr((i >> 8) & 0xFF) + chr(i & 0xFF))
  
def wrap_message(message_id, payload=None):
    if payload is not None:
        ben_payload = bencode(payload)
        message = tobinary(1+len(ben_payload)) + message_id + ben_payload
    else:
        message = tobinary(1) + message_id
    return message
        

class OverlaySwarm:
    # Code to make this a singleton
    __single = None
    infohash = overlay_infohash

    def __init__(self):
        if OverlaySwarm.__single:
            raise RuntimeError, "OverlaySwarm is singleton"
        OverlaySwarm.__single = self 
        self.myid = createPeerID()
        self.myid = self.myid[:16] + pack('<H', LowestVersion) + pack('<H', CurrentVersion)
        self.protocol = protocol_name
        self.crs = {}
        self.registered = False
                    
    def getInstance(*args, **kw):
        if OverlaySwarm.__single is None:
            OverlaySwarm(*args, **kw)
        return OverlaySwarm.__single
    getInstance = staticmethod(getInstance)

    def register(self, listen_port, secure_overlay, multihandler, config):
        # Register overlay_infohash as known swarm with MultiHandler
        
        if self.registered:
            return
        
        self.myid = self.myid[:14] + pack('<H', listen_port) + self.myid[16:]
        self.secure_overlay = secure_overlay
        self.config = config
        self.doneflag = Event()
        self.rawserver = multihandler.newRawServer(self.infohash, 
                                              self.doneflag,
                                              self.protocol)

        # Create Connecter and Encoder for the swarm. TODO: ratelimiter
        self.connecter = OverlayConnecter(self, self.config)
        self.encoder = OverlayEncoder(self, self.connecter, self.rawserver, 
            self.myid, self.config['max_message_length'], self.rawserver.add_task, 
            self.config['keepalive_interval'], self.infohash, 
            lambda x: None, self.config)
        self.registered = True

    def isRegistered(self):
        return self.registered

    def start_listening(self):
        self.rawserver.start_listening(self.encoder)
            
    def connectPeer(self, dns):
        """ Connect to Overlay Socket given peer's ip and port """
        
        if DEBUG:
            print >> sys.stderr,"overlay: Start overlay swarm connection to", dns
        self.encoder.start_connection(dns, 0)
            
    def sendMessage(self, connection, message):
        if DEBUG:
            print >> sys.stderr,"overlay: send message", getMessageName(message[0]), "to", connection.get_dns(), show_permid2(connection.permid)
        connection.send_message(message)

    def connectionMade(self, connection):
        """ phase 1: Connecter.Connection is created but permid has not been verified """

        if DEBUG:
            print >> sys.stderr,"overlay: Bare connection",connection.get_myip(),connection.get_myport(),"to",connection.get_ip(),connection.get_port(),"reported by thread",currentThread().getName()
        
        #def c(conn = connection):
        #""" Start permid exchange and challenge/response validation """
        if not connection or self.crs.has_key(connection):
            return    # don't start c/r if connection is invalid or permid was exchanged
        cr = ChallengeResponse(self.myid, self)
        self.crs[connection] = cr
        cr.start_cr(connection)
        #self.rawserver.add_task(c, 0)
            
    def permidSocketMade(self, connection):    # Connecter.Connection. 
        """ phase 2: notify that the connection has been made """
        
        if self.crs.has_key(connection):
            self.crs.pop(connection)
        ## Arno: I don't see the need for letting the rawserver do it.
        ## gotMessage isn't scheduled on rawserver.
        #def notify(connection=connection):
        self.secure_overlay.connectionMade(connection)
        #self.rawserver.add_task(notify, 0)
                
    def connectionLost(self,connection):
        if DEBUG:
            print >> sys.stderr,"overlay: connectionLost: connection is",connection.get_ip(),connection.get_port()
        if connection.permid is None:
            # No permid, so it was never reported to the SecureOverlay
            return
        #def notify(connection=connection):
        self.secure_overlay.connectionLost(connection)
        #self.rawserver.add_task(notify, 0)

    def got_message(self, conn, message):    # Connecter.Connection
        """ Handle message for overlay swarm and return if the message is valid """

        if DEBUG:
            print >> sys.stderr, "overlay: Got",getMessageName(message[0]),"len",len(message), show_permid2(conn.permid)
        
        if not conn:
            return False
        t = message[0]
        
        if t in PermIDMessages:
            try:
                if not self.crs.has_key(conn):    # incoming permid exchange
                    self.crs[conn] = ChallengeResponse(self.myid, self)
                if self.crs[conn].got_message(conn, message) == False:
                    if conn and self.crs.has_key(conn):
                        self.crs.pop(conn)
                        conn.close()
            except:
                print_exc()
        else:
            if conn.permid:    # Do not go ahead without permid
                self.secure_overlay.gotMessage(conn.permid, message)
            else:
                print >> sys.stderr, "overlay: Got a message but not found the permid"
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.