home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / BitTorrent / Connecter.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  13.2 KB  |  435 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.4)
  3.  
  4. from bitfield import Bitfield
  5. from binascii import b2a_hex
  6. from CurrentRateMeasure import Measure
  7.  
  8. def toint(s):
  9.     return long(b2a_hex(s), 16)
  10.  
  11.  
  12. def tobinary(i):
  13.     return chr(i >> 24) + chr(i >> 16 & 255) + chr(i >> 8 & 255) + chr(i & 255)
  14.  
  15. CHOKE = chr(0)
  16. UNCHOKE = chr(1)
  17. INTERESTED = chr(2)
  18. NOT_INTERESTED = chr(3)
  19. HAVE = chr(4)
  20. BITFIELD = chr(5)
  21. REQUEST = chr(6)
  22. PIECE = chr(7)
  23. CANCEL = chr(8)
  24.  
  25. class Connection:
  26.     
  27.     def __init__(self, connection, connecter):
  28.         self.connection = connection
  29.         self.connecter = connecter
  30.         self.got_anything = False
  31.  
  32.     
  33.     def get_ip(self):
  34.         return self.connection.get_ip()
  35.  
  36.     
  37.     def get_id(self):
  38.         return self.connection.get_id()
  39.  
  40.     
  41.     def close(self):
  42.         self.connection.close()
  43.  
  44.     
  45.     def is_flushed(self):
  46.         if self.connecter.rate_capped:
  47.             return False
  48.         
  49.         return self.connection.is_flushed()
  50.  
  51.     
  52.     def is_locally_initiated(self):
  53.         return self.connection.is_locally_initiated()
  54.  
  55.     
  56.     def send_interested(self):
  57.         self.connection.send_message(INTERESTED)
  58.  
  59.     
  60.     def send_not_interested(self):
  61.         self.connection.send_message(NOT_INTERESTED)
  62.  
  63.     
  64.     def send_choke(self):
  65.         self.connection.send_message(CHOKE)
  66.  
  67.     
  68.     def send_unchoke(self):
  69.         self.connection.send_message(UNCHOKE)
  70.  
  71.     
  72.     def send_request(self, index, begin, length):
  73.         self.connection.send_message(REQUEST + tobinary(index) + tobinary(begin) + tobinary(length))
  74.  
  75.     
  76.     def send_cancel(self, index, begin, length):
  77.         self.connection.send_message(CANCEL + tobinary(index) + tobinary(begin) + tobinary(length))
  78.  
  79.     
  80.     def send_piece(self, index, begin, piece):
  81.         self.connecter._update_upload_rate(len(piece))
  82.         self.connection.send_message(PIECE + tobinary(index) + tobinary(begin) + piece)
  83.  
  84.     
  85.     def send_bitfield(self, bitfield):
  86.         self.connection.send_message(BITFIELD + bitfield)
  87.  
  88.     
  89.     def send_have(self, index):
  90.         self.connection.send_message(HAVE + tobinary(index))
  91.  
  92.     
  93.     def get_upload(self):
  94.         return self.upload
  95.  
  96.     
  97.     def get_download(self):
  98.         return self.download
  99.  
  100.  
  101.  
  102. class Connecter:
  103.     
  104.     def __init__(self, make_upload, downloader, choker, numpieces, totalup, max_upload_rate = 0, sched = None):
  105.         self.downloader = downloader
  106.         self.make_upload = make_upload
  107.         self.choker = choker
  108.         self.numpieces = numpieces
  109.         self.max_upload_rate = max_upload_rate
  110.         self.sched = sched
  111.         self.totalup = totalup
  112.         self.rate_capped = False
  113.         self.connections = { }
  114.  
  115.     
  116.     def _update_upload_rate(self, amount):
  117.         self.totalup.update_rate(amount)
  118.         if self.max_upload_rate > 0 and self.totalup.get_rate_noupdate() > self.max_upload_rate:
  119.             self.rate_capped = True
  120.             self.sched(self._uncap, self.totalup.time_until_rate(self.max_upload_rate))
  121.         
  122.  
  123.     
  124.     def _uncap(self):
  125.         self.rate_capped = False
  126.         while not self.rate_capped:
  127.             up = None
  128.             minrate = None
  129.             for i in self.connections.values():
  130.                 if not i.upload.is_choked() and i.upload.has_queries() and i.connection.is_flushed():
  131.                     rate = i.upload.get_rate()
  132.                     if up is None or rate < minrate:
  133.                         up = i.upload
  134.                         minrate = rate
  135.                     
  136.                 rate < minrate
  137.             
  138.             if up is None:
  139.                 break
  140.             
  141.             up.flushed()
  142.             if self.totalup.get_rate_noupdate() > self.max_upload_rate:
  143.                 break
  144.                 continue
  145.  
  146.     
  147.     def change_max_upload_rate(self, newval):
  148.         
  149.         def foo(self = self, newval = newval):
  150.             self._change_max_upload_rate(newval)
  151.  
  152.         self.sched(foo, 0)
  153.  
  154.     
  155.     def _change_max_upload_rate(self, newval):
  156.         self.max_upload_rate = newval
  157.         self._uncap()
  158.  
  159.     
  160.     def how_many_connections(self):
  161.         return len(self.connections)
  162.  
  163.     
  164.     def connection_made(self, connection):
  165.         c = Connection(connection, self)
  166.         self.connections[connection] = c
  167.         c.upload = self.make_upload(c)
  168.         c.download = self.downloader.make_download(c)
  169.         self.choker.connection_made(c)
  170.  
  171.     
  172.     def connection_lost(self, connection):
  173.         c = self.connections[connection]
  174.         d = c.download
  175.         del self.connections[connection]
  176.         d.disconnected()
  177.         self.choker.connection_lost(c)
  178.  
  179.     
  180.     def connection_flushed(self, connection):
  181.         self.connections[connection].upload.flushed()
  182.  
  183.     
  184.     def got_message(self, connection, message):
  185.         c = self.connections[connection]
  186.         t = message[0]
  187.         if t == BITFIELD and c.got_anything:
  188.             connection.close()
  189.             return None
  190.         
  191.         c.got_anything = True
  192.         if t in [
  193.             CHOKE,
  194.             UNCHOKE,
  195.             INTERESTED,
  196.             NOT_INTERESTED] and len(message) != 1:
  197.             connection.close()
  198.             return None
  199.         
  200.         if t == CHOKE:
  201.             c.download.got_choke()
  202.         elif t == UNCHOKE:
  203.             c.download.got_unchoke()
  204.         elif t == INTERESTED:
  205.             c.upload.got_interested()
  206.         elif t == NOT_INTERESTED:
  207.             c.upload.got_not_interested()
  208.         elif t == HAVE:
  209.             if len(message) != 5:
  210.                 connection.close()
  211.                 return None
  212.             
  213.             i = toint(message[1:])
  214.             if i >= self.numpieces:
  215.                 connection.close()
  216.                 return None
  217.             
  218.             c.download.got_have(i)
  219.         elif t == BITFIELD:
  220.             
  221.             try:
  222.                 b = Bitfield(self.numpieces, message[1:])
  223.             except ValueError:
  224.                 connection.close()
  225.                 return None
  226.  
  227.             c.download.got_have_bitfield(b)
  228.         elif t == REQUEST:
  229.             if len(message) != 13:
  230.                 connection.close()
  231.                 return None
  232.             
  233.             i = toint(message[1:5])
  234.             if i >= self.numpieces:
  235.                 connection.close()
  236.                 return None
  237.             
  238.             c.upload.got_request(i, toint(message[5:9]), toint(message[9:]))
  239.         elif t == CANCEL:
  240.             if len(message) != 13:
  241.                 connection.close()
  242.                 return None
  243.             
  244.             i = toint(message[1:5])
  245.             if i >= self.numpieces:
  246.                 connection.close()
  247.                 return None
  248.             
  249.             c.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
  250.         elif t == PIECE:
  251.             if len(message) <= 9:
  252.                 connection.close()
  253.                 return None
  254.             
  255.             i = toint(message[1:5])
  256.             if i >= self.numpieces:
  257.                 connection.close()
  258.                 return None
  259.             
  260.             if c.download.got_piece(i, toint(message[5:9]), message[9:]):
  261.                 for co in self.connections.values():
  262.                     co.send_have(i)
  263.                 
  264.             
  265.         else:
  266.             connection.close()
  267.  
  268.  
  269.  
  270. class DummyUpload:
  271.     
  272.     def __init__(self, events):
  273.         self.events = events
  274.         events.append('made upload')
  275.  
  276.     
  277.     def flushed(self):
  278.         self.events.append('flushed')
  279.  
  280.     
  281.     def got_interested(self):
  282.         self.events.append('interested')
  283.  
  284.     
  285.     def got_not_interested(self):
  286.         self.events.append('not interested')
  287.  
  288.     
  289.     def got_request(self, index, begin, length):
  290.         self.events.append(('request', index, begin, length))
  291.  
  292.     
  293.     def got_cancel(self, index, begin, length):
  294.         self.events.append(('cancel', index, begin, length))
  295.  
  296.  
  297.  
  298. class DummyDownload:
  299.     
  300.     def __init__(self, events):
  301.         self.events = events
  302.         events.append('made download')
  303.         self.hit = 0
  304.  
  305.     
  306.     def disconnected(self):
  307.         self.events.append('disconnected')
  308.  
  309.     
  310.     def got_choke(self):
  311.         self.events.append('choke')
  312.  
  313.     
  314.     def got_unchoke(self):
  315.         self.events.append('unchoke')
  316.  
  317.     
  318.     def got_have(self, i):
  319.         self.events.append(('have', i))
  320.  
  321.     
  322.     def got_have_bitfield(self, bitfield):
  323.         self.events.append(('bitfield', bitfield.tostring()))
  324.  
  325.     
  326.     def got_piece(self, index, begin, piece):
  327.         self.events.append(('piece', index, begin, piece))
  328.         self.hit += 1
  329.         return self.hit > 1
  330.  
  331.  
  332.  
  333. class DummyDownloader:
  334.     
  335.     def __init__(self, events):
  336.         self.events = events
  337.  
  338.     
  339.     def make_download(self, connection):
  340.         return DummyDownload(self.events)
  341.  
  342.  
  343.  
  344. class DummyConnection:
  345.     
  346.     def __init__(self, events):
  347.         self.events = events
  348.  
  349.     
  350.     def send_message(self, message):
  351.         self.events.append(('m', message))
  352.  
  353.  
  354.  
  355. class DummyChoker:
  356.     
  357.     def __init__(self, events, cs):
  358.         self.events = events
  359.         self.cs = cs
  360.  
  361.     
  362.     def connection_made(self, c):
  363.         self.events.append('made')
  364.         self.cs.append(c)
  365.  
  366.     
  367.     def connection_lost(self, c):
  368.         self.events.append('lost')
  369.  
  370.  
  371.  
  372. def test_operation():
  373.     events = []
  374.     cs = []
  375.     co = Connecter((lambda c, events = events: DummyUpload(events)), DummyDownloader(events), DummyChoker(events, cs), 3, Measure(10))
  376.     dc = DummyConnection(events)
  377.     co.connection_made(dc)
  378.     cc = cs[0]
  379.     co.got_message(dc, BITFIELD + chr(192))
  380.     co.got_message(dc, CHOKE)
  381.     co.got_message(dc, UNCHOKE)
  382.     co.got_message(dc, INTERESTED)
  383.     co.got_message(dc, NOT_INTERESTED)
  384.     co.got_message(dc, HAVE + tobinary(2))
  385.     co.got_message(dc, REQUEST + tobinary(1) + tobinary(5) + tobinary(6))
  386.     co.got_message(dc, CANCEL + tobinary(2) + tobinary(3) + tobinary(4))
  387.     co.got_message(dc, PIECE + tobinary(1) + tobinary(0) + 'abc')
  388.     co.got_message(dc, PIECE + tobinary(1) + tobinary(3) + 'def')
  389.     co.connection_flushed(dc)
  390.     cc.send_bitfield(chr(96))
  391.     cc.send_interested()
  392.     cc.send_not_interested()
  393.     cc.send_choke()
  394.     cc.send_unchoke()
  395.     cc.send_have(4)
  396.     cc.send_request(0, 2, 1)
  397.     cc.send_cancel(1, 2, 3)
  398.     cc.send_piece(1, 2, 'abc')
  399.     co.connection_lost(dc)
  400.     x = [
  401.         'made upload',
  402.         'made download',
  403.         'made',
  404.         ('bitfield', chr(192)),
  405.         'choke',
  406.         'unchoke',
  407.         'interested',
  408.         'not interested',
  409.         ('have', 2),
  410.         ('request', 1, 5, 6),
  411.         ('cancel', 2, 3, 4),
  412.         ('piece', 1, 0, 'abc'),
  413.         ('piece', 1, 3, 'def'),
  414.         ('m', HAVE + tobinary(1)),
  415.         'flushed',
  416.         ('m', BITFIELD + chr(96)),
  417.         ('m', INTERESTED),
  418.         ('m', NOT_INTERESTED),
  419.         ('m', CHOKE),
  420.         ('m', UNCHOKE),
  421.         ('m', HAVE + tobinary(4)),
  422.         ('m', REQUEST + tobinary(0) + tobinary(2) + tobinary(1)),
  423.         ('m', CANCEL + tobinary(1) + tobinary(2) + tobinary(3)),
  424.         ('m', PIECE + tobinary(1) + tobinary(2) + 'abc'),
  425.         'disconnected',
  426.         'lost']
  427.     for a, b in zip(events, x):
  428.         pass
  429.     
  430.  
  431.  
  432. def test_conversion():
  433.     pass
  434.  
  435.