murder 0.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/LICENSE +17 -0
- data/README +224 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/dist/BitTornado/BT1/Choker.py +128 -0
- data/dist/BitTornado/BT1/Connecter.py +288 -0
- data/dist/BitTornado/BT1/Downloader.py +594 -0
- data/dist/BitTornado/BT1/DownloaderFeedback.py +155 -0
- data/dist/BitTornado/BT1/Encrypter.py +333 -0
- data/dist/BitTornado/BT1/FileSelector.py +245 -0
- data/dist/BitTornado/BT1/Filter.py +12 -0
- data/dist/BitTornado/BT1/HTTPDownloader.py +251 -0
- data/dist/BitTornado/BT1/NatCheck.py +95 -0
- data/dist/BitTornado/BT1/PiecePicker.py +320 -0
- data/dist/BitTornado/BT1/Rerequester.py +426 -0
- data/dist/BitTornado/BT1/Statistics.py +177 -0
- data/dist/BitTornado/BT1/Storage.py +584 -0
- data/dist/BitTornado/BT1/StorageWrapper.py +1045 -0
- data/dist/BitTornado/BT1/StreamCheck.py +135 -0
- data/dist/BitTornado/BT1/T2T.py +193 -0
- data/dist/BitTornado/BT1/Uploader.py +145 -0
- data/dist/BitTornado/BT1/__init__.py +1 -0
- data/dist/BitTornado/BT1/btformats.py +100 -0
- data/dist/BitTornado/BT1/fakeopen.py +89 -0
- data/dist/BitTornado/BT1/makemetafile.py +263 -0
- data/dist/BitTornado/BT1/track.py +1067 -0
- data/dist/BitTornado/ConfigDir.py +401 -0
- data/dist/BitTornado/ConfigReader.py +1068 -0
- data/dist/BitTornado/ConnChoice.py +31 -0
- data/dist/BitTornado/CreateIcons.py +105 -0
- data/dist/BitTornado/CurrentRateMeasure.py +37 -0
- data/dist/BitTornado/HTTPHandler.py +167 -0
- data/dist/BitTornado/PSYCO.py +5 -0
- data/dist/BitTornado/RateLimiter.py +153 -0
- data/dist/BitTornado/RateMeasure.py +75 -0
- data/dist/BitTornado/RawServer.py +195 -0
- data/dist/BitTornado/ServerPortHandler.py +188 -0
- data/dist/BitTornado/SocketHandler.py +375 -0
- data/dist/BitTornado/__init__.py +63 -0
- data/dist/BitTornado/bencode.py +319 -0
- data/dist/BitTornado/bitfield.py +162 -0
- data/dist/BitTornado/clock.py +27 -0
- data/dist/BitTornado/download_bt1.py +882 -0
- data/dist/BitTornado/inifile.py +169 -0
- data/dist/BitTornado/iprangeparse.py +194 -0
- data/dist/BitTornado/launchmanycore.py +381 -0
- data/dist/BitTornado/natpunch.py +254 -0
- data/dist/BitTornado/parseargs.py +137 -0
- data/dist/BitTornado/parsedir.py +150 -0
- data/dist/BitTornado/piecebuffer.py +86 -0
- data/dist/BitTornado/selectpoll.py +109 -0
- data/dist/BitTornado/subnetparse.py +218 -0
- data/dist/BitTornado/torrentlistparse.py +38 -0
- data/dist/BitTornado/zurllib.py +100 -0
- data/dist/murder_client.py +291 -0
- data/dist/murder_make_torrent.py +46 -0
- data/dist/murder_tracker.py +28 -0
- data/doc/examples/Capfile +28 -0
- data/lib/capistrano/recipes/deploy/strategy/murder.rb +52 -0
- data/lib/murder.rb +43 -0
- data/lib/murder/admin.rb +47 -0
- data/lib/murder/murder.rb +121 -0
- data/murder.gemspec +101 -0
- metadata +129 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# Written by Bram Cohen
|
2
|
+
# see LICENSE.txt for license information
|
3
|
+
|
4
|
+
from clock import clock
|
5
|
+
try:
|
6
|
+
True
|
7
|
+
except:
|
8
|
+
True = 1
|
9
|
+
False = 0
|
10
|
+
|
11
|
+
FACTOR = 0.999
|
12
|
+
|
13
|
+
class RateMeasure:
|
14
|
+
def __init__(self):
|
15
|
+
self.last = None
|
16
|
+
self.time = 1.0
|
17
|
+
self.got = 0.0
|
18
|
+
self.remaining = None
|
19
|
+
self.broke = False
|
20
|
+
self.got_anything = False
|
21
|
+
self.last_checked = None
|
22
|
+
self.rate = 0
|
23
|
+
self.lastten = False
|
24
|
+
|
25
|
+
def data_came_in(self, amount):
|
26
|
+
if not self.got_anything:
|
27
|
+
self.got_anything = True
|
28
|
+
self.last = clock()
|
29
|
+
return
|
30
|
+
self.update(amount)
|
31
|
+
|
32
|
+
def data_rejected(self, amount):
|
33
|
+
pass
|
34
|
+
|
35
|
+
def get_time_left(self, left):
|
36
|
+
t = clock()
|
37
|
+
if not self.got_anything:
|
38
|
+
return None
|
39
|
+
if t - self.last > 15:
|
40
|
+
self.update(0)
|
41
|
+
try:
|
42
|
+
remaining = left/self.rate
|
43
|
+
if not self.lastten and remaining <= 10:
|
44
|
+
self.lastten = True
|
45
|
+
if self.lastten:
|
46
|
+
return remaining
|
47
|
+
delta = max(remaining/20,2)
|
48
|
+
if self.remaining is None:
|
49
|
+
self.remaining = remaining
|
50
|
+
elif abs(self.remaining-remaining) > delta:
|
51
|
+
self.remaining = remaining
|
52
|
+
else:
|
53
|
+
self.remaining -= t - self.last_checked
|
54
|
+
except ZeroDivisionError:
|
55
|
+
self.remaining = None
|
56
|
+
if self.remaining is not None and self.remaining < 0.1:
|
57
|
+
self.remaining = 0.1
|
58
|
+
self.last_checked = t
|
59
|
+
return self.remaining
|
60
|
+
|
61
|
+
def update(self, amount):
|
62
|
+
t = clock()
|
63
|
+
t1 = int(t)
|
64
|
+
l1 = int(self.last)
|
65
|
+
for i in xrange(l1,t1):
|
66
|
+
self.time *= FACTOR
|
67
|
+
self.got *= FACTOR
|
68
|
+
self.got += amount
|
69
|
+
if t - self.last < 20:
|
70
|
+
self.time += t - self.last
|
71
|
+
self.last = t
|
72
|
+
try:
|
73
|
+
self.rate = self.got / self.time
|
74
|
+
except ZeroDivisionError:
|
75
|
+
pass
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# Written by Bram Cohen
|
2
|
+
# see LICENSE.txt for license information
|
3
|
+
|
4
|
+
from bisect import insort
|
5
|
+
from SocketHandler import SocketHandler, UPnP_ERROR
|
6
|
+
import socket
|
7
|
+
from cStringIO import StringIO
|
8
|
+
from traceback import print_exc
|
9
|
+
from select import error
|
10
|
+
from threading import Thread, Event
|
11
|
+
from time import sleep
|
12
|
+
from clock import clock
|
13
|
+
import sys
|
14
|
+
try:
|
15
|
+
True
|
16
|
+
except:
|
17
|
+
True = 1
|
18
|
+
False = 0
|
19
|
+
|
20
|
+
|
21
|
+
def autodetect_ipv6():
|
22
|
+
try:
|
23
|
+
assert sys.version_info >= (2,3)
|
24
|
+
assert socket.has_ipv6
|
25
|
+
socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
26
|
+
except:
|
27
|
+
return 0
|
28
|
+
return 1
|
29
|
+
|
30
|
+
def autodetect_socket_style():
|
31
|
+
if sys.platform.find('linux') < 0:
|
32
|
+
return 1
|
33
|
+
else:
|
34
|
+
try:
|
35
|
+
f = open('/proc/sys/net/ipv6/bindv6only','r')
|
36
|
+
dual_socket_style = int(f.read())
|
37
|
+
f.close()
|
38
|
+
return int(not dual_socket_style)
|
39
|
+
except:
|
40
|
+
return 0
|
41
|
+
|
42
|
+
|
43
|
+
READSIZE = 100000
|
44
|
+
|
45
|
+
class RawServer:
|
46
|
+
def __init__(self, doneflag, timeout_check_interval, timeout, noisy = True,
|
47
|
+
ipv6_enable = True, failfunc = lambda x: None, errorfunc = None,
|
48
|
+
sockethandler = None, excflag = Event()):
|
49
|
+
self.timeout_check_interval = timeout_check_interval
|
50
|
+
self.timeout = timeout
|
51
|
+
self.servers = {}
|
52
|
+
self.single_sockets = {}
|
53
|
+
self.dead_from_write = []
|
54
|
+
self.doneflag = doneflag
|
55
|
+
self.noisy = noisy
|
56
|
+
self.failfunc = failfunc
|
57
|
+
self.errorfunc = errorfunc
|
58
|
+
self.exccount = 0
|
59
|
+
self.funcs = []
|
60
|
+
self.externally_added = []
|
61
|
+
self.finished = Event()
|
62
|
+
self.tasks_to_kill = []
|
63
|
+
self.excflag = excflag
|
64
|
+
|
65
|
+
if sockethandler is None:
|
66
|
+
sockethandler = SocketHandler(timeout, ipv6_enable, READSIZE)
|
67
|
+
self.sockethandler = sockethandler
|
68
|
+
self.add_task(self.scan_for_timeouts, timeout_check_interval)
|
69
|
+
|
70
|
+
def get_exception_flag(self):
|
71
|
+
return self.excflag
|
72
|
+
|
73
|
+
def _add_task(self, func, delay, id = None):
|
74
|
+
assert float(delay) >= 0
|
75
|
+
insort(self.funcs, (clock() + delay, func, id))
|
76
|
+
|
77
|
+
def add_task(self, func, delay = 0, id = None):
|
78
|
+
assert float(delay) >= 0
|
79
|
+
self.externally_added.append((func, delay, id))
|
80
|
+
|
81
|
+
def scan_for_timeouts(self):
|
82
|
+
self.add_task(self.scan_for_timeouts, self.timeout_check_interval)
|
83
|
+
self.sockethandler.scan_for_timeouts()
|
84
|
+
|
85
|
+
def bind(self, port, bind = '', reuse = False,
|
86
|
+
ipv6_socket_style = 1, upnp = False):
|
87
|
+
self.sockethandler.bind(port, bind, reuse, ipv6_socket_style, upnp)
|
88
|
+
|
89
|
+
def find_and_bind(self, minport, maxport, bind = '', reuse = False,
|
90
|
+
ipv6_socket_style = 1, upnp = 0, randomizer = False):
|
91
|
+
return self.sockethandler.find_and_bind(minport, maxport, bind, reuse,
|
92
|
+
ipv6_socket_style, upnp, randomizer)
|
93
|
+
|
94
|
+
def start_connection_raw(self, dns, socktype, handler = None):
|
95
|
+
return self.sockethandler.start_connection_raw(dns, socktype, handler)
|
96
|
+
|
97
|
+
def start_connection(self, dns, handler = None, randomize = False):
|
98
|
+
return self.sockethandler.start_connection(dns, handler, randomize)
|
99
|
+
|
100
|
+
def get_stats(self):
|
101
|
+
return self.sockethandler.get_stats()
|
102
|
+
|
103
|
+
def pop_external(self):
|
104
|
+
while self.externally_added:
|
105
|
+
(a, b, c) = self.externally_added.pop(0)
|
106
|
+
self._add_task(a, b, c)
|
107
|
+
|
108
|
+
|
109
|
+
def listen_forever(self, handler):
|
110
|
+
self.sockethandler.set_handler(handler)
|
111
|
+
try:
|
112
|
+
while not self.doneflag.isSet():
|
113
|
+
try:
|
114
|
+
self.pop_external()
|
115
|
+
self._kill_tasks()
|
116
|
+
if self.funcs:
|
117
|
+
period = self.funcs[0][0] + 0.001 - clock()
|
118
|
+
else:
|
119
|
+
period = 2 ** 30
|
120
|
+
if period < 0:
|
121
|
+
period = 0
|
122
|
+
events = self.sockethandler.do_poll(period)
|
123
|
+
if self.doneflag.isSet():
|
124
|
+
return
|
125
|
+
while self.funcs and self.funcs[0][0] <= clock():
|
126
|
+
garbage1, func, id = self.funcs.pop(0)
|
127
|
+
if id in self.tasks_to_kill:
|
128
|
+
pass
|
129
|
+
try:
|
130
|
+
# print func.func_name
|
131
|
+
func()
|
132
|
+
except (SystemError, MemoryError), e:
|
133
|
+
self.failfunc(str(e))
|
134
|
+
return
|
135
|
+
except KeyboardInterrupt:
|
136
|
+
# self.exception(True)
|
137
|
+
return
|
138
|
+
except:
|
139
|
+
if self.noisy:
|
140
|
+
self.exception()
|
141
|
+
self.sockethandler.close_dead()
|
142
|
+
self.sockethandler.handle_events(events)
|
143
|
+
if self.doneflag.isSet():
|
144
|
+
return
|
145
|
+
self.sockethandler.close_dead()
|
146
|
+
except (SystemError, MemoryError), e:
|
147
|
+
self.failfunc(str(e))
|
148
|
+
return
|
149
|
+
except error:
|
150
|
+
if self.doneflag.isSet():
|
151
|
+
return
|
152
|
+
except KeyboardInterrupt:
|
153
|
+
# self.exception(True)
|
154
|
+
return
|
155
|
+
except:
|
156
|
+
self.exception()
|
157
|
+
if self.exccount > 10:
|
158
|
+
return
|
159
|
+
finally:
|
160
|
+
# self.sockethandler.shutdown()
|
161
|
+
self.finished.set()
|
162
|
+
|
163
|
+
def is_finished(self):
|
164
|
+
return self.finished.isSet()
|
165
|
+
|
166
|
+
def wait_until_finished(self):
|
167
|
+
self.finished.wait()
|
168
|
+
|
169
|
+
def _kill_tasks(self):
|
170
|
+
if self.tasks_to_kill:
|
171
|
+
new_funcs = []
|
172
|
+
for (t, func, id) in self.funcs:
|
173
|
+
if id not in self.tasks_to_kill:
|
174
|
+
new_funcs.append((t, func, id))
|
175
|
+
self.funcs = new_funcs
|
176
|
+
self.tasks_to_kill = []
|
177
|
+
|
178
|
+
def kill_tasks(self, id):
|
179
|
+
self.tasks_to_kill.append(id)
|
180
|
+
|
181
|
+
def exception(self, kbint = False):
|
182
|
+
if not kbint:
|
183
|
+
self.excflag.set()
|
184
|
+
self.exccount += 1
|
185
|
+
if self.errorfunc is None:
|
186
|
+
print_exc()
|
187
|
+
else:
|
188
|
+
data = StringIO()
|
189
|
+
print_exc(file = data)
|
190
|
+
# print data.getvalue() # report exception here too
|
191
|
+
if not kbint: # don't report here if it's a keyboard interrupt
|
192
|
+
self.errorfunc(data.getvalue())
|
193
|
+
|
194
|
+
def shutdown(self):
|
195
|
+
self.sockethandler.shutdown()
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# Written by John Hoffman
|
2
|
+
# see LICENSE.txt for license information
|
3
|
+
|
4
|
+
from cStringIO import StringIO
|
5
|
+
#from RawServer import RawServer
|
6
|
+
try:
|
7
|
+
True
|
8
|
+
except:
|
9
|
+
True = 1
|
10
|
+
False = 0
|
11
|
+
|
12
|
+
from BT1.Encrypter import protocol_name
|
13
|
+
|
14
|
+
default_task_id = []
|
15
|
+
|
16
|
+
class SingleRawServer:
|
17
|
+
def __init__(self, info_hash, multihandler, doneflag, protocol):
|
18
|
+
self.info_hash = info_hash
|
19
|
+
self.doneflag = doneflag
|
20
|
+
self.protocol = protocol
|
21
|
+
self.multihandler = multihandler
|
22
|
+
self.rawserver = multihandler.rawserver
|
23
|
+
self.finished = False
|
24
|
+
self.running = False
|
25
|
+
self.handler = None
|
26
|
+
self.taskqueue = []
|
27
|
+
|
28
|
+
def shutdown(self):
|
29
|
+
if not self.finished:
|
30
|
+
self.multihandler.shutdown_torrent(self.info_hash)
|
31
|
+
|
32
|
+
def _shutdown(self):
|
33
|
+
if not self.finished:
|
34
|
+
self.finished = True
|
35
|
+
self.running = False
|
36
|
+
self.rawserver.kill_tasks(self.info_hash)
|
37
|
+
if self.handler:
|
38
|
+
self.handler.close_all()
|
39
|
+
|
40
|
+
def _external_connection_made(self, c, options, already_read):
|
41
|
+
if self.running:
|
42
|
+
c.set_handler(self.handler)
|
43
|
+
self.handler.externally_handshaked_connection_made(
|
44
|
+
c, options, already_read)
|
45
|
+
|
46
|
+
### RawServer functions ###
|
47
|
+
|
48
|
+
def add_task(self, func, delay=0, id = default_task_id):
|
49
|
+
if id is default_task_id:
|
50
|
+
id = self.info_hash
|
51
|
+
if not self.finished:
|
52
|
+
self.rawserver.add_task(func, delay, id)
|
53
|
+
|
54
|
+
# def bind(self, port, bind = '', reuse = False):
|
55
|
+
# pass # not handled here
|
56
|
+
|
57
|
+
def start_connection(self, dns, handler = None):
|
58
|
+
if not handler:
|
59
|
+
handler = self.handler
|
60
|
+
c = self.rawserver.start_connection(dns, handler)
|
61
|
+
return c
|
62
|
+
|
63
|
+
# def listen_forever(self, handler):
|
64
|
+
# pass # don't call with this
|
65
|
+
|
66
|
+
def start_listening(self, handler):
|
67
|
+
self.handler = handler
|
68
|
+
self.running = True
|
69
|
+
return self.shutdown # obviously, doesn't listen forever
|
70
|
+
|
71
|
+
def is_finished(self):
|
72
|
+
return self.finished
|
73
|
+
|
74
|
+
def get_exception_flag(self):
|
75
|
+
return self.rawserver.get_exception_flag()
|
76
|
+
|
77
|
+
|
78
|
+
class NewSocketHandler: # hand a new socket off where it belongs
|
79
|
+
def __init__(self, multihandler, connection):
|
80
|
+
self.multihandler = multihandler
|
81
|
+
self.connection = connection
|
82
|
+
connection.set_handler(self)
|
83
|
+
self.closed = False
|
84
|
+
self.buffer = StringIO()
|
85
|
+
self.complete = False
|
86
|
+
self.next_len, self.next_func = 1, self.read_header_len
|
87
|
+
self.multihandler.rawserver.add_task(self._auto_close, 15)
|
88
|
+
|
89
|
+
def _auto_close(self):
|
90
|
+
if not self.complete:
|
91
|
+
self.close()
|
92
|
+
|
93
|
+
def close(self):
|
94
|
+
if not self.closed:
|
95
|
+
self.connection.close()
|
96
|
+
self.closed = True
|
97
|
+
|
98
|
+
|
99
|
+
# header format:
|
100
|
+
# connection.write(chr(len(protocol_name)) + protocol_name +
|
101
|
+
# (chr(0) * 8) + self.encrypter.download_id + self.encrypter.my_id)
|
102
|
+
|
103
|
+
# copied from Encrypter and modified
|
104
|
+
|
105
|
+
def read_header_len(self, s):
|
106
|
+
l = ord(s)
|
107
|
+
return l, self.read_header
|
108
|
+
|
109
|
+
def read_header(self, s):
|
110
|
+
self.protocol = s
|
111
|
+
return 8, self.read_reserved
|
112
|
+
|
113
|
+
def read_reserved(self, s):
|
114
|
+
self.options = s
|
115
|
+
return 20, self.read_download_id
|
116
|
+
|
117
|
+
def read_download_id(self, s):
|
118
|
+
if self.multihandler.singlerawservers.has_key(s):
|
119
|
+
if self.multihandler.singlerawservers[s].protocol == self.protocol:
|
120
|
+
return True
|
121
|
+
return None
|
122
|
+
|
123
|
+
def read_dead(self, s):
|
124
|
+
return None
|
125
|
+
|
126
|
+
def data_came_in(self, garbage, s):
|
127
|
+
while True:
|
128
|
+
if self.closed:
|
129
|
+
return
|
130
|
+
i = self.next_len - self.buffer.tell()
|
131
|
+
if i > len(s):
|
132
|
+
self.buffer.write(s)
|
133
|
+
return
|
134
|
+
self.buffer.write(s[:i])
|
135
|
+
s = s[i:]
|
136
|
+
m = self.buffer.getvalue()
|
137
|
+
self.buffer.reset()
|
138
|
+
self.buffer.truncate()
|
139
|
+
try:
|
140
|
+
x = self.next_func(m)
|
141
|
+
except:
|
142
|
+
self.next_len, self.next_func = 1, self.read_dead
|
143
|
+
raise
|
144
|
+
if x is None:
|
145
|
+
self.close()
|
146
|
+
return
|
147
|
+
if x == True: # ready to process
|
148
|
+
self.multihandler.singlerawservers[m]._external_connection_made(
|
149
|
+
self.connection, self.options, s)
|
150
|
+
self.complete = True
|
151
|
+
return
|
152
|
+
self.next_len, self.next_func = x
|
153
|
+
|
154
|
+
def connection_flushed(self, ss):
|
155
|
+
pass
|
156
|
+
|
157
|
+
def connection_lost(self, ss):
|
158
|
+
self.closed = True
|
159
|
+
|
160
|
+
class MultiHandler:
|
161
|
+
def __init__(self, rawserver, doneflag):
|
162
|
+
self.rawserver = rawserver
|
163
|
+
self.masterdoneflag = doneflag
|
164
|
+
self.singlerawservers = {}
|
165
|
+
self.connections = {}
|
166
|
+
self.taskqueues = {}
|
167
|
+
|
168
|
+
def newRawServer(self, info_hash, doneflag, protocol=protocol_name):
|
169
|
+
new = SingleRawServer(info_hash, self, doneflag, protocol)
|
170
|
+
self.singlerawservers[info_hash] = new
|
171
|
+
return new
|
172
|
+
|
173
|
+
def shutdown_torrent(self, info_hash):
|
174
|
+
self.singlerawservers[info_hash]._shutdown()
|
175
|
+
del self.singlerawservers[info_hash]
|
176
|
+
|
177
|
+
def listen_forever(self):
|
178
|
+
self.rawserver.listen_forever(self)
|
179
|
+
for srs in self.singlerawservers.values():
|
180
|
+
srs.finished = True
|
181
|
+
srs.running = False
|
182
|
+
srs.doneflag.set()
|
183
|
+
|
184
|
+
### RawServer handler functions ###
|
185
|
+
# be wary of name collisions
|
186
|
+
|
187
|
+
def external_connection_made(self, ss):
|
188
|
+
NewSocketHandler(self, ss)
|