Blame | Last modification | View Log | Download
# Written by John Hoffman
# see LICENSE.txt for license information
from cStringIO import StringIO
#from RawServer import RawServer
try:
True
except:
True = 1
False = 0
from BT1.Encrypter import protocol_name
default_task_id = []
class SingleRawServer:
def __init__(self, info_hash, multihandler, doneflag, protocol):
self.info_hash = info_hash
self.doneflag = doneflag
self.protocol = protocol
self.multihandler = multihandler
self.rawserver = multihandler.rawserver
self.finished = False
self.running = False
self.handler = None
self.taskqueue = []
def shutdown(self):
if not self.finished:
self.multihandler.shutdown_torrent(self.info_hash)
def _shutdown(self):
if not self.finished:
self.finished = True
self.running = False
self.rawserver.kill_tasks(self.info_hash)
if self.handler:
self.handler.close_all()
def _external_connection_made(self, c, options, already_read):
if self.running:
c.set_handler(self.handler)
self.handler.externally_handshaked_connection_made(
c, options, already_read)
### RawServer functions ###
def add_task(self, func, delay=0, id = default_task_id):
if id is default_task_id:
id = self.info_hash
if not self.finished:
self.rawserver.add_task(func, delay, id)
# def bind(self, port, bind = '', reuse = False):
# pass # not handled here
def start_connection(self, dns, handler = None):
if not handler:
handler = self.handler
c = self.rawserver.start_connection(dns, handler)
return c
# def listen_forever(self, handler):
# pass # don't call with this
def start_listening(self, handler):
self.handler = handler
self.running = True
return self.shutdown # obviously, doesn't listen forever
def is_finished(self):
return self.finished
def get_exception_flag(self):
return self.rawserver.get_exception_flag()
class NewSocketHandler: # hand a new socket off where it belongs
def __init__(self, multihandler, connection):
self.multihandler = multihandler
self.connection = connection
connection.set_handler(self)
self.closed = False
self.buffer = StringIO()
self.complete = False
self.next_len, self.next_func = 1, self.read_header_len
self.multihandler.rawserver.add_task(self._auto_close, 15)
def _auto_close(self):
if not self.complete:
self.close()
def close(self):
if not self.closed:
self.connection.close()
self.closed = True
# header format:
# connection.write(chr(len(protocol_name)) + protocol_name +
# (chr(0) * 8) + self.encrypter.download_id + self.encrypter.my_id)
# copied from Encrypter and modified
def read_header_len(self, s):
l = ord(s)
return l, self.read_header
def read_header(self, s):
self.protocol = s
return 8, self.read_reserved
def read_reserved(self, s):
self.options = s
return 20, self.read_download_id
def read_download_id(self, s):
if self.multihandler.singlerawservers.has_key(s):
if self.multihandler.singlerawservers[s].protocol == self.protocol:
return True
return None
def read_dead(self, s):
return None
def data_came_in(self, garbage, s):
while True:
if self.closed:
return
i = self.next_len - self.buffer.tell()
if i > len(s):
self.buffer.write(s)
return
self.buffer.write(s[:i])
s = s[i:]
m = self.buffer.getvalue()
self.buffer.reset()
self.buffer.truncate()
try:
x = self.next_func(m)
except:
self.next_len, self.next_func = 1, self.read_dead
raise
if x is None:
self.close()
return
if x == True: # ready to process
self.multihandler.singlerawservers[m]._external_connection_made(
self.connection, self.options, s)
self.complete = True
return
self.next_len, self.next_func = x
def connection_flushed(self, ss):
pass
def connection_lost(self, ss):
self.closed = True
class MultiHandler:
def __init__(self, rawserver, doneflag):
self.rawserver = rawserver
self.masterdoneflag = doneflag
self.singlerawservers = {}
self.connections = {}
self.taskqueues = {}
def newRawServer(self, info_hash, doneflag, protocol=protocol_name):
new = SingleRawServer(info_hash, self, doneflag, protocol)
self.singlerawservers[info_hash] = new
return new
def shutdown_torrent(self, info_hash):
self.singlerawservers[info_hash]._shutdown()
del self.singlerawservers[info_hash]
def listen_forever(self):
self.rawserver.listen_forever(self)
for srs in self.singlerawservers.values():
srs.finished = True
srs.running = False
srs.doneflag.set()
### RawServer handler functions ###
# be wary of name collisions
def external_connection_made(self, ss):
NewSocketHandler(self, ss)