home *** CD-ROM | disk | FTP | other *** search
/ Chip 2006 June / CHIP 2006-06.2.iso / program / freeware / Democracy-0.8.2.exe / xulrunner / python / BitTorrent / Encoder.py < prev    next >
Encoding:
Python Source  |  2006-04-10  |  5.7 KB  |  177 lines

  1. # The contents of this file are subject to the BitTorrent Open Source License
  2. # Version 1.0 (the License).  You may not copy or use this file, in either
  3. # source code or executable form, except in compliance with the License.  You
  4. # may obtain a copy of the License at http://www.bittorrent.com/license/.
  5. #
  6. # Software distributed under the License is distributed on an AS IS basis,
  7. # WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
  8. # for the specific language governing rights and limitations under the
  9. # License.
  10.  
  11. # Written by Bram Cohen
  12.  
  13. from socket import error as socketerror
  14.  
  15. from BitTorrent.Connecter import Connection
  16. from BitTorrent import BTFailure
  17.  
  18.  
  19. # header, reserved, download id, my id, [length, message]
  20.  
  21.  
  22. class Encoder(object):
  23.  
  24.     def __init__(self, make_upload, downloader, choker, numpieces, ratelimiter,
  25.                raw_server, config, my_id, schedulefunc, download_id, context):
  26.         self.make_upload = make_upload
  27.         self.downloader = downloader
  28.         self.choker = choker
  29.         self.numpieces = numpieces
  30.         self.ratelimiter = ratelimiter
  31.         self.raw_server = raw_server
  32.         self.my_id = my_id
  33.         self.config = config
  34.         self.schedulefunc = schedulefunc
  35.         self.download_id = download_id
  36.         self.context = context
  37.         self.everinc = False
  38.         self.connections = {}
  39.         self.complete_connections = {}
  40.         self.spares = []
  41.         self.banned = {}
  42.         schedulefunc(self.send_keepalives, config['keepalive_interval'])
  43.  
  44.     def send_keepalives(self):
  45.         self.schedulefunc(self.send_keepalives,
  46.                           self.config['keepalive_interval'])
  47.         for c in self.complete_connections:
  48.             c.send_keepalive()
  49.  
  50.     def start_connection(self, dns, id):
  51.         if dns[0] in self.banned:
  52.             return
  53.         if id == self.my_id:
  54.             return
  55.         for v in self.connections.values():
  56.             if id and v.id == id:
  57.                 return
  58.             if self.config['one_connection_per_ip'] and v.ip == dns[0]:
  59.                 return
  60.         if len(self.connections) >= self.config['max_initiate']:
  61.             if len(self.spares) < self.config['max_initiate'] and \
  62.                    dns not in self.spares:
  63.                 self.spares.append(dns)
  64.             return
  65.         try:
  66.             c = self.raw_server.start_connection(dns, None, self.context)
  67.         except socketerror:
  68.             pass
  69.         else:
  70.             con = Connection(self, c, id, True)
  71.             self.connections[c] = con
  72.             c.handler = con
  73.  
  74.     def connection_completed(self, c):
  75.         self.complete_connections[c] = 1
  76.         c.upload = self.make_upload(c)
  77.         c.download = self.downloader.make_download(c)
  78.         self.choker.connection_made(c)
  79.  
  80.     def ever_got_incoming(self):
  81.         return self.everinc
  82.  
  83.     def how_many_connections(self):
  84.         return len(self.complete_connections)
  85.  
  86.     def replace_connection(self):
  87.         while len(self.connections) < self.config['max_initiate'] and \
  88.                   self.spares:
  89.             self.start_connection(self.spares.pop(), None)
  90.  
  91.     def close_connections(self):
  92.         for c in self.connections.itervalues():
  93.             if not c.closed:
  94.                 c.connection.close()
  95.                 c.closed = True
  96.  
  97.     def singleport_connection(self, listener, con):
  98.         if con.ip in self.banned:
  99.             return
  100.         m = self.config['max_allow_in']
  101.         if m and len(self.connections) >= m:
  102.             return
  103.         self.connections[con.connection] = con
  104.         del listener.connections[con.connection]
  105.         con.encoder = self
  106.         con.connection.context = self.context
  107.  
  108.     def ban(self, ip):
  109.         self.banned[ip] = None
  110.  
  111.  
  112. class SingleportListener(object):
  113.  
  114.     def __init__(self, rawserver):
  115.         self.rawserver = rawserver
  116.         self.port = 0
  117.         self.ports = {}
  118.         self.torrents = {}
  119.         self.connections = {}
  120.         self.download_id = None
  121.  
  122.     def _check_close(self, port):
  123.         if not port or self.port == port or self.ports[port][1] > 0:
  124.             return
  125.         serversocket = self.ports[port][0]
  126.         self.rawserver.stop_listening(serversocket)
  127.         serversocket.close()
  128.         del self.ports[port]
  129.  
  130.     def open_port(self, port, config):
  131.         if port in self.ports:
  132.             self.port = port
  133.             return
  134.         serversocket = self.rawserver.create_serversocket(
  135.             port, config['bind'], reuse=True, tos=config['peer_socket_tos'])
  136.         self.rawserver.start_listening(serversocket, self)
  137.         oldport = self.port
  138.         self.port = port
  139.         self.ports[port] = [serversocket, 0]
  140.         self._check_close(oldport)
  141.  
  142.     def get_port(self):
  143.         if self.port:
  144.             self.ports[self.port][1] += 1
  145.         return self.port
  146.  
  147.     def release_port(self, port):
  148.         self.ports[port][1] -= 1
  149.         self._check_close(port)
  150.  
  151.     def close_sockets(self):
  152.         for serversocket, _ in self.ports.itervalues():
  153.             self.rawserver.stop_listening(serversocket)
  154.             serversocket.close()
  155.  
  156.     def add_torrent(self, infohash, encoder):
  157.         if infohash in self.torrents:
  158.             raise BTFailure("Can't start two separate instances of the same "
  159.                             "torrent")
  160.         self.torrents[infohash] = encoder
  161.  
  162.     def remove_torrent(self, infohash):
  163.         del self.torrents[infohash]
  164.  
  165.     def select_torrent(self, conn, infohash):
  166.         if infohash not in self.torrents:
  167.             return
  168.         self.torrents[infohash].singleport_connection(self, conn)
  169.  
  170.     def external_connection_made(self, connection):
  171.         con = Connection(self, connection, None, False)
  172.         self.connections[connection] = con
  173.         connection.handler = con
  174.  
  175.     def replace_connection(self):
  176.         pass
  177.